1 #include <stdio.h>
2 #include <math.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include "gd.h"
6
7 #define TRUE 1
8 #define FALSE 0
9
10 /* Exported functions: */
11 extern void gdImageGd (gdImagePtr im, FILE * out);
12
13
14 /* Use this for commenting out debug-print statements. */
15 /* Just use the first '#define' to allow all the prints... */
16 /*#define GD2_DBG(s) (s) */
17 #define GD2_DBG(s)
18
19 /* */
20 /* Shared code to read color tables from gd file. */
21 /* */
_gdGetColors(gdIOCtx * in,gdImagePtr im,int gd2xFlag)22 int _gdGetColors (gdIOCtx * in, gdImagePtr im, int gd2xFlag)
23 {
24 int i;
25 if (gd2xFlag) {
26 int trueColorFlag;
27 if (!gdGetByte(&trueColorFlag, in)) {
28 goto fail1;
29 }
30 /* 2.0.12: detect bad truecolor .gd files created by pre-2.0.12.
31 * Beginning in 2.0.12 truecolor is indicated by the initial 2-byte
32 * signature.
33 */
34 if (trueColorFlag != im->trueColor) {
35 goto fail1;
36 }
37 /* This should have been a word all along */
38 if (!im->trueColor) {
39 if (!gdGetWord(&im->colorsTotal, in)) {
40 goto fail1;
41 }
42 if (im->colorsTotal > gdMaxColors) {
43 goto fail1;
44 }
45 }
46 /* Int to accommodate truecolor single-color transparency */
47 if (!gdGetInt(&im->transparent, in)) {
48 goto fail1;
49 }
50 } else {
51 if (!gdGetByte(&im->colorsTotal, in)) {
52 goto fail1;
53 }
54 if (!gdGetWord(&im->transparent, in)) {
55 goto fail1;
56 }
57 if (im->transparent == 257) {
58 im->transparent = (-1);
59 }
60 }
61
62 GD2_DBG(printf("Palette had %d colours (T=%d)\n", im->colorsTotal, im->transparent));
63
64 if (im->trueColor) {
65 return TRUE;
66 }
67
68 for (i = 0; i < gdMaxColors; i++) {
69 if (!gdGetByte(&im->red[i], in)) {
70 goto fail1;
71 }
72 if (!gdGetByte(&im->green[i], in)) {
73 goto fail1;
74 }
75 if (!gdGetByte(&im->blue[i], in)) {
76 goto fail1;
77 }
78 if (gd2xFlag) {
79 if (!gdGetByte(&im->alpha[i], in)) {
80 goto fail1;
81 }
82 }
83 }
84
85 for (i = 0; i < im->colorsTotal; i++) {
86 im->open[i] = 0;
87 }
88
89 return TRUE;
90 fail1:
91 return FALSE;
92 }
93
94 /* */
95 /* Use the common basic header info to make the image object. */
96 /* */
_gdCreateFromFile(gdIOCtx * in,int * sx,int * sy)97 static gdImagePtr _gdCreateFromFile (gdIOCtx * in, int *sx, int *sy)
98 {
99 gdImagePtr im;
100 int gd2xFlag = 0;
101 int trueColorFlag = 0;
102
103 if (!gdGetWord(sx, in)) {
104 goto fail1;
105 }
106 if (*sx == 65535 || *sx == 65534) {
107 /* This is a gd 2.0 .gd file */
108 gd2xFlag = 1;
109 /* 2.0.12: 65534 signals a truecolor .gd file. There is a slight redundancy here but we can live with it. */
110 if (*sx == 65534) {
111 trueColorFlag = 1;
112 }
113 if (!gdGetWord(sx, in)) {
114 goto fail1;
115 }
116 }
117 if (!gdGetWord(sy, in)) {
118 goto fail1;
119 }
120
121 GD2_DBG(printf("Image is %dx%d\n", *sx, *sy));
122
123 if (trueColorFlag) {
124 im = gdImageCreateTrueColor(*sx, *sy);
125 } else {
126 im = gdImageCreate(*sx, *sy);
127 }
128 if(!im) {
129 goto fail1;
130 }
131 if (!_gdGetColors(in, im, gd2xFlag)) {
132 goto fail2;
133 }
134
135 return im;
136 fail2:
137 gdImageDestroy(im);
138 fail1:
139 return 0;
140 }
141
gdImageCreateFromGd(FILE * inFile)142 gdImagePtr gdImageCreateFromGd (FILE * inFile)
143 {
144 gdImagePtr im;
145 gdIOCtx *in;
146
147 in = gdNewFileCtx(inFile);
148 im = gdImageCreateFromGdCtx(in);
149
150 in->gd_free(in);
151
152 return im;
153 }
154
gdImageCreateFromGdPtr(int size,void * data)155 gdImagePtr gdImageCreateFromGdPtr (int size, void *data)
156 {
157 gdImagePtr im;
158 gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0);
159 im = gdImageCreateFromGdCtx(in);
160 in->gd_free(in);
161
162 return im;
163 }
164
gdImageCreateFromGdCtx(gdIOCtxPtr in)165 gdImagePtr gdImageCreateFromGdCtx (gdIOCtxPtr in)
166 {
167 int sx, sy;
168 int x, y;
169 gdImagePtr im;
170
171 /* Read the header */
172 im = _gdCreateFromFile(in, &sx, &sy);
173
174 if (im == NULL) {
175 goto fail1;
176 }
177
178 /* Then the data... */
179 /* 2.0.12: support truecolor properly in .gd as well as in .gd2. Problem reported by Andreas Pfaller. */
180 if (im->trueColor) {
181 for (y = 0; y < sy; y++) {
182 for (x = 0; x < sx; x++) {
183 int pix;
184 if (!gdGetInt(&pix, in)) {
185 goto fail2;
186 }
187 im->tpixels[y][x] = pix;
188 }
189 }
190 } else {
191 for (y = 0; y < sy; y++) {
192 for (x = 0; x < sx; x++) {
193 int ch;
194 ch = gdGetC(in);
195 if (ch == EOF) {
196 goto fail2;
197 }
198 /* ROW-MAJOR IN GD 1.3 */
199 im->pixels[y][x] = ch;
200 }
201 }
202 }
203
204 return im;
205
206 fail2:
207 gdImageDestroy (im);
208 fail1:
209 return 0;
210 }
211
_gdPutColors(gdImagePtr im,gdIOCtx * out)212 void _gdPutColors (gdImagePtr im, gdIOCtx * out)
213 {
214 int i;
215
216 gdPutC(im->trueColor, out);
217 if (!im->trueColor) {
218 gdPutWord(im->colorsTotal, out);
219 }
220 gdPutInt(im->transparent, out);
221 if (!im->trueColor) {
222 for (i = 0; i < gdMaxColors; i++) {
223 gdPutC((unsigned char) im->red[i], out);
224 gdPutC((unsigned char) im->green[i], out);
225 gdPutC((unsigned char) im->blue[i], out);
226 gdPutC((unsigned char) im->alpha[i], out);
227 }
228 }
229 }
230
_gdPutHeader(gdImagePtr im,gdIOCtx * out)231 static void _gdPutHeader (gdImagePtr im, gdIOCtx * out)
232 {
233 /* 65535 indicates this is a gd 2.x .gd file.
234 * 2.0.12: 65534 indicates truecolor.
235 */
236 if (im->trueColor) {
237 gdPutWord(65534, out);
238 } else {
239 gdPutWord(65535, out);
240 }
241 gdPutWord(im->sx, out);
242 gdPutWord(im->sy, out);
243
244 _gdPutColors(im, out);
245 }
246
_gdImageGd(gdImagePtr im,gdIOCtx * out)247 static void _gdImageGd (gdImagePtr im, gdIOCtx * out)
248 {
249 int x, y;
250
251 _gdPutHeader(im, out);
252
253 for (y = 0; y < im->sy; y++) {
254 for (x = 0; x < im->sx; x++) {
255 /* ROW-MAJOR IN GD 1.3 */
256 if (im->trueColor) {
257 gdPutInt(im->tpixels[y][x], out);
258 } else {
259 gdPutC((unsigned char) im->pixels[y][x], out);
260 }
261 }
262 }
263 }
264
gdImageGd(gdImagePtr im,FILE * outFile)265 void gdImageGd (gdImagePtr im, FILE * outFile)
266 {
267 gdIOCtx *out = gdNewFileCtx(outFile);
268 _gdImageGd(im, out);
269 out->gd_free(out);
270 }
271
gdImageGdPtr(gdImagePtr im,int * size)272 void *gdImageGdPtr (gdImagePtr im, int *size)
273 {
274 void *rv;
275 gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
276 _gdImageGd(im, out);
277 rv = gdDPExtractData(out, size);
278 out->gd_free(out);
279 return rv;
280 }
281