You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

476 lines
11KB

  1. /*
  2. * SGI image format
  3. * Todd Kirby <doubleshot@pacbell.net>
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. #include "avformat.h"
  20. #include "avio.h"
  21. /* #define DEBUG */
  22. #define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
  23. #define BE_32(x) ((((uint8_t*)(x))[0] << 24) | \
  24. (((uint8_t*)(x))[1] << 16) | \
  25. (((uint8_t*)(x))[2] << 8) | \
  26. ((uint8_t*)(x))[3])
  27. /* sgi image file signature */
  28. #define SGI_MAGIC 474
  29. #define SGI_HEADER_SIZE 512
  30. #define SGI_GRAYSCALE 1
  31. #define SGI_RGB 3
  32. #define SGI_RGBA 4
  33. #define SGI_SINGLE_CHAN 2
  34. #define SGI_MULTI_CHAN 3
  35. typedef struct SGIInfo{
  36. short magic;
  37. char rle;
  38. char bytes_per_channel;
  39. unsigned short dimension;
  40. unsigned short xsize;
  41. unsigned short ysize;
  42. unsigned short zsize;
  43. } SGIInfo;
  44. static int sgi_probe(AVProbeData *pd)
  45. {
  46. /* test for sgi magic */
  47. if (pd->buf_size >= 2 && BE_16(&pd->buf[0]) == SGI_MAGIC) {
  48. return AVPROBE_SCORE_MAX;
  49. } else {
  50. return 0;
  51. }
  52. }
  53. /* read sgi header fields */
  54. static void read_sgi_header(ByteIOContext *f, SGIInfo *info)
  55. {
  56. info->magic = (unsigned short) get_be16(f);
  57. info->rle = get_byte(f);
  58. info->bytes_per_channel = get_byte(f);
  59. info->dimension = (unsigned short)get_be16(f);
  60. info->xsize = (unsigned short) get_be16(f);
  61. info->ysize = (unsigned short) get_be16(f);
  62. info->zsize = (unsigned short) get_be16(f);
  63. #ifdef DEBUG
  64. printf("sgi header fields:\n");
  65. printf(" magic: %d\n", info->magic);
  66. printf(" rle: %d\n", info->rle);
  67. printf(" bpc: %d\n", info->bytes_per_channel);
  68. printf(" dim: %d\n", info->dimension);
  69. printf(" xsize: %d\n", info->xsize);
  70. printf(" ysize: %d\n", info->ysize);
  71. printf(" zsize: %d\n", info->zsize);
  72. #endif
  73. return;
  74. }
  75. /* read an uncompressed sgi image */
  76. static int read_uncompressed_sgi(const SGIInfo *si,
  77. AVPicture *pict, ByteIOContext *f)
  78. {
  79. int x, y, z, chan_offset, ret = 0;
  80. uint8_t *dest_row, *tmp_row = NULL;
  81. tmp_row = av_malloc(si->xsize);
  82. /* skip header */
  83. url_fseek(f, SGI_HEADER_SIZE, SEEK_SET);
  84. pict->linesize[0] = si->xsize;
  85. for (z = 0; z < si->zsize; z++) {
  86. #ifndef WORDS_BIGENDIAN
  87. /* rgba -> bgra for rgba32 on little endian cpus */
  88. if (si->zsize == 4 && z != 3)
  89. chan_offset = 2 - z;
  90. else
  91. #endif
  92. chan_offset = z;
  93. for (y = si->ysize - 1; y >= 0; y--) {
  94. dest_row = pict->data[0] + (y * si->xsize * si->zsize);
  95. if (!get_buffer(f, tmp_row, si->xsize)) {
  96. ret = -1;
  97. goto cleanup;
  98. }
  99. for (x = 0; x < si->xsize; x++) {
  100. dest_row[chan_offset] = tmp_row[x];
  101. dest_row += si->zsize;
  102. }
  103. }
  104. }
  105. cleanup:
  106. av_free(tmp_row);
  107. return ret;
  108. }
  109. /* expand an rle row into a channel */
  110. static void expand_rle_row(unsigned char *optr, unsigned char *iptr,
  111. int chan_offset, int pixelstride)
  112. {
  113. unsigned char pixel, count;
  114. #ifndef WORDS_BIGENDIAN
  115. /* rgba -> bgra for rgba32 on little endian cpus */
  116. if (pixelstride == 4 && chan_offset != 3) {
  117. chan_offset = 2 - chan_offset;
  118. }
  119. #endif
  120. optr += chan_offset;
  121. while (1) {
  122. pixel = *iptr++;
  123. if (!(count = (pixel & 0x7f))) {
  124. return;
  125. }
  126. if (pixel & 0x80) {
  127. while (count--) {
  128. *optr = *iptr;
  129. optr += pixelstride;
  130. iptr++;
  131. }
  132. } else {
  133. pixel = *iptr++;
  134. while (count--) {
  135. *optr = pixel;
  136. optr += pixelstride;
  137. }
  138. }
  139. }
  140. }
  141. /* read a run length encoded sgi image */
  142. static int read_rle_sgi(const SGIInfo *sgi_info,
  143. AVPicture *pict, ByteIOContext *f)
  144. {
  145. uint8_t *dest_row, *rle_data = NULL;
  146. unsigned long *start_table, *length_table;
  147. int y, z, xsize, ysize, zsize, tablen;
  148. long start_offset, run_length;
  149. int ret = 0;
  150. xsize = sgi_info->xsize;
  151. ysize = sgi_info->ysize;
  152. zsize = sgi_info->zsize;
  153. rle_data = av_malloc(xsize);
  154. /* skip header */
  155. url_fseek(f, SGI_HEADER_SIZE, SEEK_SET);
  156. /* size of rle offset and length tables */
  157. tablen = ysize * zsize * sizeof(long);
  158. start_table = (unsigned long *)av_malloc(tablen);
  159. length_table = (unsigned long *)av_malloc(tablen);
  160. if (!get_buffer(f, (uint8_t *)start_table, tablen)) {
  161. ret = -1;
  162. goto fail;
  163. }
  164. if (!get_buffer(f, (uint8_t *)length_table, tablen)) {
  165. ret = -1;
  166. goto fail;
  167. }
  168. for (z = 0; z < zsize; z++) {
  169. for (y = 0; y < ysize; y++) {
  170. dest_row = pict->data[0] + (ysize - 1 - y) * (xsize * zsize);
  171. start_offset = BE_32(&start_table[y + z * ysize]);
  172. run_length = BE_32(&length_table[y + z * ysize]);
  173. /* don't seek if already in the correct spot */
  174. if (url_ftell(f) != start_offset) {
  175. url_fseek(f, start_offset, SEEK_SET);
  176. }
  177. get_buffer(f, rle_data, run_length);
  178. expand_rle_row(dest_row, rle_data, z, zsize);
  179. }
  180. }
  181. fail:
  182. av_free(start_table);
  183. av_free(length_table);
  184. av_free(rle_data);
  185. return ret;
  186. }
  187. static int sgi_read(ByteIOContext *f,
  188. int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
  189. {
  190. SGIInfo sgi_info, *s = &sgi_info;
  191. AVImageInfo info1, *info = &info1;
  192. int ret;
  193. read_sgi_header(f, s);
  194. if (s->bytes_per_channel != 1) {
  195. return AVERROR_INVALIDDATA;
  196. }
  197. /* check for supported image dimensions */
  198. if (s->dimension != 2 && s->dimension != 3) {
  199. return AVERROR_INVALIDDATA;
  200. }
  201. if (s->zsize == SGI_GRAYSCALE) {
  202. info->pix_fmt = PIX_FMT_GRAY8;
  203. } else if (s->zsize == SGI_RGB) {
  204. info->pix_fmt = PIX_FMT_RGB24;
  205. } else if (s->zsize == SGI_RGBA) {
  206. info->pix_fmt = PIX_FMT_RGBA32;
  207. } else {
  208. return AVERROR_INVALIDDATA;
  209. }
  210. info->width = s->xsize;
  211. info->height = s->ysize;
  212. ret = alloc_cb(opaque, info);
  213. if (ret)
  214. return ret;
  215. if (s->rle) {
  216. return read_rle_sgi(s, &info->pict, f);
  217. } else {
  218. return read_uncompressed_sgi(s, &info->pict, f);
  219. }
  220. return 0; /* not reached */
  221. }
  222. #ifdef CONFIG_ENCODERS
  223. static void write_sgi_header(ByteIOContext *f, const SGIInfo *info)
  224. {
  225. int i;
  226. put_be16(f, SGI_MAGIC);
  227. put_byte(f, info->rle);
  228. put_byte(f, info->bytes_per_channel);
  229. put_be16(f, info->dimension);
  230. put_be16(f, info->xsize);
  231. put_be16(f, info->ysize);
  232. put_be16(f, info->zsize);
  233. /* The rest are constant in this implementation */
  234. put_be32(f, 0L); /* pixmin */
  235. put_be32(f, 255L); /* pixmax */
  236. put_be32(f, 0L); /* dummy */
  237. /* name */
  238. for (i = 0; i < 80; i++) {
  239. put_byte(f, 0);
  240. }
  241. put_be32(f, 0L); /* colormap */
  242. /* The rest of the 512 byte header is unused. */
  243. for (i = 0; i < 404; i++) {
  244. put_byte(f, 0);
  245. }
  246. }
  247. static int rle_row(ByteIOContext *f, char *row, int stride, int rowsize)
  248. {
  249. int length, count, i, x;
  250. char *start, repeat = 0;
  251. for (x = rowsize, length = 0; x > 0;) {
  252. start = row;
  253. row += (2 * stride);
  254. x -= 2;
  255. while (x > 0 && (row[-2 * stride] != row[-1 * stride] ||
  256. row[-1 * stride] != row[0])) {
  257. row += stride;
  258. x--;
  259. };
  260. row -= (2 * stride);
  261. x += 2;
  262. count = (row - start) / stride;
  263. while (count > 0) {
  264. i = count > 126 ? 126 : count;
  265. count -= i;
  266. put_byte(f, 0x80 | i);
  267. length++;
  268. while (i > 0) {
  269. put_byte(f, *start);
  270. start += stride;
  271. i--;
  272. length++;
  273. };
  274. };
  275. if (x <= 0) {
  276. break;
  277. }
  278. start = row;
  279. repeat = row[0];
  280. row += stride;
  281. x--;
  282. while (x > 0 && *row == repeat) {
  283. row += stride;
  284. x--;
  285. };
  286. count = (row - start) / stride;
  287. while (count > 0) {
  288. i = count > 126 ? 126 : count;
  289. count -= i;
  290. put_byte(f, i);
  291. length++;
  292. put_byte(f, repeat);
  293. length++;
  294. };
  295. };
  296. length++;
  297. put_byte(f, 0);
  298. return (length);
  299. }
  300. static int sgi_write(ByteIOContext *pb, AVImageInfo *info)
  301. {
  302. SGIInfo sgi_info, *si = &sgi_info;
  303. long *offsettab, *lengthtab;
  304. int i, y, z;
  305. int tablesize, chan_offset;
  306. uint8_t *srcrow;
  307. si->xsize = info->width;
  308. si->ysize = info->height;
  309. si->rle = 1;
  310. si->bytes_per_channel = 1;
  311. switch(info->pix_fmt) {
  312. case PIX_FMT_GRAY8:
  313. si->dimension = SGI_SINGLE_CHAN;
  314. si->zsize = SGI_GRAYSCALE;
  315. break;
  316. case PIX_FMT_RGB24:
  317. si->dimension = SGI_MULTI_CHAN;
  318. si->zsize = SGI_RGB;
  319. break;
  320. case PIX_FMT_RGBA32:
  321. si->dimension = SGI_MULTI_CHAN;
  322. si->zsize = SGI_RGBA;
  323. break;
  324. default:
  325. return AVERROR_INVALIDDATA;
  326. }
  327. write_sgi_header(pb, si);
  328. tablesize = si->zsize * si->ysize * sizeof(long);
  329. /* skip rle offset and length tables, write them at the end. */
  330. url_fseek(pb, tablesize * 2, SEEK_CUR);
  331. put_flush_packet(pb);
  332. lengthtab = av_malloc(tablesize);
  333. offsettab = av_malloc(tablesize);
  334. for (z = 0; z < si->zsize; z++) {
  335. #ifndef WORDS_BIGENDIAN
  336. /* rgba -> bgra for rgba32 on little endian cpus */
  337. if (si->zsize == 4 && z != 3)
  338. chan_offset = 2 - z;
  339. else
  340. #endif
  341. chan_offset = z;
  342. srcrow = info->pict.data[0] + chan_offset;
  343. for (y = si->ysize -1; y >= 0; y--) {
  344. offsettab[(z * si->ysize) + y] = url_ftell(pb);
  345. lengthtab[(z * si->ysize) + y] = rle_row(pb, srcrow,
  346. si->zsize, si->xsize);
  347. srcrow += info->pict.linesize[0];
  348. }
  349. }
  350. url_fseek(pb, 512, SEEK_SET);
  351. /* write offset table */
  352. for (i = 0; i < (si->ysize * si->zsize); i++) {
  353. put_be32(pb, offsettab[i]);
  354. }
  355. /* write length table */
  356. for (i = 0; i < (si->ysize * si->zsize); i++) {
  357. put_be32(pb, lengthtab[i]);
  358. }
  359. put_flush_packet(pb);
  360. av_free(lengthtab);
  361. av_free(offsettab);
  362. return 0;
  363. }
  364. #endif // CONFIG_ENCODERS
  365. AVImageFormat sgi_image_format = {
  366. "sgi",
  367. "sgi,rgb,rgba,bw",
  368. sgi_probe,
  369. sgi_read,
  370. (1 << PIX_FMT_GRAY8) | (1 << PIX_FMT_RGB24) | (1 << PIX_FMT_RGBA32),
  371. #ifdef CONFIG_ENCODERS
  372. sgi_write,
  373. #else
  374. NULL,
  375. #endif // CONFIG_ENCODERS
  376. };