]> git.saurik.com Git - wxWidgets.git/blame - src/gdk_imlib/save.c
Various bug fixes, cosmetic changes
[wxWidgets.git] / src / gdk_imlib / save.c
CommitLineData
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
7gint
8gdk_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}