]>
Commit | Line | Data |
---|---|---|
c801d85f | 1 | #define _GNU_SOURCE |
1f0299c1 | 2 | #include "../gdk_imlib/config.h" |
c801d85f | 3 | |
1f0299c1 KB |
4 | #include "../gdk_imlib/gdk_imlib.h" |
5 | #include "../gdk_imlib/gdk_imlib_private.h" | |
c801d85f KB |
6 | |
7 | gint | |
8 | gdk_imlib_save_image(GdkImlibImage * im, char *file, GdkImlibSaveInfo * info) | |
9 | { | |
10 | char *ext; | |
11 | char cmd[10240]; | |
12 | FILE *f; | |
13 | GdkImlibSaveInfo defaults; | |
14 | ||
15 | if (!im || !file) | |
16 | return 0; | |
17 | ||
18 | defaults.quality = 208; | |
19 | defaults.scaling = 1024; | |
20 | defaults.xjustification = 512; | |
21 | defaults.yjustification = 512; | |
22 | defaults.page_size = PAGE_SIZE_LETTER; | |
23 | defaults.color = 1; | |
24 | ||
25 | if (!info) | |
26 | info = &defaults; | |
27 | ext = g_GetExtension(file); | |
28 | ||
29 | if ((!strcasecmp(ext, "ppm")) || (!strcasecmp(ext, "pnm"))) | |
30 | { | |
31 | f = fopen(file, "wb"); | |
32 | if (f) | |
33 | { | |
34 | if (!fprintf(f, "P6\n# Created by Imlib\n%i %i\n255\n", im->rgb_width, im->rgb_height)) | |
35 | { | |
36 | fclose(f); | |
37 | return 0; | |
38 | } | |
39 | if (!fwrite(im->rgb_data, 1, (im->rgb_width * im->rgb_height * 3), f)) | |
40 | { | |
41 | fclose(f); | |
42 | return 0; | |
43 | } | |
44 | fclose(f); | |
45 | return 1; | |
46 | } | |
47 | } | |
48 | else if (!strcasecmp(ext, "pgm")) | |
49 | { | |
50 | int x, y; | |
51 | unsigned char *ptr, val; | |
52 | int v; | |
53 | ||
54 | f = fopen(file, "wb"); | |
55 | if (f) | |
56 | { | |
57 | if (!fprintf(f, "P5\n# Created by Imlib\n%i %i\n255\n", im->rgb_width, im->rgb_height)) | |
58 | { | |
59 | fclose(f); | |
60 | return 0; | |
61 | } | |
62 | ptr = im->rgb_data; | |
63 | for (y = 0; y < im->rgb_height; y++) | |
64 | { | |
65 | for (x = 0; x < im->rgb_width; x++) | |
66 | { | |
67 | v = (int)(*ptr++); | |
68 | v += (int)(*ptr++); | |
69 | v += (int)(*ptr++); | |
70 | val = (unsigned char)(v / 3); | |
71 | if (!fwrite(&val, 1, 1, f)) | |
72 | { | |
73 | fclose(f); | |
74 | return 0; | |
75 | } | |
76 | } | |
77 | } | |
78 | fclose(f); | |
79 | return 1; | |
80 | } | |
81 | } | |
82 | else if (!strcasecmp(ext, "ps")) | |
83 | { | |
84 | int bx, by, bxx, byy; | |
85 | int w, h; | |
86 | int sx, sy; | |
87 | int tx = 35, ty = 35; | |
88 | int x, y; | |
89 | unsigned char *ptr; | |
90 | int v; | |
91 | ||
92 | f = fopen(file, "wb"); | |
93 | ||
94 | if (f == NULL) | |
95 | return 0; | |
96 | ||
97 | w = im->rgb_width; | |
98 | h = im->rgb_height; | |
99 | ||
100 | switch (info->page_size) | |
101 | { | |
102 | case PAGE_SIZE_EXECUTIVE: | |
103 | sx = 540; | |
104 | sy = 720; | |
105 | break; | |
106 | case PAGE_SIZE_LETTER: | |
107 | sx = 612; | |
108 | sy = 792; | |
109 | break; | |
110 | case PAGE_SIZE_LEGAL: | |
111 | sx = 612; | |
112 | sy = 1008; | |
113 | break; | |
114 | case PAGE_SIZE_A4: | |
115 | sx = 595; | |
116 | sy = 842; | |
117 | break; | |
118 | case PAGE_SIZE_A3: | |
119 | sx = 842; | |
120 | sy = 1190; | |
121 | break; | |
122 | case PAGE_SIZE_A5: | |
123 | sx = 420; | |
124 | sy = 595; | |
125 | break; | |
126 | case PAGE_SIZE_FOLIO: | |
127 | sx = 612; | |
128 | sy = 936; | |
129 | break; | |
130 | } | |
131 | bxx = ((sx - (tx * 2)) * info->scaling) >> 10; | |
132 | byy = ((h * bxx / w) * info->scaling) >> 10; | |
133 | if ((((sy - (ty * 2)) * info->scaling) >> 10) < byy) | |
134 | { | |
135 | byy = ((sy - (ty * 2)) * info->scaling) >> 10; | |
136 | bxx = ((w * byy / h) * info->scaling) >> 10; | |
137 | } | |
138 | bx = tx + ((((sx - (tx * 2)) - bxx) * info->xjustification) >> 10); | |
139 | by = ty + ((((sy - (ty * 2)) - byy) * info->yjustification) >> 10); | |
140 | if (f) | |
141 | { | |
142 | fprintf(f, "%%!PS-Adobe-2.0 EPSF-2.0\n"); | |
143 | fprintf(f, "%%%%Title: %s\n", file); | |
144 | fprintf(f, "%%%%Creator: Imlib by The Rasterman\n"); | |
145 | fprintf(f, "%%%%BoundingBox: %i %i %i %i\n", bx, by, bxx, byy); | |
146 | fprintf(f, "%%%%Pages: 1\n"); | |
147 | fprintf(f, "%%%%DocumentFonts:\n"); | |
148 | fprintf(f, "%%%%EndComments\n"); | |
149 | fprintf(f, "%%%%EndProlog\n"); | |
150 | fprintf(f, "%%%%Page: 1 1\n"); | |
151 | fprintf(f, "/origstate save def\n"); | |
152 | fprintf(f, "20 dict begin\n"); | |
153 | if (info->color) | |
154 | { | |
155 | fprintf(f, "/pix %i string def\n", w * 3); | |
156 | fprintf(f, "/grays %i string def\n", w); | |
157 | fprintf(f, "/npixls 0 def\n"); | |
158 | fprintf(f, "/rgbindx 0 def\n"); | |
159 | fprintf(f, "%i %i translate\n", bx, by); | |
160 | fprintf(f, "%i %i scale\n", bxx, byy); | |
161 | fprintf(f, | |
162 | "/colorimage where\n" | |
163 | "{ pop }\n" | |
164 | "{\n" | |
165 | "/colortogray {\n" | |
166 | "/rgbdata exch store\n" | |
167 | "rgbdata length 3 idiv\n" | |
168 | "/npixls exch store\n" | |
169 | "/rgbindx 0 store\n" | |
170 | "0 1 npixls 1 sub {\n" | |
171 | "grays exch\n" | |
172 | "rgbdata rgbindx get 20 mul\n" | |
173 | "rgbdata rgbindx 1 add get 32 mul\n" | |
174 | "rgbdata rgbindx 2 add get 12 mul\n" | |
175 | "add add 64 idiv\n" | |
176 | "put\n" | |
177 | "/rgbindx rgbindx 3 add store\n" | |
178 | "} for\n" | |
179 | "grays 0 npixls getinterval\n" | |
180 | "} bind def\n" | |
181 | "/mergeprocs {\n" | |
182 | "dup length\n" | |
183 | "3 -1 roll\n" | |
184 | "dup\n" | |
185 | "length\n" | |
186 | "dup\n" | |
187 | "5 1 roll\n" | |
188 | "3 -1 roll\n" | |
189 | "add\n" | |
190 | "array cvx\n" | |
191 | "dup\n" | |
192 | "3 -1 roll\n" | |
193 | "0 exch\n" | |
194 | "putinterval\n" | |
195 | "dup\n" | |
196 | "4 2 roll\n" | |
197 | "putinterval\n" | |
198 | "} bind def\n" | |
199 | "/colorimage {\n" | |
200 | "pop pop\n" | |
201 | "{colortogray} mergeprocs\n" | |
202 | "image\n" | |
203 | "} bind def\n" | |
204 | "} ifelse\n"); | |
205 | fprintf(f, "%i %i 8\n", w, h); | |
206 | fprintf(f, "[%i 0 0 -%i 0 %i]\n", w, h, h); | |
207 | fprintf(f, "{currentfile pix readhexstring pop}\n"); | |
208 | fprintf(f, "false 3 colorimage\n"); | |
209 | fprintf(f, "\n"); | |
210 | ptr = im->rgb_data; | |
211 | for (y = 0; y < h; y++) | |
212 | { | |
213 | for (x = 0; x < w; x++) | |
214 | { | |
215 | v = (int)(*ptr++); | |
216 | if (v < 0x10) | |
217 | fprintf(f, "0%x", v); | |
218 | else | |
219 | fprintf(f, "%x", v); | |
220 | v = (int)(*ptr++); | |
221 | if (v < 0x10) | |
222 | fprintf(f, "0%x", v); | |
223 | else | |
224 | fprintf(f, "%x", v); | |
225 | v = (int)(*ptr++); | |
226 | if (v < 0x10) | |
227 | fprintf(f, "0%x", v); | |
228 | else | |
229 | fprintf(f, "%x", v); | |
230 | } | |
231 | fprintf(f, "\n"); | |
232 | } | |
233 | } | |
234 | else | |
235 | { | |
236 | fprintf(f, "/pix %i string def\n", w); | |
237 | fprintf(f, "/grays %i string def\n", w); | |
238 | fprintf(f, "/npixls 0 def\n"); | |
239 | fprintf(f, "/rgbindx 0 def\n"); | |
240 | fprintf(f, "%i %i translate\n", bx, by); | |
241 | fprintf(f, "%i %i scale\n", bxx, byy); | |
242 | fprintf(f, "%i %i 8\n", w, h); | |
243 | fprintf(f, "[%i 0 0 -%i 0 %i]\n", w, h, h); | |
244 | fprintf(f, "{currentfile pix readhexstring pop}\n"); | |
245 | fprintf(f, "image\n"); | |
246 | fprintf(f, "\n"); | |
247 | ptr = im->rgb_data; | |
248 | for (y = 0; y < h; y++) | |
249 | { | |
250 | for (x = 0; x < w; x++) | |
251 | { | |
252 | v = (int)(*ptr++); | |
253 | v += (int)(*ptr++); | |
254 | v += (int)(*ptr++); | |
255 | v /= 3; | |
256 | if (v < 0x10) | |
257 | fprintf(f, "0%x", v); | |
258 | else | |
259 | fprintf(f, "%x", v); | |
260 | } | |
261 | fprintf(f, "\n"); | |
262 | } | |
263 | } | |
264 | fprintf(f, "\n"); | |
265 | fprintf(f, "showpage\n"); | |
266 | fprintf(f, "end\n"); | |
267 | fprintf(f, "origstate restore\n"); | |
268 | fprintf(f, "%%%%Trailer\n"); | |
269 | fclose(f); | |
270 | return 1; | |
271 | } | |
272 | } | |
273 | else if ((!strcasecmp(ext, "jpeg")) || (!strcasecmp(ext, "jpg"))) | |
274 | { | |
275 | #ifdef HAVE_LIBJPEG | |
276 | struct jpeg_compress_struct cinfo; | |
277 | struct jpeg_error_mgr jerr; | |
278 | JSAMPROW row_pointer[1]; | |
279 | int row_stride; | |
280 | int y; | |
281 | ||
282 | f = fopen(file, "wb"); | |
283 | if (f) | |
284 | { | |
285 | cinfo.err = jpeg_std_error(&jerr); | |
286 | jpeg_create_compress(&cinfo); | |
287 | jpeg_stdio_dest(&cinfo, f); | |
288 | cinfo.image_width = im->rgb_width; | |
289 | cinfo.image_height = im->rgb_height; | |
290 | cinfo.input_components = 3; | |
291 | cinfo.in_color_space = JCS_RGB; | |
292 | jpeg_set_defaults(&cinfo); | |
293 | jpeg_set_quality(&cinfo, (100 * info->quality) >> 8, TRUE); | |
294 | jpeg_start_compress(&cinfo, TRUE); | |
295 | row_stride = cinfo.image_width * 3; | |
296 | while (cinfo.next_scanline < cinfo.image_height) | |
297 | { | |
298 | row_pointer[0] = im->rgb_data + (cinfo.next_scanline * row_stride); | |
299 | jpeg_write_scanlines(&cinfo, row_pointer, 1); | |
300 | } | |
301 | jpeg_finish_compress(&cinfo); | |
302 | fclose(f); | |
303 | return 1; | |
304 | } | |
305 | #endif | |
306 | } | |
307 | else if (!strcasecmp(ext, "png")) | |
308 | { | |
309 | #ifdef HAVE_LIBPNG | |
310 | png_structp png_ptr; | |
311 | png_infop info_ptr; | |
312 | unsigned char *data, *ptr; | |
313 | int x, y; | |
314 | png_bytep row_ptr; | |
315 | png_color_8 sig_bit; | |
316 | ||
317 | f = fopen(file, "wb"); | |
318 | if (f) | |
319 | { | |
320 | png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, | |
321 | NULL, NULL, NULL); | |
322 | if (!png_ptr) | |
323 | { | |
324 | fclose(f); | |
325 | return 0; | |
326 | } | |
327 | info_ptr = png_create_info_struct(png_ptr); | |
328 | if (info_ptr == NULL) | |
329 | { | |
330 | fclose(f); | |
331 | png_destroy_write_struct(&png_ptr, (png_infopp) NULL); | |
332 | return 0; | |
333 | } | |
334 | if (setjmp(png_ptr->jmpbuf)) | |
335 | { | |
336 | fclose(f); | |
337 | png_destroy_write_struct(&png_ptr, (png_infopp) NULL); | |
338 | return 0; | |
339 | } | |
340 | png_init_io(png_ptr, f); | |
341 | png_set_IHDR(png_ptr, info_ptr, im->rgb_width, im->rgb_height, 8, | |
342 | PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, | |
343 | PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); | |
344 | sig_bit.red = 8; | |
345 | sig_bit.green = 8; | |
346 | sig_bit.blue = 8; | |
347 | sig_bit.alpha = 8; | |
348 | png_set_sBIT(png_ptr, info_ptr, &sig_bit); | |
349 | png_write_info(png_ptr, info_ptr); | |
350 | png_set_shift(png_ptr, &sig_bit); | |
351 | png_set_packing(png_ptr); | |
352 | data = malloc(im->rgb_width * 4); | |
353 | if (!data) | |
354 | { | |
355 | fclose(f); | |
356 | png_destroy_write_struct(&png_ptr, (png_infopp) NULL); | |
357 | return 0; | |
358 | } | |
359 | for (y = 0; y < im->rgb_height; y++) | |
360 | { | |
361 | ptr = im->rgb_data + (y * im->rgb_width * 3); | |
362 | for (x = 0; x < im->rgb_width; x++) | |
363 | { | |
364 | data[(x << 2) + 0] = *ptr++; | |
365 | data[(x << 2) + 1] = *ptr++; | |
366 | data[(x << 2) + 2] = *ptr++; | |
367 | if ((data[(x << 2) + 0] == im->shape_color.r) && | |
368 | (data[(x << 2) + 1] == im->shape_color.g) && | |
369 | (data[(x << 2) + 2] == im->shape_color.b)) | |
370 | data[(x << 2) + 3] = 0; | |
371 | else | |
372 | data[(x << 2) + 3] = 255; | |
373 | } | |
374 | row_ptr = data; | |
375 | png_write_rows(png_ptr, &row_ptr, 1); | |
376 | } | |
377 | free(data); | |
378 | png_write_end(png_ptr, info_ptr); | |
379 | png_destroy_write_struct(&png_ptr, (png_infopp) NULL); | |
380 | ||
381 | fclose(f); | |
382 | return 1; | |
383 | } | |
384 | #endif | |
385 | } | |
386 | else if ((!strcasecmp(ext, "tiff")) || (!strcasecmp(ext, "tif"))) | |
387 | { | |
388 | #ifdef HAVE_LIBTIFF | |
389 | TIFF *tif; | |
390 | unsigned char *ptr, *data; | |
391 | int x, y; | |
392 | int w; | |
393 | ||
394 | tif = TIFFOpen(file, "w"); | |
395 | if (tif) | |
396 | { | |
397 | TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, im->rgb_width); | |
398 | TIFFSetField(tif, TIFFTAG_IMAGELENGTH, im->rgb_height); | |
399 | TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); | |
400 | TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); | |
401 | TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); | |
402 | TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW); | |
403 | { | |
404 | TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3); | |
405 | TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); | |
406 | w = TIFFScanlineSize(tif); | |
407 | TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, | |
408 | TIFFDefaultStripSize(tif, -1)); | |
409 | for (y = 0; y < im->rgb_height; y++) | |
410 | { | |
411 | data = im->rgb_data + (y * im->rgb_width * 3); | |
412 | TIFFWriteScanline(tif, data, y, 0); | |
413 | } | |
414 | } | |
415 | TIFFClose(tif); | |
416 | return 1; | |
417 | } | |
418 | #endif | |
419 | } | |
420 | if (id->fallback) | |
421 | { | |
422 | f = open_helper("%C/convert pnm:- %s", file, "wb"); | |
423 | if (f) | |
424 | { | |
425 | if (!fprintf(f, "P6\n# Created by Imlib\n%i %i\n255\n", im->rgb_width, im->rgb_height)) | |
426 | { | |
427 | close_helper(f); | |
428 | return 0; | |
429 | } | |
430 | if (!fwrite(im->rgb_data, 1, (im->rgb_width * im->rgb_height * 3), f)) | |
431 | { | |
432 | close_helper(f); | |
433 | return 0; | |
434 | } | |
435 | if (close_helper(f)) | |
436 | return 0; | |
437 | return 1; | |
438 | } | |
439 | ||
440 | if (!strcasecmp(ext, "jpeg")) | |
441 | g_snprintf(cmd, sizeof(cmd), "%%H -quality %i -progressive -outfile %%s", 100 * info->quality / 256); | |
442 | else if (!strcasecmp(ext, "jpg")) | |
443 | g_snprintf(cmd, sizeof(cmd), "%%H -quality %i -progressive -outfile %%s", 100 * info->quality / 256); | |
444 | else if (!strcasecmp(ext, "bmp")) | |
445 | strcpy(cmd, "%Q %N/ppmtobmp >%s"); | |
446 | else if (!strcasecmp(ext, "gif")) | |
447 | strcpy(cmd, "%Q %N/ppmtogif -interlace >%s"); | |
448 | else if (!strcasecmp(ext, "ilbm")) | |
449 | strcpy(cmd, "%N/ppmtoilbm -24if -hires -lace -compress >%s"); | |
450 | else if (!strcasecmp(ext, "ilb")) | |
451 | strcpy(cmd, "%N/ppmtoilbm -24if -hires -lace -compress >%s"); | |
452 | else if (!strcasecmp(ext, "iff")) | |
453 | strcpy(cmd, "%N/ppmtoilbm -24if -hires -lace -compress >%s"); | |
454 | else if (!strcasecmp(ext, "icr")) | |
455 | strcpy(cmd, "%N/ppmtoicr >%s"); | |
456 | else if (!strcasecmp(ext, "map")) | |
457 | strcpy(cmd, "%N/ppmtomap >%s"); | |
458 | else if (!strcasecmp(ext, "mit")) | |
459 | strcpy(cmd, "%N/ppmtomitsu -sharpness 4 >%s"); | |
460 | else if (!strcasecmp(ext, "mitsu")) | |
461 | strcpy(cmd, "%N/ppmtomitsu -sharpness 4 >%s"); | |
462 | else if (!strcasecmp(ext, "pcx")) | |
463 | strcpy(cmd, "%N/ppmtopcx -24bit -packed >%s"); | |
464 | else if (!strcasecmp(ext, "pgm")) | |
465 | strcpy(cmd, "%N/ppmtopgm >%s"); | |
466 | else if (!strcasecmp(ext, "pi1")) | |
467 | strcpy(cmd, "%N/ppmtopi1 >%s"); | |
468 | else if (!strcasecmp(ext, "pic")) | |
469 | strcpy(cmd, "%Q %N/ppmtopict >%s"); | |
470 | else if (!strcasecmp(ext, "pict")) | |
471 | strcpy(cmd, "%Q %N/ppmtopict >%s"); | |
472 | else if (!strcasecmp(ext, "pj")) | |
473 | strcpy(cmd, "%N/ppmtopj >%s"); | |
474 | else if (!strcasecmp(ext, "pjxl")) | |
475 | strcpy(cmd, "%N/ppmtopjxl >%s"); | |
476 | else if (!strcasecmp(ext, "puz")) | |
477 | strcpy(cmd, "%N/ppmtopuzz >%s"); | |
478 | else if (!strcasecmp(ext, "puzz")) | |
479 | strcpy(cmd, "%N/ppmtopuzz >%s"); | |
480 | else if (!strcasecmp(ext, "rgb3")) | |
481 | strcpy(cmd, "%N/ppmtorgb3 >%s"); | |
482 | else if (!strcasecmp(ext, "six")) | |
483 | strcpy(cmd, "%N/ppmtosixel >%s"); | |
484 | else if (!strcasecmp(ext, "sixel")) | |
485 | strcpy(cmd, "%N/ppmtosizel >%s"); | |
486 | else if (!strcasecmp(ext, "tga")) | |
487 | strcpy(cmd, "%N/ppmtotga -rgb >%s"); | |
488 | else if (!strcasecmp(ext, "targa")) | |
489 | strcpy(cmd, "%N/ppmtotga -rgb >%s"); | |
490 | else if (!strcasecmp(ext, "uil")) | |
491 | strcpy(cmd, "%N/ppmtouil >%s"); | |
492 | else if (!strcasecmp(ext, "xpm")) | |
493 | strcpy(cmd, "%Q %N/ppmtoxpm >%s"); | |
494 | else if (!strcasecmp(ext, "yuv")) | |
495 | strcpy(cmd, "%N/ppmtoyuv >%s"); | |
496 | else if (!strcasecmp(ext, "png")) | |
497 | strcpy(cmd, "%N/pnmtopng >%s"); | |
498 | else if (!strcasecmp(ext, "ps")) | |
499 | strcpy(cmd, "%N/pnmtops -center -scale 100 >%s"); | |
500 | else if (!strcasecmp(ext, "rast")) | |
501 | strcpy(cmd, "%N/pnmtorast -rle >%s"); | |
502 | else if (!strcasecmp(ext, "ras")) | |
503 | strcpy(cmd, "%N/pnmtorast -rle >%s"); | |
504 | else if (!strcasecmp(ext, "sgi")) | |
505 | strcpy(cmd, "%N/pnmtosgi >%s"); | |
506 | else if (!strcasecmp(ext, "sir")) | |
507 | strcpy(cmd, "%N/pnmtosir >%s"); | |
508 | else if (!strcasecmp(ext, "tif")) | |
509 | strcpy(cmd, "%N/pnmtotiff -lzw >%s"); | |
510 | else if (!strcasecmp(ext, "tiff")) | |
511 | strcpy(cmd, "%N/pnmtotiff -lzw >%s"); | |
512 | else if (!strcasecmp(ext, "xwd")) | |
513 | strcpy(cmd, "%N/pnmtoxwd >%s"); | |
514 | else | |
515 | ext = ""; | |
516 | if (ext[0]) | |
517 | { | |
518 | f = open_helper(cmd, file, "wb"); | |
519 | if (f) | |
520 | { | |
521 | if (!fprintf(f, "P6\n# Created by Imlib\n%i %i\n255\n", im->rgb_width, im->rgb_height)) | |
522 | { | |
523 | close_helper(f); | |
524 | return 0; | |
525 | } | |
526 | if (!fwrite(im->rgb_data, 1, (im->rgb_width * im->rgb_height * 3), f)) | |
527 | { | |
528 | close_helper(f); | |
529 | return 0; | |
530 | } | |
531 | if (close_helper(f)) | |
532 | return 0; | |
533 | return 1; | |
534 | } | |
535 | } | |
536 | } | |
537 | return 0; | |
538 | } |