Closed memory leaks when an error occurs during load of targa images. Fixed
[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 /*
79 =item bpp_to_bytes(bpp)
80
81 Convert bits per pixel into bytes per pixel
82
83    bpp - bits per pixel
84
85 =cut
86 */
87
88
89 static
90 int
91 bpp_to_bytes(unsigned int bpp) {
92   switch (bpp) {
93   case 8:
94     return 1;
95   case 15:
96   case 16:
97     return 2;
98   case 24:
99     return 3;
100   case 32:
101     return 4;
102   }
103   return 0;
104 }
105
106
107
108 /*
109 =item bpp_to_channels(bpp)
110
111 Convert bits per pixel into channels in the image
112
113    bpp - bits per pixel
114
115 =cut
116 */
117
118 static
119 int
120 bpp_to_channels(unsigned int bpp) {
121   switch (bpp) {
122   case 8:
123     return 1;
124   case 15:
125     return 3;
126   case 16:
127     return 4;
128   case 24:
129     return 3;
130   case 32:
131     return 4;
132   }
133   return 0;
134 }
135
136
137
138 /* 
139  * Packing functions - used for (un)packing
140  * datastructures into raw bytes.
141  */
142
143
144 /*
145 =item color_unpack(buf, bytepp, val)
146
147 Unpacks bytes into colour structures, for 2 byte type the first byte
148 coming from the file will actually be GGGBBBBB, and the second will be
149 ARRRRRGG.  "A" represents an attribute bit.  The 3 byte entry contains
150 1 byte each of blue, green, and red.  The 4 byte entry contains 1 byte
151 each of blue, green, red, and attribute.
152
153    buf - pointer to data
154    bytepp - bytes per pixel
155    val - pointer to color to store to
156
157 =cut
158 */
159
160 static
161 void
162 color_unpack(unsigned char *buf, int bytepp, i_color *val) {
163   switch (bytepp) {
164   case 1:
165     val->gray.gray_color = buf[0];
166     break;
167   case 2:
168     val->rgba.r = (buf[1] & 0x7c) << 1;
169     val->rgba.g = ((buf[1] & 0x03) << 6) | ((buf[0] & 0xe0) >> 2);
170     val->rgba.b = (buf[0] & 0x1f) << 3;
171     val->rgba.a = (buf[1] & 0x80) ? 255 : 0;
172     val->rgba.r |= val->rgba.r >> 5;
173     val->rgba.g |= val->rgba.g >> 5;
174     val->rgba.b |= val->rgba.b >> 5;
175     break;
176   case 3:
177     val->rgb.b = buf[0];
178     val->rgb.g = buf[1];
179     val->rgb.r = buf[2];
180     break;
181   case 4:
182     val->rgba.b = buf[0];
183     val->rgba.g = buf[1];
184     val->rgba.r = buf[2];
185     val->rgba.a = buf[3];
186     break;
187   default:
188   }
189 }
190
191
192
193 /*
194 =item color_pack
195
196 Packs a colour into an array of bytes, for 2 byte type the first byte
197 will be GGGBBBBB, and the second will be ARRRRRGG.  "A" represents an
198 attribute bit.  The 3 byte entry contains 1 byte each of blue, green,
199 and red.  The 4 byte entry contains 1 byte each of blue, green, red,
200 and attribute.
201
202     buf - destination buffer
203     bitspp - bits per pixel
204     val - color to pack
205
206 =cut
207 */
208
209 static
210 void
211 color_pack(unsigned char *buf, int bitspp, i_color *val) {
212   switch (bitspp) {
213   case 8:
214     buf[0] = val->gray.gray_color;
215     break;
216   case 15:
217     buf[0]  = (val->rgba.b >> 3);
218     buf[0] |= (val->rgba.g & 0x38) << 2;
219     buf[1]  = (val->rgba.r & 0xf8)>> 1;
220     buf[1] |= (val->rgba.g >> 6);
221   case 16:
222     buf[1] |=  val->rgba.a & 0x80;
223     break;
224   case 24:
225     buf[0] = val->rgb.b;
226     buf[1] = val->rgb.g;
227     buf[2] = val->rgb.r;
228     break;
229   case 32:
230     buf[0] = val->rgba.b;
231     buf[1] = val->rgba.g;
232     buf[2] = val->rgba.r;
233     buf[3] = val->rgba.a;
234     break;
235   default:
236   }
237 }
238
239
240 /*
241 =item find_repeat
242
243 Helper function for rle compressor to find the next triple repeat of the 
244 same pixel value in buffer.
245
246     buf - buffer
247     length - number of pixel values in buffer
248     bytepp - number of bytes in a pixel value
249
250 =cut
251 */
252
253 static
254 int
255 find_repeat(unsigned char *buf, int length, int bytepp) {
256   int i = 0;
257   
258   while(i<length-1) {
259     if(memcmp(buf+i*bytepp, buf+(i+1)*bytepp, bytepp) == 0) {
260       if (i == length-2) return -1;
261       if (memcmp(buf+(i+1)*bytepp, buf+(i+2)*bytepp,bytepp) == 0)  
262         return i;
263       else i++;
264     }
265     i++;
266   }
267   return -1;
268 }
269
270
271 /*
272 =item find_span
273
274 Helper function for rle compressor to find the length of a span where
275 the same pixel value is in the buffer.
276
277     buf - buffer
278     length - number of pixel values in buffer
279     bytepp - number of bytes in a pixel value
280
281 =cut
282 */
283
284 static
285 int
286 find_span(unsigned char *buf, int length, int bytepp) {
287   int i = 0;
288   while(i<length) {
289     if(memcmp(buf, buf+(i*bytepp), bytepp) != 0) return i;
290     i++;
291   }
292   return length;
293 }
294
295
296 /*
297 =item tga_header_unpack(header, headbuf)
298
299 Unpacks the header structure into from buffer and stores
300 in the header structure.
301
302     header - header structure
303     headbuf - buffer to unpack from
304
305 =cut
306 */
307
308 static
309 void
310 tga_header_unpack(tga_header *header, unsigned char headbuf[18]) {
311   header->idlength        = headbuf[0];
312   header->colourmaptype   = headbuf[1];
313   header->datatypecode    = headbuf[2];
314   header->colourmaporigin = (headbuf[4] << 8) + headbuf[3];
315   header->colourmaplength = (headbuf[6] << 8) + headbuf[5];
316   header->colourmapdepth  = headbuf[7];
317   header->x_origin        = (headbuf[9] << 8) + headbuf[8];
318   header->y_origin        = (headbuf[11] << 8) + headbuf[10];
319   header->width           = (headbuf[13] << 8) + headbuf[12];
320   header->height          = (headbuf[15] << 8) + headbuf[14];
321   header->bitsperpixel    = headbuf[16];
322   header->imagedescriptor = headbuf[17];
323 }
324
325
326 /*
327 =item tga_header_pack(header, headbuf)
328
329 Packs header structure into buffer for writing.
330
331     header - header structure
332     headbuf - buffer to pack into
333
334 =cut
335 */
336
337 static
338 void
339 tga_header_pack(tga_header *header, unsigned char headbuf[18]) {
340   headbuf[0] = header->idlength;
341   headbuf[1] = header->colourmaptype;
342   headbuf[2] = header->datatypecode;
343   headbuf[3] = header->colourmaporigin & 0xff;
344   headbuf[4] = header->colourmaporigin >> 8;
345   headbuf[5] = header->colourmaplength & 0xff;
346   headbuf[6] = header->colourmaplength >> 8;
347   headbuf[7] = header->colourmapdepth;
348   headbuf[8] = header->x_origin & 0xff;
349   headbuf[9] = header->x_origin >> 8;
350   headbuf[10] = header->y_origin & 0xff;
351   headbuf[11] = header->y_origin >> 8;
352   headbuf[12] = header->width & 0xff;
353   headbuf[13] = header->width >> 8;
354   headbuf[14] = header->height & 0xff;
355   headbuf[15] = header->height >> 8;
356   headbuf[16] = header->bitsperpixel;
357   headbuf[17] = header->imagedescriptor;
358 }
359
360
361 /*
362 =item tga_source_read(s, buf, pixels)
363
364 Reads pixel number of pixels from source s into buffer buf.  Takes
365 care of decompressing the stream if needed.
366
367     s - data source 
368     buf - destination buffer
369     pixels - number of pixels to put into buffer
370
371 =cut
372 */
373
374 static
375 int
376 tga_source_read(tga_source *s, unsigned char *buf, size_t pixels) {
377   int cp = 0, j, k;
378   if (!s->compressed) {
379     if (s->ig->readcb(s->ig, buf, pixels*s->bytepp) != pixels*s->bytepp) return 0;
380     return 1;
381   }
382   
383   while(cp < pixels) {
384     int ml;
385     if (s->len == 0) s->state = NoInit;
386     switch (s->state) {
387     case NoInit:
388       if (s->ig->readcb(s->ig, &s->hdr, 1) != 1) return 0;
389
390       s->len = (s->hdr &~(1<<7))+1;
391       s->state = (s->hdr & (1<<7)) ? Rle : Raw;
392       if (s->state == Rle && s->ig->readcb(s->ig, s->cval, s->bytepp) != s->bytepp) return 0;
393
394       break;
395     case Rle:
396       ml = min(s->len, pixels-cp);
397       for(k=0; k<ml; k++) for(j=0; j<s->bytepp; j++) 
398         buf[(cp+k)*s->bytepp+j] = s->cval[j];
399       //      memset(buf+cp, s->cidx, ml);
400       cp     += ml;
401       s->len -= ml;
402       break;
403     case Raw:
404       ml = min(s->len, pixels-cp);
405       if (s->ig->readcb(s->ig, buf+cp*s->bytepp, ml*s->bytepp) != ml*s->bytepp) return 0;
406       cp     += ml;
407       s->len -= ml;
408       break;
409     }
410   }
411   return 1;
412 }
413
414
415
416
417 /*
418 =item tga_dest_write(s, buf, pixels)
419
420 Writes pixels from buf to destination s.  Takes care of compressing if the
421 destination is compressed.
422
423     s - data destination
424     buf - source buffer
425     pixels - number of pixels to put write to destination
426
427 =cut
428 */
429
430 static
431 int
432 tga_dest_write(tga_dest *s, unsigned char *buf, size_t pixels) {
433   int cp = 0, j, k;
434
435   if (!s->compressed) {
436     if (s->ig->writecb(s->ig, buf, pixels*s->bytepp) != pixels*s->bytepp) return 0;
437     return 1;
438   }
439   
440   while(cp < pixels) {
441     int tlen;
442     int nxtrip = find_repeat(buf+cp*s->bytepp, pixels-cp, s->bytepp);
443     tlen = (nxtrip == -1) ? pixels-cp : nxtrip;
444     while(tlen) {
445       int clen = (tlen>128) ? 128 : tlen;
446       clen--;
447       if (s->ig->writecb(s->ig, &clen, 1) != 1) return 0;
448       clen++;
449       if (s->ig->writecb(s->ig, buf+cp*s->bytepp, clen*s->bytepp) != clen*s->bytepp) return 0;
450       tlen -= clen;
451       cp += clen;
452     }
453     if (cp >= pixels) break;
454     tlen = find_span(buf+cp*s->bytepp, pixels-cp, s->bytepp);
455     if (tlen <3) continue;
456     while (tlen) {
457       int clen = (tlen>128) ? 128 : tlen;
458       clen = (clen - 1) | 0x80;
459       if (s->ig->writecb(s->ig, &clen, 1) != 1) return 0;
460       clen = (clen & ~0x80) + 1;
461       if (s->ig->writecb(s->ig, buf+cp*s->bytepp, s->bytepp) != s->bytepp) return 0;
462       tlen -= clen;
463       cp += clen;
464     }
465   }
466   return 1;
467 }
468
469
470
471
472
473
474 /*
475 =item tga_palette_read(ig, img, bytepp, colourmaplength)
476
477 Reads the colormap from a tga file and stores in the paletted image
478 structure.
479
480     ig - iolayer data source
481     img - image structure
482     bytepp - bytes per pixel
483     colourmaplength - number of colours in colourmap
484
485 =cut
486 */
487
488 static
489 int
490 tga_palette_read(io_glue *ig, i_img *img, int bytepp, int colourmaplength) {
491   int i;
492   size_t palbsize;
493   unsigned char *palbuf;
494   i_color val;
495
496   palbsize = colourmaplength*bytepp;
497   palbuf   = mymalloc(palbsize);
498   
499   if (ig->readcb(ig, palbuf, palbsize) != palbsize) {
500     i_push_error(errno, "could not read targa colourmap");
501     return 0;
502   }
503   
504   /* populate the palette of the new image */
505   for(i=0; i<colourmaplength; i++) {
506     color_unpack(palbuf+i*bytepp, bytepp, &val);
507     i_addcolors(img, &val, 1);
508   }
509   myfree(palbuf);
510   return 1;
511 }
512
513
514 /*
515 =item tga_palette_write(ig, img, bitspp, colourmaplength)
516
517 Stores the colormap of an image in the destination ig.
518
519     ig - iolayer data source
520     img - image structure
521     bitspp - bits per pixel in colourmap
522     colourmaplength - number of colours in colourmap
523
524 =cut
525 */
526
527 static
528 int
529 tga_palette_write(io_glue *ig, i_img *img, int bitspp, int colourmaplength) {
530   int i;
531   int bytepp = bpp_to_bytes(bitspp);
532   size_t palbsize = i_colorcount(img)*bytepp;
533   unsigned char *palbuf = mymalloc(palbsize);
534   
535   for(i=0; i<colourmaplength; i++) {
536     i_color val;
537     i_getcolors(img, i, &val, 1);
538     color_pack(palbuf+i*bytepp, bitspp, &val);
539   }
540   
541   if (ig->writecb(ig, palbuf, palbsize) != palbsize) {
542     i_push_error(errno, "could not write targa colourmap");
543     return 0;
544   }
545   myfree(palbuf);
546   return 1;
547 }
548
549
550
551 /*
552 =item i_readtga_wiol(ig, length)
553
554 Read in an image from the iolayer data source and return the image structure to it.
555 Returns NULL on error.
556
557    ig     - io_glue object
558    length - maximum length to read from data source, before closing it -1 
559             signifies no limit.
560
561 =cut
562 */
563
564 i_img *
565 i_readtga_wiol(io_glue *ig, int length) {
566   i_img* img = NULL;
567   int x, y, i;
568   int width, height, channels;
569   int mapped;
570   char *idstring = NULL;
571
572   tga_source src;
573   tga_header header;
574   unsigned char headbuf[18];
575   unsigned char *databuf;
576   unsigned char *reorderbuf;
577
578   i_color *linebuf = NULL;
579   i_clear_error();
580
581   mm_log((1,"i_readtga(ig %p, length %d)\n", ig, length));
582   
583   io_glue_commit_types(ig);
584
585   if (ig->readcb(ig, &headbuf, 18) != 18) {
586     i_push_error(errno, "could not read targa header");
587     return NULL;
588   }
589
590   tga_header_unpack(&header, headbuf);
591
592   mm_log((1,"Id length:         %d\n",header.idlength));
593   mm_log((1,"Colour map type:   %d\n",header.colourmaptype));
594   mm_log((1,"Image type:        %d\n",header.datatypecode));
595   mm_log((1,"Colour map offset: %d\n",header.colourmaporigin));
596   mm_log((1,"Colour map length: %d\n",header.colourmaplength));
597   mm_log((1,"Colour map depth:  %d\n",header.colourmapdepth));
598   mm_log((1,"X origin:          %d\n",header.x_origin));
599   mm_log((1,"Y origin:          %d\n",header.y_origin));
600   mm_log((1,"Width:             %d\n",header.width));
601   mm_log((1,"Height:            %d\n",header.height));
602   mm_log((1,"Bits per pixel:    %d\n",header.bitsperpixel));
603   mm_log((1,"Descriptor:        %d\n",header.imagedescriptor));
604
605   if (header.idlength) {
606     idstring = mymalloc(header.idlength+1);
607     if (ig->readcb(ig, idstring, header.idlength) != header.idlength) {
608       i_push_error(errno, "short read on targa idstring");
609       return NULL;
610     }
611   }
612
613   width = header.width;
614   height = header.height;
615   
616   /* Set tags here */
617   
618   switch (header.datatypecode) {
619   case 0: /* No data in image */
620     i_push_error(0, "Targa image contains no image data");
621     if (idstring) myfree(idstring);
622     return NULL;
623     break;
624   case 1:  /* Uncompressed, color-mapped images */
625   case 9:  /* Compressed,   color-mapped images */
626   case 3:  /* Uncompressed, grayscale images    */
627   case 11: /* Compressed,   grayscale images    */
628     if (header.bitsperpixel != 8) {
629       i_push_error(0, "Targa: mapped/grayscale image's bpp is not 8, unsupported.");
630       if (idstring) myfree(idstring);
631       return NULL;
632     }
633     src.bytepp = 1;
634     break;
635   case 2:  /* Uncompressed, rgb images          */
636   case 10: /* Compressed,   rgb images          */
637     if ((src.bytepp = bpp_to_bytes(header.bitsperpixel)))
638       break;
639     i_push_error(0, "Targa: direct color image's bpp is not 15/16/24/32 - unsupported.");
640     if (idstring) myfree(idstring);
641     return NULL;
642     break;
643   case 32: /* Compressed color-mapped, Huffman, Delta and runlength */
644   case 33: /* Compressed color-mapped, Huffman, Delta and runlength */
645     i_push_error(0, "Unsupported Targa (Huffman/delta/rle/quadtree) subformat is not supported");
646     if (idstring) myfree(idstring);
647     return NULL;
648     break;
649   default: /* All others which we don't know which might be */
650     i_push_error(0, "Unknown targa format");
651     if (idstring) myfree(idstring);
652     return NULL;
653     break;
654   }
655   
656   src.state = NoInit;
657   src.len = 0;
658   src.ig = ig;
659   src.compressed = !!(header.datatypecode & (1<<3));
660
661   /* Determine number of channels */
662   
663   mapped = 1;
664   switch (header.datatypecode) {
665     int tbpp;
666   case 2:  /* Uncompressed, rgb images          */
667   case 10: /* Compressed,   rgb images          */
668     mapped = 0;
669   case 1:  /* Uncompressed, color-mapped images */
670   case 9:  /* Compressed,   color-mapped images */
671     if ((channels = bpp_to_channels(mapped ? 
672                                    header.colourmapdepth : 
673                                    header.bitsperpixel))) break;
674     i_push_error(0, "Targa Image has none of 15/16/24/32 pixel layout");
675     if (idstring) myfree(idstring);
676     return NULL;
677     break;
678   case 3:  /* Uncompressed, grayscale images    */
679   case 11: /* Compressed,   grayscale images    */
680     mapped = 0;
681     channels = 1;
682     break;
683   }
684   
685   img = mapped ? 
686     i_img_pal_new(width, height, channels, 256) :
687     i_img_empty_ch(NULL, width, height, channels);
688   
689   if (idstring) {
690     i_tags_add(&img->tags, "tga_idstring", 0, idstring, header.idlength, 0);
691     free(idstring);
692   }
693
694   if (mapped &&
695       !tga_palette_read(ig,
696                         img,
697                         bpp_to_bytes(header.colourmapdepth),
698                         header.colourmaplength)
699       ) {
700     i_push_error(0, "Targa Image has none of 15/16/24/32 pixel layout");
701     if (idstring) myfree(idstring);
702     if (img) i_img_destroy(img);
703     return NULL;
704   }
705   
706   /* Allocate buffers */
707   databuf = mymalloc(width*src.bytepp);
708   if (!mapped) linebuf = mymalloc(width*sizeof(i_color));
709   
710   for(y=0; y<height; y++) {
711     if (!tga_source_read(&src, databuf, width)) {
712       i_push_error(errno, "read for targa data failed");
713       myfree(databuf);
714       if (img) i_img_destroy(img);
715       return NULL;
716     }
717     if (mapped && header.colourmaporigin) for(x=0; x<width; x++) databuf[x] -= header.colourmaporigin;
718     if (mapped) i_ppal(img, 0, width, header.imagedescriptor & (1<<5) ? y : height-1-y, databuf);
719     else {
720       for(x=0; x<width; x++) color_unpack(databuf+x*src.bytepp, src.bytepp, linebuf+x);
721       i_plin(img, 0, width, header.imagedescriptor & (1<<5) ? y : height-1-y, linebuf);
722     }
723   }
724   myfree(databuf);
725   if (linebuf) myfree(linebuf);
726   
727   i_tags_addn(&img->tags, "tga_bitspp", 0, mapped?header.colourmapdepth:header.bitsperpixel);
728   if (src.compressed) i_tags_addn(&img->tags, "compressed", 0, 1);
729   return img;
730 }
731
732
733
734 /*
735 =item i_writetga_wiol(img, ig)
736
737 Writes an image in targa format.  Returns 0 on error.
738
739    img    - image to store
740    ig     - io_glue object
741
742 =cut
743 */
744
745 undef_int
746 i_writetga_wiol(i_img *img, io_glue *ig, int wierdpack, int compress, char *idstring, size_t idlen) {
747   static int rgb_chan[] = { 2, 1, 0, 3 };
748   tga_header header;
749   tga_dest dest;
750   unsigned char headbuf[18];
751   //  unsigned char *data;
752   unsigned int bitspp;
753   
754   int mapped;
755
756   /* parameters */
757
758   /*
759     int compress = 1;
760     char *idstring = "testing";
761     int wierdpack = 0;
762   */
763
764   idlen = strlen(idstring);
765   mapped = img->type == i_palette_type;
766
767   mm_log((1,"i_writetga_wiol(img %p, ig %p, idstring %p, idlen %d, wierdpack %d, compress %d)\n",
768           img, ig, idstring, idlen, wierdpack, compress));
769   mm_log((1, "virtual %d, paletted %d\n", img->virtual, mapped));
770   mm_log((1, "channels %d\n", img->channels));
771   
772   i_clear_error();
773   
774   switch (img->channels) {
775   case 1:
776     bitspp = 8;
777     if (wierdpack) {
778       mm_log((1,"wierdpack option ignored for 1 channel images\n"));
779       wierdpack=0;
780     }
781     break;
782   case 2:
783     i_push_error(0, "Cannot store 2 channel image in targa format");
784     return 0;
785     break;
786   case 3:
787     bitspp = wierdpack ? 15 : 24;
788     break;
789   case 4:
790     bitspp = wierdpack ? 16 : 32;
791     break;
792   default:
793     i_push_error(0, "Targa only handles 1,3 and 4 channel images.");
794     return 0;
795   }
796
797   io_glue_commit_types(ig);
798   
799   header.idlength;
800   header.idlength = idlen;
801   header.colourmaptype   = mapped ? 1 : 0;
802   header.datatypecode    = mapped ? 1 : img->channels == 1 ? 3 : 2;
803   header.datatypecode   += compress ? 8 : 0;
804   mm_log((1, "datatypecode %d\n", header.datatypecode));
805   header.colourmaporigin = 0;
806   header.colourmaplength = mapped ? i_colorcount(img) : 0;
807   header.colourmapdepth  = mapped ? bitspp : 0;
808   header.x_origin        = 0;
809   header.y_origin        = 0;
810   header.width           = img->xsize;
811   header.height          = img->ysize;
812   header.bitsperpixel    = mapped ? 8 : bitspp;
813   header.imagedescriptor = (1<<5); /* normal order instead of upside down */
814
815   tga_header_pack(&header, headbuf);
816
817   if (ig->writecb(ig, &headbuf, sizeof(headbuf)) != sizeof(headbuf)) {
818     i_push_error(errno, "could not write targa header");
819     return 0;
820   }
821
822   if (idlen) {
823     if (ig->writecb(ig, idstring, idlen) != idlen) {
824       i_push_error(errno, "could not write targa idstring");
825       return 0;
826     }
827   }
828   
829   /* Make this into a constructor? */
830   dest.compressed = compress;
831   dest.bytepp     = mapped ? 1 : bpp_to_bytes(bitspp);
832   dest.ig         = ig;
833
834   mm_log((1, "dest.compressed = %d\n", dest.compressed));
835   mm_log((1, "dest.bytepp = %d\n", dest.bytepp));
836
837   if (img->type == i_palette_type) {
838     int i;
839     int bytepp = bpp_to_bytes(bitspp);
840     if (!tga_palette_write(ig, img, bitspp, i_colorcount(img))) return 0;
841     
842     if (!img->virtual && !dest.compressed) {
843       if (ig->writecb(ig, img->idata, img->bytes) != img->bytes) {
844         i_push_error(errno, "could not write targa image data");
845         return 0;
846       }
847     } else {
848       int y;
849       i_palidx *vals = mymalloc(sizeof(i_palidx)*img->xsize);
850       for(y=0; y<img->ysize; y++) {
851         i_gpal(img, 0, img->xsize, y, vals);
852         tga_dest_write(&dest, vals, img->xsize);
853       }
854       myfree(vals);
855     }
856   } else { /* direct type */
857     int x, y;
858     int bytepp = wierdpack ? 2 : bpp_to_bytes(bitspp);
859     int lsize = bytepp * img->xsize;
860     i_color *vals = mymalloc(img->xsize*sizeof(i_color));
861     unsigned char *buf = mymalloc(lsize);
862     
863     for(y=0; y<img->ysize; y++) {
864       i_glin(img, 0, img->xsize, y, vals);
865       for(x=0; x<img->xsize; x++) color_pack(buf+x*bytepp, bitspp, vals+x);
866       tga_dest_write(&dest, buf, img->xsize);
867     }
868     myfree(buf);
869     myfree(vals);
870   }
871   return 1;
872 }