12 tga.c - implements reading and writing targa files, uses io layer.
16 io_glue *ig = io_new_fd( fd );
17 i_img *im = i_readtga_wiol(ig, -1); // no limit on how much is read
19 io_glue *ig = io_new_fd( fd );
20 return_code = i_writetga_wiol(im, ig);
24 tga.c implements the basic functions to read and write portable targa
25 files. It uses the iolayer and needs either a seekable source or an
26 entire memory mapped buffer.
28 =head1 FUNCTION REFERENCE
30 Some of these functions are internal.
41 unsigned char idlength;
44 short int colourmaporigin;
45 short int colourmaplength;
56 typedef enum { NoInit, Raw, Rle } rle_state;
62 unsigned char cval[4];
78 =item bpp_to_bytes(bpp)
80 Convert bits per pixel into bytes per pixel
90 bpp_to_bytes(unsigned int bpp) {
108 =item bpp_to_channels(bpp)
110 Convert bits per pixel into channels in the image
119 bpp_to_channels(unsigned int bpp) {
138 * Packing functions - used for (un)packing
139 * datastructures into raw bytes.
144 =item color_unpack(buf, bytepp, val)
146 Unpacks bytes into colour structures, for 2 byte type the first byte
147 coming from the file will actually be GGGBBBBB, and the second will be
148 ARRRRRGG. "A" represents an attribute bit. The 3 byte entry contains
149 1 byte each of blue, green, and red. The 4 byte entry contains 1 byte
150 each of blue, green, red, and attribute.
152 buf - pointer to data
153 bytepp - bytes per pixel
154 val - pointer to color to store to
161 color_unpack(unsigned char *buf, int bytepp, i_color *val) {
164 val->gray.gray_color = buf[0];
167 val->rgba.r = (buf[1] & 0x7c) << 1;
168 val->rgba.g = ((buf[1] & 0x03) << 6) | ((buf[0] & 0xe0) >> 2);
169 val->rgba.b = (buf[0] & 0x1f) << 3;
170 val->rgba.a = (buf[1] & 0x80) ? 255 : 0;
171 val->rgba.r |= val->rgba.r >> 5;
172 val->rgba.g |= val->rgba.g >> 5;
173 val->rgba.b |= val->rgba.b >> 5;
181 val->rgba.b = buf[0];
182 val->rgba.g = buf[1];
183 val->rgba.r = buf[2];
184 val->rgba.a = buf[3];
194 Packs a colour into an array of bytes, for 2 byte type the first byte
195 will be GGGBBBBB, and the second will be ARRRRRGG. "A" represents an
196 attribute bit. The 3 byte entry contains 1 byte each of blue, green,
197 and red. The 4 byte entry contains 1 byte each of blue, green, red,
200 buf - destination buffer
201 bitspp - bits per pixel
209 color_pack(unsigned char *buf, int bitspp, i_color *val) {
212 buf[0] = val->gray.gray_color;
215 buf[0] = (val->rgba.b >> 3);
216 buf[0] |= (val->rgba.g & 0x38) << 2;
217 buf[1] = (val->rgba.r & 0xf8)>> 1;
218 buf[1] |= (val->rgba.g >> 6);
220 buf[1] |= val->rgba.a & 0x80;
228 buf[0] = val->rgba.b;
229 buf[1] = val->rgba.g;
230 buf[2] = val->rgba.r;
231 buf[3] = val->rgba.a;
240 Helper function for rle compressor to find the next triple repeat of the
241 same pixel value in buffer.
244 length - number of pixel values in buffer
245 bytepp - number of bytes in a pixel value
252 find_repeat(unsigned char *buf, int length, int bytepp) {
256 if(memcmp(buf+i*bytepp, buf+(i+1)*bytepp, bytepp) == 0) {
257 if (i == length-2) return -1;
258 if (memcmp(buf+(i+1)*bytepp, buf+(i+2)*bytepp,bytepp) == 0)
271 Helper function for rle compressor to find the length of a span where
272 the same pixel value is in the buffer.
275 length - number of pixel values in buffer
276 bytepp - number of bytes in a pixel value
283 find_span(unsigned char *buf, int length, int bytepp) {
286 if(memcmp(buf, buf+(i*bytepp), bytepp) != 0) return i;
294 =item tga_header_unpack(header, headbuf)
296 Unpacks the header structure into from buffer and stores
297 in the header structure.
299 header - header structure
300 headbuf - buffer to unpack from
307 tga_header_unpack(tga_header *header, unsigned char headbuf[18]) {
308 header->idlength = headbuf[0];
309 header->colourmaptype = headbuf[1];
310 header->datatypecode = headbuf[2];
311 header->colourmaporigin = (headbuf[4] << 8) + headbuf[3];
312 header->colourmaplength = (headbuf[6] << 8) + headbuf[5];
313 header->colourmapdepth = headbuf[7];
314 header->x_origin = (headbuf[9] << 8) + headbuf[8];
315 header->y_origin = (headbuf[11] << 8) + headbuf[10];
316 header->width = (headbuf[13] << 8) + headbuf[12];
317 header->height = (headbuf[15] << 8) + headbuf[14];
318 header->bitsperpixel = headbuf[16];
319 header->imagedescriptor = headbuf[17];
323 /* this function should never produce diagnostics to stdout, maybe to the logfile */
325 tga_header_verify(unsigned char headbuf[18]) {
327 tga_header_unpack(&header, headbuf);
328 switch (header.datatypecode) {
330 /*printf("bad typecode!\n");*/
332 case 1: /* Uncompressed, color-mapped images */
333 case 3: /* Uncompressed, grayscale images */
334 case 9: /* Compressed, color-mapped images */
335 case 11: /* Compressed, grayscale images */
336 if (header.bitsperpixel != 8)
340 case 2: /* Uncompressed, rgb images */
341 case 10: /* Compressed, rgb images */
342 if (header.bitsperpixel != 15 && header.bitsperpixel != 16
343 && header.bitsperpixel != 24 && header.bitsperpixel != 23)
348 switch (header.colourmaptype) {
350 /*printf("bad colourmaptype!\n");*/
353 if (header.datatypecode != 1 && header.datatypecode != 9)
354 return 0; /* only get a color map on a color mapped image */
359 switch (header.colourmapdepth) {
362 case 0: /* can be 0 if no colour map */
375 =item tga_header_pack(header, headbuf)
377 Packs header structure into buffer for writing.
379 header - header structure
380 headbuf - buffer to pack into
387 tga_header_pack(tga_header *header, unsigned char headbuf[18]) {
388 headbuf[0] = header->idlength;
389 headbuf[1] = header->colourmaptype;
390 headbuf[2] = header->datatypecode;
391 headbuf[3] = header->colourmaporigin & 0xff;
392 headbuf[4] = header->colourmaporigin >> 8;
393 headbuf[5] = header->colourmaplength & 0xff;
394 headbuf[6] = header->colourmaplength >> 8;
395 headbuf[7] = header->colourmapdepth;
396 headbuf[8] = header->x_origin & 0xff;
397 headbuf[9] = header->x_origin >> 8;
398 headbuf[10] = header->y_origin & 0xff;
399 headbuf[11] = header->y_origin >> 8;
400 headbuf[12] = header->width & 0xff;
401 headbuf[13] = header->width >> 8;
402 headbuf[14] = header->height & 0xff;
403 headbuf[15] = header->height >> 8;
404 headbuf[16] = header->bitsperpixel;
405 headbuf[17] = header->imagedescriptor;
410 =item tga_source_read(s, buf, pixels)
412 Reads pixel number of pixels from source s into buffer buf. Takes
413 care of decompressing the stream if needed.
416 buf - destination buffer
417 pixels - number of pixels to put into buffer
424 tga_source_read(tga_source *s, unsigned char *buf, size_t pixels) {
426 if (!s->compressed) {
427 if (s->ig->readcb(s->ig, buf, pixels*s->bytepp) != pixels*s->bytepp) return 0;
433 if (s->len == 0) s->state = NoInit;
436 if (s->ig->readcb(s->ig, &s->hdr, 1) != 1) return 0;
438 s->len = (s->hdr &~(1<<7))+1;
439 s->state = (s->hdr & (1<<7)) ? Rle : Raw;
443 printf("%04d %s: %d\n", cnt++, s->state==Rle?"RLE":"RAW", s->len);
446 if (s->state == Rle && s->ig->readcb(s->ig, s->cval, s->bytepp) != s->bytepp) return 0;
450 ml = i_min(s->len, pixels-cp);
451 for(k=0; k<ml; k++) for(j=0; j<s->bytepp; j++)
452 buf[(cp+k)*s->bytepp+j] = s->cval[j];
457 ml = i_min(s->len, pixels-cp);
458 if (s->ig->readcb(s->ig, buf+cp*s->bytepp, ml*s->bytepp) != ml*s->bytepp) return 0;
471 =item tga_dest_write(s, buf, pixels)
473 Writes pixels from buf to destination s. Takes care of compressing if the
474 destination is compressed.
478 pixels - number of pixels to put write to destination
485 tga_dest_write(tga_dest *s, unsigned char *buf, size_t pixels) {
488 if (!s->compressed) {
489 if (s->ig->writecb(s->ig, buf, pixels*s->bytepp) != pixels*s->bytepp) return 0;
495 int nxtrip = find_repeat(buf+cp*s->bytepp, pixels-cp, s->bytepp);
496 tlen = (nxtrip == -1) ? pixels-cp : nxtrip;
498 unsigned char clen = (tlen>128) ? 128 : tlen;
500 if (s->ig->writecb(s->ig, &clen, 1) != 1) return 0;
502 if (s->ig->writecb(s->ig, buf+cp*s->bytepp, clen*s->bytepp) != clen*s->bytepp) return 0;
506 if (cp >= pixels) break;
507 tlen = find_span(buf+cp*s->bytepp, pixels-cp, s->bytepp);
508 if (tlen <3) continue;
510 unsigned char clen = (tlen>128) ? 128 : tlen;
511 clen = (clen - 1) | 0x80;
512 if (s->ig->writecb(s->ig, &clen, 1) != 1) return 0;
513 clen = (clen & ~0x80) + 1;
514 if (s->ig->writecb(s->ig, buf+cp*s->bytepp, s->bytepp) != s->bytepp) return 0;
528 =item tga_palette_read(ig, img, bytepp, colourmaplength)
530 Reads the colormap from a tga file and stores in the paletted image
533 ig - iolayer data source
534 img - image structure
535 bytepp - bytes per pixel
536 colourmaplength - number of colours in colourmap
543 tga_palette_read(io_glue *ig, i_img *img, int bytepp, int colourmaplength) {
546 unsigned char *palbuf;
549 palbsize = colourmaplength*bytepp;
550 palbuf = mymalloc(palbsize);
552 if (ig->readcb(ig, palbuf, palbsize) != palbsize) {
553 i_push_error(errno, "could not read targa colourmap");
557 /* populate the palette of the new image */
558 for(i=0; i<colourmaplength; i++) {
559 color_unpack(palbuf+i*bytepp, bytepp, &val);
560 i_addcolors(img, &val, 1);
568 =item tga_palette_write(ig, img, bitspp, colourmaplength)
570 Stores the colormap of an image in the destination ig.
572 ig - iolayer data source
573 img - image structure
574 bitspp - bits per pixel in colourmap
575 colourmaplength - number of colours in colourmap
582 tga_palette_write(io_glue *ig, i_img *img, int bitspp, int colourmaplength) {
584 int bytepp = bpp_to_bytes(bitspp);
585 size_t palbsize = i_colorcount(img)*bytepp;
586 unsigned char *palbuf = mymalloc(palbsize);
588 for(i=0; i<colourmaplength; i++) {
590 i_getcolors(img, i, &val, 1);
591 color_pack(palbuf+i*bytepp, bitspp, &val);
594 if (ig->writecb(ig, palbuf, palbsize) != palbsize) {
595 i_push_error(errno, "could not write targa colourmap");
605 =item i_readtga_wiol(ig, length)
607 Read in an image from the iolayer data source and return the image structure to it.
608 Returns NULL on error.
611 length - maximum length to read from data source, before closing it -1
618 i_readtga_wiol(io_glue *ig, int length) {
621 int width, height, channels;
623 char *idstring = NULL;
627 unsigned char headbuf[18];
628 unsigned char *databuf;
630 i_color *linebuf = NULL;
633 mm_log((1,"i_readtga(ig %p, length %d)\n", ig, length));
635 io_glue_commit_types(ig);
637 if (ig->readcb(ig, &headbuf, 18) != 18) {
638 i_push_error(errno, "could not read targa header");
642 tga_header_unpack(&header, headbuf);
644 mm_log((1,"Id length: %d\n",header.idlength));
645 mm_log((1,"Colour map type: %d\n",header.colourmaptype));
646 mm_log((1,"Image type: %d\n",header.datatypecode));
647 mm_log((1,"Colour map offset: %d\n",header.colourmaporigin));
648 mm_log((1,"Colour map length: %d\n",header.colourmaplength));
649 mm_log((1,"Colour map depth: %d\n",header.colourmapdepth));
650 mm_log((1,"X origin: %d\n",header.x_origin));
651 mm_log((1,"Y origin: %d\n",header.y_origin));
652 mm_log((1,"Width: %d\n",header.width));
653 mm_log((1,"Height: %d\n",header.height));
654 mm_log((1,"Bits per pixel: %d\n",header.bitsperpixel));
655 mm_log((1,"Descriptor: %d\n",header.imagedescriptor));
657 if (header.idlength) {
658 idstring = mymalloc(header.idlength+1);
659 if (ig->readcb(ig, idstring, header.idlength) != header.idlength) {
660 i_push_error(errno, "short read on targa idstring");
665 width = header.width;
666 height = header.height;
671 switch (header.datatypecode) {
672 case 0: /* No data in image */
673 i_push_error(0, "Targa image contains no image data");
674 if (idstring) myfree(idstring);
677 case 1: /* Uncompressed, color-mapped images */
678 case 9: /* Compressed, color-mapped images */
679 case 3: /* Uncompressed, grayscale images */
680 case 11: /* Compressed, grayscale images */
681 if (header.bitsperpixel != 8) {
682 i_push_error(0, "Targa: mapped/grayscale image's bpp is not 8, unsupported.");
683 if (idstring) myfree(idstring);
688 case 2: /* Uncompressed, rgb images */
689 case 10: /* Compressed, rgb images */
690 if ((src.bytepp = bpp_to_bytes(header.bitsperpixel)))
692 i_push_error(0, "Targa: direct color image's bpp is not 15/16/24/32 - unsupported.");
693 if (idstring) myfree(idstring);
696 case 32: /* Compressed color-mapped, Huffman, Delta and runlength */
697 case 33: /* Compressed color-mapped, Huffman, Delta and runlength */
698 i_push_error(0, "Unsupported Targa (Huffman/delta/rle/quadtree) subformat is not supported");
699 if (idstring) myfree(idstring);
702 default: /* All others which we don't know which might be */
703 i_push_error(0, "Unknown targa format");
704 if (idstring) myfree(idstring);
712 src.compressed = !!(header.datatypecode & (1<<3));
714 /* Determine number of channels */
717 switch (header.datatypecode) {
718 case 2: /* Uncompressed, rgb images */
719 case 10: /* Compressed, rgb images */
721 case 1: /* Uncompressed, color-mapped images */
722 case 9: /* Compressed, color-mapped images */
723 if ((channels = bpp_to_channels(mapped ?
724 header.colourmapdepth :
725 header.bitsperpixel))) break;
726 i_push_error(0, "Targa Image has none of 15/16/24/32 pixel layout");
727 if (idstring) myfree(idstring);
730 case 3: /* Uncompressed, grayscale images */
731 case 11: /* Compressed, grayscale images */
736 i_push_error(0, "invalid or unsupported datatype code");
740 if (!i_int_check_image_file_limits(width, height, channels,
741 sizeof(i_sample_t))) {
742 mm_log((1, "i_readtga_wiol: image size exceeds limits\n"));
747 i_img_pal_new(width, height, channels, 256) :
748 i_img_empty_ch(NULL, width, height, channels);
757 i_tags_add(&img->tags, "tga_idstring", 0, idstring, header.idlength, 0);
762 !tga_palette_read(ig,
764 bpp_to_bytes(header.colourmapdepth),
765 header.colourmaplength)
767 i_push_error(0, "Targa Image has none of 15/16/24/32 pixel layout");
768 if (idstring) myfree(idstring);
769 if (img) i_img_destroy(img);
773 /* Allocate buffers */
774 databuf = mymalloc(width*src.bytepp);
775 if (!mapped) linebuf = mymalloc(width*sizeof(i_color));
777 for(y=0; y<height; y++) {
778 if (!tga_source_read(&src, databuf, width)) {
779 i_push_error(errno, "read for targa data failed");
780 if (linebuf) myfree(linebuf);
782 if (img) i_img_destroy(img);
785 if (mapped && header.colourmaporigin) for(x=0; x<width; x++) databuf[x] -= header.colourmaporigin;
786 if (mapped) i_ppal(img, 0, width, header.imagedescriptor & (1<<5) ? y : height-1-y, databuf);
788 for(x=0; x<width; x++) color_unpack(databuf+x*src.bytepp, src.bytepp, linebuf+x);
789 i_plin(img, 0, width, header.imagedescriptor & (1<<5) ? y : height-1-y, linebuf);
793 if (linebuf) myfree(linebuf);
795 i_tags_add(&img->tags, "i_format", 0, "tga", -1, 0);
796 i_tags_addn(&img->tags, "tga_bitspp", 0, mapped?header.colourmapdepth:header.bitsperpixel);
797 if (src.compressed) i_tags_addn(&img->tags, "compressed", 0, 1);
804 =item i_writetga_wiol(img, ig)
806 Writes an image in targa format. Returns 0 on error.
815 i_writetga_wiol(i_img *img, io_glue *ig, int wierdpack, int compress, char *idstring, size_t idlen) {
818 unsigned char headbuf[18];
827 char *idstring = "testing";
831 idlen = strlen(idstring);
832 mapped = img->type == i_palette_type;
834 mm_log((1,"i_writetga_wiol(img %p, ig %p, idstring %p, idlen %d, wierdpack %d, compress %d)\n",
835 img, ig, idstring, idlen, wierdpack, compress));
836 mm_log((1, "virtual %d, paletted %d\n", img->virtual, mapped));
837 mm_log((1, "channels %d\n", img->channels));
840 io_glue_commit_types(ig);
842 switch (img->channels) {
846 mm_log((1,"wierdpack option ignored for 1 channel images\n"));
851 i_push_error(0, "Cannot store 2 channel image in targa format");
855 bitspp = wierdpack ? 15 : 24;
858 bitspp = wierdpack ? 16 : 32;
861 i_push_error(0, "Targa only handles 1,3 and 4 channel images.");
865 header.idlength = idlen;
866 header.colourmaptype = mapped ? 1 : 0;
867 header.datatypecode = mapped ? 1 : img->channels == 1 ? 3 : 2;
868 header.datatypecode += compress ? 8 : 0;
869 mm_log((1, "datatypecode %d\n", header.datatypecode));
870 header.colourmaporigin = 0;
871 header.colourmaplength = mapped ? i_colorcount(img) : 0;
872 header.colourmapdepth = mapped ? bitspp : 0;
875 header.width = img->xsize;
876 header.height = img->ysize;
877 header.bitsperpixel = mapped ? 8 : bitspp;
878 header.imagedescriptor = (1<<5); /* normal order instead of upside down */
880 tga_header_pack(&header, headbuf);
882 if (ig->writecb(ig, &headbuf, sizeof(headbuf)) != sizeof(headbuf)) {
883 i_push_error(errno, "could not write targa header");
888 if (ig->writecb(ig, idstring, idlen) != idlen) {
889 i_push_error(errno, "could not write targa idstring");
894 /* Make this into a constructor? */
895 dest.compressed = compress;
896 dest.bytepp = mapped ? 1 : bpp_to_bytes(bitspp);
899 mm_log((1, "dest.compressed = %d\n", dest.compressed));
900 mm_log((1, "dest.bytepp = %d\n", dest.bytepp));
902 if (img->type == i_palette_type) {
903 if (!tga_palette_write(ig, img, bitspp, i_colorcount(img))) return 0;
905 if (!img->virtual && !dest.compressed) {
906 if (ig->writecb(ig, img->idata, img->bytes) != img->bytes) {
907 i_push_error(errno, "could not write targa image data");
912 i_palidx *vals = mymalloc(sizeof(i_palidx)*img->xsize);
913 for(y=0; y<img->ysize; y++) {
914 i_gpal(img, 0, img->xsize, y, vals);
915 tga_dest_write(&dest, vals, img->xsize);
919 } else { /* direct type */
921 int bytepp = wierdpack ? 2 : bpp_to_bytes(bitspp);
922 int lsize = bytepp * img->xsize;
923 i_color *vals = mymalloc(img->xsize*sizeof(i_color));
924 unsigned char *buf = mymalloc(lsize);
926 for(y=0; y<img->ysize; y++) {
927 i_glin(img, 0, img->xsize, y, vals);
928 for(x=0; x<img->xsize; x++) color_pack(buf+x*bytepp, bitspp, vals+x);
929 tga_dest_write(&dest, buf, img->xsize);
945 Arnar M. Hrafnkelsson <addi@umich.edu>