tga.c should now support reading/writing all variants of targa files. XS needs
[imager.git] / tga.c
1 #include "image.h"
2 #include "io.h"
3 #include "log.h"
4 #include "iolayer.h"
5
6 #include <stdlib.h>
7 #include <errno.h>
8
9
10 /*
11 =head1 NAME
12
13 tga.c - implements reading and writing targa files, uses io layer.
14
15 =head1 SYNOPSIS
16
17    io_glue *ig = io_new_fd( fd );
18    i_img *im   = i_readtga_wiol(ig, -1); // no limit on how much is read
19    // or 
20    io_glue *ig = io_new_fd( fd );
21    return_code = i_writetga_wiol(im, ig); 
22
23 =head1 DESCRIPTION
24
25 tga.c implements the basic functions to read and write portable targa
26 files.  It uses the iolayer and needs either a seekable source or an
27 entire memory mapped buffer.
28
29 =head1 FUNCTION REFERENCE
30
31 Some of these functions are internal.
32
33 =over 4
34
35 =cut
36 */
37
38
39
40
41 typedef struct {
42   char  idlength;
43   char  colourmaptype;
44   char  datatypecode;
45   short int colourmaporigin;
46   short int colourmaplength;
47   char  colourmapdepth;
48   short int x_origin;
49   short int y_origin;
50   short width;
51   short height;
52   char  bitsperpixel;
53   char  imagedescriptor;
54 } tga_header;
55
56
57 typedef enum { NoInit, Raw, Rle } rle_state;
58
59 typedef struct {
60   int compressed;
61   int bytepp;
62   rle_state state;
63   unsigned char cval[4];
64   int len;
65   unsigned char hdr;
66   io_glue *ig;
67 } tga_source;
68
69
70 typedef struct {
71   int compressed;
72   int bytepp;
73   io_glue *ig;
74 } tga_dest;
75
76
77
78 static
79 int
80 bpp_to_bytes(unsigned int bpp) {
81   switch (bpp) {
82   case 8:
83     return 1;
84   case 15:
85   case 16:
86     return 2;
87   case 24:
88     return 3;
89   case 32:
90     return 4;
91   }
92   return 0;
93 }
94
95 static
96 int
97 bpp_to_channels(unsigned int bpp) {
98   switch (bpp) {
99   case 8:
100     return 1;
101   case 15:
102     return 3;
103   case 16:
104     return 4;
105   case 24:
106     return 3;
107   case 32:
108     return 4;
109   }
110   return 0;
111 }
112
113
114
115 /* 
116  * Packing functions - used for (un)packing
117  * datastructures into raw bytes.
118 */
119
120
121 /* color_unpack
122
123 Unpacks bytes into colours, for 2 byte type the first byte coming from
124 the file will actually be GGGBBBBB, and the second will be ARRRRRGG.
125 "A" represents an attribute bit.  The 3 byte entry contains 1 byte
126 each of blue, green, and red.  The 4 byte entry contains 1 byte each
127 of blue, green, red, and attribute.
128 */
129
130 static
131 void
132 color_unpack(unsigned char *buf, int bytepp, i_color *val) {
133   switch (bytepp) {
134   case 1:
135     val->gray.gray_color = buf[0];
136     break;
137   case 2:
138     val->rgba.r = (buf[1] & 0x7c) << 1;
139     val->rgba.g = ((buf[1] & 0x03) << 6) | ((buf[0] & 0xe0) >> 2);
140     val->rgba.b = (buf[0] & 0x1f) << 3;
141     val->rgba.a = (buf[1] & 0x80) ? 255 : 0;
142     val->rgba.r |= val->rgba.r >> 5;
143     val->rgba.g |= val->rgba.g >> 5;
144     val->rgba.b |= val->rgba.b >> 5;
145     break;
146   case 3:
147     val->rgb.b = buf[0];
148     val->rgb.g = buf[1];
149     val->rgb.r = buf[2];
150     break;
151   case 4:
152     val->rgba.b = buf[0];
153     val->rgba.g = buf[1];
154     val->rgba.r = buf[2];
155     val->rgba.a = buf[3];
156     break;
157   default:
158   }
159 }
160
161
162
163 /* color_pack
164
165 Packs colous into bytes, for 2 byte type the first byte will be
166 GGGBBBBB, and the second will be ARRRRRGG.  "A" represents an
167 attribute bit.  The 3 byte entry contains 1 byte each of blue, green,
168 and red.  The 4 byte entry contains 1 byte each of blue, green, red,
169 and attribute.
170 */
171
172 static
173 void
174 color_pack(unsigned char *buf, int bitspp, i_color *val) {
175   switch (bitspp) {
176   case 8:
177     buf[0] = val->gray.gray_color;
178     break;
179   case 15:
180     buf[0]  = (val->rgba.b >> 3);
181     buf[0] |= (val->rgba.g & 0x38) << 2;
182     buf[1]  = (val->rgba.r & 0xf8)>> 1;
183     buf[1] |= (val->rgba.g >> 6);
184   case 16:
185     buf[1] |=  val->rgba.a & 0x80;
186     break;
187   case 24:
188     buf[0] = val->rgb.b;
189     buf[1] = val->rgb.g;
190     buf[2] = val->rgb.r;
191     break;
192   case 32:
193     buf[0] = val->rgba.b;
194     buf[1] = val->rgba.g;
195     buf[2] = val->rgba.r;
196     buf[3] = val->rgba.a;
197     break;
198   default:
199   }
200   //  printf("%d  %3d %3d %3d\n", bitspp, val->rgb.r, val->rgb.g, val->rgb.b);
201 }
202
203
204
205
206 static
207 int
208 find_repeat(unsigned char *buf, int length, int bytepp) {
209   int i = 0;
210   
211   while(i<length-1) {
212     if(memcmp(buf+i*bytepp, buf+(i+1)*bytepp, bytepp) == 0) {
213       if (i == length-2) return -1;
214       if (memcmp(buf+(i+1)*bytepp, buf+(i+2)*bytepp,bytepp) == 0)  
215         return i;
216       else i++;
217     }
218     i++;
219   }
220   return -1;
221 }
222
223
224 static
225 int
226 find_span(unsigned char *buf, int length, int bytepp) {
227   int i = 0;
228   while(i<length) {
229     if(memcmp(buf, buf+(i*bytepp), bytepp) != 0) return i;
230     i++;
231   }
232   return length;
233 }
234
235
236
237
238
239 static
240 int
241 tga_source_read(tga_source *s, unsigned char *buf, size_t pixels) {
242   int cp = 0, j, k;
243   if (!s->compressed) {
244     if (s->ig->readcb(s->ig, buf, pixels*s->bytepp) != pixels*s->bytepp) return 0;
245     return 1;
246   }
247   
248   while(cp < pixels) {
249     int ml;
250     if (s->len == 0) s->state = NoInit;
251     switch (s->state) {
252     case NoInit:
253       if (s->ig->readcb(s->ig, &s->hdr, 1) != 1) return 0;
254
255       s->len = (s->hdr &~(1<<7))+1;
256       s->state = (s->hdr & (1<<7)) ? Rle : Raw;
257       if (s->state == Rle && s->ig->readcb(s->ig, s->cval, s->bytepp) != s->bytepp) return 0;
258
259       break;
260     case Rle:
261       ml = min(s->len, pixels-cp);
262       for(k=0; k<ml; k++) for(j=0; j<s->bytepp; j++) 
263         buf[(cp+k)*s->bytepp+j] = s->cval[j];
264       //      memset(buf+cp, s->cidx, ml);
265       cp     += ml;
266       s->len -= ml;
267       break;
268     case Raw:
269       ml = min(s->len, pixels-cp);
270       if (s->ig->readcb(s->ig, buf+cp*s->bytepp, ml*s->bytepp) != ml*s->bytepp) return 0;
271       cp     += ml;
272       s->len -= ml;
273       break;
274     }
275   }
276   return 1;
277 }
278
279
280
281 /* 
282    tga_dest_write
283    
284    Note that it is possible for length to be more than 0 and the state
285    still be noinit.  That just means that there isn't enough data yet to
286    determine the next packet type.
287
288 */
289
290 static
291 int
292 tga_dest_write(tga_dest *s, unsigned char *buf, size_t pixels) {
293   int cp = 0, j, k;
294
295   if (!s->compressed) {
296     if (s->ig->writecb(s->ig, buf, pixels*s->bytepp) != pixels*s->bytepp) return 0;
297     return 1;
298   }
299   
300   while(cp < pixels) {
301     int tlen;
302     int nxtrip = find_repeat(buf+cp*s->bytepp, pixels-cp, s->bytepp);
303     tlen = (nxtrip == -1) ? pixels-cp : nxtrip;
304     while(tlen) {
305       int clen = (tlen>128) ? 128 : tlen;
306       clen--;
307       if (s->ig->writecb(s->ig, &clen, 1) != 1) return 0;
308       clen++;
309       if (s->ig->writecb(s->ig, buf+cp*s->bytepp, clen*s->bytepp) != clen*s->bytepp) return 0;
310       tlen -= clen;
311       cp += clen;
312     }
313     if (cp >= pixels) break;
314     tlen = find_span(buf+cp*s->bytepp, pixels-cp, s->bytepp);
315     while (tlen) {
316       int clen = (tlen>128) ? 128 : tlen;
317       clen = (clen - 1) | 0x80;
318       if (s->ig->writecb(s->ig, &clen, 1) != 1) return 0;
319       clen = (clen & ~0x80) + 1;
320       if (s->ig->writecb(s->ig, buf+cp*s->bytepp, s->bytepp) != s->bytepp) return 0;
321       tlen -= clen;
322       cp += clen;
323     }
324   }
325   return 1;
326 }
327
328
329
330
331
332
333
334
335 static
336 int
337 tga_palette_read(io_glue *ig, i_img *img, int bytepp, int colourmaplength) {
338   int i;
339   size_t palbsize;
340   unsigned char *palbuf;
341   i_color val;
342
343   palbsize = colourmaplength*bytepp;
344   palbuf   = mymalloc(palbsize);
345   
346   if (ig->readcb(ig, palbuf, palbsize) != palbsize) {
347     i_push_error(errno, "could not read targa colourmap");
348     return 0;
349   }
350   
351   /* populate the palette of the new image */
352   for(i=0; i<colourmaplength; i++) {
353     color_unpack(palbuf+i*bytepp, bytepp, &val);
354     i_addcolors(img, &val, 1);
355   }
356   myfree(palbuf);
357   return 1;
358 }
359
360
361
362 static
363 int
364 tga_palette_write(io_glue *ig, i_img *img, int bitspp, int colourmaplength) {
365   int i;
366   int bytepp = bpp_to_bytes(bitspp);
367   size_t palbsize = i_colorcount(img)*bytepp;
368   unsigned char *palbuf = mymalloc(palbsize);
369   
370   for(i=0; i<colourmaplength; i++) {
371     i_color val;
372     i_getcolors(img, i, &val, 1);
373     color_pack(palbuf+i*bytepp, bitspp, &val);
374   }
375   
376   if (ig->writecb(ig, palbuf, palbsize) != palbsize) {
377     i_push_error(errno, "could not write targa colourmap");
378     return 0;
379   }
380   myfree(palbuf);
381   return 1;
382 }
383
384 static
385 void
386 tga_header_unpack(tga_header *header, unsigned char headbuf[18]) {
387   header->idlength        = headbuf[0];
388   header->colourmaptype   = headbuf[1];
389   header->datatypecode    = headbuf[2];
390   header->colourmaporigin = (headbuf[4] << 8) + headbuf[3];
391   header->colourmaplength = (headbuf[6] << 8) + headbuf[5];
392   header->colourmapdepth  = headbuf[7];
393   header->x_origin        = (headbuf[9] << 8) + headbuf[8];
394   header->y_origin        = (headbuf[11] << 8) + headbuf[10];
395   header->width           = (headbuf[13] << 8) + headbuf[12];
396   header->height          = (headbuf[15] << 8) + headbuf[14];
397   header->bitsperpixel    = headbuf[16];
398   header->imagedescriptor = headbuf[17];
399 }
400
401
402 static
403 void
404 tga_header_pack(tga_header *header, unsigned char headbuf[18]) {
405   headbuf[0] = header->idlength;
406   headbuf[1] = header->colourmaptype;
407   headbuf[2] = header->datatypecode;
408   headbuf[3] = header->colourmaporigin & 0xff;
409   headbuf[4] = header->colourmaporigin >> 8;
410   headbuf[5] = header->colourmaplength & 0xff;
411   headbuf[6] = header->colourmaplength >> 8;
412   headbuf[7] = header->colourmapdepth;
413   headbuf[8] = header->x_origin & 0xff;
414   headbuf[9] = header->x_origin >> 8;
415   headbuf[10] = header->y_origin & 0xff;
416   headbuf[11] = header->y_origin >> 8;
417   headbuf[12] = header->width & 0xff;
418   headbuf[13] = header->width >> 8;
419   headbuf[14] = header->height & 0xff;
420   headbuf[15] = header->height >> 8;
421   headbuf[16] = header->bitsperpixel;
422   headbuf[17] = header->imagedescriptor;
423 }
424
425
426
427 /*
428 =item i_readtga_wiol(ig, length)
429
430 Retrieve an image and stores in the iolayer object. Returns NULL on fatal error.
431
432    ig     - io_glue object
433    length - maximum length to read from data source, before closing it -1 
434             signifies no limit.
435
436 =cut
437 */
438
439 i_img *
440 i_readtga_wiol(io_glue *ig, int length) {
441   i_img* img;
442   int x, y, i;
443   int width, height, channels;
444   int mapped;
445   char *idstring;
446
447   tga_source src;
448   tga_header header;
449   unsigned char headbuf[18];
450   unsigned char *databuf;
451   unsigned char *reorderbuf;
452
453   i_color *linebuf = NULL;
454   i_clear_error();
455
456   mm_log((1,"i_readtga(ig %p, length %d)\n", ig, length));
457   
458   io_glue_commit_types(ig);
459
460   if (ig->readcb(ig, &headbuf, 18) != 18) {
461     i_push_error(errno, "could not read targa header");
462     return NULL;
463   }
464
465   tga_header_unpack(&header, headbuf);
466
467   mm_log((1,"Id length:         %d\n",header.idlength));
468   mm_log((1,"Colour map type:   %d\n",header.colourmaptype));
469   mm_log((1,"Image type:        %d\n",header.datatypecode));
470   mm_log((1,"Colour map offset: %d\n",header.colourmaporigin));
471   mm_log((1,"Colour map length: %d\n",header.colourmaplength));
472   mm_log((1,"Colour map depth:  %d\n",header.colourmapdepth));
473   mm_log((1,"X origin:          %d\n",header.x_origin));
474   mm_log((1,"Y origin:          %d\n",header.y_origin));
475   mm_log((1,"Width:             %d\n",header.width));
476   mm_log((1,"Height:            %d\n",header.height));
477   mm_log((1,"Bits per pixel:    %d\n",header.bitsperpixel));
478   mm_log((1,"Descriptor:        %d\n",header.imagedescriptor));
479
480   if (header.idlength) {
481     idstring = mymalloc(header.idlength+1);
482     if (ig->readcb(ig, idstring, header.idlength) != header.idlength) {
483       i_push_error(errno, "short read on targa idstring");
484       return NULL;
485     }
486     myfree(idstring); /* Move this later, once this is stored in a tag */
487   }
488
489   width = header.width;
490   height = header.height;
491   
492   /* Set tags here */
493   
494   switch (header.datatypecode) {
495   case 0: /* No data in image */
496     i_push_error(0, "Targa image contains no image data");
497     return NULL;
498     break;
499   case 1:  /* Uncompressed, color-mapped images */
500   case 9:  /* Compressed,   color-mapped images */
501   case 3:  /* Uncompressed, grayscale images    */
502   case 11: /* Compressed,   grayscale images    */
503     if (header.bitsperpixel != 8) {
504       i_push_error(0, "Targa: mapped/grayscale image's bpp is not 8, unsupported.");
505       return NULL;
506     }
507     src.bytepp = 1;
508     break;
509   case 2:  /* Uncompressed, rgb images          */
510   case 10: /* Compressed,   rgb images          */
511     if ((src.bytepp = bpp_to_bytes(header.bitsperpixel)))
512       break;
513     i_push_error(0, "Targa: direct color image's bpp is not 15/16/24/32 - unsupported.");
514     return NULL;
515     break;
516   case 32: /* Compressed color-mapped, Huffman, Delta and runlength */
517   case 33: /* Compressed color-mapped, Huffman, Delta and runlength */
518     i_push_error(0, "Unsupported Targa (Huffman/delta/rle/quadtree) subformat is not supported");
519     return NULL;
520     break;
521   default: /* All others which we don't know which might be */
522     i_push_error(0, "Unknown targa format");
523     return NULL;
524     break;
525   }
526   
527   src.state = NoInit;
528   src.len = 0;
529   src.ig = ig;
530   src.compressed = !!(header.datatypecode & (1<<3));
531
532   /* Determine number of channels */
533   
534   mapped = 1;
535   switch (header.datatypecode) {
536     int tbpp;
537   case 2:  /* Uncompressed, rgb images          */
538   case 10: /* Compressed,   rgb images          */
539     mapped = 0;
540   case 1:  /* Uncompressed, color-mapped images */
541   case 9:  /* Compressed,   color-mapped images */
542     if ((channels = bpp_to_channels(mapped ? 
543                                    header.colourmapdepth : 
544                                    header.bitsperpixel))) break;
545     i_push_error(0, "Targa Image has none of 15/16/24/32 pixel layout");
546     return NULL;
547     break;
548   case 3:  /* Uncompressed, grayscale images    */
549   case 11: /* Compressed,   grayscale images    */
550     mapped = 0;
551     channels = 1;
552     break;
553   }
554   
555   img = mapped ? 
556     i_img_pal_new(width, height, channels, 256) :
557     i_img_empty_ch(NULL, width, height, channels);
558   
559   if (mapped &&
560       !tga_palette_read(ig,
561                         img,
562                         bpp_to_bytes(header.colourmapdepth),
563                         header.colourmaplength)
564       ) {
565     i_push_error(0, "Targa Image has none of 15/16/24/32 pixel layout");
566     return NULL;
567   }
568   
569   /* Allocate buffers */
570   databuf = mymalloc(width*src.bytepp);
571   if (!mapped) linebuf = mymalloc(width*sizeof(i_color));
572   
573   for(y=0; y<height; y++) {
574     if (!tga_source_read(&src, databuf, width)) {
575       i_push_error(errno, "read for targa data failed");
576       myfree(databuf);
577       return NULL;
578     }
579     if (mapped && header.colourmaporigin) for(x=0; x<width; x++) databuf[x] -= header.colourmaporigin;
580     if (mapped) i_ppal(img, 0, width, header.imagedescriptor & (1<<5) ? y : height-1-y, databuf);
581     else {
582       for(x=0; x<width; x++) color_unpack(databuf+x*src.bytepp, src.bytepp, linebuf+x);
583       i_plin(img, 0, width, header.imagedescriptor & (1<<5) ? y : height-1-y, linebuf);
584     }
585   }
586   myfree(databuf);
587   if (linebuf) myfree(linebuf);
588   return img;
589 }
590
591
592
593
594
595
596
597
598
599 undef_int
600 i_writetga_wiol(i_img *img, io_glue *ig) {
601   static int rgb_chan[] = { 2, 1, 0, 3 };
602   tga_header header;
603   tga_dest dest;
604   unsigned char headbuf[18];
605   //  unsigned char *data;
606   unsigned int bitspp;
607   
608   int idlen;
609   int mapped;
610
611   /* parameters */
612   int compress = 1;
613   char *idstring = "testing";
614   int wierdpack = 0;
615
616   idlen = strlen(idstring);
617   mapped = img->type == i_palette_type;
618
619   mm_log((1,"i_writetga_wiol(img %p, ig %p)\n", img, ig));
620   mm_log((1, "virtual %d, paletted %d\n", img->virtual, mapped));
621   mm_log((1, "channels %d\n", img->channels));
622   
623   i_clear_error();
624   
625   switch (img->channels) {
626   case 1:
627     bitspp = 8;
628     if (wierdpack) {
629       mm_log((1,"wierdpack option ignored for 1 channel images\n"));
630       wierdpack=0;
631     }
632     break;
633   case 2:
634     i_push_error(0, "Cannot store 2 channel image in targa format");
635     return 0;
636     break;
637   case 3:
638     bitspp = wierdpack ? 15 : 24;
639     break;
640   case 4:
641     bitspp = wierdpack ? 16 : 32;
642     break;
643   default:
644     i_push_error(0, "Targa only handles 1,3 and 4 channel images.");
645     return 0;
646   }
647
648   io_glue_commit_types(ig);
649   
650   header.idlength;
651   header.idlength = idlen;
652   header.colourmaptype   = mapped ? 1 : 0;
653   header.datatypecode    = mapped ? 1 : img->channels == 1 ? 3 : 2;
654   header.datatypecode   += compress ? 8 : 0;
655   mm_log((1, "datatypecode %d\n", header.datatypecode));
656   header.colourmaporigin = 0;
657   header.colourmaplength = mapped ? i_colorcount(img) : 0;
658   header.colourmapdepth  = mapped ? bitspp : 0;
659   header.x_origin        = 0;
660   header.y_origin        = 0;
661   header.width           = img->xsize;
662   header.height          = img->ysize;
663   header.bitsperpixel    = mapped ? 8 : bitspp;
664   header.imagedescriptor = (1<<5); /* normal order instead of upside down */
665
666   tga_header_pack(&header, headbuf);
667
668   if (ig->writecb(ig, &headbuf, sizeof(headbuf)) != sizeof(headbuf)) {
669     i_push_error(errno, "could not write targa header");
670     return 0;
671   }
672
673   if (idlen) {
674     if (ig->writecb(ig, idstring, idlen) != idlen) {
675       i_push_error(errno, "could not write targa idstring");
676       return 0;
677     }
678   }
679   
680   /* Make this into a constructor? */
681   dest.compressed = compress;
682   dest.bytepp     = mapped ? 1 : bpp_to_bytes(bitspp);
683   dest.ig         = ig;
684
685   mm_log((1, "dest.compressed = %d\n", dest.compressed));
686   mm_log((1, "dest.bytepp = %d\n", dest.bytepp));
687
688   if (img->type == i_palette_type) {
689     int i;
690     int bytepp = bpp_to_bytes(bitspp);
691     if (!tga_palette_write(ig, img, bitspp, i_colorcount(img))) return 0;
692     
693     if (!img->virtual && !dest.compressed) {
694       if (ig->writecb(ig, img->idata, img->bytes) != img->bytes) {
695         i_push_error(errno, "could not write targa image data");
696         return 0;
697       }
698     } else {
699       int y;
700       i_palidx *vals = mymalloc(sizeof(i_palidx)*img->xsize);
701       for(y=0; y<img->ysize; y++) {
702         i_gpal(img, 0, img->xsize, y, vals);
703         tga_dest_write(&dest, vals, img->xsize);
704       }
705       myfree(vals);
706     }
707   } else { /* direct type */
708     int x, y;
709     int bytepp = wierdpack ? 2 : bpp_to_bytes(bitspp);
710     int lsize = bytepp * img->xsize;
711     i_color *vals = mymalloc(img->xsize*sizeof(i_color));
712     unsigned char *buf = mymalloc(lsize);
713     
714     for(y=0; y<img->ysize; y++) {
715       i_glin(img, 0, img->xsize, y, vals);
716       for(x=0; x<img->xsize; x++) color_pack(buf+x*bytepp, bitspp, vals+x);
717       tga_dest_write(&dest, buf, img->xsize);
718     }
719     myfree(buf);
720     myfree(vals);
721   }
722   return 1;
723 }