1 /*
2 * xvtarga.c - load routine for 'targa' format pictures
3 *
4 * written and submitted by:
5 * Derek Dongray (dongray@genrad.com)
6 *
7 * The format read/written is actually Targa type 2 uncompressed as
8 * produced by POVray 1.0
9 *
10 * LoadTarga(fname, pinfo)
11 * WriteTarga(fp, pic, ptype, w,h, rmap,gmap,bmap,numcols, cstyle)
12 */
13
14
15 /*
16 * Targa Format (near as I can tell)
17 * 0:
18 * 1: colormap type
19 * 2: image type (1=colmap RGB, 2=uncomp RGB, 3=uncomp gray)
20 * 3:
21 * 4:
22 * 5: colormap_length, low byte
23 * 6: colormap_length, high byte
24 * 7: bits per cmap entry (8, 24, 32)
25 *
26 * 12: width, low byte
27 * 13: width, high byte
28 * 14: height, low byte
29 * 15: height, high byte
30 * 16: bits per pixel (8, 24)
31 * 17: flags
32 */
33
34
35
36 #include "xv.h"
37
38 static long filesize;
39 static const char *bname;
40
41
42 /*******************************************/
LoadTarga(fname,pinfo)43 int LoadTarga(fname, pinfo)
44 char *fname;
45 PICINFO *pinfo;
46 /*******************************************/
47 {
48 /* returns '1' on success */
49
50 FILE *fp;
51 int i, row, c, c1, w, h, npixels, bufsize, flags, intlace, topleft, trunc;
52 byte *pic24, *pp;
53
54 bname = BaseName(fname);
55
56 pinfo->pic = (byte *) NULL;
57 pinfo->comment = (char *) NULL;
58
59 fp=xv_fopen(fname,"r");
60 if (!fp) {
61 SetISTR(ISTR_WARNING,"%s: %s", bname, "can't open file");
62 return 0;
63 }
64
65 /* compute file length */
66 fseek(fp, 0L, 2);
67 filesize = ftell(fp);
68 fseek(fp, 0L, 0);
69
70 if (filesize < 18) {
71 fclose(fp);
72 SetISTR(ISTR_WARNING,"%s: %s", bname, "file is too short");
73 return 0;
74 }
75
76 /* Discard the first few bytes of the file.
77 The format check has already been done or we wouldn't be here. */
78
79 for (i=0; i<12; i++) {
80 c=getc(fp);
81 }
82
83
84 /* read in header information */
85 c=getc(fp); c1=getc(fp);
86 w = c1*256 + c;
87
88 c=getc(fp); c1=getc(fp);
89 h = c1*256 + c;
90
91 npixels = w * h;
92 bufsize = 3 * npixels;
93 if (w <= 0 || h <= 0 || npixels/w != h || bufsize/3 != npixels) {
94 fclose(fp);
95 SetISTR(ISTR_WARNING,"%s: error in Targa header (bad image size)", bname);
96 return 0;
97 }
98
99 c=getc(fp);
100 if (c!=24) {
101 fclose(fp);
102 SetISTR(ISTR_WARNING,"%s: unsupported type (not 24-bit)", bname);
103 return 0;
104 }
105
106 flags = getc(fp);
107 topleft = (flags & 0x20) >> 5;
108 intlace = (flags & 0xc0) >> 6;
109
110 #ifdef FOO
111 if (c!=0x20) {
112 fclose(fp);
113 SetISTR(ISTR_WARNING,"%s: unsupported type (not top-down, noninterlaced)",
114 bname);
115 return 0;
116 }
117 #endif
118
119
120 pic24 = (byte *) calloc((size_t) bufsize, (size_t) 1);
121 if (!pic24) FatalError("couldn't malloc 'pic24'");
122
123
124 trunc = 0;
125
126 /* read the data */
127 for (i=0; i<h; i++) {
128 if (intlace == 2) { /* four pass interlace */
129 if (i < (1*h) / 4) row = 4 * i;
130 else if (i < (2*h) / 4) row = 4 * (i - ((1*h)/4)) + 1;
131 else if (i < (3*h) / 4) row = 4 * (i - ((2*h)/4)) + 2;
132 else row = 4 * (i - ((3*h)/4)) + 3;
133 }
134
135 else if (intlace == 1) { /* two pass interlace */
136 if (i < h / 2) row = 2 * i;
137 else row = 2 * (i - h/2) + 1;
138 }
139
140 else row = i; /* no interlace */
141
142
143
144 if (!topleft) row = (h - row - 1); /* bottom-left origin: invert y */
145
146
147 c = fread(pic24 + (row*w*3), (size_t) 1, (size_t) w*3, fp);
148 if (c != w*3) trunc=1;
149 }
150
151 if (trunc) SetISTR(ISTR_WARNING,"%s: File appears to be truncated.",bname);
152
153
154 /* swap R,B values (file is in BGR, pic24 should be in RGB) */
155 for (i=0, pp=pic24; i<npixels; i++, pp+=3) {
156 c = pp[0]; pp[0] = pp[2]; pp[2] = c;
157 }
158
159
160 pinfo->pic = pic24;
161 pinfo->type = PIC24;
162 pinfo->w = w;
163 pinfo->h = h;
164 pinfo->normw = pinfo->w; pinfo->normh = pinfo->h;
165 pinfo->frmType = F_TARGA;
166 sprintf(pinfo->fullInfo,"Targa, uncompressed RGB. (%ld bytes)", filesize);
167 sprintf(pinfo->shrtInfo,"%dx%d Targa.", w,h);
168 pinfo->colType = F_FULLCOLOR;
169
170 fclose(fp);
171
172 return 1;
173 }
174
175
176 /*******************************************/
WriteTarga(fp,pic,ptype,w,h,rmap,gmap,bmap,numcols,colorstyle)177 int WriteTarga(fp,pic,ptype,w,h,rmap,gmap,bmap,numcols,colorstyle)
178 FILE *fp;
179 byte *pic;
180 int ptype, w,h;
181 byte *rmap, *gmap, *bmap;
182 int numcols, colorstyle;
183 /*******************************************/
184 {
185 int i, j;
186 byte *xpic;
187
188 /* write the header */
189 for (i=0; i<12; i++) putc( (i==2) ? 2 : 0, fp);
190
191 putc(w&0xff, fp);
192 putc((w>>8)&0xff,fp);
193 putc(h&0xff, fp);
194 putc((h>>8)&0xff,fp);
195
196 putc(24,fp);
197 putc(0x20,fp);
198
199 xpic = pic;
200
201 for (i=0; i<h; i++) {
202 if ((i&63)==0) WaitCursor();
203
204 for (j=0; j<w; j++) {
205 if (ptype==PIC8) {
206 putc(bmap[*xpic],fp); putc(gmap[*xpic],fp); putc(rmap[*xpic],fp);
207 xpic++;
208 }
209 else { /* PIC24 */
210 putc(xpic[2], fp); /* b */
211 putc(xpic[1], fp); /* g */
212 putc(xpic[0], fp); /* r */
213 xpic+=3;
214 }
215 }
216 }
217
218 if (ferror(fp)) return -1;
219
220 return 0;
221 }
222