File Coverage

tga.c
Criterion Covered Total %
statement 318 395 80.5
branch 154 224 68.7
condition n/a
subroutine n/a
pod n/a
total 472 619 76.2


line stmt bran cond sub pod time code
1             #include "imageri.h"
2             #include "log.h"
3             #include "iolayer.h"
4              
5             #include
6             #include
7              
8              
9             /*
10             =head1 NAME
11              
12             tga.c - implements reading and writing targa files, uses io layer.
13              
14             =head1 SYNOPSIS
15              
16             io_glue *ig = io_new_fd( fd );
17             i_img *im = i_readtga_wiol(ig, -1); // no limit on how much is read
18             // or
19             io_glue *ig = io_new_fd( fd );
20             return_code = i_writetga_wiol(im, ig);
21              
22             =head1 DESCRIPTION
23              
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.
27              
28             =head1 FUNCTION REFERENCE
29              
30             Some of these functions are internal.
31              
32             =over
33              
34             =cut
35             */
36              
37              
38              
39              
40             typedef struct {
41             unsigned char idlength;
42             char colourmaptype;
43             char datatypecode;
44             short int colourmaporigin;
45             short int colourmaplength;
46             char colourmapdepth;
47             short int x_origin;
48             short int y_origin;
49             int width;
50             int height;
51             char bitsperpixel;
52             char imagedescriptor;
53             } tga_header;
54              
55              
56             typedef enum { NoInit, Raw, Rle } rle_state;
57              
58             typedef struct {
59             int compressed;
60             size_t bytepp;
61             rle_state state;
62             unsigned char cval[4];
63             int len;
64             unsigned char hdr;
65             io_glue *ig;
66             } tga_source;
67              
68              
69             typedef struct {
70             int compressed;
71             int bytepp;
72             io_glue *ig;
73             } tga_dest;
74              
75             #define TGA_MAX_DIM 0xFFFF
76              
77             /*
78             =item bpp_to_bytes(bpp)
79              
80             Convert bits per pixel into bytes per pixel
81              
82             bpp - bits per pixel
83              
84             =cut
85             */
86              
87              
88             static
89             size_t
90 62           bpp_to_bytes(unsigned int bpp) {
91 62           switch (bpp) {
92             case 8:
93 0           return 1;
94             case 15:
95             case 16:
96 7           return 2;
97             case 24:
98 55           return 3;
99             case 32:
100 0           return 4;
101             }
102 0           return 0;
103             }
104              
105              
106              
107             /*
108             =item bpp_to_channels(bpp)
109              
110             Convert bits per pixel and the number of attribute bits into channels
111             in the image
112              
113             bpp - bits per pixel
114             attr_bit_count - number of attribute bits
115              
116             =cut
117             */
118              
119             static
120             int
121 26           bpp_to_channels(unsigned int bpp, int attr_bit_count) {
122 26           switch (bpp) {
123             case 8:
124 0           return 1;
125             case 16:
126 2 50         if (attr_bit_count == 1)
127 2           return 4;
128             case 15:
129 0           return 3;
130             case 32:
131 0 0         if (attr_bit_count == 8)
132 0           return 4;
133             case 24:
134 24           return 3;
135             }
136 0           return 0;
137             }
138              
139              
140              
141             /*
142             * Packing functions - used for (un)packing
143             * datastructures into raw bytes.
144             */
145              
146              
147             /*
148             =item color_unpack(buf, bytepp, val)
149              
150             Unpacks bytes into colour structures, for 2 byte type the first byte
151             coming from the file will actually be GGGBBBBB, and the second will be
152             ARRRRRGG. "A" represents an attribute bit. The 3 byte entry contains
153             1 byte each of blue, green, and red. The 4 byte entry contains 1 byte
154             each of blue, green, red, and attribute.
155              
156             buf - pointer to data
157             bytepp - bytes per pixel
158             val - pointer to color to store to
159              
160             =cut
161             */
162              
163             static
164             void
165 484024           color_unpack(unsigned char *buf, int bytepp, i_color *val) {
166 484024           switch (bytepp) {
167             case 1:
168 0           val->gray.gray_color = buf[0];
169 0           break;
170             case 2:
171 800           val->rgba.r = (buf[1] & 0x7c) << 1;
172 800           val->rgba.g = ((buf[1] & 0x03) << 6) | ((buf[0] & 0xe0) >> 2);
173 800           val->rgba.b = (buf[0] & 0x1f) << 3;
174 800 100         val->rgba.a = (buf[1] & 0x80) ? 0 : 255;
175 800           val->rgba.r |= val->rgba.r >> 5;
176 800           val->rgba.g |= val->rgba.g >> 5;
177 800           val->rgba.b |= val->rgba.b >> 5;
178 800           break;
179             case 3:
180 483224           val->rgb.b = buf[0];
181 483224           val->rgb.g = buf[1];
182 483224           val->rgb.r = buf[2];
183 483224           break;
184             case 4:
185 0           val->rgba.b = buf[0];
186 0           val->rgba.g = buf[1];
187 0           val->rgba.r = buf[2];
188 0           val->rgba.a = buf[3];
189 0           break;
190             }
191 484024           }
192              
193              
194              
195             /*
196             =item color_pack
197              
198             Packs a colour into an array of bytes, for 2 byte type the first byte
199             will be GGGBBBBB, and the second will be ARRRRRGG. "A" represents an
200             attribute bit. The 3 byte entry contains 1 byte each of blue, green,
201             and red. The 4 byte entry contains 1 byte each of blue, green, red,
202             and attribute.
203              
204             buf - destination buffer
205             bitspp - bits per pixel
206             val - color to pack
207              
208             =cut
209             */
210              
211             static
212             void
213 497084           color_pack(unsigned char *buf, int bitspp, i_color *val) {
214 497084           switch (bitspp) {
215             case 8:
216 0           buf[0] = val->gray.gray_color;
217 0           break;
218             case 16:
219 400           buf[0] = (val->rgba.b >> 3);
220 400           buf[0] |= (val->rgba.g & 0x38) << 2;
221 400           buf[1] = (val->rgba.r & 0xf8)>> 1;
222 400           buf[1] |= (val->rgba.g >> 6);
223 400 100         buf[1] |= val->rgba.a > 0x7f ? 0 : 0x80;
224 400           break;
225             case 15:
226 45432           buf[0] = (val->rgba.b >> 3);
227 45432           buf[0] |= (val->rgba.g & 0x38) << 2;
228 45432           buf[1] = (val->rgba.r & 0xf8)>> 1;
229 45432           buf[1] |= (val->rgba.g >> 6);
230 45432           break;
231             case 24:
232 451252           buf[0] = val->rgb.b;
233 451252           buf[1] = val->rgb.g;
234 451252           buf[2] = val->rgb.r;
235 451252           break;
236             case 32:
237 0           buf[0] = val->rgba.b;
238 0           buf[1] = val->rgba.g;
239 0           buf[2] = val->rgba.r;
240 0           buf[3] = val->rgba.a;
241 0           break;
242             }
243 497084           }
244              
245              
246             /*
247             =item find_repeat
248              
249             Helper function for rle compressor to find the next triple repeat of the
250             same pixel value in buffer.
251              
252             buf - buffer
253             length - number of pixel values in buffer
254             bytepp - number of bytes in a pixel value
255              
256             =cut
257             */
258              
259             static
260             int
261 132482           find_repeat(unsigned char *buf, int length, int bytepp) {
262 132482           int i = 0;
263            
264 193399 100         while(i
265 86904 100         if(memcmp(buf+i*bytepp, buf+(i+1)*bytepp, bytepp) == 0) {
266 29883 50         if (i == length-2) return -1;
267 29883 100         if (memcmp(buf+(i+1)*bytepp, buf+(i+2)*bytepp,bytepp) == 0)
268 25987           return i;
269 3896           else i++;
270             }
271 60917           i++;
272             }
273 106495           return -1;
274             }
275              
276              
277             /*
278             =item find_span
279              
280             Helper function for rle compressor to find the length of a span where
281             the same pixel value is in the buffer.
282              
283             buf - buffer
284             length - number of pixel values in buffer
285             bytepp - number of bytes in a pixel value
286              
287             =cut
288             */
289              
290             static
291             int
292 25987           find_span(unsigned char *buf, int length, int bytepp) {
293 25987           int i = 0;
294 440669 100         while(i
295 438247 100         if(memcmp(buf, buf+(i*bytepp), bytepp) != 0) return i;
296 414682           i++;
297             }
298 2422           return length;
299             }
300              
301              
302             /*
303             =item tga_header_unpack(header, headbuf)
304              
305             Unpacks the header structure into from buffer and stores
306             in the header structure.
307              
308             header - header structure
309             headbuf - buffer to unpack from
310              
311             =cut
312             */
313              
314             static
315             void
316 70           tga_header_unpack(tga_header *header, unsigned char headbuf[18]) {
317 70           header->idlength = headbuf[0];
318 70           header->colourmaptype = headbuf[1];
319 70           header->datatypecode = headbuf[2];
320 70           header->colourmaporigin = (headbuf[4] << 8) + headbuf[3];
321 70           header->colourmaplength = (headbuf[6] << 8) + headbuf[5];
322 70           header->colourmapdepth = headbuf[7];
323 70           header->x_origin = (headbuf[9] << 8) + headbuf[8];
324 70           header->y_origin = (headbuf[11] << 8) + headbuf[10];
325 70           header->width = (headbuf[13] << 8) + headbuf[12];
326 70           header->height = (headbuf[15] << 8) + headbuf[14];
327 70           header->bitsperpixel = headbuf[16];
328 70           header->imagedescriptor = headbuf[17];
329 70           }
330              
331              
332             /* this function should never produce diagnostics to stdout, maybe to the logfile */
333             int
334 44           tga_header_verify(unsigned char headbuf[18]) {
335             tga_header header;
336 44           tga_header_unpack(&header, headbuf);
337 44           switch (header.datatypecode) {
338             default:
339             /*printf("bad typecode!\n");*/
340 3           return 0;
341             case 1: /* Uncompressed, color-mapped images */
342             case 3: /* Uncompressed, grayscale images */
343             case 9: /* Compressed, color-mapped images */
344             case 11: /* Compressed, grayscale images */
345 17 50         if (header.bitsperpixel != 8)
346 17           return 0;
347 0           break;
348             case 0:
349             case 2: /* Uncompressed, rgb images */
350             case 10: /* Compressed, rgb images */
351 24 50         if (header.bitsperpixel != 15 && header.bitsperpixel != 16
    100          
352 22 100         && header.bitsperpixel != 24 && header.bitsperpixel != 32)
    100          
353 6           return 0;
354 18           break;
355             }
356              
357 18           switch (header.colourmaptype) {
358             default:
359             /*printf("bad colourmaptype!\n");*/
360 0           return 0;
361             case 1:
362 0 0         if (header.datatypecode != 1 && header.datatypecode != 9)
    0          
363 0           return 0; /* only get a color map on a color mapped image */
364             case 0:
365 18           break;
366             }
367              
368 18 50         switch (header.colourmapdepth) {
369             default:
370 0           return 0;
371             case 0: /* can be 0 if no colour map */
372             case 15:
373             case 16:
374             case 24:
375             case 32:
376 18           break;
377             }
378            
379 44           return 1;
380             }
381              
382              
383             /*
384             =item tga_header_pack(header, headbuf)
385              
386             Packs header structure into buffer for writing.
387              
388             header - header structure
389             headbuf - buffer to pack into
390              
391             =cut
392             */
393              
394             static
395             void
396 23           tga_header_pack(tga_header *header, unsigned char headbuf[18]) {
397 23           headbuf[0] = header->idlength;
398 23           headbuf[1] = header->colourmaptype;
399 23           headbuf[2] = header->datatypecode;
400 23           headbuf[3] = header->colourmaporigin & 0xff;
401 23           headbuf[4] = header->colourmaporigin >> 8;
402 23           headbuf[5] = header->colourmaplength & 0xff;
403 23           headbuf[6] = header->colourmaplength >> 8;
404 23           headbuf[7] = header->colourmapdepth;
405 23           headbuf[8] = header->x_origin & 0xff;
406 23           headbuf[9] = header->x_origin >> 8;
407 23           headbuf[10] = header->y_origin & 0xff;
408 23           headbuf[11] = header->y_origin >> 8;
409 23           headbuf[12] = header->width & 0xff;
410 23           headbuf[13] = header->width >> 8;
411 23           headbuf[14] = header->height & 0xff;
412 23           headbuf[15] = header->height >> 8;
413 23           headbuf[16] = header->bitsperpixel;
414 23           headbuf[17] = header->imagedescriptor;
415 23           }
416              
417              
418             /*
419             =item tga_source_read(s, buf, pixels)
420              
421             Reads pixel number of pixels from source s into buffer buf. Takes
422             care of decompressing the stream if needed.
423              
424             s - data source
425             buf - destination buffer
426             pixels - number of pixels to put into buffer
427              
428             =cut
429             */
430              
431             static
432             int
433 108789           tga_source_read(tga_source *s, unsigned char *buf, size_t pixels) {
434 108789           int cp = 0, j, k;
435 108789 100         if (!s->compressed) {
436 900 50         if (i_io_read(s->ig, buf, pixels*s->bytepp) != pixels*s->bytepp) return 0;
437 900           return 1;
438             }
439            
440 371039 100         while(cp < pixels) {
441             int ml;
442 263150 100         if (s->len == 0) s->state = NoInit;
443 263150           switch (s->state) {
444             case NoInit:
445 131575 50         if (i_io_read(s->ig, &s->hdr, 1) != 1) return 0;
446              
447 131575           s->len = (s->hdr &~(1<<7))+1;
448 131575 100         s->state = (s->hdr & (1<<7)) ? Rle : Raw;
449             {
450             /*
451             static cnt = 0;
452             printf("%04d %s: %d\n", cnt++, s->state==Rle?"RLE":"RAW", s->len);
453             */
454             }
455 131575 100         if (s->state == Rle && i_io_read(s->ig, s->cval, s->bytepp) != s->bytepp) return 0;
    50          
456              
457 131575           break;
458             case Rle:
459 21876           ml = i_min(s->len, pixels-cp);
460 1113728 100         for(k=0; kbytepp; j++)
    100          
461 796713           buf[(cp+k)*s->bytepp+j] = s->cval[j];
462 21876           cp += ml;
463 21876           s->len -= ml;
464 21876           break;
465             case Raw:
466 109699           ml = i_min(s->len, pixels-cp);
467 109699 50         if (i_io_read(s->ig, buf+cp*s->bytepp, ml*s->bytepp) != ml*s->bytepp) return 0;
468 109699           cp += ml;
469 109699           s->len -= ml;
470 109699           break;
471             }
472             }
473 107889           return 1;
474             }
475              
476              
477              
478              
479             /*
480             =item tga_dest_write(s, buf, pixels)
481              
482             Writes pixels from buf to destination s. Takes care of compressing if the
483             destination is compressed.
484              
485             s - data destination
486             buf - source buffer
487             pixels - number of pixels to put write to destination
488              
489             =cut
490             */
491              
492             static
493             int
494 109067           tga_dest_write(tga_dest *s, unsigned char *buf, size_t pixels) {
495 109067           int cp = 0;
496              
497 109067 100         if (!s->compressed) {
498 150 50         if (i_io_write(s->ig, buf, pixels*s->bytepp) != pixels*s->bytepp) return 0;
499 150           return 1;
500             }
501            
502 134904 100         while(cp < pixels) {
503             int tlen;
504 132482           int nxtrip = find_repeat(buf+cp*s->bytepp, pixels-cp, s->bytepp);
505 132482 100         tlen = (nxtrip == -1) ? pixels-cp : nxtrip;
506 245801 100         while(tlen) {
507 113319           unsigned char clen = (tlen>128) ? 128 : tlen;
508 113319           clen--;
509 113319 50         if (i_io_write(s->ig, &clen, 1) != 1) return 0;
510 113319           clen++;
511 113319 50         if (i_io_write(s->ig, buf+cp*s->bytepp, clen*s->bytepp) != clen*s->bytepp) return 0;
512 113319           tlen -= clen;
513 113319           cp += clen;
514             }
515 132482 100         if (cp >= pixels) break;
516 25987           tlen = find_span(buf+cp*s->bytepp, pixels-cp, s->bytepp);
517 25987 50         if (tlen <3) continue;
518 52881 100         while (tlen) {
519 26894           unsigned char clen = (tlen>128) ? 128 : tlen;
520 26894           clen = (clen - 1) | 0x80;
521 26894 50         if (i_io_write(s->ig, &clen, 1) != 1) return 0;
522 26894           clen = (clen & ~0x80) + 1;
523 26894 50         if (i_io_write(s->ig, buf+cp*s->bytepp, s->bytepp) != s->bytepp) return 0;
524 26894           tlen -= clen;
525 26894           cp += clen;
526             }
527             }
528 108917           return 1;
529             }
530              
531              
532              
533              
534              
535              
536             /*
537             =item tga_palette_read(ig, img, bytepp, colourmaplength)
538              
539             Reads the colormap from a tga file and stores in the paletted image
540             structure.
541              
542             ig - iolayer data source
543             img - image structure
544             bytepp - bytes per pixel
545             colourmaplength - number of colours in colourmap
546              
547             =cut
548             */
549              
550             static
551             int
552 4           tga_palette_read(io_glue *ig, i_img *img, int bytepp, int colourmaplength) {
553             int i;
554             size_t palbsize;
555             unsigned char *palbuf;
556             i_color val;
557              
558 4           palbsize = (size_t)colourmaplength * bytepp;
559 4           palbuf = mymalloc(palbsize);
560            
561 4 100         if (i_io_read(ig, palbuf, palbsize) != palbsize) {
562 1           myfree(palbuf);
563 1           i_push_error(errno, "could not read targa colormap");
564 1           return 0;
565             }
566            
567             /* populate the palette of the new image */
568 233 100         for(i=0; i
569 230           color_unpack(palbuf+i*bytepp, bytepp, &val);
570 230 50         i_addcolors(img, &val, 1);
571             }
572 3           myfree(palbuf);
573 4           return 1;
574             }
575              
576              
577             /*
578             =item tga_palette_write(ig, img, bitspp, colourmaplength)
579              
580             Stores the colormap of an image in the destination ig.
581              
582             ig - iolayer data source
583             img - image structure
584             bitspp - bits per pixel in colourmap
585             colourmaplength - number of colours in colourmap
586              
587             =cut
588             */
589              
590             static
591             int
592 7           tga_palette_write(io_glue *ig, i_img *img, int bitspp, int colourmaplength) {
593             int i;
594 7           size_t bytepp = bpp_to_bytes(bitspp);
595 7 50         size_t palbsize = i_colorcount(img)*bytepp;
596 7           unsigned char *palbuf = mymalloc(palbsize);
597            
598 1101 100         for(i=0; i
599             i_color val;
600 1094 50         i_getcolors(img, i, &val, 1);
601 1094           color_pack(palbuf+i*bytepp, bitspp, &val);
602             }
603            
604 7 50         if (i_io_write(ig, palbuf, palbsize) != palbsize) {
605 0           i_push_error(errno, "could not write targa colormap");
606 0           return 0;
607             }
608 7           myfree(palbuf);
609 7           return 1;
610             }
611              
612              
613              
614             /*
615             =item i_readtga_wiol(ig, length)
616              
617             Read in an image from the iolayer data source and return the image structure to it.
618             Returns NULL on error.
619              
620             ig - io_glue object
621             length - maximum length to read from data source, before closing it -1
622             signifies no limit.
623              
624             =cut
625             */
626              
627             i_img *
628 26           i_readtga_wiol(io_glue *ig, int length) {
629 26           i_img* img = NULL;
630             int x, y;
631             int width, height, channels;
632             int mapped;
633 26           char *idstring = NULL;
634              
635             tga_source src;
636             tga_header header;
637             unsigned char headbuf[18];
638             unsigned char *databuf;
639              
640 26           i_color *linebuf = NULL;
641 26           i_clear_error();
642              
643 26           mm_log((1,"i_readtga(ig %p, length %d)\n", ig, length));
644            
645 26 50         if (i_io_read(ig, &headbuf, 18) != 18) {
646 0           i_push_error(errno, "could not read targa header");
647 0           return NULL;
648             }
649              
650 26           tga_header_unpack(&header, headbuf);
651              
652 26           mm_log((1,"Id length: %d\n",header.idlength));
653 26           mm_log((1,"Colour map type: %d\n",header.colourmaptype));
654 26           mm_log((1,"Image type: %d\n",header.datatypecode));
655 26           mm_log((1,"Colour map offset: %d\n",header.colourmaporigin));
656 26           mm_log((1,"Colour map length: %d\n",header.colourmaplength));
657 26           mm_log((1,"Colour map depth: %d\n",header.colourmapdepth));
658 26           mm_log((1,"X origin: %d\n",header.x_origin));
659 26           mm_log((1,"Y origin: %d\n",header.y_origin));
660 26           mm_log((1,"Width: %d\n",header.width));
661 26           mm_log((1,"Height: %d\n",header.height));
662 26           mm_log((1,"Bits per pixel: %d\n",header.bitsperpixel));
663 26           mm_log((1,"Descriptor: %d\n",header.imagedescriptor));
664              
665 26 100         if (header.idlength) {
666             /* max of 256, so this is safe */
667 3           idstring = mymalloc(header.idlength+1);
668 3 50         if (i_io_read(ig, idstring, header.idlength) != header.idlength) {
669 0           i_push_error(errno, "short read on targa idstring");
670 0           return NULL;
671             }
672             }
673              
674 26           width = header.width;
675 26           height = header.height;
676              
677            
678             /* Set tags here */
679            
680 26           switch (header.datatypecode) {
681             case 0: /* No data in image */
682 0           i_push_error(0, "Targa image contains no image data");
683 0 0         if (idstring) myfree(idstring);
684 0           return NULL;
685             break;
686             case 1: /* Uncompressed, color-mapped images */
687             case 9: /* Compressed, color-mapped images */
688             case 3: /* Uncompressed, grayscale images */
689             case 11: /* Compressed, grayscale images */
690 4 50         if (header.bitsperpixel != 8) {
691 0           i_push_error(0, "Targa: mapped/grayscale image's bpp is not 8, unsupported.");
692 0 0         if (idstring) myfree(idstring);
693 0           return NULL;
694             }
695 4           src.bytepp = 1;
696 4           break;
697             case 2: /* Uncompressed, rgb images */
698             case 10: /* Compressed, rgb images */
699 22 50         if ((src.bytepp = bpp_to_bytes(header.bitsperpixel)))
700 22           break;
701 0           i_push_error(0, "Targa: direct color image's bpp is not 15/16/24/32 - unsupported.");
702 0 0         if (idstring) myfree(idstring);
703 0           return NULL;
704             break;
705             case 32: /* Compressed color-mapped, Huffman, Delta and runlength */
706             case 33: /* Compressed color-mapped, Huffman, Delta and runlength */
707 0           i_push_error(0, "Unsupported Targa (Huffman/delta/rle/quadtree) subformat is not supported");
708 0 0         if (idstring) myfree(idstring);
709 0           return NULL;
710             break;
711             default: /* All others which we don't know which might be */
712 0           i_push_error(0, "Unknown targa format");
713 0 0         if (idstring) myfree(idstring);
714 0           return NULL;
715             break;
716             }
717            
718 26           src.state = NoInit;
719 26           src.len = 0;
720 26           src.ig = ig;
721 26           src.compressed = !!(header.datatypecode & (1<<3));
722              
723             /* Determine number of channels */
724            
725 26           mapped = 1;
726 26           switch (header.datatypecode) {
727             case 2: /* Uncompressed, rgb images */ /* FALLTHROUGH */
728             case 10: /* Compressed, rgb images */ /* FALLTHROUGH */
729 22           mapped = 0;
730             case 1: /* Uncompressed, color-mapped images */
731             case 9: /* Compressed, color-mapped images */
732 26 100         if ((channels = bpp_to_channels(mapped ?
    50          
733 4           header.colourmapdepth :
734 22           header.bitsperpixel,
735 26           header.imagedescriptor & 0xF))) break;
736 0           i_push_error(0, "Targa Image has none of 15/16/24/32 pixel layout");
737 0 0         if (idstring) myfree(idstring);
738 0           return NULL;
739             break;
740             case 3: /* Uncompressed, grayscale images */ /* FALLTHROUGH */
741             case 11: /* Compressed, grayscale images */
742 0           mapped = 0;
743 0           channels = 1;
744 0           break;
745             default:
746 0           i_push_error(0, "invalid or unsupported datatype code");
747 0           return NULL;
748             }
749              
750 26 100         if (!i_int_check_image_file_limits(width, height, channels,
751             sizeof(i_sample_t))) {
752 3           mm_log((1, "i_readtga_wiol: image size exceeds limits\n"));
753 3           return NULL;
754             }
755            
756 23           img = mapped ?
757 42 100         i_img_pal_new(width, height, channels, 256) :
758 19           i_img_empty_ch(NULL, width, height, channels);
759              
760 23 50         if (!img) {
761 0 0         if (idstring)
762 0           myfree(idstring);
763 0           return NULL;
764             }
765            
766 23 100         if (idstring) {
767 3           i_tags_add(&img->tags, "tga_idstring", 0, idstring, header.idlength, 0);
768 3           myfree(idstring);
769             }
770              
771 27           if (mapped &&
772 4           !tga_palette_read(ig,
773             img,
774 4           bpp_to_bytes(header.colourmapdepth),
775 4           header.colourmaplength)
776             ) {
777             /* tga_palette_read() sets a message */
778 1 50         if (img) i_img_destroy(img);
779 1           return NULL;
780             }
781            
782             /* Allocate buffers */
783             /* width is max 0xffff, src.bytepp is max 4, so this is safe */
784 22           databuf = mymalloc(width*src.bytepp);
785             /* similarly here */
786 22 100         if (!mapped) linebuf = mymalloc(width*sizeof(i_color));
787            
788 108811 100         for(y=0; y
789 108789 50         if (!tga_source_read(&src, databuf, width)) {
790 0           i_push_error(errno, "read for targa data failed");
791 0 0         if (linebuf) myfree(linebuf);
792 0           myfree(databuf);
793 0 0         if (img) i_img_destroy(img);
794 0           return NULL;
795             }
796 108789 100         if (mapped && header.colourmaporigin) for(x=0; x
    50          
    0          
797 108789 100         if (mapped) i_ppal(img, 0, width, header.imagedescriptor & (1<<5) ? y : height-1-y, databuf);
    50          
    50          
798             else {
799 592133 100         for(x=0; x
800 108339 50         i_plin(img, 0, width, header.imagedescriptor & (1<<5) ? y : height-1-y, linebuf);
801             }
802             }
803 22           myfree(databuf);
804 22 100         if (linebuf) myfree(linebuf);
805            
806 22           i_tags_add(&img->tags, "i_format", 0, "tga", -1, 0);
807 22 100         i_tags_addn(&img->tags, "tga_bitspp", 0, mapped?header.colourmapdepth:header.bitsperpixel);
808 22 100         if (src.compressed) i_tags_addn(&img->tags, "compressed", 0, 1);
809 26           return img;
810             }
811              
812              
813              
814             /*
815             =item i_writetga_wiol(img, ig)
816              
817             Writes an image in targa format. Returns 0 on error.
818              
819             img - image to store
820             ig - io_glue object
821              
822             =cut
823             */
824              
825             undef_int
826 26           i_writetga_wiol(i_img *img, io_glue *ig, int wierdpack, int compress, char *idstring, size_t idlen) {
827             tga_header header;
828             tga_dest dest;
829             unsigned char headbuf[18];
830             unsigned int bitspp;
831 26           unsigned int attr_bits = 0;
832            
833             int mapped;
834              
835             /* parameters */
836              
837             /*
838             int compress = 1;
839             char *idstring = "testing";
840             int wierdpack = 0;
841             */
842              
843 26           idlen = strlen(idstring);
844 26           mapped = img->type == i_palette_type;
845              
846 26           mm_log((1,"i_writetga_wiol(img %p, ig %p, idstring %p, idlen %ld, wierdpack %d, compress %d)\n",
847             img, ig, idstring, (long)idlen, wierdpack, compress));
848 26           mm_log((1, "virtual %d, paletted %d\n", i_img_virtual(img), mapped));
849 26           mm_log((1, "channels %d\n", img->channels));
850            
851 26           i_clear_error();
852              
853 26 100         if (img->xsize > TGA_MAX_DIM || img->ysize > TGA_MAX_DIM) {
    100          
854 2           i_push_error(0, "image too large for TGA");
855 2           return 0;
856             }
857              
858 24           switch (img->channels) {
859             case 1:
860 0           bitspp = 8;
861 0 0         if (wierdpack) {
862 0           mm_log((1,"wierdpack option ignored for 1 channel images\n"));
863 0           wierdpack=0;
864             }
865 0           break;
866             case 2:
867 1           i_push_error(0, "Cannot store 2 channel image in targa format");
868 1           return 0;
869             break;
870             case 3:
871 22 100         bitspp = wierdpack ? 15 : 24;
872 22           break;
873             case 4:
874 1 50         bitspp = wierdpack ? 16 : 32;
875 1 50         attr_bits = wierdpack ? 1 : 8;
876 1           break;
877             default:
878 0           i_push_error(0, "Targa only handles 1,3 and 4 channel images.");
879 0           return 0;
880             }
881              
882 23           header.idlength = idlen;
883 23           header.colourmaptype = mapped ? 1 : 0;
884 23 100         header.datatypecode = mapped ? 1 : img->channels == 1 ? 3 : 2;
    50          
885 23 100         header.datatypecode += compress ? 8 : 0;
886 23           mm_log((1, "datatypecode %d\n", header.datatypecode));
887 23           header.colourmaporigin = 0;
888 23 100         header.colourmaplength = mapped ? i_colorcount(img) : 0;
    50          
889 23 100         header.colourmapdepth = mapped ? bitspp : 0;
890 23           header.x_origin = 0;
891 23           header.y_origin = 0;
892 23           header.width = img->xsize;
893 23           header.height = img->ysize;
894 23 100         header.bitsperpixel = mapped ? 8 : bitspp;
895 23           header.imagedescriptor = (1<<5) | attr_bits; /* normal order instead of upside down */
896              
897 23           tga_header_pack(&header, headbuf);
898              
899 23 50         if (i_io_write(ig, &headbuf, sizeof(headbuf)) != sizeof(headbuf)) {
900 0           i_push_error(errno, "could not write targa header");
901 0           return 0;
902             }
903              
904 23 100         if (idlen) {
905 2 50         if (i_io_write(ig, idstring, idlen) != idlen) {
906 0           i_push_error(errno, "could not write targa idstring");
907 0           return 0;
908             }
909             }
910            
911             /* Make this into a constructor? */
912 23           dest.compressed = compress;
913 23 100         dest.bytepp = mapped ? 1 : bpp_to_bytes(bitspp);
914 23           dest.ig = ig;
915              
916 23           mm_log((1, "dest.compressed = %d\n", dest.compressed));
917 23           mm_log((1, "dest.bytepp = %d\n", dest.bytepp));
918              
919 23 100         if (img->type == i_palette_type) {
920 7 50         if (!tga_palette_write(ig, img, bitspp, i_colorcount(img))) return 0;
    50          
921            
922 7 50         if (!i_img_virtual(img) && !dest.compressed) {
    100          
923 2 50         if (i_io_write(ig, img->idata, img->bytes) != img->bytes) {
924 0           i_push_error(errno, "could not write targa image data");
925 0           return 0;
926             }
927             } else {
928             int y;
929 5           i_palidx *vals = mymalloc(sizeof(i_palidx)*img->xsize);
930 755 100         for(y=0; yysize; y++) {
931 750 50         i_gpal(img, 0, img->xsize, y, vals);
932 750           tga_dest_write(&dest, vals, img->xsize);
933             }
934 7           myfree(vals);
935             }
936             } else { /* direct type */
937             int x, y;
938 16 100         size_t bytepp = wierdpack ? 2 : bpp_to_bytes(bitspp);
939 16           size_t lsize = bytepp * img->xsize;
940 16           i_color *vals = mymalloc(img->xsize*sizeof(i_color));
941 16           unsigned char *buf = mymalloc(lsize);
942            
943 108333 100         for(y=0; yysize; y++) {
944 108317           i_glin(img, 0, img->xsize, y, vals);
945 604307 100         for(x=0; xxsize; x++) color_pack(buf+x*bytepp, bitspp, vals+x);
946 108317           tga_dest_write(&dest, buf, img->xsize);
947             }
948 16           myfree(buf);
949 16           myfree(vals);
950             }
951              
952 23 100         if (i_io_close(ig))
953 1           return 0;
954              
955 26           return 1;
956             }
957              
958             /*
959             =back
960              
961             =head1 AUTHOR
962              
963             Arnar M. Hrafnkelsson
964              
965             =head1 SEE ALSO
966              
967             Imager(3)
968              
969             =cut
970             */