1
/* The GIMP -- an image manipulation program
2
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
3
* PostScript file plugin
4
* PostScript writing and GhostScript interfacing code
5
* Copyright (C) 1997-98 Peter Kirchgessner
6
* (email: peter@kirchgessner.net, WWW: http://www.kirchgessner.net)
8
* Added controls for TextAlphaBits and GraphicsAlphaBits
9
* George White <aa056@chebucto.ns.ca>
11
* Added Ascii85 encoding
12
* Austin Donnelly <austin@gimp.org>
14
* This program is free software; you can redistribute it and/or modify
15
* it under the terms of the GNU General Public License as published by
16
* the Free Software Foundation; either version 2 of the License, or
17
* (at your option) any later version.
19
* This program is distributed in the hope that it will be useful,
20
* but WITHOUT ANY WARRANTY; without even the implied warranty of
21
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
* GNU General Public License for more details.
24
* You should have received a copy of the GNU General Public License
25
* along with this program; if not, write to the Free Software
26
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31
* V 0.90, PK, 28-Mar-97: Creation.
32
* V 0.91, PK, 03-Apr-97: Clip everything outside BoundingBox.
33
* 24-Apr-97: Multi page read support.
34
* V 1.00, PK, 30-Apr-97: PDF support.
35
* V 1.01, PK, 05-Oct-97: Parse rc-file.
36
* V 1.02, GW, 09-Oct-97: Antialiasing support.
37
* PK, 11-Oct-97: No progress bars when running non-interactive.
38
* New procedure file_ps_load_setargs to set
39
* load-arguments non-interactively.
40
* If GS_OPTIONS are not set, use at least "-dSAFER"
41
* V 1.03, nn, 20-Dec-97: Initialize some variables
42
* V 1.04, PK, 20-Dec-97: Add Encapsulated PostScript output and preview
43
* V 1.05, PK, 21-Sep-98: Write b/w-images (indexed) using image-operator
44
* V 1.06, PK, 22-Dec-98: Fix problem with writing color PS files.
45
* Ghostview may hang when displaying the files.
46
* V 1.07, PK, 14-Sep-99: Add resolution to image
47
* V 1.08, PK, 16-Jan-2000: Add PostScript-Level 2 by Austin Donnelly
48
* V 1.09, PK, 15-Feb-2000: Force showpage on EPS-files
49
* Add "RunLength" compression
50
* Fix problem with "Level 2" toggle
51
* V 1.10, PK, 15-Mar-2000: For load EPSF, allow negative Bounding Box Values
52
* Save PS: dont start lines of image data with %%
53
* to prevent problems with stupid PostScript
54
* analyzer programs (Stanislav Brabec)
55
* Add BeginData/EndData comments
56
* Save PS: Set default rotation to 0
57
* V 1.11, PK, 20-Aug-2000: Fix problem with BoundingBox recognition
59
* Fix problem with loop when reading not all
60
* images of a multi page file.
61
* PK, 31-Aug-2000: Load PS: Add checks for space in filename.
62
* V 1.12 PK, 19-Jun-2001: Fix problem with command line switch --
63
* (reported by Ferenc Wagner)
64
* V 1.13 PK, 07-Apr-2002: Fix problem with DOS binary EPS files
65
* V 1.14 PK, 14-May-2002: Workaround EPS files of Adb. Ill. 8.0
66
* V 1.15 PK, 04-Oct-2002: Be more accurate with using BoundingBox
67
* V 1.16 PK, 22-Jan-2004: Don't use popen(), use g_spawn_async_with_pipes()
69
* V 1.17 PK, 19-Sep-2004: Fix problem with interpretation of bounding box
72
static char dversio[] = "v1.17 19-Sep-2004";
73
static char ident[] = "@(#) GIMP PostScript/PDF file-plugin v1.17 19-Sep-2004";
83
#include <sys/types.h>
89
#include <libgimp/gimp.h>
90
#include <libgimp/gimpui.h>
92
#include "libgimp/stdplugins-intl.h"
95
/* On Win32 we don't use pipes. Use a real output file for ghostscript */
96
#define USE_REAL_OUTPUTFILE
99
#ifdef USE_REAL_OUTPUTFILE
102
#include <process.h> /* For _getpid() */
105
#ifdef HAVE_SYS_WAIT_H
106
#include <sys/wait.h>
111
#define STR_LENGTH 64
114
#define DEFAULT_GS_PROG "gs"
116
/* We want the console ghostscript application. It should be in the PATH */
117
#define DEFAULT_GS_PROG "gswin32c"
124
guint resolution; /* resolution (dpi) at which to run ghostscript */
125
guint width, height; /* desired size (ghostscript may ignore this) */
126
gint use_bbox; /* 0: use width/height, 1: try to use BoundingBox */
127
gchar pages[STR_LENGTH]; /* Pages to load (eg.: 1,3,5-7) */
128
gint pnm_type; /* 4: pbm, 5: pgm, 6: ppm, 7: automatic */
129
gint textalpha; /* antialiasing: 1,2, or 4 TextAlphaBits */
130
gint graphicsalpha; /* antialiasing: 1,2, or 4 GraphicsAlphaBits */
133
static PSLoadVals plvals =
136
826, 1170, /* default width/height (A4) */
137
1, /* try to use BoundingBox */
138
"1", /* pages to load */
139
6, /* use ppm (colour) */
140
1, /* dont use text antialiasing */
141
1 /* dont use graphics antialiasing */
148
gdouble width, height; /* Size of image */
149
gdouble x_offset, y_offset; /* Offset to image on page */
150
gint unit_mm; /* Unit of measure (0: inch, 1: mm) */
151
gint keep_ratio; /* Keep aspect ratio */
152
gint rotate; /* Rotation (0, 90, 180, 270) */
153
gint level; /* PostScript Level */
154
gint eps; /* Encapsulated PostScript flag */
155
gint preview; /* Preview Flag */
156
gint preview_size; /* Preview size */
159
static PSSaveVals psvals =
161
287.0, 200.0, /* Image size (A4) */
162
5.0, 5.0, /* Offset */
164
1, /* Keep edge ratio */
166
2, /* PostScript Level */
167
0, /* Encapsulated PostScript flag */
168
0, /* Preview flag */
169
256 /* Preview size */
173
/* Declare some local functions.
175
static void query (void);
176
static void run (const gchar *name,
178
const GimpParam *param,
180
GimpParam **return_vals);
182
static gint32 load_image (const gchar *filename);
183
static gint save_image (const gchar *filename,
187
static gint save_gray (FILE *ofp,
190
static gint save_bw (FILE *ofp,
193
static gint save_index (FILE *ofp,
196
static gint save_rgb (FILE *ofp,
200
static gint32 create_new_image (const gchar *filename,
204
GimpImageBaseType type,
206
GimpDrawable **drawable,
207
GimpPixelRgn *pixel_rgn);
209
static void check_load_vals (void);
210
static void check_save_vals (void);
212
static gint page_in_list (gchar *list,
215
static gint get_bbox (const gchar *filename,
221
static FILE * ps_open (const gchar *filename,
222
const PSLoadVals *loadopt,
230
static void ps_close (FILE *ifp,
233
static gboolean skip_ps (FILE *ifp);
235
static gint32 load_ps (const gchar *filename,
243
static void save_ps_header (FILE *ofp,
244
const gchar *filename);
245
static void save_ps_setup (FILE *ofp,
250
static void save_ps_trailer (FILE *ofp);
251
static void save_ps_preview (FILE *ofp,
253
static void dither_grey (guchar *grey,
259
/* Dialog-handling */
261
static gboolean load_dialog (void);
262
static void load_pages_entry_callback (GtkWidget *widget,
267
GtkObject *adjustment[4];
271
static gboolean save_dialog (void);
272
static void save_unit_toggle_update (GtkWidget *widget,
275
GimpPlugInInfo PLUG_IN_INFO =
277
NULL, /* init_proc */
278
NULL, /* quit_proc */
279
query, /* query_proc */
285
static GimpRunMode l_run_mode;
287
static void compress_packbits (int nin,
293
static guint32 ascii85_buf;
294
static int ascii85_len = 0;
295
static int ascii85_linewidth = 0;
301
ascii85_linewidth = 0;
305
ascii85_flush (FILE *ofp)
309
gboolean zero_case = (ascii85_buf == 0);
310
static int max_linewidth = 75;
312
for (i=4; i >= 0; i--)
314
c[i] = (ascii85_buf % 85) + '!';
317
/* check for special case: "!!!!!" becomes "z", but only if not
319
if (zero_case && (ascii85_len == 4))
321
if (ascii85_linewidth >= max_linewidth)
324
ascii85_linewidth = 0;
331
for (i=0; i < ascii85_len+1; i++)
333
if ((ascii85_linewidth >= max_linewidth) && (c[i] != '%'))
336
ascii85_linewidth = 0;
348
ascii85_out (unsigned char byte, FILE *ofp)
350
if (ascii85_len == 4)
359
ascii85_nout (int n, unsigned char *uptr, FILE *ofp)
363
ascii85_out (*uptr, ofp);
369
ascii85_done (FILE *ofp)
373
/* zero any unfilled buffer portion, then flush */
374
ascii85_buf <<= (8 * (4-ascii85_len));
385
compress_packbits (int nin,
390
{register unsigned char c;
391
int nrepeat, nliteral;
392
unsigned char *run_start;
393
unsigned char *start_dst = dst;
394
unsigned char *last_literal = NULL;
403
/* Search repeat bytes */
404
if ((nin > 1) && (c == src[1]))
409
while ((nin > 0) && (c == *src))
414
if (nrepeat == 127) break; /* Maximum repeat */
417
/* Add two-byte repeat to last literal run ? */
419
&& (last_literal != NULL) && (((*last_literal)+1)+2 <= 128))
428
*(dst++) = (unsigned char)((-nrepeat) & 0xff);
433
/* Search literal bytes */
442
if ((nin >= 2) && (src[0] == src[1])) /* A two byte repeat ? */
448
if (nliteral == 128) break; /* Maximum literal run */
451
/* Could be added to last literal run ? */
452
if ((last_literal != NULL) && (((*last_literal)+1)+nliteral <= 128))
454
*last_literal += nliteral;
459
*(dst++) = (unsigned char)(nliteral-1);
461
while (nliteral-- > 0) *(dst++) = *(run_start++);
463
*nout = dst - start_dst;
473
static PS_DATA_POS ps_data_pos = { 0, 0 };
476
ps_begin_data (FILE *ofp)
479
/* %%BeginData: 123456789012 ASCII Bytes */
480
fprintf (ofp, "%s", "%%BeginData: ");
482
ps_data_pos.eol = ftell (ofp);
485
ps_data_pos.begin_data = ftell (ofp);
489
ps_end_data (FILE *ofp)
494
if ((ps_data_pos.begin_data > 0) && (ps_data_pos.eol > 0))
497
end_data = ftell (ofp);
500
sprintf (s, "%ld ASCII Bytes", end_data-ps_data_pos.begin_data);
501
if (fseek (ofp, ps_data_pos.eol - strlen (s), SEEK_SET) == 0)
503
fprintf (ofp, "%s", s);
504
fseek (ofp, 0, SEEK_END);
508
fprintf (ofp, "%s\n", "%%EndData");
517
static GimpParamDef load_args[] =
519
{ GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
520
{ GIMP_PDB_STRING, "filename", "The name of the file to load" },
521
{ GIMP_PDB_STRING, "raw_filename", "The name of the file to load" }
523
static GimpParamDef load_return_vals[] =
525
{ GIMP_PDB_IMAGE, "image", "Output image" }
528
static GimpParamDef set_load_args[] =
530
{ GIMP_PDB_INT32, "resolution", "Resolution to interprete image (dpi)" },
531
{ GIMP_PDB_INT32, "width", "Desired width" },
532
{ GIMP_PDB_INT32, "height", "Desired height" },
533
{ GIMP_PDB_INT32, "check_bbox", "0: Use width/height, 1: Use BoundingBox" },
534
{ GIMP_PDB_STRING, "pages", "Pages to load (e.g.: 1,3,5-7)" },
535
{ GIMP_PDB_INT32, "coloring", "4: b/w, 5: grey, 6: colour image, 7: automatic" },
536
{ GIMP_PDB_INT32, "TextAlphaBits", "1, 2, or 4" },
537
{ GIMP_PDB_INT32, "GraphicsAlphaBits", "1, 2, or 4" }
540
static GimpParamDef thumb_args[] =
542
{ GIMP_PDB_STRING, "filename", "The name of the file to load" },
543
{ GIMP_PDB_INT32, "thumb_size", "Preferred thumbnail size" }
545
static GimpParamDef thumb_return_vals[] =
547
{ GIMP_PDB_IMAGE, "image", "Output image" }
550
static GimpParamDef save_args[] =
552
{ GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
553
{ GIMP_PDB_IMAGE, "image", "Input image" },
554
{ GIMP_PDB_DRAWABLE, "drawable", "Drawable to save" },
555
{ GIMP_PDB_STRING, "filename", "The name of the file to save the image in" },
556
{ GIMP_PDB_STRING, "raw_filename",
557
"The name of the file to save the image in" },
558
{ GIMP_PDB_FLOAT, "width", "Width of the image in PostScript file (0: use input image size)" },
559
{ GIMP_PDB_FLOAT, "height", "Height of image in PostScript file (0: use input image size)" },
560
{ GIMP_PDB_FLOAT, "x_offset", "X-offset to image from lower left corner" },
561
{ GIMP_PDB_FLOAT, "y_offset", "Y-offset to image from lower left corner" },
562
{ GIMP_PDB_INT32, "unit", "Unit for width/height/offset. 0: inches, 1: millimeters" },
563
{ GIMP_PDB_INT32, "keep_ratio", "0: use width/height, 1: keep aspect ratio" },
564
{ GIMP_PDB_INT32, "rotation", "0, 90, 180, 270" },
565
{ GIMP_PDB_INT32, "eps_flag", "0: PostScript, 1: Encapsulated PostScript" },
566
{ GIMP_PDB_INT32, "preview", "0: no preview, >0: max. size of preview" },
567
{ GIMP_PDB_INT32, "level", "1: PostScript Level 1, 2: PostScript Level 2" }
570
gimp_install_procedure ("file_ps_load",
571
"load PostScript documents",
572
"load PostScript documents",
573
"Peter Kirchgessner <peter@kirchgessner.net>",
574
"Peter Kirchgessner",
576
N_("PostScript document"),
579
G_N_ELEMENTS (load_args),
580
G_N_ELEMENTS (load_return_vals),
581
load_args, load_return_vals);
583
gimp_register_file_handler_mime ("file_ps_load", "application/postscript");
584
gimp_register_magic_load_handler ("file_ps_load",
587
"0,string,%!,0,long,0xc5d0d3c6");
589
gimp_install_procedure ("file_eps_load",
590
"load Encapsulated PostScript images",
591
"load Encapsulated PostScript images",
592
"Peter Kirchgessner <peter@kirchgessner.net>",
593
"Peter Kirchgessner",
595
N_("Encapsulated PostScript image"),
598
G_N_ELEMENTS (load_args),
599
G_N_ELEMENTS (load_return_vals),
600
load_args, load_return_vals);
602
gimp_register_file_handler_mime ("file_eps_load", "image/x-eps");
603
gimp_register_magic_load_handler ("file_eps_load",
606
"0,string,%!,0,long,0xc5d0d3c6");
608
gimp_install_procedure ("file_pdf_load",
609
"load PDF documents",
610
"load PDF documents",
611
"Peter Kirchgessner <peter@kirchgessner.net>",
612
"Peter Kirchgessner",
617
G_N_ELEMENTS (load_args),
618
G_N_ELEMENTS (load_return_vals),
619
load_args, load_return_vals);
621
gimp_register_file_handler_mime ("file_pdf_load", "application/pdf");
622
gimp_register_magic_load_handler ("file_pdf_load",
627
gimp_install_procedure ("file_ps_load_setargs",
628
"set additional parameters for procedure file_ps_load",
629
"set additional parameters for procedure file_ps_load",
630
"Peter Kirchgessner <peter@kirchgessner.net>",
631
"Peter Kirchgessner",
636
G_N_ELEMENTS (set_load_args), 0,
637
set_load_args, NULL);
639
gimp_install_procedure ("file_ps_load_thumb",
640
"Loads a small preview from a Postscript or PDF document",
642
"Peter Kirchgessner <peter@kirchgessner.net>",
643
"Peter Kirchgessner",
648
G_N_ELEMENTS (thumb_args),
649
G_N_ELEMENTS (thumb_return_vals),
650
thumb_args, thumb_return_vals);
652
gimp_register_thumbnail_loader ("file_ps_load", "file_ps_load_thumb");
653
gimp_register_thumbnail_loader ("file_eps_load", "file_ps_load_thumb");
654
gimp_register_thumbnail_loader ("file_pdf_load", "file_ps_load_thumb");
656
gimp_install_procedure ("file_ps_save",
657
"save image as PostScript docuement",
658
"PostScript saving handles all image types except those with alpha channels.",
659
"Peter Kirchgessner <peter@kirchgessner.net>",
660
"Peter Kirchgessner",
662
N_("PostScript document"),
663
"RGB, GRAY, INDEXED",
665
G_N_ELEMENTS (save_args), 0,
668
gimp_register_file_handler_mime ("file_ps_save", "application/postscript");
669
gimp_register_save_handler ("file_ps_save", "ps", "");
671
gimp_install_procedure ("file_eps_save",
672
"save image as Encapsulated PostScript image",
673
"PostScript saving handles all image types except those with alpha channels.",
674
"Peter Kirchgessner <peter@kirchgessner.net>",
675
"Peter Kirchgessner",
677
N_("Encapsulated PostScript image"),
678
"RGB, GRAY, INDEXED",
680
G_N_ELEMENTS (save_args), 0,
683
gimp_register_file_handler_mime ("file_eps_save", "application/x-eps");
684
gimp_register_save_handler ("file_eps_save", "eps", "");
688
ps_set_save_size (PSSaveVals *vals,
691
gdouble xres, yres, factor, iw, ih;
695
gimp_image_get_resolution (image_ID, &xres, &yres);
696
if ((xres < 1e-5) || (yres < 1e-5))
700
/* Calculate size of image in inches */
701
width = gimp_image_width (image_ID);
702
height = gimp_image_height (image_ID);
706
unit = gimp_image_get_unit (image_ID);
707
factor = gimp_unit_get_factor (unit);
708
if (factor == 0.0254 ||
713
vals->unit_mm = TRUE;
726
run (const gchar *name,
728
const GimpParam *param,
730
GimpParam **return_vals)
732
static GimpParam values[2];
733
GimpRunMode run_mode;
734
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
735
gint32 image_ID = -1;
736
gint32 drawable_ID = -1;
737
gint32 orig_image_ID = -1;
738
GimpExportReturn export = GIMP_EXPORT_CANCEL;
740
l_run_mode = run_mode = param[0].data.d_int32;
745
*return_vals = values;
747
values[0].type = GIMP_PDB_STATUS;
748
values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
750
if (strcmp (name, "file_ps_load") == 0 ||
751
strcmp (name, "file_eps_load") == 0 ||
752
strcmp (name, "file_pdf_load") == 0)
756
case GIMP_RUN_INTERACTIVE:
757
/* Possibly retrieve data */
758
gimp_get_data ("file_ps_load", &plvals);
760
if (! load_dialog ())
761
status = GIMP_PDB_CANCEL;
764
case GIMP_RUN_NONINTERACTIVE:
765
/* Make sure all the arguments are there! */
767
status = GIMP_PDB_CALLING_ERROR;
768
else /* Get additional interpretation arguments */
769
gimp_get_data ("file_ps_load", &plvals);
772
case GIMP_RUN_WITH_LAST_VALS:
773
/* Possibly retrieve data */
774
gimp_get_data ("file_ps_load", &plvals);
781
if (status == GIMP_PDB_SUCCESS)
784
image_ID = load_image (param[1].data.d_string);
789
values[1].type = GIMP_PDB_IMAGE;
790
values[1].data.d_image = image_ID;
794
status = GIMP_PDB_EXECUTION_ERROR;
798
/* Store plvals data */
799
if (status == GIMP_PDB_SUCCESS)
800
gimp_set_data ("file_ps_load", &plvals, sizeof (PSLoadVals));
802
else if (strcmp (name, "file_ps_load_thumb") == 0)
806
status = GIMP_PDB_CALLING_ERROR;
810
gint size = param[1].data.d_int32;
812
/* We should look for an embedded preview but for now we
813
* just load the document at a small resolution and the
817
plvals.resolution = size / 4;
819
plvals.height = size;
820
strcpy (plvals.pages, "1");
823
image_ID = load_image (param[0].data.d_string);
828
values[1].type = GIMP_PDB_IMAGE;
829
values[1].data.d_image = image_ID;
833
status = GIMP_PDB_EXECUTION_ERROR;
837
else if (strcmp (name, "file_ps_save") == 0 ||
838
strcmp (name, "file_eps_save") == 0)
840
psvals.eps = strcmp (name, "file_ps_save");
842
image_ID = orig_image_ID = param[1].data.d_int32;
843
drawable_ID = param[2].data.d_int32;
845
/* eventually export the image */
848
case GIMP_RUN_INTERACTIVE:
849
case GIMP_RUN_WITH_LAST_VALS:
850
gimp_ui_init ("ps", FALSE);
851
export = gimp_export_image (&image_ID, &drawable_ID,
852
psvals.eps ? "EPS" : "PostScript",
853
(GIMP_EXPORT_CAN_HANDLE_RGB |
854
GIMP_EXPORT_CAN_HANDLE_GRAY |
855
GIMP_EXPORT_CAN_HANDLE_INDEXED));
856
if (export == GIMP_EXPORT_CANCEL)
858
values[0].data.d_status = GIMP_PDB_CANCEL;
868
case GIMP_RUN_INTERACTIVE:
869
/* Possibly retrieve data */
870
gimp_get_data (name, &psvals);
872
ps_set_save_size (&psvals, orig_image_ID);
874
/* First acquire information with a dialog */
875
if (! save_dialog ())
876
status = GIMP_PDB_CANCEL;
879
case GIMP_RUN_NONINTERACTIVE:
880
/* Make sure all the arguments are there! */
883
status = GIMP_PDB_CALLING_ERROR;
887
psvals.width = param[5].data.d_float;
888
psvals.height = param[6].data.d_float;
889
psvals.x_offset = param[7].data.d_float;
890
psvals.y_offset = param[8].data.d_float;
891
psvals.unit_mm = (param[9].data.d_int32 != 0);
892
psvals.keep_ratio = (param[10].data.d_int32 != 0);
893
psvals.rotate = param[11].data.d_int32;
894
psvals.eps = param[12].data.d_int32;
895
psvals.preview = (param[13].data.d_int32 != 0);
896
psvals.preview_size = param[13].data.d_int32;
897
psvals.level = param[14].data.d_int32;
901
case GIMP_RUN_WITH_LAST_VALS:
902
/* Possibly retrieve data */
903
gimp_get_data (name, &psvals);
910
if (status == GIMP_PDB_SUCCESS)
912
if ((psvals.width == 0.0) || (psvals.height == 0.0))
913
ps_set_save_size (&psvals, orig_image_ID);
916
if (save_image (param[3].data.d_string, image_ID, drawable_ID))
918
/* Store psvals data */
919
gimp_set_data (name, &psvals, sizeof (PSSaveVals));
923
status = GIMP_PDB_EXECUTION_ERROR;
927
if (export == GIMP_EXPORT_EXPORT)
928
gimp_image_delete (image_ID);
930
else if (strcmp (name, "file_ps_load_setargs") == 0)
932
/* Make sure all the arguments are there! */
935
status = GIMP_PDB_CALLING_ERROR;
939
plvals.resolution = param[0].data.d_int32;
940
plvals.width = param[1].data.d_int32;
941
plvals.height = param[2].data.d_int32;
942
plvals.use_bbox = param[3].data.d_int32;
943
if (param[4].data.d_string != NULL)
944
strncpy (plvals.pages, param[4].data.d_string,
945
sizeof (plvals.pages));
947
plvals.pages[0] = '\0';
948
plvals.pages[sizeof (plvals.pages) - 1] = '\0';
949
plvals.pnm_type = param[5].data.d_int32;
950
plvals.textalpha = param[6].data.d_int32;
951
plvals.graphicsalpha = param[7].data.d_int32;
953
gimp_set_data ("file_ps_load", &plvals, sizeof (PSLoadVals));
958
status = GIMP_PDB_CALLING_ERROR;
961
values[0].data.d_status = status;
966
load_image (const gchar *filename)
968
gint32 image_ID, *image_list, *nl;
973
int llx, lly, urx, ury;
974
int k, n_images, max_images, max_pagenum;
978
g_print ("load_image:\n resolution = %d\n", plvals.resolution);
979
g_print (" %dx%d pixels\n", plvals.width, plvals.height);
980
g_print (" BoundingBox: %d\n", plvals.use_bbox);
981
g_print (" Colouring: %d\n", plvals.pnm_type);
982
g_print (" TextAlphaBits: %d\n", plvals.textalpha);
983
g_print (" GraphicsAlphaBits: %d\n", plvals.graphicsalpha);
986
/* Try to see if PostScript file is available */
987
ifp = fopen (filename, "r");
990
g_message (_("Could not open '%s' for reading: %s"),
991
gimp_filename_to_utf8 (filename), g_strerror (errno));
996
temp = g_strdup_printf (_("Opening '%s'..."),
997
gimp_filename_to_utf8 (filename));
998
gimp_progress_init (temp);
1001
ifp = ps_open (filename, &plvals, &llx, &lly, &urx, &ury, &is_epsf,
1005
g_message (_("Could not interpret '%s'"),
1006
gimp_filename_to_utf8 (filename));
1010
image_list = g_new (gint32, 10);
1014
max_pagenum = 9999; /* Try to get the maximum pagenumber to read */
1018
if (!page_in_list (plvals.pages, max_pagenum)) /* Is there a limit in list ? */
1021
for (temp = plvals.pages; *temp != '\0'; temp++)
1023
if ((*temp < '0') || (*temp > '9'))
1024
continue; /* Search next digit */
1025
sscanf (temp, "%d", &k);
1026
if (k > max_pagenum)
1028
while ((*temp >= '0') && (*temp <= '9'))
1033
if (max_pagenum < 1)
1037
/* Load all images */
1038
for (page_count = 1; page_count <= max_pagenum; page_count++)
1040
if (page_in_list (plvals.pages, page_count))
1042
image_ID = load_ps (filename, page_count, ifp, llx, lly, urx, ury);
1046
gimp_image_set_resolution (image_ID,
1047
(double) plvals.resolution,
1048
(double) plvals.resolution);
1050
if (n_images == max_images)
1052
nl = (gint32 *) g_realloc (image_list,
1053
(max_images+10)*sizeof (gint32));
1054
if (nl == NULL) break;
1058
image_list[n_images++] = image_ID;
1060
else /* Skip an image */
1063
if (! skip_ps (ifp))
1068
ps_close (ifp, ChildPid);
1070
/* Display images in reverse order. The last will be displayed by GIMP itself*/
1071
if (l_run_mode != GIMP_RUN_NONINTERACTIVE)
1073
for (k = n_images-1; k >= 1; k--)
1074
gimp_display_new (image_list[k]);
1077
image_ID = (n_images > 0) ? image_list[0] : -1;
1078
g_free (image_list);
1085
save_image (const gchar *filename,
1090
GimpImageType drawable_type;
1092
char *temp = ident; /* Just to satisfy lint/gcc */
1098
drawable_type = gimp_drawable_type (drawable_ID);
1100
/* Make sure we're not saving an image with an alpha channel */
1101
if (gimp_drawable_has_alpha (drawable_ID))
1103
g_message (_("PostScript save cannot handle images with alpha channels"));
1107
switch (drawable_type)
1109
case GIMP_INDEXED_IMAGE:
1110
case GIMP_GRAY_IMAGE:
1111
case GIMP_RGB_IMAGE:
1114
g_message (_("Cannot operate on unknown image types."));
1119
/* Open the output file. */
1120
ofp = fopen (filename, "wb");
1123
g_message (_("Could not open '%s' for writing: %s"),
1124
gimp_filename_to_utf8 (filename), g_strerror (errno));
1128
temp = g_strdup_printf (_("Saving '%s'..."),
1129
gimp_filename_to_utf8 (filename));
1130
gimp_progress_init (temp);
1133
save_ps_header (ofp, filename);
1135
if (drawable_type == GIMP_GRAY_IMAGE)
1136
retval = save_gray (ofp, image_ID, drawable_ID);
1137
else if (drawable_type == GIMP_INDEXED_IMAGE)
1138
retval = save_index (ofp, image_ID, drawable_ID);
1139
else if (drawable_type == GIMP_RGB_IMAGE)
1140
retval = save_rgb (ofp, image_ID, drawable_ID);
1142
save_ps_trailer (ofp);
1150
/* Check (and correct) the load values plvals */
1152
check_load_vals (void)
1154
if (plvals.resolution < 5)
1155
plvals.resolution = 5;
1156
else if (plvals.resolution > 1440)
1157
plvals.resolution = 1440;
1159
if (plvals.width < 2)
1161
if (plvals.height < 2)
1163
plvals.use_bbox = (plvals.use_bbox != 0);
1164
if (plvals.pages[0] == '\0')
1165
strcpy (plvals.pages, "1-99");
1166
if ((plvals.pnm_type < 4) || (plvals.pnm_type > 7))
1167
plvals.pnm_type = 6;
1168
if ( (plvals.textalpha != 1) && (plvals.textalpha != 2)
1169
&& (plvals.textalpha != 4))
1170
plvals.textalpha = 1;
1171
if ( (plvals.graphicsalpha != 1) && (plvals.graphicsalpha != 2)
1172
&& (plvals.graphicsalpha != 4))
1173
plvals.graphicsalpha = 1;
1177
/* Check (and correct) the save values psvals */
1179
check_save_vals (void)
1184
if ((i != 0) && (i != 90) && (i != 180) && (i != 270))
1186
if (psvals.preview_size <= 0)
1187
psvals.preview = FALSE;
1191
/* Check if a page is in a given list */
1193
page_in_list (gchar *list,
1196
char tmplist[STR_LENGTH], *c0, *c1;
1197
int state, start_num, end_num;
1198
#define READ_STARTNUM 0
1199
#define READ_ENDNUM 1
1200
#define CHK_LIST(a,b,c) {int low=(a),high=(b),swp; \
1201
if ((low>0) && (high>0)) { \
1202
if (low>high) {swp=low; low=high; high=swp;} \
1203
if ((low<=(c))&&(high>=(c))) return (1); } }
1205
if ((list == NULL) || (*list == '\0'))
1208
strncpy (tmplist, list, STR_LENGTH);
1209
tmplist[STR_LENGTH-1] = '\0';
1212
while (*c1) /* Remove all whitespace and break on unsupported characters */
1214
if ((*c1 >= '0') && (*c1 <= '9'))
1218
else if ((*c1 == '-') || (*c1 == ','))
1219
{ /* Try to remove double occurances of these characters */
1241
/* Now we have a comma separated list like 1-4-1,-3,1- */
1243
start_num = end_num = -1;
1244
state = READ_STARTNUM;
1245
for (c0 = tmplist; *c0 != '\0'; c0++)
1252
if ((start_num > 0) && (start_num == (int)page_num))
1256
else if (*c0 == '-')
1258
if (start_num < 0) start_num = 1;
1259
state = READ_ENDNUM;
1261
else /* '0' - '9' */
1263
if (start_num < 0) start_num = 0;
1265
start_num += *c0 - '0';
1272
if (end_num < 0) end_num = 9999;
1273
CHK_LIST (start_num, end_num, (int)page_num);
1274
start_num = end_num = -1;
1275
state = READ_STARTNUM;
1277
else if (*c0 == '-')
1279
CHK_LIST (start_num, end_num, (int)page_num);
1280
start_num = end_num;
1283
else /* '0' - '9' */
1285
if (end_num < 0) end_num = 0;
1287
end_num += *c0 - '0';
1292
if (state == READ_STARTNUM)
1295
return (start_num == (int) page_num);
1299
if (end_num < 0) end_num = 9999;
1300
CHK_LIST (start_num, end_num, (int)page_num);
1308
/* A function like fgets, but treats single CR-character as line break. */
1309
/* As a line break the newline-character is returned. */
1310
static char *psfgets (char *s, int size, FILE *stream)
1331
/* At this point we have space in sptr for at least two characters */
1332
if (c == '\n') /* Got end of line (UNIX line end) ? */
1337
else if (c == '\r') /* Got a carriage return. Check next charcater */
1340
if ((c == EOF) || (c == '\n')) /* EOF or DOS line end ? */
1342
*(sptr++) = '\n'; /* Return UNIX line end */
1345
else /* Single carriage return. Return UNIX line end. */
1347
ungetc (c, stream); /* Save the extra character */
1352
else /* no line end character */
1354
*(sptr++) = (char)c;
1358
break; /* Only space for the nul-character ? */
1371
/* Get the BoundingBox of a PostScript file. On success, 0 is returned. */
1372
/* On failure, -1 is returned. */
1374
get_bbox (const gchar *filename,
1380
char line[1024], *src;
1384
ifp = fopen (filename, "rb");
1390
if (psfgets (line, sizeof (line)-1, ifp) == NULL) break;
1391
if ((line[0] != '%') || (line[1] != '%')) continue;
1393
while ((*src == ' ') || (*src == '\t')) src++;
1394
if (strncmp (src, "BoundingBox", 11) != 0) continue;
1396
while ((*src == ' ') || (*src == '\t') || (*src == ':')) src++;
1397
if (strncmp (src, "(atend)", 7) == 0) continue;
1398
if (sscanf (src, "%d%d%d%d", x0, y0, x1, y1) == 4)
1407
static gchar *pnmfile;
1409
/* Open the PostScript file. On failure, NULL is returned. */
1410
/* The filepointer returned will give a PNM-file generated */
1411
/* by the PostScript-interpreter. */
1413
ps_open (const gchar *filename,
1414
const PSLoadVals *loadopt,
1425
FILE *fd_popen = NULL;
1427
int width, height, resolution;
1429
int offx = 0, offy = 0;
1430
int is_pdf, maybe_epsf = 0;
1431
GError *Gerr = NULL;
1433
#ifndef USE_REAL_OUTPUTFILE
1438
resolution = loadopt->resolution;
1440
width = loadopt->width;
1441
height = loadopt->height;
1445
/* Check if the file is a PDF. For PDF, we cant set geometry */
1448
/* Check if it is a EPS-file */
1451
eps_file = fopen (filename, "rb");
1453
if (eps_file != NULL)
1457
fread (hdr, 1, sizeof(hdr), eps_file);
1458
is_pdf = (strncmp (hdr, "%PDF", 4) == 0);
1460
if (!is_pdf) /* Check for EPSF */
1464
static unsigned char doseps[5] = { 0xc5, 0xd0, 0xd3, 0xc6, 0 };
1466
hdr[sizeof(hdr)-1] = '\0';
1467
adobe = strstr (hdr, "PS-Adobe-");
1468
epsf = strstr (hdr, "EPSF-");
1470
if ((adobe != NULL) && (epsf != NULL))
1473
*is_epsf = ((ds >= 11) && (ds <= 15));
1475
/* Illustrator uses negative values in BoundingBox without marking */
1476
/* files as EPSF. Try to handle that. */
1478
(strstr (hdr, "%%Creator: Adobe Illustrator(R) 8.0") != 0);
1480
/* Check DOS EPS binary file */
1481
if ((!*is_epsf) && (strncmp (hdr, (char *)doseps, 4) == 0))
1488
if ((!is_pdf) && (loadopt->use_bbox)) /* Try the BoundingBox ? */
1490
if (get_bbox (filename, &x0, &y0, &x1, &y1) == 0)
1492
if (maybe_epsf && ((x0 < 0) || (y0 < 0)))
1495
if (*is_epsf) /* Handle negative BoundingBox for EPSF */
1497
offx = -x0; x1 += offx; x0 += offx;
1498
offy = -y0; y1 += offy; y0 += offy;
1500
if ((x0 >= 0) && (y0 >= 0) && (x1 > x0) && (y1 > y0))
1502
*llx = (int)((x0/72.0) * resolution + 0.0001);
1503
*lly = (int)((y0/72.0) * resolution + 0.0001);
1504
/* Use upper bbox values as image size */
1505
width = (int)((x1/72.0) * resolution + 0.5);
1506
height = (int)((y1/72.0) * resolution + 0.5);
1507
/* Pixel coordinates must be one less */
1510
if (*urx < *llx) *urx = *llx;
1511
if (*ury < *lly) *ury = *lly;
1516
if (loadopt->pnm_type == 4)
1518
else if (loadopt->pnm_type == 5)
1520
else if (loadopt->pnm_type == 7)
1525
#ifdef USE_REAL_OUTPUTFILE
1526
/* For instance, the Win32 port of ghostscript doesn't work correctly when
1527
* using standard output as output file.
1528
* Thus, use a real output file.
1530
pnmfile = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "p%lx",
1531
g_get_tmp_dir (), (gulong) getpid ());
1536
gs = getenv ("GS_PROG");
1538
gs = DEFAULT_GS_PROG;
1540
/* Build command array */
1541
cmdA = g_ptr_array_new ();
1543
g_ptr_array_add (cmdA, g_strdup (gs));
1544
g_ptr_array_add (cmdA, g_strdup_printf ("-sDEVICE=%s", driver));
1545
g_ptr_array_add (cmdA, g_strdup_printf ("-r%d", resolution));
1549
/* Acrobat Reader honors CropBox over MediaBox, so let's match that
1552
g_ptr_array_add (cmdA, g_strdup ("-dUseCropBox"));
1556
/* For PDF, we can't set geometry */
1557
g_ptr_array_add (cmdA, g_strdup_printf ("-g%dx%d", width, height));
1560
/* Antialiasing not available for PBM-device */
1561
if ((loadopt->pnm_type != 4) && (loadopt->textalpha != 1))
1562
g_ptr_array_add (cmdA, g_strdup_printf ("-dTextAlphaBits=%d",
1563
loadopt->textalpha));
1564
if ((loadopt->pnm_type != 4) && (loadopt->graphicsalpha != 1))
1565
g_ptr_array_add (cmdA, g_strdup_printf ("-dGraphicsAlphaBits=%d",
1566
loadopt->graphicsalpha));
1567
g_ptr_array_add (cmdA, g_strdup ("-q"));
1568
g_ptr_array_add (cmdA, g_strdup ("-dBATCH"));
1569
g_ptr_array_add (cmdA, g_strdup ("-dNOPAUSE"));
1571
/* If no additional options specified, use at least -dSAFER */
1572
if (getenv ("GS_OPTIONS") == NULL)
1573
g_ptr_array_add (cmdA, g_strdup ("-dSAFER"));
1575
/* Output file name */
1576
g_ptr_array_add (cmdA, g_strdup_printf ("-sOutputFile=%s", pnmfile));
1578
/* Offset command for gs to get image part with negative x/y-coord. */
1579
if ((offx != 0) || (offy != 0))
1581
g_ptr_array_add (cmdA, g_strdup ("-c"));
1582
g_ptr_array_add (cmdA, g_strdup_printf ("%d", offx));
1583
g_ptr_array_add (cmdA, g_strdup_printf ("%d", offy));
1584
g_ptr_array_add (cmdA, g_strdup ("translate"));
1587
/* input file name */
1588
g_ptr_array_add (cmdA, g_strdup ("-f"));
1589
g_ptr_array_add (cmdA, g_strdup (filename));
1593
g_ptr_array_add (cmdA, g_strdup ("-c"));
1594
g_ptr_array_add (cmdA, g_strdup ("showpage"));
1597
g_ptr_array_add (cmdA, g_strdup ("-c"));
1598
g_ptr_array_add (cmdA, g_strdup ("quit"));
1599
g_ptr_array_add (cmdA, NULL);
1601
pcmdA = (gchar **) cmdA->pdata;
1606
g_print ("Starting command:\n");
1610
g_print ("%s\n", *p);
1616
/* Start the command */
1617
#ifndef USE_REAL_OUTPUTFILE
1618
Gflags = G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD;
1620
if ( !g_spawn_async_with_pipes (NULL, /* working dir */
1621
pcmdA, /* command array */
1622
NULL, /* environment */
1624
NULL, NULL, /* Child setup and userdata */
1631
g_message (_("Error starting ghostscript (%s)"), Gerr->message);
1632
g_error_free (Gerr);
1640
g_print ("Ghostscript started with pid=%d\n", *ChildPidPtr);
1643
/* Get a file pointer from the descriptor */
1644
fd_popen = fdopen (ChildStdout, "rb");
1648
/* Use a real outputfile. Wait until ghostscript has finished */
1649
Gflags = G_SPAWN_SEARCH_PATH;
1651
if ( !g_spawn_sync (NULL, /* working dir */
1652
pcmdA, /* command array */
1653
NULL, /* environment */
1655
NULL, NULL, /* Child setup and userdata */
1658
NULL, /* exit code */
1661
g_message (_("Error starting ghostscript: %s"), Gerr->message);
1662
g_error_free (Gerr);
1669
/* Don't care about exit status of ghostscript. */
1670
/* Just try to read what it wrote. */
1672
fd_popen = fopen (pnmfile, "rb");
1677
g_ptr_array_free (cmdA, FALSE);
1684
/* Close the PNM-File of the PostScript interpreter */
1686
ps_close (FILE *ifp, gint ChildPid)
1689
#ifndef USE_REAL_OUTPUTFILE
1693
/* Enabling the code below causes us to read the pipe until EOF even
1694
* if we dont want all images. Should be enabled if people report that
1695
* the gs subprocess does not finish. For now it is disabled since it
1696
* causes a significant slowdown.
1702
g_print ("Reading rest from pipe\n");
1705
while (fread (buf, sizeof (buf), 1, ifp));
1706
#endif /* EMPTY_PIPE */
1708
/* Finish reading from pipe. */
1711
/* Wait for the child to exit */
1715
g_print ("Waiting for %d to finish\n", (int)ChildPid);
1718
RetVal = waitpid (ChildPid, &status, 0);
1722
g_print ("waitpid() failed\n");
1724
g_print ("child has finished\n");
1728
#else /* USE_REAL_OUTPUTFILE */
1729
/* If a real outputfile was used, close the file and remove it. */
1736
/* Read the header of a raw PNM-file and return type (4-6) or -1 on failure */
1738
read_pnmraw_type (FILE *ifp,
1743
register int frst, scnd, thrd;
1747
/* GhostScript may write some informational messages infront of the header. */
1748
/* We are just looking at a Px\n in the input stream. */
1754
if (thrd == EOF) return -1;
1756
if (thrd == '\r') thrd = getc (ifp);
1758
if ((thrd == '\n') && (frst == 'P') && (scnd >= '1') && (scnd <= '6'))
1764
pnmtype = scnd - '0';
1765
/* We dont use the ASCII-versions */
1766
if ((pnmtype >= 1) && (pnmtype <= 3))
1769
/* Read width/height */
1772
if (fgets (line, sizeof (line)-1, ifp) == NULL)
1777
if (sscanf (line, "%d%d", width, height) != 2)
1782
if (pnmtype != 4) /* Read maxval */
1786
if (fgets (line, sizeof (line)-1, ifp) == NULL)
1791
if (sscanf (line, "%d", maxval) != 1)
1799
/* Create an image. Sets layer_ID, drawable and rgn. Returns image_ID */
1801
create_new_image (const gchar *filename,
1805
GimpImageBaseType type,
1807
GimpDrawable **drawable,
1808
GimpPixelRgn *pixel_rgn)
1811
GimpImageType gdtype;
1813
if (type == GIMP_GRAY) gdtype = GIMP_GRAY_IMAGE;
1814
else if (type == GIMP_INDEXED) gdtype = GIMP_INDEXED_IMAGE;
1815
else gdtype = GIMP_RGB_IMAGE;
1817
image_ID = gimp_image_new (width, height, type);
1823
tmp = g_strdup_printf ("%s-pg%ld", filename, (long)pagenum);
1824
gimp_image_set_filename (image_ID, tmp);
1829
gimp_image_set_filename (image_ID, filename);
1832
*layer_ID = gimp_layer_new (image_ID, "Background", width, height,
1833
gdtype, 100, GIMP_NORMAL_MODE);
1834
gimp_image_add_layer (image_ID, *layer_ID, 0);
1836
*drawable = gimp_drawable_get (*layer_ID);
1837
gimp_pixel_rgn_init (pixel_rgn, *drawable, 0, 0, (*drawable)->width,
1838
(*drawable)->height, TRUE, FALSE);
1844
/* Skip PNM image generated from PostScript file. */
1845
/* Return TRUE on success, FALSE otherwise. */
1851
gint pnmtype, width, height, maxval, bpl;
1853
pnmtype = read_pnmraw_type (ifp, &width, &height, &maxval);
1855
if (pnmtype == 4) /* Portable bitmap */
1856
bpl = (width + 7) / 8;
1857
else if (pnmtype == 5)
1859
else if (pnmtype == 6)
1867
gsize bytes = fread (buf, 1, MIN (len, sizeof (buf)), ifp);
1869
if (bytes < MIN (len, sizeof (buf)))
1879
/* Load PNM image generated from PostScript file */
1881
load_ps (const gchar *filename,
1889
register guchar *dest;
1890
guchar *data, *bitline = NULL, *byteline = NULL, *byteptr, *temp;
1891
guchar bit2byte[256*8];
1892
int width, height, tile_height, scan_lines, total_scan_lines;
1893
int image_width, image_height;
1894
int skip_left, skip_bottom;
1895
int i, j, pnmtype, maxval, bpp, nread;
1896
GimpImageBaseType imagetype;
1897
gint32 layer_ID, image_ID;
1898
GimpPixelRgn pixel_rgn;
1899
GimpDrawable *drawable;
1902
pnmtype = read_pnmraw_type (ifp, &width, &height, &maxval);
1904
if ((width == urx+1) && (height == ury+1)) /* gs respected BoundingBox ? */
1906
skip_left = llx; skip_bottom = lly;
1907
image_width = width - skip_left;
1908
image_height = height - skip_bottom;
1912
skip_left = skip_bottom = 0;
1913
image_width = width;
1914
image_height = height;
1916
if (pnmtype == 4) /* Portable Bitmap */
1918
imagetype = GIMP_INDEXED;
1919
nread = (width+7)/8;
1921
bitline = (guchar *)g_malloc (nread);
1922
byteline = (guchar *)g_malloc (nread*8);
1924
/* Get an array for mapping 8 bits in a byte to 8 bytes */
1926
for (j = 0; j < 256; j++)
1927
for (i = 7; i >= 0; i--)
1928
*(temp++) = ((j & (1 << i)) != 0);
1930
else if (pnmtype == 5) /* Portable Greymap */
1932
imagetype = GIMP_GRAY;
1935
byteline = (unsigned char *)g_malloc (nread);
1937
else if (pnmtype == 6) /* Portable Pixmap */
1939
imagetype = GIMP_RGB;
1942
byteline = (guchar *)g_malloc (nread);
1947
image_ID = create_new_image (filename, pagenum,
1948
image_width, image_height, imagetype,
1949
&layer_ID, &drawable, &pixel_rgn);
1951
tile_height = gimp_tile_height ();
1952
data = g_malloc (tile_height * image_width * bpp);
1955
total_scan_lines = scan_lines = 0;
1957
if (pnmtype == 4) /* Read bitimage ? Must be mapped to indexed */
1958
{static unsigned char BWColorMap[2*3] = { 255, 255, 255, 0, 0, 0 };
1960
gimp_image_set_colormap (image_ID, BWColorMap, 2);
1962
for (i = 0; i < height; i++)
1964
e = (fread (bitline, 1, nread, ifp) != nread);
1965
if (total_scan_lines >= image_height) continue;
1969
j = width; /* Map 1 byte of bitimage to 8 bytes of indexed image */
1974
memcpy (byteptr, bit2byte + *(temp++)*8, 8);
1979
memcpy (byteptr, bit2byte + *temp*8, j);
1981
memcpy (dest, byteline+skip_left, image_width);
1982
dest += image_width;
1987
gimp_progress_update ((double)(i+1) / (double)image_height);
1989
if ((scan_lines == tile_height) || ((i+1) == image_height))
1991
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
1992
image_width, scan_lines);
1999
else /* Read gray/rgb-image */
2001
for (i = 0; i < height; i++)
2003
e = (fread (byteline, bpp, width, ifp) != width);
2004
if (total_scan_lines >= image_height) continue;
2008
memcpy (dest, byteline+skip_left*bpp, image_width*bpp);
2009
dest += image_width*bpp;
2014
gimp_progress_update ((double)(i+1) / (double)image_height);
2016
if ((scan_lines == tile_height) || ((i+1) == image_height))
2018
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
2019
image_width, scan_lines);
2028
if (byteline) g_free (byteline);
2029
if (bitline) g_free (bitline);
2032
g_message ("EOF encountered on reading");
2034
gimp_drawable_flush (drawable);
2036
return (err ? -1 : image_ID);
2040
/* Write out the PostScript file header */
2041
static void save_ps_header (FILE *ofp,
2042
const gchar *filename)
2044
gchar *basename = g_path_get_basename (filename);
2045
time_t cutime = time (NULL);
2047
fprintf (ofp, "%%!PS-Adobe-3.0%s\n", psvals.eps ? " EPSF-3.0" : "");
2048
fprintf (ofp, "%%%%Creator: GIMP PostScript file plugin V %4.2f \
2049
by Peter Kirchgessner\n", VERSIO);
2050
fprintf (ofp, "%%%%Title: %s\n", basename);
2051
fprintf (ofp, "%%%%CreationDate: %s", ctime (&cutime));
2052
fprintf (ofp, "%%%%DocumentData: Clean7Bit\n");
2053
if (psvals.eps || (psvals.level > 1)) fprintf (ofp,"%%%%LanguageLevel: 2\n");
2054
fprintf (ofp, "%%%%Pages: 1\n");
2060
/* Write out transformation for image */
2062
save_ps_setup (FILE *ofp,
2068
double x_offset, y_offset, x_size, y_size;
2070
double x_scale, y_scale;
2071
double width_inch, height_inch;
2072
double f1, f2, dx, dy;
2075
char tmpbuf[G_ASCII_DTOSTR_BUF_SIZE];
2082
x_offset = psvals.x_offset;
2083
y_offset = psvals.y_offset;
2084
width_inch = fabs (psvals.width);
2085
height_inch = fabs (psvals.height);
2089
x_offset /= 25.4; y_offset /= 25.4;
2090
width_inch /= 25.4; height_inch /= 25.4;
2092
if (psvals.keep_ratio) /* Proportions to keep ? */
2093
{ /* Fit the image into the allowed size */
2094
f1 = width_inch / width;
2095
f2 = height_inch / height;
2097
height_inch = width_inch * (double)(height)/(double)(width);
2099
width_inch = fabs (height_inch) * (double)(width)/(double)(height);
2101
if ((psvals.rotate == 0) || (psvals.rotate == 180))
2103
x_size = width_inch; y_size = height_inch;
2107
y_size = width_inch; x_size = height_inch;
2110
/* Round up upper right corner only for non-integer values */
2111
urx = (x_offset+x_size)*72.0;
2112
ury = (y_offset+y_size)*72.0;
2115
if (urx != (double)i_urx) i_urx++; /* Check for non-integer value */
2116
if (ury != (double)i_ury) i_ury++;
2118
fprintf (ofp, "%%%%BoundingBox: %d %d %d %d\n",(int)(x_offset*72.0),
2119
(int)(y_offset*72.0), i_urx, i_ury);
2120
fprintf (ofp, "%%%%EndComments\n");
2122
if (psvals.preview && (psvals.preview_size > 0))
2124
save_ps_preview (ofp, drawable_ID);
2127
fprintf (ofp, "%%%%BeginProlog\n");
2128
fprintf (ofp, "%% Use own dictionary to avoid conflicts\n");
2129
fprintf (ofp, "10 dict begin\n");
2130
fprintf (ofp, "%%%%EndProlog\n");
2131
fprintf (ofp, "%%%%Page: 1 1\n");
2132
fprintf (ofp, "%% Translate for offset\n");
2133
fprintf (ofp, "%s", g_ascii_dtostr (tmpbuf, sizeof (tmpbuf), x_offset*72.0));
2134
fprintf (ofp, " %s translate\n", g_ascii_dtostr (tmpbuf, sizeof (tmpbuf), y_offset*72.0));
2136
/* Calculate translation to startpoint of first scanline */
2137
switch (psvals.rotate)
2139
case 0: dx = 0.0; dy = y_size*72.0;
2141
case 90: dx = dy = 0.0;
2142
x_scale = 72.0 * width_inch;
2143
y_scale = -72.0 * height_inch;
2145
case 180: dx = x_size*72.0; dy = 0.0;
2147
case 270: dx = x_size*72.0; dy = y_size*72.0;
2150
if ((dx != 0.0) || (dy != 0.0))
2152
fprintf (ofp, "%% Translate to begin of first scanline\n");
2153
fprintf (ofp, "%s", g_ascii_dtostr (tmpbuf, sizeof (tmpbuf), dx));
2154
fprintf (ofp, " %s translate\n", g_ascii_dtostr (tmpbuf, sizeof (tmpbuf), dy));
2157
fprintf (ofp, "%d rotate\n", (int)psvals.rotate);
2158
fprintf (ofp, "%s", g_ascii_dtostr (tmpbuf, sizeof (tmpbuf), 72.0*width_inch));
2159
fprintf (ofp, " %s scale\n", g_ascii_dtostr (tmpbuf, sizeof (tmpbuf), -72.0*height_inch));
2161
/* Write the PostScript procedures to read the image */
2162
if (psvals.level <= 1)
2164
fprintf (ofp, "%% Variable to keep one line of raster data\n");
2166
fprintf (ofp, "/scanline %d string def\n", (width+7)/8);
2168
fprintf (ofp, "/scanline %d %d mul string def\n", width, bpp/8);
2170
fprintf (ofp, "%% Image geometry\n%d %d %d\n", width, height,
2171
(bpp == 1) ? 1 : 8);
2172
fprintf (ofp, "%% Transformation matrix\n");
2173
xtrans = ytrans = 0;
2174
if (psvals.width < 0.0) { width = -width; xtrans = -width; }
2175
if (psvals.height < 0.0) { height = -height; ytrans = -height; }
2176
fprintf (ofp, "[ %d 0 0 %d %d %d ]\n", width, height, xtrans, ytrans);
2181
save_ps_trailer (FILE *ofp)
2183
fprintf (ofp, "%%%%Trailer\n");
2184
fprintf (ofp, "end\n%%%%EOF\n");
2187
/* Do a Floyd-Steinberg dithering on a greyscale scanline. */
2188
/* linecount must keep the counter for the actual scanline (0, 1, 2, ...). */
2189
/* If linecount is less than zero, all used memory is freed. */
2192
dither_grey (guchar *grey,
2197
register guchar *greyptr, *bwptr, mask;
2199
int x, greyval, fse_inline;
2200
static int *fs_error = NULL;
2201
static int do_init_arrays = 1;
2202
static int limit_array[1278];
2203
static int east_error[256],seast_error[256],south_error[256],swest_error[256];
2204
int *limit = &(limit_array[512]);
2208
if (fs_error) g_free (fs_error-1);
2209
if (linecount < 0) return;
2210
fs_error = g_new (int, npix+2);
2211
memset ((char *)fs_error, 0, (npix+2)*sizeof (int));
2214
/* Initialize some arrays that speed up dithering */
2218
for (x = -511; x <= 766; x++)
2219
limit[x] = (x < 0) ? 0 : ((x > 255) ? 255 : x);
2220
for (greyval = 0; greyval < 256; greyval++)
2222
east_error[greyval] = (greyval < 128) ? ((greyval * 79) >> 8)
2223
: (((greyval-255)*79) >> 8);
2224
seast_error[greyval] = (greyval < 128) ? ((greyval * 34) >> 8)
2225
: (((greyval-255)*34) >> 8);
2226
south_error[greyval] = (greyval < 128) ? ((greyval * 56) >> 8)
2227
: (((greyval-255)*56) >> 8);
2228
swest_error[greyval] = (greyval < 128) ? ((greyval * 12) >> 8)
2229
: (((greyval-255)*12) >> 8);
2233
if (fs_error == NULL) return;
2235
memset (bw, 0, (npix+7)/8); /* Initialize with white */
2240
fse_inline = fs_error[0];
2241
for (x = 0, fse = fs_error; x < npix; x++, fse++)
2243
greyval = limit[*(greyptr++) + fse_inline]; /* 0 <= greyval <= 255 */
2244
if (greyval < 128) *bwptr |= mask; /* Set a black pixel */
2246
/* Error distribution */
2247
fse_inline = east_error[greyval] + fse[1];
2248
fse[1] = seast_error[greyval];
2249
fse[0] += south_error[greyval];
2250
fse[-1] += swest_error[greyval];
2252
mask >>= 1; /* Get mask for next b/w-pixel */
2261
/* Write a device independant screen preview */
2263
save_ps_preview (FILE *ofp,
2266
register guchar *bwptr, *greyptr;
2267
GimpImageType drawable_type;
2268
GimpDrawable *drawable;
2269
GimpPixelRgn src_rgn;
2270
int width, height, x, y, nbsl, out_count;
2271
int nchar_pl = 72, src_y;
2273
guchar *grey, *bw, *src_row, *src_ptr;
2277
if (psvals.preview_size <= 0) return;
2279
drawable = gimp_drawable_get (drawable_ID);
2280
drawable_type = gimp_drawable_type (drawable_ID);
2282
/* Calculate size of preview */
2283
if ( (drawable->width <= psvals.preview_size)
2284
&& (drawable->height <= psvals.preview_size))
2286
width = drawable->width;
2287
height = drawable->height;
2291
f1 = (double)psvals.preview_size / (double)drawable->width;
2292
f2 = (double)psvals.preview_size / (double)drawable->height;
2295
width = psvals.preview_size;
2296
height = drawable->height * f1;
2297
if (height <= 0) height = 1;
2301
height = psvals.preview_size;
2302
width = drawable->width * f1;
2303
if (width <= 0) width = 1;
2307
nbsl = (width+7)/8; /* Number of bytes per scanline in bitmap */
2309
grey = (guchar *)g_malloc (width);
2310
bw = (guchar *)g_malloc (nbsl);
2311
src_row = (guchar *)g_malloc (drawable->width * drawable->bpp);
2313
fprintf (ofp, "%%%%BeginPreview: %d %d 1 %d\n", width, height,
2314
((nbsl*2+nchar_pl-1)/nchar_pl)*height);
2316
gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0, drawable->width,
2317
drawable->height, FALSE, FALSE);
2319
cmap = NULL; /* Check if we need a colour table */
2320
if (gimp_drawable_type (drawable_ID) == GIMP_INDEXED_IMAGE)
2322
gimp_image_get_colormap (gimp_drawable_get_image (drawable_ID), &ncols);
2324
for (y = 0; y < height; y++)
2326
/* Get a scanline from the input image and scale it to the desired width */
2327
src_y = (y * drawable->height) / height;
2328
gimp_pixel_rgn_get_row (&src_rgn, src_row, 0, src_y, drawable->width);
2331
if (drawable->bpp == 3) /* RGB-image */
2333
for (x = 0; x < width; x++)
2334
{ /* Convert to grey */
2335
src_ptr = src_row + ((x * drawable->width) / width) * 3;
2336
*(greyptr++) = (3*src_ptr[0] + 6*src_ptr[1] + src_ptr[2]) / 10;
2339
else if (cmap) /* Indexed image */
2341
for (x = 0; x < width; x++)
2343
src_ptr = src_row + ((x * drawable->width) / width);
2344
cind = *src_ptr; /* Get colour index and convert to grey */
2345
src_ptr = (cind >= ncols) ? cmap : (cmap + 3*cind);
2346
*(greyptr++) = (3*src_ptr[0] + 6*src_ptr[1] + src_ptr[2]) / 10;
2349
else /* Grey image */
2351
for (x = 0; x < width; x++)
2352
*(greyptr++) = *(src_row + ((x * drawable->width) / width));
2355
/* Now we have a greyscale line for the desired width. */
2356
/* Dither it to b/w */
2357
dither_grey (grey, bw, width, y);
2359
/* Write out the b/w line */
2362
for (x = 0; x < nbsl; x++)
2364
if (out_count == 0) fprintf (ofp, "%% ");
2365
fprintf (ofp, "%02x", *(bwptr++));
2367
if (out_count >= nchar_pl)
2369
fprintf (ofp, "\n");
2374
fprintf (ofp, "\n");
2377
gimp_progress_update ((double)(y) / (double)height);
2380
fprintf (ofp, "%%%%EndPreview\n");
2382
dither_grey (grey, bw, width, -1);
2387
gimp_drawable_detach (drawable);
2391
save_gray (FILE *ofp,
2395
int height, width, i, j;
2397
unsigned char *data, *src;
2398
unsigned char *packb = NULL;
2399
GimpPixelRgn pixel_rgn;
2400
GimpDrawable *drawable;
2401
GimpImageType drawable_type;
2402
static char *hex = "0123456789abcdef";
2403
int level2 = (psvals.level > 1);
2405
drawable = gimp_drawable_get (drawable_ID);
2406
drawable_type = gimp_drawable_type (drawable_ID);
2407
width = drawable->width;
2408
height = drawable->height;
2409
tile_height = gimp_tile_height ();
2410
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, width, height, FALSE, FALSE);
2412
/* allocate a buffer for retrieving information from the pixel region */
2413
src = data = (guchar *)g_malloc (tile_height * width * drawable->bpp);
2415
/* Set up transformation in PostScript */
2416
save_ps_setup (ofp, drawable_ID, width, height, 1*8);
2418
/* Write read image procedure */
2421
fprintf (ofp, "{ currentfile scanline readhexstring pop }\n");
2425
fprintf (ofp,"currentfile /ASCII85Decode filter /RunLengthDecode filter\n");
2427
/* Allocate buffer for packbits data. Worst case: Less than 1% increase */
2428
packb = (guchar *)g_malloc ((width * 105)/100+2);
2430
ps_begin_data (ofp);
2431
fprintf (ofp, "image\n");
2433
#define GET_GRAY_TILE(begin) \
2435
scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i); \
2436
gimp_pixel_rgn_get_rect (&pixel_rgn, begin, 0, i, width, scan_lines); \
2439
for (i = 0; i < height; i++)
2441
if ((i % tile_height) == 0) GET_GRAY_TILE (data); /* Get more data */
2444
for (j = 0; j < width; j++)
2446
putc (hex[(*src) >> 4], ofp);
2447
putc (hex[(*(src++)) & 0x0f], ofp);
2448
if (((j+1) % 39) == 0) putc ('\n', ofp);
2455
compress_packbits (width, src, &nout, packb);
2456
ascii85_nout (nout, packb, ofp);
2461
gimp_progress_update ((double) i / (double) height);
2466
ascii85_out (128, ofp); /* Write EOD of RunLengthDecode filter */
2471
fprintf (ofp, "showpage\n");
2477
gimp_drawable_detach (drawable);
2481
g_message (_("Write error occurred"));
2486
#undef GET_GRAY_TILE
2495
int height, width, i, j;
2496
int ncols, nbsl, nwrite;
2500
guchar *packb = NULL;
2501
guchar *scanline, *dst, mask;
2502
guchar *hex_scanline;
2503
GimpPixelRgn pixel_rgn;
2504
GimpDrawable *drawable;
2505
GimpImageType drawable_type;
2506
static char *hex = "0123456789abcdef";
2507
gint level2 = (psvals.level > 1);
2509
cmap = gimp_image_get_colormap (image_ID, &ncols);
2511
drawable = gimp_drawable_get (drawable_ID);
2512
drawable_type = gimp_drawable_type (drawable_ID);
2513
width = drawable->width;
2514
height = drawable->height;
2515
tile_height = gimp_tile_height ();
2516
gimp_pixel_rgn_init (&pixel_rgn,
2517
drawable, 0, 0, width, height, FALSE, FALSE);
2519
/* allocate a buffer for retrieving information from the pixel region */
2520
src = data = g_new (guchar, tile_height * width * drawable->bpp);
2522
scanline = g_new (guchar, nbsl + 1);
2523
hex_scanline = g_new (guchar, (nbsl + 1) * 2);
2525
/* Set up transformation in PostScript */
2526
save_ps_setup (ofp, drawable_ID, width, height, 1);
2528
/* Write read image procedure */
2531
fprintf (ofp, "{ currentfile scanline readhexstring pop }\n");
2535
fprintf (ofp,"currentfile /ASCII85Decode filter /RunLengthDecode filter\n");
2537
/* Allocate buffer for packbits data. Worst case: Less than 1% increase */
2538
packb = g_new (guchar, ((nbsl+1) * 105) / 100 + 2);
2540
ps_begin_data (ofp);
2541
fprintf (ofp, "image\n");
2543
#define GET_BW_TILE(begin) \
2545
scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i); \
2546
gimp_pixel_rgn_get_rect (&pixel_rgn, begin, 0, i, width, scan_lines); \
2549
for (i = 0; i < height; i++)
2551
if ((i % tile_height) == 0) GET_BW_TILE (data); /* Get more data */
2553
memset (dst, 0, nbsl);
2555
/* Build a bitmap for a scanline */
2556
for (j = 0; j < width; j++)
2558
ct = cmap + *(src++)*3;
2559
if (ct[0] || ct[1] || ct[2])
2561
if (mask == 0x01) { mask = 0x80; dst++; } else mask >>= 1;
2565
/* Convert to hexstring */
2566
for (j = 0; j < nbsl; j++)
2568
hex_scanline[j*2] = (unsigned char)hex[scanline[j] >> 4];
2569
hex_scanline[j*2+1] = (unsigned char)hex[scanline[j] & 0x0f];
2571
/* Write out hexstring */
2576
nwrite = (j > 78) ? 78 : j;
2577
fwrite (dst, nwrite, 1, ofp);
2586
compress_packbits (nbsl, scanline, &nout, packb);
2587
ascii85_nout (nout, packb, ofp);
2591
gimp_progress_update ((double) i / (double) height);
2596
ascii85_out (128, ofp); /* Write EOD of RunLengthDecode filter */
2601
fprintf (ofp, "showpage\n");
2603
g_free (hex_scanline);
2610
gimp_drawable_detach (drawable);
2614
g_message (_("Write error occurred"));
2624
save_index (FILE *ofp,
2628
int height, width, i, j;
2631
guchar *cmap, *cmap_start;
2633
guchar *packb = NULL, *plane = NULL;
2634
char coltab[256*6], *ct;
2635
GimpPixelRgn pixel_rgn;
2636
GimpDrawable *drawable;
2637
GimpImageType drawable_type;
2638
static char *hex = "0123456789abcdef";
2639
static char *background = "000000";
2640
int level2 = (psvals.level > 1);
2642
cmap = cmap_start = gimp_image_get_colormap (image_ID, &ncols);
2646
for (j = 0; j < 256; j++)
2650
memcpy (ct, background, 6);
2655
bw &= ((cmap[0] == 0) && (cmap[1] == 0) && (cmap[2] == 0))
2656
|| ((cmap[0] == 255) && (cmap[1] == 255) && (cmap[2] == 255));
2657
*(ct++) = (guchar)hex[(*cmap) >> 4];
2658
*(ct++) = (guchar)hex[(*(cmap++)) & 0x0f];
2659
*(ct++) = (guchar)hex[(*cmap) >> 4];
2660
*(ct++) = (guchar)hex[(*(cmap++)) & 0x0f];
2661
*(ct++) = (guchar)hex[(*cmap) >> 4];
2662
*(ct++) = (guchar)hex[(*(cmap++)) & 0x0f];
2666
return (save_bw (ofp, image_ID, drawable_ID));
2668
drawable = gimp_drawable_get (drawable_ID);
2669
drawable_type = gimp_drawable_type (drawable_ID);
2670
width = drawable->width;
2671
height = drawable->height;
2672
tile_height = gimp_tile_height ();
2673
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, width, height, FALSE, FALSE);
2675
/* allocate a buffer for retrieving information from the pixel region */
2676
src = data = (guchar *)g_malloc (tile_height * width * drawable->bpp);
2678
/* Set up transformation in PostScript */
2679
save_ps_setup (ofp, drawable_ID, width, height, 3*8);
2681
/* Write read image procedure */
2684
fprintf (ofp, "{ currentfile scanline readhexstring pop } false 3\n");
2688
fprintf (ofp, "%% Strings to hold RGB-samples per scanline\n");
2689
fprintf (ofp, "/rstr %d string def\n", width);
2690
fprintf (ofp, "/gstr %d string def\n", width);
2691
fprintf (ofp, "/bstr %d string def\n", width);
2693
"{currentfile /ASCII85Decode filter /RunLengthDecode filter\
2694
rstr readstring pop}\n");
2696
"{currentfile /ASCII85Decode filter /RunLengthDecode filter\
2697
gstr readstring pop}\n");
2699
"{currentfile /ASCII85Decode filter /RunLengthDecode filter\
2700
bstr readstring pop}\n");
2701
fprintf (ofp, "true 3\n");
2703
/* Allocate buffer for packbits data. Worst case: Less than 1% increase */
2704
packb = (guchar *)g_malloc ((width * 105)/100+2);
2705
plane = (guchar *)g_malloc (width);
2707
ps_begin_data (ofp);
2708
fprintf (ofp, "colorimage\n");
2710
#define GET_INDEX_TILE(begin) \
2712
scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i); \
2713
gimp_pixel_rgn_get_rect (&pixel_rgn, begin, 0, i, width, scan_lines); \
2716
for (i = 0; i < height; i++)
2718
if ((i % tile_height) == 0) GET_INDEX_TILE (data); /* Get more data */
2721
for (j = 0; j < width; j++)
2723
fwrite (coltab+(*(src++))*6, 6, 1, ofp);
2724
if (((j+1) % 13) == 0) putc ('\n', ofp);
2729
{guchar *plane_ptr, *src_ptr;
2732
for (rgb = 0; rgb < 3; rgb++)
2736
for (j = 0; j < width; j++)
2737
*(plane_ptr++) = cmap_start[3 * *(src_ptr++) + rgb];
2738
compress_packbits (width, plane, &nout, packb);
2740
ascii85_nout (nout, packb, ofp);
2741
ascii85_out (128, ofp); /* Write EOD of RunLengthDecode filter */
2748
gimp_progress_update ((double) i / (double) height);
2752
fprintf (ofp, "showpage\n");
2762
gimp_drawable_detach (drawable);
2766
g_message (_("Write error occurred"));
2771
#undef GET_INDEX_TILE
2776
save_rgb (FILE *ofp,
2780
int height, width, tile_height;
2783
guchar *packb = NULL, *plane = NULL;
2784
GimpPixelRgn pixel_rgn;
2785
GimpDrawable *drawable;
2786
GimpImageType drawable_type;
2787
static char *hex = "0123456789abcdef";
2788
int level2 = (psvals.level > 1);
2790
drawable = gimp_drawable_get (drawable_ID);
2791
drawable_type = gimp_drawable_type (drawable_ID);
2792
width = drawable->width;
2793
height = drawable->height;
2794
tile_height = gimp_tile_height ();
2795
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, width, height, FALSE, FALSE);
2797
/* allocate a buffer for retrieving information from the pixel region */
2798
src = data = (guchar *)g_malloc (tile_height * width * drawable->bpp);
2800
/* Set up transformation in PostScript */
2801
save_ps_setup (ofp, drawable_ID, width, height, 3*8);
2803
/* Write read image procedure */
2806
fprintf (ofp, "{ currentfile scanline readhexstring pop } false 3\n");
2810
fprintf (ofp, "%% Strings to hold RGB-samples per scanline\n");
2811
fprintf (ofp, "/rstr %d string def\n", width);
2812
fprintf (ofp, "/gstr %d string def\n", width);
2813
fprintf (ofp, "/bstr %d string def\n", width);
2815
"{currentfile /ASCII85Decode filter /RunLengthDecode filter\
2816
rstr readstring pop}\n");
2818
"{currentfile /ASCII85Decode filter /RunLengthDecode filter\
2819
gstr readstring pop}\n");
2821
"{currentfile /ASCII85Decode filter /RunLengthDecode filter\
2822
bstr readstring pop}\n");
2823
fprintf (ofp, "true 3\n");
2825
/* Allocate buffer for packbits data. Worst case: Less than 1% increase */
2826
packb = (guchar *)g_malloc ((width * 105)/100+2);
2827
plane = (guchar *)g_malloc (width);
2829
ps_begin_data (ofp);
2830
fprintf (ofp, "colorimage\n");
2832
#define GET_RGB_TILE(begin) \
2834
scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i); \
2835
gimp_pixel_rgn_get_rect (&pixel_rgn, begin, 0, i, width, scan_lines); \
2838
for (i = 0; i < height; i++)
2840
if ((i % tile_height) == 0) GET_RGB_TILE (data); /* Get more data */
2843
for (j = 0; j < width; j++)
2845
putc (hex[(*src) >> 4], ofp); /* Red */
2846
putc (hex[(*(src++)) & 0x0f], ofp);
2847
putc (hex[(*src) >> 4], ofp); /* Green */
2848
putc (hex[(*(src++)) & 0x0f], ofp);
2849
putc (hex[(*src) >> 4], ofp); /* Blue */
2850
putc (hex[(*(src++)) & 0x0f], ofp);
2851
if (((j+1) % 13) == 0) putc ('\n', ofp);
2856
{guchar *plane_ptr, *src_ptr;
2859
for (rgb = 0; rgb < 3; rgb++)
2861
src_ptr = src + rgb;
2863
for (j = 0; j < width; j++)
2865
*(plane_ptr++) = *src_ptr;
2868
compress_packbits (width, plane, &nout, packb);
2870
ascii85_nout (nout, packb, ofp);
2871
ascii85_out (128, ofp); /* Write EOD of RunLengthDecode filter */
2878
gimp_progress_update ((double) i / (double) height);
2882
fprintf (ofp, "showpage\n");
2891
gimp_drawable_detach (drawable);
2895
g_message (_("Write error occurred"));
2903
/* Load interface functions */
2909
GtkWidget *main_vbox;
2914
GtkWidget *spinbutton;
2920
gimp_ui_init ("ps", FALSE);
2922
dialog = gimp_dialog_new (_("Load PostScript"), "ps",
2924
gimp_standard_help_func, "file-ps-load",
2926
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2927
GTK_STOCK_OK, GTK_RESPONSE_OK,
2931
main_vbox = gtk_vbox_new (FALSE, 12);
2932
gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
2933
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), main_vbox,
2935
gtk_widget_show (main_vbox);
2937
hbox = gtk_hbox_new (TRUE, 12);
2938
gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
2939
gtk_widget_show (hbox);
2942
frame = gimp_frame_new (_("Rendering"));
2943
gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
2945
vbox = gtk_vbox_new (FALSE, 6);
2946
gtk_container_add (GTK_CONTAINER (frame), vbox);
2948
/* Resolution/Width/Height/Pages labels */
2949
table = gtk_table_new (4, 2, FALSE);
2950
gtk_table_set_row_spacings (GTK_TABLE (table), 6);
2951
gtk_table_set_col_spacings (GTK_TABLE (table), 6);
2952
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
2953
gtk_widget_show (table);
2955
spinbutton = gimp_spin_button_new (&adj, plvals.resolution,
2956
5, 1440, 1, 10, 0, 1, 0);
2957
gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
2958
_("Resolution:"), 0.0, 0.5,
2959
spinbutton, 1, FALSE);
2960
g_signal_connect (adj, "value_changed",
2961
G_CALLBACK (gimp_int_adjustment_update),
2962
&plvals.resolution);
2964
spinbutton = gimp_spin_button_new (&adj, plvals.width,
2965
1, GIMP_MAX_IMAGE_SIZE, 1, 10, 0, 1, 0);
2966
gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
2967
_("_Width:"), 0.0, 0.5,
2968
spinbutton, 1, FALSE);
2969
g_signal_connect (adj, "value_changed",
2970
G_CALLBACK (gimp_int_adjustment_update),
2973
spinbutton = gimp_spin_button_new (&adj, plvals.height,
2974
1, GIMP_MAX_IMAGE_SIZE, 1, 10, 0, 1, 0);
2975
gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
2976
_("_Height:"), 0.0, 0.5,
2977
spinbutton, 1, FALSE);
2978
g_signal_connect (adj, "value_changed",
2979
G_CALLBACK (gimp_int_adjustment_update),
2982
entry = gtk_entry_new ();
2983
gtk_widget_set_size_request (entry, 80, -1);
2984
gtk_entry_set_text (GTK_ENTRY (entry), plvals.pages);
2985
gimp_table_attach_aligned (GTK_TABLE (table), 0, 3,
2986
_("Pages:"), 0.0, 0.5,
2988
g_signal_connect (entry, "changed",
2989
G_CALLBACK (load_pages_entry_callback),
2991
gimp_help_set_help_data (GTK_WIDGET (entry),
2992
_("Pages to load (e.g.: 1-4 or 1,3,5-7)"), NULL);
2994
toggle = gtk_check_button_new_with_label (_("Try Bounding Box"));
2995
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
2996
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), plvals.use_bbox);
2997
gtk_widget_show (toggle);
2999
g_signal_connect (toggle, "toggled",
3000
G_CALLBACK (gimp_toggle_button_update),
3003
gtk_widget_show (vbox);
3004
gtk_widget_show (frame);
3007
frame = gimp_int_radio_group_new (TRUE, _("Coloring"),
3008
G_CALLBACK (gimp_radio_button_update),
3009
&plvals.pnm_type, plvals.pnm_type,
3013
_("Color"), 6, NULL,
3014
_("Automatic"), 7, NULL,
3017
gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
3018
gtk_widget_show (frame);
3020
hbox = gtk_hbox_new (TRUE, 12);
3021
gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
3022
gtk_widget_show (hbox);
3024
frame = gimp_int_radio_group_new (TRUE, _("Text antialiasing"),
3025
G_CALLBACK (gimp_radio_button_update),
3026
&plvals.textalpha, plvals.textalpha,
3030
_("Strong"), 4, NULL,
3033
gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
3034
gtk_widget_show (frame);
3036
frame = gimp_int_radio_group_new (TRUE, _("Graphic antialiasing"),
3037
G_CALLBACK (gimp_radio_button_update),
3038
&plvals.graphicsalpha, plvals.graphicsalpha,
3042
_("Strong"), 4, NULL,
3045
gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
3046
gtk_widget_show (frame);
3048
gtk_widget_show (dialog);
3050
run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
3052
gtk_widget_destroy (dialog);
3058
load_pages_entry_callback (GtkWidget *widget,
3061
gsize nelem = sizeof (plvals.pages);
3063
strncpy (plvals.pages, gtk_entry_get_text (GTK_ENTRY (widget)), nelem);
3064
plvals.pages[nelem-1] = '\0';
3068
/* Save interface functions */
3073
SaveDialogVals *vals;
3076
GtkWidget *frame, *uframe;
3077
GtkWidget *hbox, *vbox;
3078
GtkWidget *main_vbox[2];
3080
GtkWidget *spinbutton;
3085
vals = g_new (SaveDialogVals, 1);
3086
vals->level = (psvals.level > 1);
3088
dialog = gimp_dialog_new (_("Save as PostScript"), "ps",
3090
gimp_standard_help_func, "file-ps-save",
3092
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
3093
GTK_STOCK_OK, GTK_RESPONSE_OK,
3098
hbox = gtk_hbox_new (FALSE, 12);
3099
gtk_container_set_border_width (GTK_CONTAINER (hbox), 12);
3100
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox,
3102
main_vbox[0] = main_vbox[1] = NULL;
3104
for (j = 0; j < G_N_ELEMENTS (main_vbox); j++)
3106
main_vbox[j] = gtk_vbox_new (FALSE, 12);
3107
gtk_box_pack_start (GTK_BOX (hbox), main_vbox[j], FALSE, TRUE, 0);
3108
gtk_widget_show (main_vbox[j]);
3112
frame = gimp_frame_new (_("Image Size"));
3113
gtk_box_pack_start (GTK_BOX (main_vbox[0]), frame, FALSE, TRUE, 0);
3115
vbox = gtk_vbox_new (FALSE, 6);
3116
gtk_container_add (GTK_CONTAINER (frame), vbox);
3118
/* Width/Height/X-/Y-offset labels */
3119
table = gtk_table_new (4, 2, FALSE);
3120
gtk_table_set_row_spacings (GTK_TABLE (table), 6);
3121
gtk_table_set_col_spacings (GTK_TABLE (table), 6);
3122
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
3123
gtk_widget_show (table);
3125
spinbutton = gimp_spin_button_new (&vals->adjustment[0], psvals.width,
3126
1e-5, GIMP_MAX_IMAGE_SIZE, 1, 10, 0, 1, 2);
3127
gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
3128
_("_Width:"), 0.0, 0.5,
3129
spinbutton, 1, FALSE);
3130
g_signal_connect (vals->adjustment[0], "value_changed",
3131
G_CALLBACK (gimp_double_adjustment_update),
3134
spinbutton = gimp_spin_button_new (&vals->adjustment[1], psvals.height,
3135
1e-5, GIMP_MAX_IMAGE_SIZE, 1, 10, 0, 1, 2);
3136
gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
3137
_("_Height:"), 0.0, 0.5,
3138
spinbutton, 1, FALSE);
3139
g_signal_connect (vals->adjustment[1], "value_changed",
3140
G_CALLBACK (gimp_double_adjustment_update),
3143
spinbutton = gimp_spin_button_new (&vals->adjustment[2], psvals.x_offset,
3144
0.0, GIMP_MAX_IMAGE_SIZE, 1, 10, 0, 1, 2);
3145
gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
3146
_("_X offset:"), 0.0, 0.5,
3147
spinbutton, 1, FALSE);
3148
g_signal_connect (vals->adjustment[2], "value_changed",
3149
G_CALLBACK (gimp_double_adjustment_update),
3152
spinbutton = gimp_spin_button_new (&vals->adjustment[3], psvals.y_offset,
3153
0.0, GIMP_MAX_IMAGE_SIZE, 1, 10, 0, 1, 2);
3154
gimp_table_attach_aligned (GTK_TABLE (table), 0, 3,
3155
_("_Y offset:"), 0.0, 0.5,
3156
spinbutton, 1, FALSE);
3157
g_signal_connect (vals->adjustment[3], "value_changed",
3158
G_CALLBACK (gimp_double_adjustment_update),
3161
toggle = gtk_check_button_new_with_mnemonic (_("_Keep aspect ratio"));
3162
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
3163
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), psvals.keep_ratio);
3164
gtk_widget_show (toggle);
3166
gimp_help_set_help_data (toggle,
3167
_("When toggled, the resulting image will be scaled to fit "
3168
"into the given size without changing the aspect ratio."),
3169
"#keep_aspect_ratio"),
3171
g_signal_connect (toggle, "toggled",
3172
G_CALLBACK (gimp_toggle_button_update),
3173
&psvals.keep_ratio);
3176
uframe = gimp_int_radio_group_new (TRUE, _("Unit"),
3177
G_CALLBACK (save_unit_toggle_update),
3178
vals, psvals.unit_mm,
3180
_("_Inch"), FALSE, NULL,
3181
_("_Millimeter"), TRUE, NULL,
3185
gtk_box_pack_start (GTK_BOX (main_vbox[0]), uframe, TRUE, TRUE, 0);
3186
gtk_widget_show (uframe);
3188
gtk_widget_show (vbox);
3189
gtk_widget_show (frame);
3192
frame = gimp_int_radio_group_new (TRUE, _("Rotation"),
3193
G_CALLBACK (gimp_radio_button_update),
3194
&psvals.rotate, psvals.rotate,
3203
gtk_box_pack_start (GTK_BOX (main_vbox[1]), frame, TRUE, TRUE, 0);
3204
gtk_widget_show (frame);
3207
frame = gimp_frame_new (_("Output"));
3208
gtk_box_pack_start (GTK_BOX (main_vbox[1]), frame, TRUE, TRUE, 0);
3210
vbox = gtk_vbox_new (FALSE, 6);
3211
gtk_container_add (GTK_CONTAINER (frame), vbox);
3213
toggle = gtk_check_button_new_with_mnemonic (_("_PostScript level 2"));
3214
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
3215
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), vals->level);
3216
gtk_widget_show (toggle);
3218
g_signal_connect (toggle, "toggled",
3219
G_CALLBACK (gimp_toggle_button_update),
3222
toggle = gtk_check_button_new_with_mnemonic (_("_Encapsulated PostScript"));
3223
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
3224
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), psvals.eps);
3225
gtk_widget_show (toggle);
3227
g_signal_connect (toggle, "toggled",
3228
G_CALLBACK (gimp_toggle_button_update),
3231
toggle = gtk_check_button_new_with_mnemonic (_("P_review"));
3232
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
3233
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), psvals.preview);
3234
gtk_widget_show (toggle);
3236
g_signal_connect (toggle, "toggled",
3237
G_CALLBACK (gimp_toggle_button_update),
3240
/* Preview size label/entry */
3241
table = gtk_table_new (1, 2, FALSE);
3242
gtk_table_set_col_spacings (GTK_TABLE (table), 6);
3243
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
3244
gtk_widget_show (table);
3246
g_object_set_data (G_OBJECT (toggle), "set_sensitive", table);
3247
gtk_widget_set_sensitive (table, psvals.preview);
3249
spinbutton = gimp_spin_button_new (&adj, psvals.preview_size,
3250
0, 1024, 1, 10, 0, 1, 0);
3251
gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
3252
_("Preview _size:"), 1.0, 0.5,
3253
spinbutton, 1, FALSE);
3254
gtk_widget_show (spinbutton);
3256
g_signal_connect (adj, "value_changed",
3257
G_CALLBACK (gimp_int_adjustment_update),
3258
&psvals.preview_size);
3260
gtk_widget_show (vbox);
3261
gtk_widget_show (frame);
3263
gtk_widget_show (hbox);
3264
gtk_widget_show (dialog);
3266
run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
3268
gtk_widget_destroy (dialog);
3270
psvals.level = (vals->level) ? 2 : 1;
3278
save_unit_toggle_update (GtkWidget *widget,
3281
if (GTK_TOGGLE_BUTTON (widget)->active)
3283
SaveDialogVals *vals;
3289
vals = (SaveDialogVals *) data;
3290
unit_mm = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
3293
psvals.unit_mm = unit_mm;
3298
factor = 1.0 / 25.4;
3300
for (i = 0; i < 4; i++)
3302
value = GTK_ADJUSTMENT (vals->adjustment[i])->value * factor;
3304
gtk_adjustment_set_value (GTK_ADJUSTMENT (vals->adjustment[i]), value);