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.

461 lines
11KB

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