10 /* values for the storage field */
11 #define SGI_STORAGE_VERBATIM 0
12 #define SGI_STORAGE_RLE 1
14 /* values for the colormap field */
15 #define SGI_COLORMAP_NORMAL 0
16 #define SGI_COLORMAP_DITHERED 1
17 #define SGI_COLORMAP_SCREEN 2
18 #define SGI_COLORMAP_COLORMAP 3
20 /* we add that little bit to avoid rounding issues */
21 #define SampleFTo16(num) ((int)((num) * 65535.0 + 0.01))
23 /* maximum size of an SGI image */
24 #define SGI_DIM_LIMIT 0xFFFF
27 unsigned short imagic;
28 unsigned char storagetype;
30 unsigned short dimensions;
31 unsigned short xsize, ysize, zsize;
32 unsigned int pixmin, pixmax;
34 unsigned int colormap;
38 read_rgb_8_verbatim(i_img *im, io_glue *ig, rgb_header const *hdr);
40 read_rgb_8_rle(i_img *im, io_glue *ig, rgb_header const *hdr);
42 read_rgb_16_verbatim(i_img *im, io_glue *ig, rgb_header const *hdr);
44 read_rgb_16_rle(i_img *im, io_glue *ig, rgb_header const *hdr);
46 write_sgi_header(i_img *img, io_glue *ig, int *rle, int *bpc2);
48 write_sgi_8_rle(i_img *img, io_glue *ig);
50 write_sgi_8_verb(i_img *img, io_glue *ig);
52 write_sgi_16_rle(i_img *img, io_glue *ig);
54 write_sgi_16_verb(i_img *img, io_glue *ig);
56 #define Sample16ToF(num) ((num) / 65535.0)
59 #define STRING(x) _STRING(x)
64 rgb.c - implements reading and writing sgi image files, uses io layer.
68 io_glue *ig = io_new_fd( fd );
69 i_img *im = i_readrgb_wiol(ig, 0); // disallow partial reads
71 io_glue *ig = io_new_fd( fd );
72 return_code = i_writergb_wiol(im, ig);
76 imsgi.c implements the basic functions to read and write portable SGI
77 files. It uses the iolayer and needs either a seekable source or an
78 entire memory mapped buffer.
80 =head1 FUNCTION REFERENCE
82 Some of these functions are internal.
90 =item rgb_header_unpack(header, headbuf)
92 Unpacks the header structure into from buffer and stores
93 in the header structure.
95 header - header structure
96 headbuf - buffer to unpack from
104 rgb_header_unpack(rgb_header *header, const unsigned char *headbuf) {
105 header->imagic = (headbuf[0]<<8) + headbuf[1];
106 header->storagetype = headbuf[2];
107 header->BPC = headbuf[3];
108 header->dimensions = (headbuf[4]<<8) + headbuf[5];
109 header->xsize = (headbuf[6]<<8) + headbuf[7];
110 header->ysize = (headbuf[8]<<8) + headbuf[9];
111 header->zsize = (headbuf[10]<<8) + headbuf[11];
112 header->pixmin = (headbuf[12]<<24) + (headbuf[13]<<16)+(headbuf[14]<<8)+headbuf[15];
113 header->pixmax = (headbuf[16]<<24) + (headbuf[17]<<16)+(headbuf[18]<<8)+headbuf[19];
114 memcpy(header->name,headbuf+24,80);
115 header->name[79] = '\0';
116 header->colormap = (headbuf[104]<<24) + (headbuf[105]<<16)+(headbuf[106]<<8)+headbuf[107];
119 /* don't make this a macro */
121 store_16(unsigned char *buf, unsigned short value) {
123 buf[1] = value & 0xFF;
127 store_32(unsigned char *buf, unsigned long value) {
128 buf[0] = value >> 24;
129 buf[1] = (value >> 16) & 0xFF;
130 buf[2] = (value >> 8) & 0xFF;
131 buf[3] = value & 0xFF;
135 =item rgb_header_pack(header, headbuf)
137 Packs header structure into buffer for writing.
139 header - header structure
140 headbuf - buffer to pack into
147 rgb_header_pack(const rgb_header *header, unsigned char headbuf[512]) {
148 memset(headbuf, 0, 512);
149 store_16(headbuf, header->imagic);
150 headbuf[2] = header->storagetype;
151 headbuf[3] = header->BPC;
152 store_16(headbuf+4, header->dimensions);
153 store_16(headbuf+6, header->xsize);
154 store_16(headbuf+8, header->ysize);
155 store_16(headbuf+10, header->zsize);
156 store_32(headbuf+12, header->pixmin);
157 store_32(headbuf+16, header->pixmax);
158 memccpy(headbuf+24, header->name, '\0', 80);
159 store_32(headbuf+104, header->colormap);
163 =item i_readsgi_wiol(ig, partial)
165 Read in an image from the iolayer data source and return the image structure to it.
166 Returns NULL on error.
169 length - maximum length to read from data source, before closing it -1
176 i_readsgi_wiol(io_glue *ig, int partial) {
178 int width, height, channels;
180 unsigned char headbuf[512];
182 mm_log((1,"i_readsgi(ig %p, partial %d)\n", ig, partial));
185 if (i_io_read(ig, headbuf, 512) != 512) {
186 i_push_error(errno, "SGI image: could not read header");
190 rgb_header_unpack(&header, headbuf);
192 if (header.imagic != SGI_MAGIC) {
193 i_push_error(0, "SGI image: invalid magic number");
197 mm_log((1,"imagic: %d\n", header.imagic));
198 mm_log((1,"storagetype: %d\n", header.storagetype));
199 mm_log((1,"BPC: %d\n", header.BPC));
200 mm_log((1,"dimensions: %d\n", header.dimensions));
201 mm_log((1,"xsize: %d\n", header.xsize));
202 mm_log((1,"ysize: %d\n", header.ysize));
203 mm_log((1,"zsize: %d\n", header.zsize));
204 mm_log((1,"min: %d\n", header.pixmin));
205 mm_log((1,"max: %d\n", header.pixmax));
206 mm_log((1,"name [skipped]\n"));
207 mm_log((1,"colormap: %d\n", header.colormap));
209 if (header.colormap != SGI_COLORMAP_NORMAL) {
210 i_push_errorf(0, "SGI image: invalid value for colormap (%d)", header.colormap);
214 if (header.BPC != 1 && header.BPC != 2) {
215 i_push_errorf(0, "SGI image: invalid value for BPC (%d)", header.BPC);
219 if (header.storagetype != SGI_STORAGE_VERBATIM
220 && header.storagetype != SGI_STORAGE_RLE) {
221 i_push_error(0, "SGI image: invalid storage type field");
225 if (header.pixmin >= header.pixmax) {
226 i_push_error(0, "SGI image: invalid pixmin >= pixmax");
230 width = header.xsize;
231 height = header.ysize;
232 channels = header.zsize;
234 switch (header.dimensions) {
245 /* fall through and use all of the dimensions */
249 i_push_error(0, "SGI image: invalid dimension field");
253 if (!i_int_check_image_file_limits(width, height, channels, header.BPC)) {
254 mm_log((1, "i_readsgi_wiol: image size exceeds limits\n"));
258 if (header.BPC == 1) {
259 img = i_img_8_new(width, height, channels);
263 switch (header.storagetype) {
264 case SGI_STORAGE_VERBATIM:
265 img = read_rgb_8_verbatim(img, ig, &header);
268 case SGI_STORAGE_RLE:
269 img = read_rgb_8_rle(img, ig, &header);
277 img = i_img_16_new(width, height, channels);
281 switch (header.storagetype) {
282 case SGI_STORAGE_VERBATIM:
283 img = read_rgb_16_verbatim(img, ig, &header);
286 case SGI_STORAGE_RLE:
287 img = read_rgb_16_rle(img, ig, &header);
299 i_tags_set(&img->tags, "i_comment", header.name, -1);
300 i_tags_setn(&img->tags, "sgi_pixmin", header.pixmin);
301 i_tags_setn(&img->tags, "sgi_pixmax", header.pixmax);
302 i_tags_setn(&img->tags, "sgi_bpc", header.BPC);
303 i_tags_setn(&img->tags, "sgi_rle", header.storagetype == SGI_STORAGE_RLE);
304 i_tags_set(&img->tags, "i_format", "sgi", -1);
309 if (img) i_img_destroy(img);
314 =item i_writergb_wiol(img, ig)
316 Writes an image in targa format. Returns 0 on error.
325 i_writesgi_wiol(io_glue *ig, i_img *img) {
331 if (img->xsize > SGI_DIM_LIMIT || img->ysize > SGI_DIM_LIMIT) {
332 i_push_error(0, "image too large for SGI");
336 if (!write_sgi_header(img, ig, &rle, &bpc2))
339 mm_log((1, "format rle %d bpc2 %d\n", rle, bpc2));
343 return write_sgi_16_rle(img, ig);
345 return write_sgi_16_verb(img, ig);
349 return write_sgi_8_rle(img, ig);
351 return write_sgi_8_verb(img, ig);
356 read_rgb_8_verbatim(i_img *img, io_glue *ig, rgb_header const *header) {
358 unsigned char *databuf;
361 i_img_dim width = i_img_get_width(img);
362 i_img_dim height = i_img_get_height(img);
363 int channels = i_img_getchannels(img);
364 int pixmin = header->pixmin;
365 int pixmax = header->pixmax;
366 int outmax = pixmax - pixmin;
368 linebuf = mymalloc(width * sizeof(i_color)); /* checked 31Jul07 TonyC */
369 databuf = mymalloc(width); /* checked 31Jul07 TonyC */
371 savemask = i_img_getmask(img);
373 for(c = 0; c < channels; c++) {
374 i_img_setmask(img, 1<<c);
375 for(y = 0; y < height; y++) {
378 if (i_io_read(ig, databuf, width) != width) {
379 i_push_error(0, "SGI image: cannot read image data");
386 if (pixmin == 0 && pixmax == 255) {
387 for(x = 0; x < img->xsize; x++)
388 linebuf[x].channel[c] = databuf[x];
391 for(x = 0; x < img->xsize; x++) {
392 int sample = databuf[x];
395 else if (sample > pixmax)
400 linebuf[x].channel[c] = sample * 255 / outmax;
404 i_plin(img, 0, width, height-1-y, linebuf);
407 i_img_setmask(img, savemask);
416 read_rle_tables(io_glue *ig, i_img *img,
417 unsigned long **pstart_tab, unsigned long **plength_tab,
418 unsigned long *pmax_length) {
419 i_img_dim height = i_img_get_height(img);
420 int channels = i_img_getchannels(img);
421 unsigned char *databuf;
422 unsigned long *start_tab, *length_tab;
423 unsigned long max_length = 0;
425 size_t databuf_size = (size_t)height * channels * 4;
426 size_t tab_size = (size_t)height * channels * sizeof(unsigned long);
428 /* assumption: that the lengths are in bytes rather than in pixels */
429 if (databuf_size / height / channels != 4
430 || tab_size / height / channels != sizeof(unsigned long)) {
431 i_push_error(0, "SGI image: integer overflow calculating allocation size");
434 databuf = mymalloc(height * channels * 4); /* checked 31Jul07 TonyC */
435 start_tab = mymalloc(height*channels*sizeof(unsigned long));
436 length_tab = mymalloc(height*channels*sizeof(unsigned long));
438 /* Read offset table */
439 if (i_io_read(ig, databuf, height * channels * 4) != height * channels * 4) {
440 i_push_error(0, "SGI image: short read reading RLE start table");
444 for(i = 0; i < height * channels; i++)
445 start_tab[i] = (databuf[i*4] << 24) | (databuf[i*4+1] << 16) |
446 (databuf[i*4+2] << 8) | (databuf[i*4+3]);
449 /* Read length table */
450 if (i_io_read(ig, databuf, height*channels*4) != height*channels*4) {
451 i_push_error(0, "SGI image: short read reading RLE length table");
455 for(i=0; i < height * channels; i++) {
456 length_tab[i] = (databuf[i*4] << 24) + (databuf[i*4+1] << 16)+
457 (databuf[i*4+2] << 8) + (databuf[i*4+3]);
458 if (length_tab[i] > max_length)
459 max_length = length_tab[i];
462 mm_log((3, "Offset/length table:\n"));
463 for(i=0; i < height * channels; i++)
464 mm_log((3, "%d: %lu/%lu\n", i, start_tab[i], length_tab[i]));
466 *pstart_tab = start_tab;
467 *plength_tab = length_tab;
468 *pmax_length = max_length;
483 read_rgb_8_rle(i_img *img, io_glue *ig, rgb_header const *header) {
484 i_color *linebuf = NULL;
485 unsigned char *databuf = NULL;
486 unsigned long *start_tab, *length_tab;
487 unsigned long max_length;
488 i_img_dim width = i_img_get_width(img);
489 i_img_dim height = i_img_get_height(img);
490 int channels = i_img_getchannels(img);
493 int pixmin = header->pixmin;
494 int pixmax = header->pixmax;
495 int outmax = pixmax - pixmin;
497 if (!read_rle_tables(ig, img,
498 &start_tab, &length_tab, &max_length)) {
503 mm_log((1, "maxlen for an rle buffer: %lu\n", max_length));
505 if (max_length > (img->xsize + 1) * 2) {
506 i_push_errorf(0, "SGI image: ridiculous RLE line length %lu", max_length);
510 linebuf = mymalloc(width*sizeof(i_color)); /* checked 31Jul07 TonyC */
511 databuf = mymalloc(max_length); /* checked 31Jul07 TonyC */
513 for(y = 0; y < img->ysize; y++) {
514 for(c = 0; c < channels; c++) {
515 int ci = height * c + y;
516 int datalen = length_tab[ci];
519 int data_left = datalen;
520 int pixels_left = width;
523 if (i_io_seek(ig, start_tab[ci], SEEK_SET) != start_tab[ci]) {
524 i_push_error(0, "SGI image: cannot seek to RLE data");
527 if (i_io_read(ig, databuf, datalen) != datalen) {
528 i_push_error(0, "SGI image: cannot read RLE data");
536 int count = code & 0x7f;
544 if (count > pixels_left) {
545 i_push_error(0, "SGI image: literal run overflows scanline");
548 if (count > data_left) {
549 i_push_error(0, "SGI image: literal run consumes more data than available");
553 pixels_left -= count;
555 if (pixmin == 0 && pixmax == 255) {
556 while (count-- > 0) {
557 outp->channel[c] = *inp++;
562 while (count-- > 0) {
566 else if (sample > pixmax)
570 outp->channel[c] = sample * 255 / outmax;
577 if (count > pixels_left) {
578 i_push_error(0, "SGI image: RLE run overflows scanline");
579 mm_log((2, "RLE run overflows scanline (y %" i_DF " chan %d offset %lu len %lu)\n", i_DFc(y), c, start_tab[ci], length_tab[ci]));
583 i_push_error(0, "SGI image: RLE run has no data for pixel");
587 if (pixmin != 0 || pixmax != 255) {
590 else if (sample > pixmax)
594 sample = sample * 255 / outmax;
597 pixels_left -= count;
598 while (count-- > 0) {
599 outp->channel[c] = sample;
604 /* must have a full scanline */
606 i_push_error(0, "SGI image: incomplete RLE scanline");
609 /* must have used all of the data */
611 i_push_errorf(0, "SGI image: unused RLE data");
615 i_plin(img, 0, width, height-1-y, linebuf);
637 read_rgb_16_verbatim(i_img *img, io_glue *ig, rgb_header const *header) {
639 unsigned char *databuf;
642 i_img_dim width = i_img_get_width(img);
643 i_img_dim height = i_img_get_height(img);
644 int channels = i_img_getchannels(img);
645 int pixmin = header->pixmin;
646 int pixmax = header->pixmax;
647 int outmax = pixmax - pixmin;
649 linebuf = mymalloc(width * sizeof(i_fcolor)); /* checked 31Jul07 TonyC */
650 databuf = mymalloc(width * 2); /* checked 31Jul07 TonyC */
652 savemask = i_img_getmask(img);
654 for(c = 0; c < channels; c++) {
655 i_img_setmask(img, 1<<c);
656 for(y = 0; y < height; y++) {
659 if (i_io_read(ig, databuf, width*2) != width*2) {
660 i_push_error(0, "SGI image: cannot read image data");
667 if (pixmin == 0 && pixmax == 65535) {
668 for(x = 0; x < img->xsize; x++)
669 linebuf[x].channel[c] = (databuf[x*2] * 256 + databuf[x*2+1]) / 65535.0;
672 for(x = 0; x < img->xsize; x++) {
673 int sample = databuf[x*2] * 256 + databuf[x*2+1];
676 else if (sample > pixmax)
681 linebuf[x].channel[c] = (double)sample / outmax;
685 i_plinf(img, 0, width, height-1-y, linebuf);
688 i_img_setmask(img, savemask);
697 read_rgb_16_rle(i_img *img, io_glue *ig, rgb_header const *header) {
698 i_fcolor *linebuf = NULL;
699 unsigned char *databuf = NULL;
700 unsigned long *start_tab, *length_tab;
701 unsigned long max_length;
702 i_img_dim width = i_img_get_width(img);
703 i_img_dim height = i_img_get_height(img);
704 int channels = i_img_getchannels(img);
707 int pixmin = header->pixmin;
708 int pixmax = header->pixmax;
709 int outmax = pixmax - pixmin;
711 if (!read_rle_tables(ig, img,
712 &start_tab, &length_tab, &max_length)) {
717 mm_log((1, "maxlen for an rle buffer: %lu\n", max_length));
719 if (max_length > (img->xsize * 2 + 1) * 2) {
720 i_push_errorf(0, "SGI image: ridiculous RLE line length %lu", max_length);
724 linebuf = mymalloc(width*sizeof(i_fcolor)); /* checked 31Jul07 TonyC */
725 databuf = mymalloc(max_length); /* checked 31Jul07 TonyC */
727 for(y = 0; y < img->ysize; y++) {
728 for(c = 0; c < channels; c++) {
729 int ci = height * c + y;
730 int datalen = length_tab[ci];
733 int data_left = datalen;
734 int pixels_left = width;
738 i_push_error(0, "SGI image: invalid RLE length value for BPC=2");
741 if (i_io_seek(ig, start_tab[ci], SEEK_SET) != start_tab[ci]) {
742 i_push_error(0, "SGI image: cannot seek to RLE data");
745 if (i_io_read(ig, databuf, datalen) != datalen) {
746 i_push_error(0, "SGI image: cannot read RLE data");
752 while (data_left > 0) {
753 int code = inp[0] * 256 + inp[1];
754 int count = code & 0x7f;
763 if (count > pixels_left) {
764 i_push_error(0, "SGI image: literal run overflows scanline");
767 if (count > data_left) {
768 i_push_error(0, "SGI image: literal run consumes more data than available");
772 pixels_left -= count;
773 data_left -= count * 2;
774 if (pixmin == 0 && pixmax == 65535) {
775 while (count-- > 0) {
776 outp->channel[c] = (inp[0] * 256 + inp[1]) / 65535.0;
782 while (count-- > 0) {
783 int sample = inp[0] * 256 + inp[1];
786 else if (sample > pixmax)
790 outp->channel[c] = (double)sample / outmax;
799 if (count > pixels_left) {
800 i_push_error(0, "SGI image: RLE run overflows scanline");
804 i_push_error(0, "SGI image: RLE run has no data for pixel");
807 sample = inp[0] * 256 + inp[1];
810 if (pixmin != 0 || pixmax != 65535) {
813 else if (sample > pixmax)
817 fsample = (double)sample / outmax;
820 fsample = (double)sample / 65535.0;
822 pixels_left -= count;
823 while (count-- > 0) {
824 outp->channel[c] = fsample;
829 /* must have a full scanline */
831 i_push_error(0, "SGI image: incomplete RLE scanline");
834 /* must have used all of the data */
836 i_push_errorf(0, "SGI image: unused RLE data");
840 i_plinf(img, 0, width, height-1-y, linebuf);
862 write_sgi_header(i_img *img, io_glue *ig, int *rle, int *bpc2) {
864 unsigned char headbuf[512] = { 0 };
866 header.imagic = SGI_MAGIC;
867 if (!i_tags_get_int(&img->tags, "sgi_rle", 0, rle))
869 header.storagetype = *rle ? SGI_STORAGE_RLE : SGI_STORAGE_VERBATIM;
871 header.colormap = SGI_COLORMAP_NORMAL;
872 *bpc2 = img->bits > 8;
875 header.pixmax = 65535;
881 if (img->channels == 1) {
882 header.dimensions = 2;
885 header.dimensions = 3;
887 header.xsize = img->xsize;
888 header.ysize = img->ysize;
889 header.zsize = img->channels;
890 memset(header.name, 0, sizeof(header.name));
891 i_tags_get_string(&img->tags, "i_comment", 0,
892 header.name, sizeof(header.name));
894 rgb_header_pack(&header, headbuf);
896 if (i_io_write(ig, headbuf, sizeof(headbuf)) != sizeof(headbuf)) {
897 i_push_error(0, "SGI image: cannot write header");
905 write_sgi_8_verb(i_img *img, io_glue *ig) {
907 i_img_dim width = img->xsize;
911 linebuf = mymalloc(width); /* checked 31Jul07 TonyC */
912 for (c = 0; c < img->channels; ++c) {
913 for (y = img->ysize - 1; y >= 0; --y) {
914 i_gsamp(img, 0, width, y, linebuf, &c, 1);
915 if (i_io_write(ig, linebuf, width) != width) {
916 i_push_error(errno, "SGI image: error writing image data");
931 write_sgi_8_rle(i_img *img, io_glue *ig) {
933 unsigned char *comp_buf;
934 i_img_dim width = img->xsize;
937 unsigned char *offsets;
938 unsigned char *lengths;
940 size_t offsets_size = (size_t)4 * img->ysize * img->channels * 2;
941 unsigned long start_offset = 512 + offsets_size;
942 unsigned long current_offset = start_offset;
948 if (offsets_size / 2 / 4 / img->channels != img->ysize) {
949 i_push_error(0, "SGI image: integer overflow calculating allocation size");
953 linebuf = mymalloc(width); /* checked 31Jul07 TonyC */
954 comp_buf = mymalloc((width + 1) * 2); /* checked 31Jul07 TonyC */
955 offsets = mymalloc(offsets_size);
956 memset(offsets, 0, offsets_size);
957 if (i_io_write(ig, offsets, offsets_size) != offsets_size) {
958 i_push_error(errno, "SGI image: error writing offsets/lengths");
961 lengths = offsets + img->ysize * img->channels * 4;
962 for (c = 0; c < img->channels; ++c) {
963 for (y = img->ysize - 1; y >= 0; --y) {
964 i_gsamp(img, 0, width, y, linebuf, &c, 1);
969 unsigned char *run_start = inp;
971 /* first try for an RLE run */
973 while (in_left - run_length >= 2 && inp[0] == inp[1] && run_length < 127) {
977 if (in_left - run_length == 1 && inp[0] == inp[1] && run_length < 127) {
981 if (run_length > 2) {
982 *outp++ = run_length;
985 in_left -= run_length;
990 /* scan for a literal run */
993 while (in_left - run_length > 1 && (inp[0] != inp[1] || inp[1] != inp[2]) && run_length < 127) {
999 /* fill out the run if 2 or less samples left and there's space */
1000 if (in_left - run_length <= 2
1001 && in_left <= 127) {
1002 run_length = in_left;
1004 in_left -= run_length;
1005 *outp++ = run_length | 0x80;
1006 while (run_length--) {
1007 *outp++ = *run_start++;
1012 comp_size = outp - comp_buf;
1013 store_32(offsets + offset_pos, current_offset);
1014 store_32(lengths + offset_pos, comp_size);
1016 current_offset += comp_size;
1017 if (i_io_write(ig, comp_buf, comp_size) != comp_size) {
1018 i_push_error(errno, "SGI image: error writing RLE data");
1024 /* seek back to store the offsets and lengths */
1025 if (i_io_seek(ig, 512, SEEK_SET) != 512) {
1026 i_push_error(errno, "SGI image: cannot seek to RLE table");
1030 if (i_io_write(ig, offsets, offsets_size) != offsets_size) {
1031 i_push_error(errno, "SGI image: cannot write final RLE table");
1052 write_sgi_16_verb(i_img *img, io_glue *ig) {
1053 i_fsample_t *linebuf;
1054 unsigned char *encbuf;
1055 unsigned char *outp;
1056 i_img_dim width = img->xsize;
1061 linebuf = mymalloc(width * sizeof(i_fsample_t)); /* checked 31Jul07 TonyC */
1062 encbuf = mymalloc(width * 2); /* checked 31Jul07 TonyC */
1063 for (c = 0; c < img->channels; ++c) {
1064 for (y = img->ysize - 1; y >= 0; --y) {
1065 i_gsampf(img, 0, width, y, linebuf, &c, 1);
1066 for (x = 0, outp = encbuf; x < width; ++x, outp+=2) {
1067 unsigned short samp16 = SampleFTo16(linebuf[x]);
1068 store_16(outp, samp16);
1070 if (i_io_write(ig, encbuf, width * 2) != width * 2) {
1071 i_push_error(errno, "SGI image: error writing image data");
1088 write_sgi_16_rle(i_img *img, io_glue *ig) {
1089 i_fsample_t *sampbuf;
1090 unsigned short *linebuf;
1091 unsigned char *comp_buf;
1092 i_img_dim width = img->xsize;
1095 unsigned char *offsets;
1096 unsigned char *lengths;
1098 size_t offsets_size = (size_t)4 * img->ysize * img->channels * 2;
1099 unsigned long start_offset = 512 + offsets_size;
1100 unsigned long current_offset = start_offset;
1102 unsigned char *outp;
1103 unsigned short *inp;
1107 if (offsets_size / 4 / 2 / img->channels != img->ysize) {
1108 i_push_error(0, "SGI image: integer overflow calculating allocation size");
1112 sampbuf = mymalloc(width * sizeof(i_fsample_t)); /* checked 31Jul07 TonyC */
1113 linebuf = mymalloc(width * sizeof(unsigned short)); /* checked 31Jul07 TonyC */
1114 comp_buf = mymalloc((width + 1) * 2 * 2); /* checked 31Jul07 TonyC */
1115 offsets = mymalloc(offsets_size);
1116 memset(offsets, 0, offsets_size);
1117 if (i_io_write(ig, offsets, offsets_size) != offsets_size) {
1118 i_push_error(errno, "SGI image: error writing offsets/lengths");
1121 lengths = offsets + img->ysize * img->channels * 4;
1122 for (c = 0; c < img->channels; ++c) {
1123 for (y = img->ysize - 1; y >= 0; --y) {
1124 i_gsampf(img, 0, width, y, sampbuf, &c, 1);
1125 for (x = 0; x < width; ++x)
1126 linebuf[x] = (unsigned short)(SampleFTo16(sampbuf[x]));
1131 unsigned short *run_start = inp;
1133 /* first try for an RLE run */
1135 while (in_left - run_length >= 2 && inp[0] == inp[1] && run_length < 127) {
1139 if (in_left - run_length == 1 && inp[0] == inp[1] && run_length < 127) {
1143 if (run_length > 2) {
1144 store_16(outp, run_length);
1145 store_16(outp+2, inp[0]);
1148 in_left -= run_length;
1153 /* scan for a literal run */
1156 while (in_left - run_length > 1 && (inp[0] != inp[1] || inp[1] != inp[2]) && run_length < 127) {
1162 /* fill out the run if 2 or less samples left and there's space */
1163 if (in_left - run_length <= 2
1164 && in_left <= 127) {
1165 run_length = in_left;
1167 in_left -= run_length;
1168 store_16(outp, run_length | 0x80);
1170 while (run_length--) {
1171 store_16(outp, *run_start++);
1178 comp_size = outp - comp_buf;
1179 store_32(offsets + offset_pos, current_offset);
1180 store_32(lengths + offset_pos, comp_size);
1182 current_offset += comp_size;
1183 if (i_io_write(ig, comp_buf, comp_size) != comp_size) {
1184 i_push_error(errno, "SGI image: error writing RLE data");
1190 /* seek back to store the offsets and lengths */
1191 if (i_io_seek(ig, 512, SEEK_SET) != 512) {
1192 i_push_error(errno, "SGI image: cannot seek to RLE table");
1196 if (i_io_write(ig, offsets, offsets_size) != offsets_size) {
1197 i_push_error(errno, "SGI image: cannot write final RLE table");