2006-12-09 21:33:38 +00:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
1997-11-24 22:05:25 +00:00
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
* PostScript file plugin
|
|
|
|
* PostScript writing and GhostScript interfacing code
|
1999-01-03 22:41:12 +00:00
|
|
|
* Copyright (C) 1997-98 Peter Kirchgessner
|
|
|
|
* (email: peter@kirchgessner.net, WWW: http://www.kirchgessner.net)
|
1997-11-24 22:05:25 +00:00
|
|
|
*
|
|
|
|
* Added controls for TextAlphaBits and GraphicsAlphaBits
|
|
|
|
* George White <aa056@chebucto.ns.ca>
|
|
|
|
*
|
2000-01-22 22:26:20 +00:00
|
|
|
* Added Ascii85 encoding
|
|
|
|
* Austin Donnelly <austin@gimp.org>
|
|
|
|
*
|
2009-01-17 22:28:01 +00:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
1997-11-24 22:05:25 +00:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2009-01-17 22:28:01 +00:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
1997-11-24 22:05:25 +00:00
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2018-07-11 23:27:07 +02:00
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
1997-11-24 22:05:25 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Event history:
|
|
|
|
* V 0.90, PK, 28-Mar-97: Creation.
|
|
|
|
* V 0.91, PK, 03-Apr-97: Clip everything outside BoundingBox.
|
|
|
|
* 24-Apr-97: Multi page read support.
|
|
|
|
* V 1.00, PK, 30-Apr-97: PDF support.
|
|
|
|
* V 1.01, PK, 05-Oct-97: Parse rc-file.
|
|
|
|
* V 1.02, GW, 09-Oct-97: Antialiasing support.
|
|
|
|
* PK, 11-Oct-97: No progress bars when running non-interactive.
|
|
|
|
* New procedure file_ps_load_setargs to set
|
|
|
|
* load-arguments non-interactively.
|
|
|
|
* If GS_OPTIONS are not set, use at least "-dSAFER"
|
1997-12-26 07:08:20 +00:00
|
|
|
* V 1.03, nn, 20-Dec-97: Initialize some variables
|
|
|
|
* V 1.04, PK, 20-Dec-97: Add Encapsulated PostScript output and preview
|
1999-01-03 22:41:12 +00:00
|
|
|
* V 1.05, PK, 21-Sep-98: Write b/w-images (indexed) using image-operator
|
|
|
|
* V 1.06, PK, 22-Dec-98: Fix problem with writing color PS files.
|
|
|
|
* Ghostview may hang when displaying the files.
|
1999-09-14 20:54:02 +00:00
|
|
|
* V 1.07, PK, 14-Sep-99: Add resolution to image
|
2000-01-22 22:26:20 +00:00
|
|
|
* V 1.08, PK, 16-Jan-2000: Add PostScript-Level 2 by Austin Donnelly
|
2000-03-10 17:27:25 +00:00
|
|
|
* V 1.09, PK, 15-Feb-2000: Force showpage on EPS-files
|
|
|
|
* Add "RunLength" compression
|
|
|
|
* Fix problem with "Level 2" toggle
|
2000-04-05 10:26:08 +00:00
|
|
|
* V 1.10, PK, 15-Mar-2000: For load EPSF, allow negative Bounding Box Values
|
2018-04-18 20:57:03 +02:00
|
|
|
* Save PS: don't start lines of image data with %%
|
2000-03-25 22:19:17 +00:00
|
|
|
* to prevent problems with stupid PostScript
|
|
|
|
* analyzer programs (Stanislav Brabec)
|
2000-04-05 10:26:08 +00:00
|
|
|
* Add BeginData/EndData comments
|
|
|
|
* Save PS: Set default rotation to 0
|
2000-08-20 23:26:11 +00:00
|
|
|
* V 1.11, PK, 20-Aug-2000: Fix problem with BoundingBox recognition
|
|
|
|
* for Mac files.
|
|
|
|
* Fix problem with loop when reading not all
|
|
|
|
* images of a multi page file.
|
2000-10-06 18:16:58 +00:00
|
|
|
* PK, 31-Aug-2000: Load PS: Add checks for space in filename.
|
2001-06-21 09:25:06 +00:00
|
|
|
* V 1.12 PK, 19-Jun-2001: Fix problem with command line switch --
|
|
|
|
* (reported by Ferenc Wagner)
|
2002-04-11 10:58:19 +00:00
|
|
|
* V 1.13 PK, 07-Apr-2002: Fix problem with DOS binary EPS files
|
2002-05-14 20:04:29 +00:00
|
|
|
* V 1.14 PK, 14-May-2002: Workaround EPS files of Adb. Ill. 8.0
|
2002-10-08 10:53:10 +00:00
|
|
|
* V 1.15 PK, 04-Oct-2002: Be more accurate with using BoundingBox
|
2004-01-25 23:46:24 +00:00
|
|
|
* V 1.16 PK, 22-Jan-2004: Don't use popen(), use g_spawn_async_with_pipes()
|
|
|
|
* or g_spawn_sync().
|
2004-09-19 10:54:48 +00:00
|
|
|
* V 1.17 PK, 19-Sep-2004: Fix problem with interpretation of bounding box
|
1997-11-24 22:05:25 +00:00
|
|
|
*/
|
|
|
|
|
1999-05-29 16:35:47 +00:00
|
|
|
#include "config.h"
|
2000-01-08 15:23:28 +00:00
|
|
|
|
2003-06-13 14:37:00 +00:00
|
|
|
#include <errno.h>
|
1997-11-24 22:05:25 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <time.h>
|
2000-01-08 15:23:28 +00:00
|
|
|
|
2004-01-25 23:46:24 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
2005-03-04 15:12:29 +00:00
|
|
|
#include <glib/gstdio.h>
|
|
|
|
|
2000-01-08 15:23:28 +00:00
|
|
|
#include <libgimp/gimp.h>
|
|
|
|
#include <libgimp/gimpui.h>
|
|
|
|
|
1999-05-29 16:35:47 +00:00
|
|
|
#include "libgimp/stdplugins-intl.h"
|
|
|
|
|
2012-01-22 09:56:08 +05:30
|
|
|
#include <ghostscript/ierrors.h>
|
|
|
|
#include <ghostscript/iapi.h>
|
|
|
|
#include <ghostscript/gdevdsp.h>
|
2004-01-25 23:46:24 +00:00
|
|
|
|
|
|
|
|
2019-08-18 17:04:53 +02:00
|
|
|
#define VERSION 1.17
|
|
|
|
static const gchar dversion[] = "v1.17 19-Sep-2004";
|
2005-08-15 10:30:39 +00:00
|
|
|
|
2019-08-18 17:04:53 +02:00
|
|
|
#define LOAD_PS_PROC "file-ps-load"
|
|
|
|
#define LOAD_EPS_PROC "file-eps-load"
|
|
|
|
#define LOAD_PS_THUMB_PROC "file-ps-load-thumb"
|
2024-04-13 15:10:25 +00:00
|
|
|
#define EXPORT_PS_PROC "file-ps-export"
|
|
|
|
#define EXPORT_EPS_PROC "file-eps-export"
|
2019-08-18 17:04:53 +02:00
|
|
|
#define PLUG_IN_BINARY "file-ps"
|
|
|
|
#define PLUG_IN_ROLE "gimp-file-ps"
|
2005-08-15 10:30:39 +00:00
|
|
|
|
2014-02-22 09:40:49 +01:00
|
|
|
#define STR_LENGTH 64
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-18 17:04:53 +02:00
|
|
|
|
|
|
|
typedef struct _PostScript PostScript;
|
|
|
|
typedef struct _PostScriptClass PostScriptClass;
|
|
|
|
|
|
|
|
struct _PostScript
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2019-08-18 17:04:53 +02:00
|
|
|
GimpPlugIn parent_instance;
|
1997-11-24 22:05:25 +00:00
|
|
|
};
|
|
|
|
|
2019-08-18 17:04:53 +02:00
|
|
|
struct _PostScriptClass
|
|
|
|
{
|
|
|
|
GimpPlugInClass parent_class;
|
|
|
|
};
|
2008-12-03 16:07:32 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-18 17:04:53 +02:00
|
|
|
#define PS_TYPE (ps_get_type ())
|
2023-10-18 18:29:37 +02:00
|
|
|
#define PS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PS_TYPE, PostScript))
|
2019-08-18 17:04:53 +02:00
|
|
|
|
|
|
|
GType ps_get_type (void) G_GNUC_CONST;
|
|
|
|
|
2023-08-06 02:56:44 +02:00
|
|
|
static GList * ps_query_procedures (GimpPlugIn *plug_in);
|
|
|
|
static GimpProcedure * ps_create_procedure (GimpPlugIn *plug_in,
|
|
|
|
const gchar *name);
|
|
|
|
|
2024-04-30 01:28:40 +02:00
|
|
|
static gboolean ps_extract (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
|
|
|
GFile *file,
|
|
|
|
GimpMetadata *metadata,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
GimpVectorLoadData *extracted_dimensions,
|
|
|
|
gpointer *data_for_run,
|
|
|
|
GDestroyNotify *data_for_run_destroy,
|
|
|
|
gpointer extract_data,
|
|
|
|
GError **error);
|
2023-08-06 02:56:44 +02:00
|
|
|
static GimpValueArray * ps_load (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
|
|
|
GFile *file,
|
2024-04-24 01:12:01 +02:00
|
|
|
gint width,
|
|
|
|
gint height,
|
2024-04-26 01:07:59 +02:00
|
|
|
GimpVectorLoadData extracted_data,
|
2023-08-06 02:56:44 +02:00
|
|
|
GimpMetadata *metadata,
|
|
|
|
GimpMetadataLoadFlags *flags,
|
|
|
|
GimpProcedureConfig *config,
|
2024-04-26 01:07:59 +02:00
|
|
|
gpointer data_from_extract,
|
2023-08-06 02:56:44 +02:00
|
|
|
gpointer run_data);
|
|
|
|
static GimpValueArray * ps_load_thumb (GimpProcedure *procedure,
|
|
|
|
GFile *file,
|
|
|
|
gint size,
|
2023-08-11 02:01:05 +02:00
|
|
|
GimpProcedureConfig *config,
|
2023-08-06 02:56:44 +02:00
|
|
|
gpointer run_data);
|
2024-04-13 15:10:25 +00:00
|
|
|
static GimpValueArray * ps_export (GimpProcedure *procedure,
|
2023-08-06 02:56:44 +02:00
|
|
|
GimpRunMode run_mode,
|
|
|
|
GimpImage *image,
|
|
|
|
GFile *file,
|
2024-05-06 18:38:12 +00:00
|
|
|
GimpExportOptions *options,
|
2023-08-06 02:56:44 +02:00
|
|
|
GimpMetadata *metadata,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
gpointer run_data);
|
|
|
|
|
|
|
|
static GimpImage * load_image (GFile *file,
|
2024-04-27 16:49:31 +00:00
|
|
|
GimpProcedureConfig *config,
|
2023-08-06 02:56:44 +02:00
|
|
|
GError **error);
|
2024-04-13 15:10:25 +00:00
|
|
|
static gboolean export_image (GFile *file,
|
2023-08-06 02:56:44 +02:00
|
|
|
GObject *config,
|
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GError **error);
|
2019-08-18 17:04:53 +02:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
static void ps_set_save_size (GObject *config,
|
2019-08-19 15:46:53 +02:00
|
|
|
GimpImage *image);
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
static gboolean save_ps_header (GOutputStream *output,
|
|
|
|
GFile *file,
|
2023-02-21 18:55:53 +00:00
|
|
|
GObject *config,
|
2014-10-26 18:54:42 +01:00
|
|
|
GError **error);
|
|
|
|
static gboolean save_ps_setup (GOutputStream *output,
|
2019-08-19 15:46:53 +02:00
|
|
|
GimpDrawable *drawable,
|
2014-10-26 18:54:42 +01:00
|
|
|
gint width,
|
|
|
|
gint height,
|
2023-02-21 18:55:53 +00:00
|
|
|
GObject *config,
|
2014-10-26 18:54:42 +01:00
|
|
|
gint bpp,
|
|
|
|
GError **error);
|
|
|
|
static gboolean save_ps_trailer (GOutputStream *output,
|
|
|
|
GError **error);
|
|
|
|
|
|
|
|
static gboolean save_ps_preview (GOutputStream *output,
|
2019-08-19 15:46:53 +02:00
|
|
|
GimpDrawable *drawable,
|
2023-02-21 18:55:53 +00:00
|
|
|
GObject *config,
|
2014-10-26 18:54:42 +01:00
|
|
|
GError **error);
|
|
|
|
|
|
|
|
static gboolean save_gray (GOutputStream *output,
|
2019-08-19 15:46:53 +02:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2023-02-21 18:55:53 +00:00
|
|
|
GObject *config,
|
2014-10-26 18:54:42 +01:00
|
|
|
GError **error);
|
|
|
|
static gboolean save_bw (GOutputStream *output,
|
2019-08-19 15:46:53 +02:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2023-02-21 18:55:53 +00:00
|
|
|
GObject *config,
|
2014-10-26 18:54:42 +01:00
|
|
|
GError **error);
|
|
|
|
static gboolean save_index (GOutputStream *output,
|
2019-08-19 15:46:53 +02:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2023-02-21 18:55:53 +00:00
|
|
|
GObject *config,
|
2014-10-26 18:54:42 +01:00
|
|
|
GError **error);
|
|
|
|
static gboolean save_rgb (GOutputStream *output,
|
2019-08-19 15:46:53 +02:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2023-02-21 18:55:53 +00:00
|
|
|
GObject *config,
|
2014-10-26 18:54:42 +01:00
|
|
|
GError **error);
|
|
|
|
|
|
|
|
static gboolean print (GOutputStream *output,
|
|
|
|
GError **error,
|
|
|
|
const gchar *format,
|
|
|
|
...) G_GNUC_PRINTF (3, 4);
|
|
|
|
|
2019-09-11 21:48:34 +02:00
|
|
|
static GimpImage * create_new_image (GFile *file,
|
2019-08-19 15:46:53 +02:00
|
|
|
guint pagenum,
|
|
|
|
guint width,
|
|
|
|
guint height,
|
|
|
|
GimpImageBaseType type,
|
|
|
|
GimpLayer **layer);
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2024-04-27 16:49:31 +00:00
|
|
|
static void check_load_vals (GimpProcedureConfig *config);
|
|
|
|
static void check_save_vals (GimpProcedureConfig *config);
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2024-04-27 16:49:31 +00:00
|
|
|
static gint page_in_list (gchar *list,
|
|
|
|
guint pagenum);
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2024-04-27 16:49:31 +00:00
|
|
|
static gint get_bbox (GFile *file,
|
|
|
|
gint *x0,
|
|
|
|
gint *y0,
|
|
|
|
gint *x1,
|
|
|
|
gint *y1);
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2024-04-30 01:28:40 +02:00
|
|
|
static gboolean ps_read_header (GFile *file,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
gboolean *is_pdf,
|
|
|
|
gboolean *is_epsf,
|
|
|
|
gint *bbox_x0,
|
|
|
|
gint *bbox_y0,
|
|
|
|
gint *bbox_x1,
|
|
|
|
gint *bbox_y1);
|
2024-04-27 16:49:31 +00:00
|
|
|
static FILE * ps_open (GFile *file,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
gint *llx,
|
|
|
|
gint *lly,
|
|
|
|
gint *urx,
|
|
|
|
gint *ury,
|
|
|
|
gboolean *is_epsf,
|
|
|
|
gchar **tmp_filename);
|
2022-05-16 14:31:50 +00:00
|
|
|
|
|
|
|
static void ps_close (FILE *ifp,
|
|
|
|
gchar *tmp_filename);
|
2024-04-30 01:28:40 +02:00
|
|
|
static gint read_pnmraw_type (FILE *ifp,
|
|
|
|
gint *width,
|
|
|
|
gint *height,
|
|
|
|
gint *maxval);
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
static gboolean skip_ps (FILE *ifp);
|
|
|
|
|
2019-09-11 21:48:34 +02:00
|
|
|
static GimpImage * load_ps (GFile *file,
|
2014-10-26 18:54:42 +01:00
|
|
|
guint pagenum,
|
|
|
|
FILE *ifp,
|
|
|
|
gint llx,
|
|
|
|
gint lly,
|
|
|
|
gint urx,
|
|
|
|
gint ury);
|
|
|
|
|
|
|
|
static void dither_grey (const guchar *grey,
|
|
|
|
guchar *bw,
|
|
|
|
gint npix,
|
|
|
|
gint linecount);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* Dialog-handling */
|
1999-10-03 18:54:54 +00:00
|
|
|
|
2024-06-08 18:37:38 +02:00
|
|
|
static gint32 count_ps_pages (GFile *file);
|
|
|
|
static gboolean load_dialog (GFile *file,
|
|
|
|
GimpVectorLoadData extracted_data,
|
|
|
|
GimpProcedure *procedure,
|
|
|
|
GObject *config);
|
2007-05-15 07:12:15 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
2014-06-22 23:01:31 +02:00
|
|
|
GtkAdjustment *adjustment[4];
|
|
|
|
gint level;
|
1997-11-24 22:05:25 +00:00
|
|
|
} SaveDialogVals;
|
|
|
|
|
2024-04-27 16:49:31 +00:00
|
|
|
static gboolean save_dialog (GimpProcedure *procedure,
|
|
|
|
GObject *config,
|
|
|
|
GimpImage *image);
|
|
|
|
static void save_unit_changed_update (GtkWidget *widget,
|
|
|
|
gpointer data);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-18 17:04:53 +02:00
|
|
|
|
|
|
|
G_DEFINE_TYPE (PostScript, ps, GIMP_TYPE_PLUG_IN)
|
|
|
|
|
|
|
|
GIMP_MAIN (PS_TYPE)
|
2022-05-26 00:59:36 +02:00
|
|
|
DEFINE_STD_SET_I18N
|
2019-08-18 17:04:53 +02:00
|
|
|
|
|
|
|
|
|
|
|
static const char hex[] = "0123456789abcdef";
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* The run mode */
|
2001-12-19 00:13:16 +00:00
|
|
|
static GimpRunMode l_run_mode;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-18 17:04:53 +02:00
|
|
|
|
|
|
|
static void
|
|
|
|
ps_class_init (PostScriptClass *klass)
|
|
|
|
{
|
|
|
|
GimpPlugInClass *plug_in_class = GIMP_PLUG_IN_CLASS (klass);
|
|
|
|
|
|
|
|
plug_in_class->query_procedures = ps_query_procedures;
|
|
|
|
plug_in_class->create_procedure = ps_create_procedure;
|
2022-05-26 00:59:36 +02:00
|
|
|
plug_in_class->set_i18n = STD_SET_I18N;
|
2019-08-18 17:04:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ps_init (PostScript *ps)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static GList *
|
|
|
|
ps_query_procedures (GimpPlugIn *plug_in)
|
|
|
|
{
|
|
|
|
GList *list = NULL;
|
|
|
|
|
2019-09-10 19:36:54 +02:00
|
|
|
list = g_list_append (list, g_strdup (LOAD_PS_THUMB_PROC));
|
2019-08-18 17:04:53 +02:00
|
|
|
list = g_list_append (list, g_strdup (LOAD_PS_PROC));
|
|
|
|
list = g_list_append (list, g_strdup (LOAD_EPS_PROC));
|
2024-04-13 15:10:25 +00:00
|
|
|
list = g_list_append (list, g_strdup (EXPORT_PS_PROC));
|
|
|
|
list = g_list_append (list, g_strdup (EXPORT_EPS_PROC));
|
2019-08-18 17:04:53 +02:00
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GimpProcedure *
|
|
|
|
ps_create_procedure (GimpPlugIn *plug_in,
|
|
|
|
const gchar *name)
|
|
|
|
{
|
|
|
|
GimpProcedure *procedure = NULL;
|
|
|
|
|
|
|
|
if (! strcmp (name, LOAD_PS_PROC) ||
|
|
|
|
! strcmp (name, LOAD_EPS_PROC))
|
|
|
|
{
|
2024-04-24 01:12:01 +02:00
|
|
|
procedure = gimp_vector_load_procedure_new (plug_in, name,
|
|
|
|
GIMP_PDB_PROC_TYPE_PLUGIN,
|
2024-04-30 01:28:40 +02:00
|
|
|
ps_extract, NULL, NULL,
|
2024-04-24 01:12:01 +02:00
|
|
|
ps_load, NULL, NULL);
|
2019-08-18 17:04:53 +02:00
|
|
|
|
|
|
|
if (! strcmp (name, LOAD_PS_PROC))
|
|
|
|
{
|
2022-07-04 22:50:53 +02:00
|
|
|
gimp_procedure_set_menu_label (procedure, _("PostScript document"));
|
2019-08-18 17:04:53 +02:00
|
|
|
|
|
|
|
gimp_procedure_set_documentation (procedure,
|
2024-04-27 16:49:31 +00:00
|
|
|
_("Load PostScript documents"),
|
|
|
|
_("Load PostScript documents"),
|
2019-08-18 17:04:53 +02:00
|
|
|
name);
|
|
|
|
|
2024-04-24 01:12:01 +02:00
|
|
|
gimp_file_procedure_set_format_name (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
_("PostScript"));
|
2019-08-18 17:04:53 +02:00
|
|
|
gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"application/postscript");
|
|
|
|
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"ps");
|
|
|
|
gimp_file_procedure_set_magics (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"0,string,%!,0,long,0xc5d0d3c6");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gimp_procedure_set_menu_label (procedure,
|
2022-07-04 22:50:53 +02:00
|
|
|
_("Encapsulated PostScript image"));
|
2019-08-18 17:04:53 +02:00
|
|
|
|
|
|
|
gimp_procedure_set_documentation (procedure,
|
2024-04-27 16:49:31 +00:00
|
|
|
_("Load Encapsulated PostScript images"),
|
|
|
|
_("Load Encapsulated PostScript images"),
|
2019-08-18 17:04:53 +02:00
|
|
|
name);
|
|
|
|
|
2024-04-24 01:12:01 +02:00
|
|
|
gimp_file_procedure_set_format_name (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
_("Encapsulated PostScript"));
|
2019-08-18 17:04:53 +02:00
|
|
|
gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"image/x-eps");
|
|
|
|
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"eps");
|
|
|
|
gimp_file_procedure_set_magics (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"0,string,%!,0,long,0xc5d0d3c6");
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_procedure_set_attribution (procedure,
|
|
|
|
"Peter Kirchgessner <peter@kirchgessner.net>",
|
|
|
|
"Peter Kirchgessner",
|
|
|
|
dversion);
|
|
|
|
|
|
|
|
gimp_load_procedure_set_thumbnail_loader (GIMP_LOAD_PROCEDURE (procedure),
|
|
|
|
LOAD_PS_THUMB_PROC);
|
|
|
|
|
2024-06-12 16:53:12 +00:00
|
|
|
gimp_procedure_add_boolean_argument (procedure, "check-bbox",
|
|
|
|
_("Try _Bounding Box"),
|
|
|
|
_("FALSE: Use width/height, TRUE: Use BoundingBox"),
|
|
|
|
TRUE,
|
|
|
|
GIMP_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_string_argument (procedure, "pages",
|
|
|
|
_("_Pages"),
|
|
|
|
_("Pages to load (e.g.: 1,3,5-7)"),
|
|
|
|
"1",
|
|
|
|
GIMP_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_choice_argument (procedure, "coloring",
|
|
|
|
_("Colorin_g"),
|
|
|
|
_("Import color format"),
|
|
|
|
gimp_choice_new_with_values ("bw", 4, _("B/W"), NULL,
|
|
|
|
"grayscale", 5, _("Gray"), NULL,
|
|
|
|
"rgb", 6, _("Color"), NULL,
|
|
|
|
"automatic", 7, _("Automatic"), NULL,
|
|
|
|
NULL),
|
|
|
|
"rgb", G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_choice_argument (procedure, "text-alpha-bits",
|
|
|
|
_("Te_xt anti-aliasing"),
|
|
|
|
_("Text anti-aliasing strength"),
|
|
|
|
gimp_choice_new_with_values ("none", 1, _("None"), NULL,
|
|
|
|
"weak", 2, _("Weak"), NULL,
|
|
|
|
"strong", 4, _("Strong"), NULL,
|
|
|
|
NULL),
|
|
|
|
"none", G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_choice_argument (procedure, "graphic-alpha-bits",
|
|
|
|
_("Gra_phic anti-aliasing"),
|
|
|
|
_("Graphic anti-aliasing strength"),
|
|
|
|
gimp_choice_new_with_values ("none", 1, _("None"), NULL,
|
|
|
|
"weak", 2, _("Weak"), NULL,
|
|
|
|
"strong", 4, _("Strong"), NULL,
|
|
|
|
NULL),
|
|
|
|
"none", G_PARAM_READWRITE);
|
2019-08-18 17:04:53 +02:00
|
|
|
}
|
|
|
|
else if (! strcmp (name, LOAD_PS_THUMB_PROC))
|
|
|
|
{
|
2019-08-30 12:52:28 +02:00
|
|
|
procedure = gimp_thumbnail_procedure_new (plug_in, name,
|
|
|
|
GIMP_PDB_PROC_TYPE_PLUGIN,
|
2019-08-19 14:04:00 +02:00
|
|
|
ps_load_thumb, NULL, NULL);
|
2019-08-18 17:04:53 +02:00
|
|
|
|
|
|
|
gimp_procedure_set_documentation (procedure,
|
2024-04-27 16:49:31 +00:00
|
|
|
_("Loads a small preview from a "
|
|
|
|
"PostScript or PDF document"),
|
2019-08-18 17:04:53 +02:00
|
|
|
"",
|
|
|
|
name);
|
|
|
|
gimp_procedure_set_attribution (procedure,
|
|
|
|
"Peter Kirchgessner <peter@kirchgessner.net>",
|
|
|
|
"Peter Kirchgessner",
|
|
|
|
dversion);
|
|
|
|
}
|
2024-04-13 15:10:25 +00:00
|
|
|
else if (! strcmp (name, EXPORT_PS_PROC) ||
|
|
|
|
! strcmp (name, EXPORT_EPS_PROC))
|
2019-08-18 17:04:53 +02:00
|
|
|
{
|
2024-04-20 03:08:57 +00:00
|
|
|
procedure = gimp_export_procedure_new (plug_in, name,
|
|
|
|
GIMP_PDB_PROC_TYPE_PLUGIN,
|
|
|
|
FALSE, ps_export, NULL, NULL);
|
2019-08-18 17:04:53 +02:00
|
|
|
|
2024-04-13 15:10:25 +00:00
|
|
|
if (! strcmp (name, EXPORT_PS_PROC))
|
2019-08-18 17:04:53 +02:00
|
|
|
{
|
2022-07-04 22:50:53 +02:00
|
|
|
gimp_procedure_set_menu_label (procedure, _("PostScript document"));
|
2019-08-18 17:04:53 +02:00
|
|
|
|
|
|
|
gimp_procedure_set_documentation (procedure,
|
2024-04-27 16:49:31 +00:00
|
|
|
_("Export image as PostScript document"),
|
|
|
|
_("PostScript exporting handles all "
|
|
|
|
"image types except those with alpha "
|
|
|
|
"channels."),
|
2019-08-18 17:04:53 +02:00
|
|
|
name);
|
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
gimp_file_procedure_set_format_name (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
_("PS"));
|
2019-08-18 17:04:53 +02:00
|
|
|
gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"application/postscript");
|
|
|
|
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"ps");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gimp_procedure_set_menu_label (procedure,
|
2023-02-21 18:55:53 +00:00
|
|
|
_("Encapsulated PostScript"));
|
2019-08-18 17:04:53 +02:00
|
|
|
|
|
|
|
gimp_procedure_set_documentation (procedure,
|
2024-04-27 16:49:31 +00:00
|
|
|
_("Export image as Encapsulated "
|
|
|
|
"PostScript image"),
|
|
|
|
_("PostScript exporting handles all "
|
|
|
|
"image types except those with alpha "
|
|
|
|
"channels."),
|
2019-08-18 17:04:53 +02:00
|
|
|
name);
|
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
gimp_file_procedure_set_format_name (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
_("EPS"));
|
2019-08-18 17:04:53 +02:00
|
|
|
gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"application/x-eps");
|
|
|
|
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"eps");
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_procedure_set_image_types (procedure, "RGB, GRAY, INDEXED");
|
|
|
|
|
|
|
|
gimp_procedure_set_attribution (procedure,
|
|
|
|
"Peter Kirchgessner <peter@kirchgessner.net>",
|
|
|
|
"Peter Kirchgessner",
|
|
|
|
dversion);
|
|
|
|
|
2019-08-19 12:05:12 +02:00
|
|
|
gimp_file_procedure_set_handles_remote (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
TRUE);
|
2019-08-18 17:04:53 +02:00
|
|
|
|
2024-05-06 18:38:12 +00:00
|
|
|
gimp_export_procedure_set_capabilities (GIMP_EXPORT_PROCEDURE (procedure),
|
|
|
|
GIMP_EXPORT_CAN_HANDLE_RGB |
|
|
|
|
GIMP_EXPORT_CAN_HANDLE_GRAY |
|
|
|
|
GIMP_EXPORT_CAN_HANDLE_INDEXED,
|
app, libgimp*, pdb, plug-ins: review and enhance MR !1549.
- Fix annotations for gimp_export_options_get_image() to make it
actually introspectable with the GimpImage being both input and
output. Even though the logic doesn't change much (the input image may
be overriden or not), it doesn't matter for introspection because
images are handled centrally by libgimp and therefore must not be
freed. Actually deleting the image from the central list of images
though remains a manual action depending on code logic, not some
automatic action to be handled by binding engines.
- Add G_GNUC_WARN_UNUSED_RESULT to gimp_export_options_get_image()
because ignoring the returned value is rarely a good idea (as you
usually want to delete the image).
- Remove gimp_export_options_new(): we don't need this constructor
because at this point, the best is to tell plug-in developers to just
pass NULL everywhere. This leaves us free to create a more useful
default constructor if needed, in the future. Main description for
GimpExportOptions has also been updated to say this.
- Add a data_destroy callback for the user data passed in
gimp_export_procedure_set_capabilities().
- Fixing annotations of 'export_options' object from pdb/pdb.pl: input
args would actually be (nullable) and would not transfer ownership
(calling code must still free the object). Return value's ownership on
the other hand is fully transfered.
- Add C and Python unit testing for GimpExportOptions and
gimp_export_options_get_image() in particular.
- Fix or improve various details.
Note that I have also considered for a long time changing the signature
of gimp_export_options_get_image() to return a boolean indicating
whether `image` had been replaced (hence needed deletion) or not. This
also meant getting rid of the GimpExportReturn enum. Right now it would
work because there are no third case, but I was considering the future
possibility that for instance we got some impossible conversion for some
future capability. I'm not sure it would ever happen; and for sure, this
is not desirable because it implies an export failure a bit late in the
workflow. But just in case, let's keep the enum return value. It does
not even make the using code that much more complicated (well just a
value comparison instead of a simple boolean test).
2024-08-17 15:06:27 +02:00
|
|
|
NULL, NULL, NULL);
|
2024-05-06 18:38:12 +00:00
|
|
|
|
2024-06-12 16:53:12 +00:00
|
|
|
gimp_procedure_add_double_argument (procedure, "width",
|
|
|
|
_("_Width"),
|
|
|
|
_("Width of the image in PostScript file "
|
|
|
|
"(0: use input image size)"),
|
|
|
|
0, GIMP_MAX_IMAGE_SIZE, 287.0,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_double_argument (procedure, "height",
|
|
|
|
_("_Height"),
|
|
|
|
_("Height of the image in PostScript file "
|
|
|
|
"(0: use input image size)"),
|
|
|
|
0, GIMP_MAX_IMAGE_SIZE, 200.0,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_double_argument (procedure, "x-offset",
|
|
|
|
_("_X offset"),
|
|
|
|
_("X-offset to image from lower left corner"),
|
|
|
|
-GIMP_MAX_IMAGE_SIZE, GIMP_MAX_IMAGE_SIZE, 5.0,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_double_argument (procedure, "y-offset",
|
|
|
|
_("Y o_ffset"),
|
|
|
|
_("Y-offset to image from lower left corner"),
|
|
|
|
-GIMP_MAX_IMAGE_SIZE, GIMP_MAX_IMAGE_SIZE, 5.0,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_choice_argument (procedure, "unit",
|
|
|
|
_("_Unit"),
|
|
|
|
_("Unit of measure for offset values"),
|
|
|
|
gimp_choice_new_with_values ("inch", 0, _("Inch"), NULL,
|
|
|
|
"millimeter", 1, _("Millimeter"), NULL,
|
|
|
|
NULL),
|
|
|
|
"inch", G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_boolean_argument (procedure, "keep-ratio",
|
|
|
|
_("_Keep aspect ratio"),
|
|
|
|
_("If enabled, aspect ratio will be maintained on export. "
|
|
|
|
"Otherwise, the width and height values will be used."),
|
|
|
|
TRUE,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_int_argument (procedure, "rotation",
|
|
|
|
_("Rotation"),
|
|
|
|
"0, 90, 180, 270",
|
|
|
|
0, 270, 0,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_boolean_argument (procedure, "level",
|
|
|
|
_("PostScript Level _2"),
|
|
|
|
_("If enabled, export in PostScript Level 2 format. "
|
|
|
|
"Otherwise, export in PostScript Level 1 format."),
|
|
|
|
TRUE,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_boolean_argument (procedure, "eps-flag",
|
|
|
|
_("Encapsula_ted PostScript"),
|
|
|
|
_("If enabled, export as Encapsulated PostScript. "
|
|
|
|
"Otherwise, export as PostScript."),
|
|
|
|
FALSE,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_boolean_argument (procedure, "show-preview",
|
|
|
|
_("_Preview"),
|
|
|
|
_("Show Preview"),
|
|
|
|
FALSE,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_int_argument (procedure, "preview",
|
|
|
|
_("Preview Si_ze"),
|
|
|
|
_("Maximum size of preview. Set to 0 for no preview."),
|
|
|
|
0, GIMP_MAX_IMAGE_SIZE, 256,
|
|
|
|
G_PARAM_READWRITE);
|
2019-08-18 17:04:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return procedure;
|
|
|
|
}
|
|
|
|
|
2024-04-30 01:28:40 +02:00
|
|
|
static gboolean
|
|
|
|
ps_extract (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
|
|
|
GFile *file,
|
|
|
|
GimpMetadata *metadata,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
GimpVectorLoadData *extracted_dimensions,
|
|
|
|
gpointer *data_for_run,
|
|
|
|
GDestroyNotify *data_for_run_destroy,
|
|
|
|
gpointer extract_data,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
gboolean has_bbox;
|
|
|
|
gboolean is_pdf;
|
|
|
|
gboolean is_epsf;
|
|
|
|
gint bbox_x0 = 0;
|
|
|
|
gint bbox_y0 = 0;
|
|
|
|
gint bbox_x1 = 0;
|
|
|
|
gint bbox_y1 = 0;
|
|
|
|
|
|
|
|
has_bbox = ps_read_header (file, NULL, &is_pdf, &is_epsf,
|
|
|
|
&bbox_x0, &bbox_y0, &bbox_x1, &bbox_y1);
|
|
|
|
|
|
|
|
if (has_bbox)
|
|
|
|
{
|
|
|
|
extracted_dimensions->width = (gdouble) bbox_x1 - bbox_x0;
|
|
|
|
extracted_dimensions->height = (gdouble) bbox_y1 - bbox_y0;
|
Issue #8900 and #9923: reimplementing GimpUnit as a proper class.
This fixes all our GObject Introspection issues with GimpUnit which was
both an enum and an int-derived type of user-defined units *completing*
the enum values. GIR clearly didn't like this!
Now GimpUnit is a proper class and units are unique objects, allowing to
compare them with an identity test (i.e. `unit == gimp_unit_pixel ()`
tells us if unit is the pixel unit or not), which makes it easy to use,
just like with int, yet adding also methods, making for nicer
introspected API.
As an aside, this also fixes #10738, by having all the built-in units
retrievable even if libgimpbase had not been properly initialized with
gimp_base_init().
I haven't checked in details how GIR works to introspect, but it looks
like it loads the library to inspect and runs functions, hence
triggering some CRITICALS because virtual methods (supposed to be
initialized with gimp_base_init() run by libgimp) are not set. This new
code won't trigger any critical because the vtable method are now not
necessary, at least for all built-in units.
Note that GimpUnit is still in libgimpbase. It could have been moved to
libgimp in order to avoid any virtual method table (since we need to
keep core and libgimp side's units in sync, PDB is required), but too
many libgimpwidgets widgets were already using GimpUnit. And technically
most of GimpUnit logic doesn't require PDB (only the creation/sync
part). This is one of the reasons why user-created GimpUnit list is
handled and stored differently from other types of objects.
Globally this simplifies the code a lot too and we don't need separate
implementations of various utils for core and libgimp, which means less
prone to errors.
2024-07-25 20:55:21 +02:00
|
|
|
extracted_dimensions->width_unit = gimp_unit_point ();
|
|
|
|
extracted_dimensions->height_unit = gimp_unit_point ();
|
2024-04-30 01:28:40 +02:00
|
|
|
extracted_dimensions->exact_width = TRUE;
|
|
|
|
extracted_dimensions->exact_height = TRUE;
|
|
|
|
extracted_dimensions->correct_ratio = TRUE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-18 17:04:53 +02:00
|
|
|
static GimpValueArray *
|
2023-08-06 02:56:44 +02:00
|
|
|
ps_load (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
|
|
|
GFile *file,
|
2024-04-24 01:12:01 +02:00
|
|
|
gint width,
|
|
|
|
gint height,
|
2024-04-26 01:07:59 +02:00
|
|
|
GimpVectorLoadData extracted_data,
|
2023-08-06 02:56:44 +02:00
|
|
|
GimpMetadata *metadata,
|
|
|
|
GimpMetadataLoadFlags *flags,
|
|
|
|
GimpProcedureConfig *config,
|
2024-04-26 01:07:59 +02:00
|
|
|
gpointer data_from_extract,
|
2023-08-06 02:56:44 +02:00
|
|
|
gpointer run_data)
|
2019-08-18 17:04:53 +02:00
|
|
|
{
|
2023-08-06 02:56:44 +02:00
|
|
|
GimpValueArray *return_vals;
|
|
|
|
GimpImage *image = NULL;
|
|
|
|
GError *error = NULL;
|
2019-08-18 17:04:53 +02:00
|
|
|
|
|
|
|
gegl_init (NULL, NULL);
|
|
|
|
|
|
|
|
l_run_mode = run_mode;
|
|
|
|
|
2024-04-24 01:12:01 +02:00
|
|
|
/* Why these values? No idea, they were the default until now, I just reuse
|
|
|
|
* them. XXX
|
|
|
|
*/
|
|
|
|
if (width == 0)
|
|
|
|
g_object_set (config, "width", 826, NULL);
|
|
|
|
if (height == 0)
|
|
|
|
g_object_set (config, "height", 1170, NULL);
|
|
|
|
|
2019-08-18 17:04:53 +02:00
|
|
|
switch (run_mode)
|
|
|
|
{
|
|
|
|
case GIMP_RUN_INTERACTIVE:
|
2024-06-08 18:37:38 +02:00
|
|
|
if (! load_dialog (file, extracted_data, procedure, G_OBJECT (config)))
|
2019-08-18 17:04:53 +02:00
|
|
|
return gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_CANCEL,
|
|
|
|
NULL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2024-04-27 16:49:31 +00:00
|
|
|
check_load_vals (config);
|
2019-08-18 17:04:53 +02:00
|
|
|
|
2024-04-27 16:49:31 +00:00
|
|
|
image = load_image (file, config, &error);
|
2023-02-21 18:55:53 +00:00
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
if (! image)
|
2019-08-18 17:04:53 +02:00
|
|
|
return gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_EXECUTION_ERROR,
|
|
|
|
error);
|
|
|
|
|
|
|
|
return_vals = gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_SUCCESS,
|
|
|
|
NULL);
|
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
GIMP_VALUES_SET_IMAGE (return_vals, 1, image);
|
2019-08-18 17:04:53 +02:00
|
|
|
|
|
|
|
return return_vals;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GimpValueArray *
|
2023-08-11 02:01:05 +02:00
|
|
|
ps_load_thumb (GimpProcedure *procedure,
|
|
|
|
GFile *file,
|
|
|
|
gint size,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
gpointer run_data)
|
2019-08-18 17:04:53 +02:00
|
|
|
{
|
2023-08-11 02:01:05 +02:00
|
|
|
GimpValueArray *return_vals;
|
|
|
|
GimpImage *image = NULL;
|
|
|
|
GError *error = NULL;
|
2019-08-18 17:04:53 +02:00
|
|
|
|
|
|
|
gegl_init (NULL, NULL);
|
|
|
|
|
|
|
|
/* We should look for an embedded preview but for now we
|
|
|
|
* just load the document at a small resolution and the
|
|
|
|
* first page only.
|
|
|
|
*/
|
2023-02-21 18:55:53 +00:00
|
|
|
check_load_vals (NULL);
|
2019-08-18 17:04:53 +02:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
image = load_image (file, NULL, &error);
|
2019-08-18 17:04:53 +02:00
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
if (! image)
|
2019-08-18 17:04:53 +02:00
|
|
|
return gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_EXECUTION_ERROR,
|
|
|
|
error);
|
|
|
|
|
|
|
|
return_vals = gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_SUCCESS,
|
|
|
|
NULL);
|
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
GIMP_VALUES_SET_IMAGE (return_vals, 1, image);
|
2019-08-18 17:04:53 +02:00
|
|
|
|
2019-08-19 14:04:00 +02:00
|
|
|
gimp_value_array_truncate (return_vals, 2);
|
|
|
|
|
2019-08-18 17:04:53 +02:00
|
|
|
return return_vals;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GimpValueArray *
|
2024-04-13 15:10:25 +00:00
|
|
|
ps_export (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
|
|
|
GimpImage *image,
|
|
|
|
GFile *file,
|
2024-05-06 18:38:12 +00:00
|
|
|
GimpExportOptions *options,
|
2024-04-13 15:10:25 +00:00
|
|
|
GimpMetadata *metadata,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
gpointer run_data)
|
2019-08-18 17:04:53 +02:00
|
|
|
{
|
2023-07-21 18:08:00 +02:00
|
|
|
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
|
2024-04-30 04:25:51 +00:00
|
|
|
GimpExportReturn export = GIMP_EXPORT_IGNORE;
|
2024-04-30 13:50:24 +00:00
|
|
|
GList *drawables;
|
2023-07-21 18:08:00 +02:00
|
|
|
GimpImage *orig_image;
|
|
|
|
gboolean eps_flag = FALSE;
|
|
|
|
GError *error = NULL;
|
2019-08-18 17:04:53 +02:00
|
|
|
|
|
|
|
gegl_init (NULL, NULL);
|
|
|
|
|
2024-04-13 15:10:25 +00:00
|
|
|
eps_flag = strcmp (gimp_procedure_get_name (procedure), EXPORT_PS_PROC);
|
2023-02-21 18:55:53 +00:00
|
|
|
g_object_set (config,
|
|
|
|
"eps-flag", eps_flag ? 1 : 0,
|
|
|
|
NULL);
|
2019-08-18 17:04:53 +02:00
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
orig_image = image;
|
2019-08-18 17:04:53 +02:00
|
|
|
|
|
|
|
switch (run_mode)
|
|
|
|
{
|
|
|
|
case GIMP_RUN_INTERACTIVE:
|
2019-09-20 19:39:00 +02:00
|
|
|
gimp_ui_init (PLUG_IN_BINARY);
|
2023-02-21 18:55:53 +00:00
|
|
|
ps_set_save_size (G_OBJECT (config), orig_image);
|
2019-08-18 17:04:53 +02:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
if (! save_dialog (procedure, G_OBJECT (config), image))
|
2019-08-18 17:04:53 +02:00
|
|
|
status = GIMP_PDB_CANCEL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_RUN_NONINTERACTIVE:
|
|
|
|
case GIMP_RUN_WITH_LAST_VALS:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2024-05-06 18:38:12 +00:00
|
|
|
export = gimp_export_options_get_image (options, &image);
|
2024-07-14 20:12:57 +00:00
|
|
|
drawables = gimp_image_list_layers (image);
|
|
|
|
|
2019-08-18 17:04:53 +02:00
|
|
|
if (status == GIMP_PDB_SUCCESS)
|
|
|
|
{
|
2023-02-21 18:55:53 +00:00
|
|
|
gdouble width = 0.0;
|
|
|
|
gdouble height = 0.0;
|
2019-08-18 17:04:53 +02:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
if (config)
|
|
|
|
g_object_get (config,
|
|
|
|
"width", &width,
|
|
|
|
"height", &height,
|
|
|
|
NULL);
|
2019-08-18 17:04:53 +02:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
if ((width == 0.0) || (height == 0.0))
|
|
|
|
ps_set_save_size (G_OBJECT (config), orig_image);
|
|
|
|
|
2024-04-27 16:49:31 +00:00
|
|
|
check_save_vals (config);
|
2023-02-21 18:55:53 +00:00
|
|
|
|
2024-04-30 13:50:24 +00:00
|
|
|
if (! export_image (file, G_OBJECT (config), image, drawables->data,
|
|
|
|
&error))
|
2023-02-21 18:55:53 +00:00
|
|
|
status = GIMP_PDB_EXECUTION_ERROR;
|
2019-08-18 17:04:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (export == GIMP_EXPORT_EXPORT)
|
2024-04-30 13:50:24 +00:00
|
|
|
gimp_image_delete (image);
|
2019-08-18 17:04:53 +02:00
|
|
|
|
2024-04-30 13:50:24 +00:00
|
|
|
g_list_free (drawables);
|
2019-08-18 17:04:53 +02:00
|
|
|
return gimp_procedure_new_return_values (procedure, status, error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-27 12:28:46 +00:00
|
|
|
static void compress_packbits (int nin,
|
2000-03-10 17:27:25 +00:00
|
|
|
unsigned char *src,
|
2003-11-27 12:28:46 +00:00
|
|
|
int *nout,
|
2000-03-10 17:27:25 +00:00
|
|
|
unsigned char *dst);
|
|
|
|
|
2005-10-28 14:57:32 +00:00
|
|
|
static guint32 ascii85_buf = 0;
|
|
|
|
static gint ascii85_len = 0;
|
|
|
|
static gint ascii85_linewidth = 0;
|
|
|
|
|
2005-08-15 08:48:45 +00:00
|
|
|
static GimpPageSelectorTarget ps_pagemode = GIMP_PAGE_SELECTOR_TARGET_LAYERS;
|
2000-01-22 22:26:20 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
ascii85_init (void)
|
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
ascii85_len = 0;
|
2000-01-25 17:46:56 +00:00
|
|
|
ascii85_linewidth = 0;
|
2000-01-22 22:26:20 +00:00
|
|
|
}
|
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
static gboolean
|
|
|
|
ascii85_flush (GOutputStream *output,
|
|
|
|
GError **error)
|
2000-01-22 22:26:20 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
gchar c[5];
|
|
|
|
gint i;
|
2000-01-25 17:46:56 +00:00
|
|
|
gboolean zero_case = (ascii85_buf == 0);
|
2014-10-26 18:54:42 +01:00
|
|
|
GString *string = g_string_new (NULL);
|
|
|
|
|
|
|
|
static gint max_linewidth = 75;
|
2000-01-22 22:26:20 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
for (i = 4; i >= 0; i--)
|
2000-01-22 22:26:20 +00:00
|
|
|
{
|
2000-01-25 17:46:56 +00:00
|
|
|
c[i] = (ascii85_buf % 85) + '!';
|
|
|
|
ascii85_buf /= 85;
|
2000-01-22 22:26:20 +00:00
|
|
|
}
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
/* check for special case: "!!!!!" becomes "z", but only if not
|
|
|
|
* at end of data. */
|
|
|
|
if (zero_case && (ascii85_len == 4))
|
2000-01-22 22:26:20 +00:00
|
|
|
{
|
2000-03-25 22:19:17 +00:00
|
|
|
if (ascii85_linewidth >= max_linewidth)
|
2014-10-26 18:54:42 +01:00
|
|
|
{
|
|
|
|
g_string_append_c (string, '\n');
|
|
|
|
|
|
|
|
ascii85_linewidth = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_string_append_c (string, 'z');
|
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
ascii85_linewidth++;
|
2000-01-22 22:26:20 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
else
|
2000-01-22 22:26:20 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
for (i = 0; i < ascii85_len + 1; i++)
|
2000-03-25 22:19:17 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
if ((ascii85_linewidth >= max_linewidth) && (c[i] != '%'))
|
|
|
|
{
|
|
|
|
g_string_append_c (string, '\n');
|
|
|
|
|
|
|
|
ascii85_linewidth = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_string_append_c (string, c[i]);
|
|
|
|
|
|
|
|
ascii85_linewidth++;
|
2000-03-25 22:19:17 +00:00
|
|
|
}
|
2000-01-22 22:26:20 +00:00
|
|
|
}
|
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
ascii85_len = 0;
|
|
|
|
ascii85_buf = 0;
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
if (string->len > 0 &&
|
|
|
|
! g_output_stream_write_all (output,
|
|
|
|
string->str, string->len, NULL,
|
|
|
|
NULL, error))
|
|
|
|
{
|
|
|
|
g_string_free (string, TRUE);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_string_free (string, TRUE);
|
|
|
|
|
|
|
|
return TRUE;
|
2000-01-22 22:26:20 +00:00
|
|
|
}
|
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
static inline gboolean
|
|
|
|
ascii85_out (GOutputStream *output,
|
|
|
|
guchar byte,
|
|
|
|
GError **error)
|
2000-01-22 22:26:20 +00:00
|
|
|
{
|
2000-01-25 17:46:56 +00:00
|
|
|
if (ascii85_len == 4)
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! ascii85_flush (output, error))
|
|
|
|
return FALSE;
|
2000-01-22 22:26:20 +00:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
ascii85_buf <<= 8;
|
|
|
|
ascii85_buf |= byte;
|
|
|
|
ascii85_len++;
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
return TRUE;
|
2000-01-22 22:26:20 +00:00
|
|
|
}
|
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
static gboolean
|
|
|
|
ascii85_nout (GOutputStream *output,
|
|
|
|
gint n,
|
|
|
|
guchar *uptr,
|
|
|
|
GError **error)
|
2000-03-10 17:27:25 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
while (n-- > 0)
|
|
|
|
{
|
|
|
|
if (! ascii85_out (output, *uptr, error))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
uptr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
2000-03-10 17:27:25 +00:00
|
|
|
}
|
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
static gboolean
|
|
|
|
ascii85_done (GOutputStream *output,
|
|
|
|
GError **error)
|
2000-01-22 22:26:20 +00:00
|
|
|
{
|
2000-01-25 17:46:56 +00:00
|
|
|
if (ascii85_len)
|
2000-01-22 22:26:20 +00:00
|
|
|
{
|
2000-01-25 17:46:56 +00:00
|
|
|
/* zero any unfilled buffer portion, then flush */
|
2014-10-26 18:54:42 +01:00
|
|
|
ascii85_buf <<= (8 * (4 - ascii85_len));
|
|
|
|
|
|
|
|
if (! ascii85_flush (output, error))
|
|
|
|
return FALSE;
|
2000-01-22 22:26:20 +00:00
|
|
|
}
|
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! print (output, error, "~>\n"))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
2000-01-22 22:26:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-03-10 17:27:25 +00:00
|
|
|
static void
|
|
|
|
compress_packbits (int nin,
|
|
|
|
unsigned char *src,
|
|
|
|
int *nout,
|
|
|
|
unsigned char *dst)
|
|
|
|
|
2013-05-15 00:22:38 +05:30
|
|
|
{
|
|
|
|
unsigned char c;
|
2000-03-10 17:27:25 +00:00
|
|
|
int nrepeat, nliteral;
|
|
|
|
unsigned char *run_start;
|
|
|
|
unsigned char *start_dst = dst;
|
|
|
|
unsigned char *last_literal = NULL;
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (nin <= 0) break;
|
|
|
|
|
|
|
|
run_start = src;
|
|
|
|
c = *run_start;
|
|
|
|
|
|
|
|
/* Search repeat bytes */
|
|
|
|
if ((nin > 1) && (c == src[1]))
|
|
|
|
{
|
|
|
|
nrepeat = 1;
|
|
|
|
nin -= 2;
|
|
|
|
src += 2;
|
|
|
|
while ((nin > 0) && (c == *src))
|
|
|
|
{
|
|
|
|
nrepeat++;
|
|
|
|
src++;
|
|
|
|
nin--;
|
|
|
|
if (nrepeat == 127) break; /* Maximum repeat */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add two-byte repeat to last literal run ? */
|
|
|
|
if ( (nrepeat == 1)
|
|
|
|
&& (last_literal != NULL) && (((*last_literal)+1)+2 <= 128))
|
|
|
|
{
|
|
|
|
*last_literal += 2;
|
|
|
|
*(dst++) = c;
|
|
|
|
*(dst++) = c;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add repeat run */
|
|
|
|
*(dst++) = (unsigned char)((-nrepeat) & 0xff);
|
|
|
|
*(dst++) = c;
|
|
|
|
last_literal = NULL;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* Search literal bytes */
|
|
|
|
nliteral = 1;
|
|
|
|
nin--;
|
|
|
|
src++;
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (nin <= 0) break;
|
|
|
|
|
|
|
|
if ((nin >= 2) && (src[0] == src[1])) /* A two byte repeat ? */
|
|
|
|
break;
|
|
|
|
|
|
|
|
nliteral++;
|
|
|
|
nin--;
|
|
|
|
src++;
|
|
|
|
if (nliteral == 128) break; /* Maximum literal run */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Could be added to last literal run ? */
|
|
|
|
if ((last_literal != NULL) && (((*last_literal)+1)+nliteral <= 128))
|
|
|
|
{
|
|
|
|
*last_literal += nliteral;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
last_literal = dst;
|
|
|
|
*(dst++) = (unsigned char)(nliteral-1);
|
|
|
|
}
|
|
|
|
while (nliteral-- > 0) *(dst++) = *(run_start++);
|
|
|
|
}
|
|
|
|
*nout = dst - start_dst;
|
|
|
|
}
|
|
|
|
|
2000-01-22 22:26:20 +00:00
|
|
|
|
2000-04-05 10:26:08 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
goffset eol;
|
|
|
|
goffset begin_data;
|
2000-04-05 10:26:08 +00:00
|
|
|
} PS_DATA_POS;
|
|
|
|
|
|
|
|
static PS_DATA_POS ps_data_pos = { 0, 0 };
|
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
static gboolean
|
|
|
|
ps_begin_data (GOutputStream *output,
|
|
|
|
GError **error)
|
2000-04-05 10:26:08 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
/* %%BeginData: 123456789012 ASCII Bytes */
|
|
|
|
if (! print (output, error, "%s", "%%BeginData: "))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
ps_data_pos.eol = g_seekable_tell (G_SEEKABLE (output));
|
|
|
|
|
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
ps_data_pos.begin_data = g_seekable_tell (G_SEEKABLE (output));
|
|
|
|
|
|
|
|
return TRUE;
|
2000-04-05 10:26:08 +00:00
|
|
|
}
|
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
static gboolean
|
|
|
|
ps_end_data (GOutputStream *output,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
goffset end_data;
|
|
|
|
gchar s[64];
|
2000-04-05 10:26:08 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
if ((ps_data_pos.begin_data > 0) && (ps_data_pos.eol > 0))
|
|
|
|
{
|
|
|
|
end_data = g_seekable_tell (G_SEEKABLE (output));
|
2000-04-05 10:26:08 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
if (end_data > 0)
|
|
|
|
{
|
|
|
|
g_snprintf (s, sizeof (s),
|
2020-05-26 12:12:10 +02:00
|
|
|
"%"G_GOFFSET_FORMAT" ASCII Bytes", end_data - ps_data_pos.begin_data);
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
if (! g_seekable_seek (G_SEEKABLE (output),
|
|
|
|
ps_data_pos.eol - strlen (s), G_SEEK_SET,
|
|
|
|
NULL, error))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (! print (output, error, "%s", s))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (! g_seekable_seek (G_SEEKABLE (output),
|
|
|
|
end_data, G_SEEK_SET,
|
|
|
|
NULL, error))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! print (output, error, "%s\n", "%%EndData"))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
2000-04-05 10:26:08 +00:00
|
|
|
}
|
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
static GimpImage *
|
2024-04-27 16:49:31 +00:00
|
|
|
load_image (GFile *file,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
GError **error)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2021-10-12 17:17:38 -04:00
|
|
|
GimpImage *image = NULL;
|
|
|
|
GimpImage **image_list, **nl;
|
|
|
|
const gchar *filename;
|
2023-02-21 18:55:53 +00:00
|
|
|
gint width;
|
|
|
|
gint height;
|
2024-04-24 01:12:01 +02:00
|
|
|
gdouble resolution;
|
2024-04-27 16:49:31 +00:00
|
|
|
gchar *pnm_type = NULL;
|
|
|
|
gchar *text_alpha = NULL;
|
|
|
|
gchar *graphics_alpha = NULL;
|
2023-02-21 18:55:53 +00:00
|
|
|
gchar *pages;
|
2021-10-12 17:17:38 -04:00
|
|
|
guint page_count;
|
|
|
|
FILE *ifp;
|
|
|
|
gchar *temp;
|
|
|
|
gint llx, lly, urx, ury;
|
|
|
|
gint k, n_images, max_images, max_pagenum;
|
|
|
|
gboolean is_epsf;
|
2022-05-16 14:31:50 +00:00
|
|
|
GdkPixbuf *pixbuf = NULL;
|
|
|
|
gchar *tmp_filename = NULL;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
if (config)
|
|
|
|
{
|
|
|
|
g_object_get (config,
|
2024-04-24 01:12:01 +02:00
|
|
|
"pixel-density", &resolution,
|
2023-02-21 18:55:53 +00:00
|
|
|
"width", &width,
|
|
|
|
"height", &height,
|
|
|
|
"pages", &pages,
|
|
|
|
"coloring", &pnm_type,
|
|
|
|
"text-alpha-bits", &text_alpha,
|
2024-04-27 16:49:31 +00:00
|
|
|
"graphic-alpha-bits", &graphics_alpha,
|
2023-02-21 18:55:53 +00:00
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pages = g_strdup_printf ("1");
|
|
|
|
}
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
#ifdef PS_DEBUG
|
2024-04-24 01:12:01 +02:00
|
|
|
g_print ("load_image:\n resolution = %f\n", resolution);
|
2023-02-21 18:55:53 +00:00
|
|
|
g_print (" %dx%d pixels\n", width, height);
|
2024-04-27 16:49:31 +00:00
|
|
|
g_print (" Coloring: %s\n", pnm_type);
|
|
|
|
g_print (" TextAlphaBits: %s\n", text_alpha);
|
|
|
|
g_print (" GraphicsAlphaBits: %s\n", graphics_alpha);
|
1997-11-24 22:05:25 +00:00
|
|
|
#endif
|
|
|
|
|
2014-07-23 16:39:00 +02:00
|
|
|
gimp_progress_init_printf (_("Opening '%s'"),
|
2019-09-11 21:48:34 +02:00
|
|
|
gimp_file_get_utf8_name (file));
|
2014-07-23 16:39:00 +02:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
/* Try to see if PostScript file is available */
|
2021-08-07 17:22:27 -04:00
|
|
|
filename = gimp_file_get_utf8_name (file);
|
2005-03-04 15:12:29 +00:00
|
|
|
ifp = g_fopen (filename, "r");
|
2019-09-11 21:48:34 +02:00
|
|
|
|
|
|
|
if (! ifp)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2008-08-18 06:53:21 +00:00
|
|
|
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
|
|
|
|
_("Could not open '%s' for reading: %s"),
|
2019-09-11 21:48:34 +02:00
|
|
|
gimp_file_get_utf8_name (file), g_strerror (errno));
|
2019-08-19 15:46:53 +02:00
|
|
|
return NULL;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
|
|
|
fclose (ifp);
|
|
|
|
|
2024-04-27 16:49:31 +00:00
|
|
|
ifp = ps_open (file, config, &llx, &lly, &urx, &ury, &is_epsf,
|
|
|
|
&tmp_filename);
|
2000-01-25 17:46:56 +00:00
|
|
|
if (!ifp)
|
|
|
|
{
|
2008-08-20 14:00:44 +00:00
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR,
|
2016-03-19 22:45:16 +01:00
|
|
|
_("Could not interpret PostScript file '%s'"),
|
2019-09-11 21:48:34 +02:00
|
|
|
gimp_file_get_utf8_name (file));
|
2019-08-19 15:46:53 +02:00
|
|
|
return NULL;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
image_list = g_new (GimpImage *, 10);
|
2000-01-25 17:46:56 +00:00
|
|
|
n_images = 0;
|
|
|
|
max_images = 10;
|
|
|
|
|
|
|
|
max_pagenum = 9999; /* Try to get the maximum pagenumber to read */
|
2004-11-18 21:10:12 +00:00
|
|
|
if (is_epsf)
|
2022-05-16 14:31:50 +00:00
|
|
|
{
|
|
|
|
max_pagenum = 1;
|
|
|
|
/* Use pixbuf to load transparent EPS as PNGs */
|
|
|
|
pixbuf = gdk_pixbuf_new_from_file (tmp_filename, error);
|
|
|
|
if (! pixbuf)
|
|
|
|
return NULL;
|
|
|
|
}
|
2004-11-18 21:10:12 +00:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
if (! page_in_list (pages, max_pagenum)) /* Is there a limit in list ? */
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
|
|
|
max_pagenum = -1;
|
2023-02-21 18:55:53 +00:00
|
|
|
for (temp = pages; *temp != '\0'; temp++)
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
|
|
|
if ((*temp < '0') || (*temp > '9'))
|
2004-11-18 21:10:12 +00:00
|
|
|
continue; /* Search next digit */
|
2006-05-08 12:23:32 +00:00
|
|
|
sscanf (temp, "%d", &k);
|
|
|
|
if (k > max_pagenum)
|
2004-11-18 21:10:12 +00:00
|
|
|
max_pagenum = k;
|
2006-05-08 12:23:32 +00:00
|
|
|
while ((*temp >= '0') && (*temp <= '9'))
|
2004-11-18 21:10:12 +00:00
|
|
|
temp++;
|
2006-05-08 12:23:32 +00:00
|
|
|
temp--;
|
|
|
|
}
|
2004-11-18 21:10:12 +00:00
|
|
|
|
|
|
|
if (max_pagenum < 1)
|
|
|
|
max_pagenum = 9999;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Load all images */
|
|
|
|
for (page_count = 1; page_count <= max_pagenum; page_count++)
|
|
|
|
{
|
2023-02-21 18:55:53 +00:00
|
|
|
if (page_in_list (pages, page_count))
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
2019-09-11 21:48:34 +02:00
|
|
|
image = load_ps (file, page_count, ifp, llx, lly, urx, ury);
|
2019-08-19 15:46:53 +02:00
|
|
|
if (! image)
|
2004-11-18 21:10:12 +00:00
|
|
|
break;
|
2001-05-22 00:36:38 +00:00
|
|
|
|
2024-04-24 01:12:01 +02:00
|
|
|
gimp_image_set_resolution (image, resolution, resolution);
|
2006-05-08 12:23:32 +00:00
|
|
|
|
|
|
|
if (n_images == max_images)
|
|
|
|
{
|
2019-08-19 15:46:53 +02:00
|
|
|
nl = (GimpImage **) g_realloc (image_list,
|
|
|
|
(max_images+10)*sizeof (GimpImage *));
|
2006-05-08 12:23:32 +00:00
|
|
|
if (nl == NULL) break;
|
|
|
|
image_list = nl;
|
|
|
|
max_images += 10;
|
|
|
|
}
|
2019-08-19 15:46:53 +02:00
|
|
|
image_list[n_images++] = image;
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
else /* Skip an image */
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
2019-08-19 15:46:53 +02:00
|
|
|
image = NULL;
|
2006-05-08 12:23:32 +00:00
|
|
|
if (! skip_ps (ifp))
|
2004-11-18 21:10:12 +00:00
|
|
|
break;
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
2004-11-18 21:10:12 +00:00
|
|
|
|
2022-05-16 14:31:50 +00:00
|
|
|
ps_close (ifp, tmp_filename);
|
|
|
|
|
|
|
|
/* EPS are now imported using pngalpha, so they can be converted
|
|
|
|
* to a layer with gimp_layer_new_from_pixbuf () and exported at
|
|
|
|
* this part of the loading process
|
|
|
|
*/
|
|
|
|
if (is_epsf)
|
|
|
|
{
|
|
|
|
GimpLayer *layer;
|
|
|
|
|
|
|
|
image = gimp_image_new (urx, ury, GIMP_RGB);
|
|
|
|
|
|
|
|
gimp_image_undo_disable (image);
|
2023-02-21 18:55:53 +00:00
|
|
|
gimp_image_set_resolution (image, resolution, resolution);
|
2022-05-16 14:31:50 +00:00
|
|
|
|
|
|
|
layer = gimp_layer_new_from_pixbuf (image, _("Rendered EPS"), pixbuf,
|
|
|
|
100,
|
|
|
|
gimp_image_get_default_new_layer_mode (image),
|
|
|
|
0.0, 1.0);
|
|
|
|
gimp_image_insert_layer (image, layer, NULL, 0);
|
|
|
|
|
|
|
|
gimp_image_undo_enable (image);
|
|
|
|
|
|
|
|
g_free (image_list);
|
|
|
|
g_object_unref (pixbuf);
|
|
|
|
|
|
|
|
return image;
|
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2005-08-15 08:48:45 +00:00
|
|
|
if (ps_pagemode == GIMP_PAGE_SELECTOR_TARGET_LAYERS)
|
|
|
|
{
|
|
|
|
for (k = 0; k < n_images; k++)
|
|
|
|
{
|
|
|
|
if (k == 0)
|
|
|
|
{
|
2019-09-11 21:48:34 +02:00
|
|
|
GFile *new_file;
|
|
|
|
gchar *uri;
|
|
|
|
gchar *new_uri;
|
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
image = image_list[0];
|
2005-08-15 08:48:45 +00:00
|
|
|
|
2019-09-11 21:48:34 +02:00
|
|
|
uri = g_file_get_uri (file);
|
|
|
|
|
|
|
|
new_uri = g_strdup_printf (_("%s-pages"), uri);
|
|
|
|
g_free (uri);
|
|
|
|
|
|
|
|
new_file = g_file_new_for_uri (new_uri);
|
|
|
|
g_free (new_uri);
|
|
|
|
|
|
|
|
g_object_unref (new_file);
|
2005-08-15 08:48:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-07-19 22:44:58 +02:00
|
|
|
GimpLayer *current_layer;
|
|
|
|
gchar *name;
|
2024-10-21 21:59:26 +02:00
|
|
|
GimpDrawable **tmp_drawables;
|
2005-08-15 08:48:45 +00:00
|
|
|
|
2024-10-21 21:59:26 +02:00
|
|
|
tmp_drawables = gimp_image_get_selected_drawables (image_list[k]);
|
2005-08-15 08:48:45 +00:00
|
|
|
|
2022-07-19 22:44:58 +02:00
|
|
|
name = gimp_item_get_name (GIMP_ITEM (tmp_drawables[0]));
|
2005-08-15 08:48:45 +00:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
current_layer = gimp_layer_new_from_drawable (GIMP_DRAWABLE (tmp_drawables[0]),
|
|
|
|
image);
|
2019-08-19 15:46:53 +02:00
|
|
|
gimp_item_set_name (GIMP_ITEM (current_layer), name);
|
|
|
|
gimp_image_insert_layer (image, current_layer, NULL, -1);
|
2005-08-15 08:48:45 +00:00
|
|
|
gimp_image_delete (image_list[k]);
|
|
|
|
|
2022-07-19 22:44:58 +02:00
|
|
|
g_free (tmp_drawables);
|
2005-08-15 08:48:45 +00:00
|
|
|
g_free (name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
gimp_image_undo_enable (image);
|
2005-08-15 08:48:45 +00:00
|
|
|
}
|
|
|
|
else
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2005-08-15 08:48:45 +00:00
|
|
|
/* Display images in reverse order.
|
|
|
|
* The last will be displayed by GIMP itself
|
|
|
|
*/
|
|
|
|
for (k = n_images - 1; k >= 0; k--)
|
|
|
|
{
|
|
|
|
gimp_image_undo_enable (image_list[k]);
|
|
|
|
gimp_image_clean_all (image_list[k]);
|
|
|
|
|
|
|
|
if (l_run_mode != GIMP_RUN_NONINTERACTIVE && k > 0)
|
|
|
|
gimp_display_new (image_list[k]);
|
|
|
|
}
|
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
image = (n_images > 0) ? image_list[0] : NULL;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
g_free (image_list);
|
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
return image;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
static gboolean
|
2024-04-13 15:10:25 +00:00
|
|
|
export_image (GFile *file,
|
|
|
|
GObject *config,
|
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GError **error)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
GOutputStream *output;
|
2018-11-27 12:27:20 +01:00
|
|
|
GCancellable *cancellable;
|
2014-10-26 18:54:42 +01:00
|
|
|
GimpImageType drawable_type;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
drawable_type = gimp_drawable_type (drawable);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2016-02-16 02:35:43 +01:00
|
|
|
/* Make sure we're not exporting an image with an alpha channel */
|
2019-08-19 15:46:53 +02:00
|
|
|
if (gimp_drawable_has_alpha (drawable))
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2008-08-20 14:00:44 +00:00
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
2016-02-16 02:35:43 +01:00
|
|
|
_("PostScript export cannot handle images with alpha channels"));
|
2000-01-25 17:46:56 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
switch (drawable_type)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2000-08-22 01:26:57 +00:00
|
|
|
case GIMP_INDEXED_IMAGE:
|
|
|
|
case GIMP_GRAY_IMAGE:
|
|
|
|
case GIMP_RGB_IMAGE:
|
1997-11-24 22:05:25 +00:00
|
|
|
break;
|
2014-10-26 18:54:42 +01:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
default:
|
2014-10-26 18:54:42 +01:00
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("Cannot operate on unknown image types."));
|
2004-11-18 21:10:12 +00:00
|
|
|
return FALSE;
|
1997-11-24 22:05:25 +00:00
|
|
|
break;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2016-02-16 02:35:43 +01:00
|
|
|
gimp_progress_init_printf (_("Exporting '%s'"),
|
2014-10-26 18:54:42 +01:00
|
|
|
gimp_file_get_utf8_name (file));
|
2014-07-23 16:39:00 +02:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
output = G_OUTPUT_STREAM (g_file_replace (file,
|
|
|
|
NULL, FALSE, G_FILE_CREATE_NONE,
|
|
|
|
NULL, error));
|
|
|
|
if (output)
|
|
|
|
{
|
|
|
|
GOutputStream *buffered;
|
|
|
|
|
|
|
|
buffered = g_buffered_output_stream_new (output);
|
|
|
|
g_object_unref (output);
|
|
|
|
|
|
|
|
output = buffered;
|
|
|
|
}
|
|
|
|
else
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2004-11-18 21:10:12 +00:00
|
|
|
return FALSE;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
if (! save_ps_header (output, file, config, error))
|
2014-10-26 18:54:42 +01:00
|
|
|
goto fail;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2011-10-10 09:56:32 +05:30
|
|
|
switch (drawable_type)
|
|
|
|
{
|
|
|
|
case GIMP_INDEXED_IMAGE:
|
2023-02-21 18:55:53 +00:00
|
|
|
if (! save_index (output, image, drawable, config, error))
|
2014-10-26 18:54:42 +01:00
|
|
|
goto fail;
|
2011-10-10 09:56:32 +05:30
|
|
|
break;
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2011-10-10 09:56:32 +05:30
|
|
|
case GIMP_GRAY_IMAGE:
|
2023-02-21 18:55:53 +00:00
|
|
|
if (! save_gray (output, image, drawable, config, error))
|
2014-10-26 18:54:42 +01:00
|
|
|
goto fail;
|
2011-10-10 09:56:32 +05:30
|
|
|
break;
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2011-10-10 09:56:32 +05:30
|
|
|
case GIMP_RGB_IMAGE:
|
2023-02-21 18:55:53 +00:00
|
|
|
if (! save_rgb (output, image, drawable, config, error))
|
2014-10-26 18:54:42 +01:00
|
|
|
goto fail;
|
2011-10-10 09:56:32 +05:30
|
|
|
break;
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2011-10-10 09:56:32 +05:30
|
|
|
default:
|
2014-10-26 18:54:42 +01:00
|
|
|
g_return_val_if_reached (FALSE);
|
2011-10-10 09:56:32 +05:30
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! save_ps_trailer (output, error))
|
|
|
|
goto fail;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! g_output_stream_close (output, NULL, error))
|
|
|
|
goto fail;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
g_object_unref (output);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
|
2018-11-27 12:27:20 +01:00
|
|
|
cancellable = g_cancellable_new ();
|
|
|
|
g_cancellable_cancel (cancellable);
|
|
|
|
g_output_stream_close (output, cancellable, NULL);
|
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
g_object_unref (output);
|
2018-11-27 12:27:20 +01:00
|
|
|
g_object_unref (cancellable);
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
return FALSE;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
/* Check (and correct) the load values */
|
1997-11-24 22:05:25 +00:00
|
|
|
static void
|
2024-04-27 16:49:31 +00:00
|
|
|
check_load_vals (GimpProcedureConfig *config)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2024-04-24 01:12:01 +02:00
|
|
|
gdouble resolution = GIMP_MIN_RESOLUTION;
|
|
|
|
gint width = 2;
|
|
|
|
gint height = 2;
|
2023-02-21 18:55:53 +00:00
|
|
|
gboolean use_bbox = FALSE;
|
|
|
|
gint pnm_type = 6;
|
|
|
|
gint text_alpha = 1;
|
|
|
|
gint graphics_alpha = 1;
|
2024-08-25 15:27:26 +02:00
|
|
|
gchar *pages = NULL;
|
2023-02-21 18:55:53 +00:00
|
|
|
|
|
|
|
if (config)
|
|
|
|
{
|
|
|
|
g_object_get (config,
|
2024-04-24 01:12:01 +02:00
|
|
|
"pixel-density", &resolution,
|
2023-02-21 18:55:53 +00:00
|
|
|
"width", &width,
|
|
|
|
"height", &height,
|
2024-04-27 16:49:31 +00:00
|
|
|
"check-bbox", &use_bbox,
|
2023-02-21 18:55:53 +00:00
|
|
|
"pages", &pages,
|
|
|
|
NULL);
|
2024-04-27 16:49:31 +00:00
|
|
|
pnm_type = gimp_procedure_config_get_choice_id (config, "coloring");
|
|
|
|
text_alpha = gimp_procedure_config_get_choice_id (config, "text-alpha-bits");
|
|
|
|
graphics_alpha = gimp_procedure_config_get_choice_id (config, "graphic-alpha-bits");
|
2023-02-21 18:55:53 +00:00
|
|
|
}
|
|
|
|
|
2024-04-24 01:12:01 +02:00
|
|
|
if (resolution < GIMP_MIN_RESOLUTION)
|
|
|
|
resolution = GIMP_MIN_RESOLUTION;
|
|
|
|
else if (resolution > GIMP_MAX_RESOLUTION)
|
|
|
|
resolution = GIMP_MAX_RESOLUTION;
|
2023-02-21 18:55:53 +00:00
|
|
|
|
|
|
|
if (width < 2)
|
|
|
|
width = 2;
|
|
|
|
if (height < 2)
|
|
|
|
height = 2;
|
|
|
|
use_bbox = (use_bbox != 0);
|
|
|
|
if (! pages)
|
|
|
|
pages = g_strdup_printf ("1-99");
|
|
|
|
if ((pnm_type < 4) || (pnm_type > 7))
|
|
|
|
pnm_type = 6;
|
|
|
|
if ((text_alpha != 1) && (text_alpha != 2) &&
|
|
|
|
(text_alpha != 4))
|
|
|
|
text_alpha = 1;
|
|
|
|
if ((graphics_alpha != 1) && (graphics_alpha != 2) &&
|
|
|
|
(graphics_alpha != 4))
|
|
|
|
graphics_alpha = 1;
|
|
|
|
|
|
|
|
if (config)
|
|
|
|
{
|
|
|
|
g_object_set (config,
|
2024-04-24 01:12:01 +02:00
|
|
|
"pixel-density", resolution,
|
2023-02-21 18:55:53 +00:00
|
|
|
"width", width,
|
|
|
|
"height", height,
|
|
|
|
"check_bbox", use_bbox ? 1 : 0,
|
|
|
|
"pages", pages,
|
|
|
|
NULL);
|
2024-04-27 16:49:31 +00:00
|
|
|
|
|
|
|
switch (pnm_type)
|
|
|
|
{
|
|
|
|
case 4:
|
|
|
|
g_object_set (config, "coloring", "bw", NULL);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
g_object_set (config, "coloring", "grayscale", NULL);
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
g_object_set (config, "coloring", "rgb", NULL);
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
default:
|
|
|
|
g_object_set (config, "coloring", "automatic", NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (text_alpha)
|
|
|
|
{
|
|
|
|
case 2:
|
|
|
|
g_object_set (config, "text-alpha-bits", "weak", NULL);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
g_object_set (config, "text-alpha-bits", "strong", NULL);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
default:
|
|
|
|
g_object_set (config, "text-alpha-bits", "none", NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (graphics_alpha)
|
|
|
|
{
|
|
|
|
case 2:
|
|
|
|
g_object_set (config, "graphic-alpha-bits", "weak", NULL);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
g_object_set (config, "graphic-alpha-bits", "strong", NULL);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
default:
|
|
|
|
g_object_set (config, "graphic-alpha-bits", "none", NULL);
|
|
|
|
}
|
2023-02-21 18:55:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
g_free (pages);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
/* Check (and correct) the save values */
|
1997-11-24 22:05:25 +00:00
|
|
|
static void
|
2024-04-27 16:49:31 +00:00
|
|
|
check_save_vals (GimpProcedureConfig *config)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2023-02-21 18:55:53 +00:00
|
|
|
gint i = 90;
|
|
|
|
gint preview_size = 0;
|
|
|
|
gboolean preview = TRUE;
|
|
|
|
|
|
|
|
g_object_get (config,
|
|
|
|
"rotation", &i,
|
|
|
|
"show-preview", &preview,
|
|
|
|
"preview", &preview_size,
|
|
|
|
NULL);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
if ((i != 0) && (i != 90) && (i != 180) && (i != 270))
|
2023-02-21 18:55:53 +00:00
|
|
|
i = 90;
|
|
|
|
if (preview_size <= 0)
|
|
|
|
preview = FALSE;
|
|
|
|
|
|
|
|
g_object_set (config,
|
|
|
|
"rotation", i,
|
|
|
|
"show-preview", preview ? 1 : 0,
|
|
|
|
"preview", preview_size,
|
|
|
|
NULL);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2019-08-18 17:04:53 +02:00
|
|
|
static void
|
2023-02-21 18:55:53 +00:00
|
|
|
ps_set_save_size (GObject *config,
|
|
|
|
GimpImage *image)
|
2019-08-18 17:04:53 +02:00
|
|
|
{
|
Issue #8900 and #9923: reimplementing GimpUnit as a proper class.
This fixes all our GObject Introspection issues with GimpUnit which was
both an enum and an int-derived type of user-defined units *completing*
the enum values. GIR clearly didn't like this!
Now GimpUnit is a proper class and units are unique objects, allowing to
compare them with an identity test (i.e. `unit == gimp_unit_pixel ()`
tells us if unit is the pixel unit or not), which makes it easy to use,
just like with int, yet adding also methods, making for nicer
introspected API.
As an aside, this also fixes #10738, by having all the built-in units
retrievable even if libgimpbase had not been properly initialized with
gimp_base_init().
I haven't checked in details how GIR works to introspect, but it looks
like it loads the library to inspect and runs functions, hence
triggering some CRITICALS because virtual methods (supposed to be
initialized with gimp_base_init() run by libgimp) are not set. This new
code won't trigger any critical because the vtable method are now not
necessary, at least for all built-in units.
Note that GimpUnit is still in libgimpbase. It could have been moved to
libgimp in order to avoid any virtual method table (since we need to
keep core and libgimp side's units in sync, PDB is required), but too
many libgimpwidgets widgets were already using GimpUnit. And technically
most of GimpUnit logic doesn't require PDB (only the creation/sync
part). This is one of the reasons why user-created GimpUnit list is
handled and stored differently from other types of objects.
Globally this simplifies the code a lot too and we don't need separate
implementations of various utils for core and libgimp, which means less
prone to errors.
2024-07-25 20:55:21 +02:00
|
|
|
gdouble xres, yres, factor, iw, ih;
|
|
|
|
guint width, height;
|
|
|
|
GimpUnit *unit;
|
|
|
|
gboolean unit_mm = FALSE;
|
2019-08-18 17:04:53 +02:00
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
gimp_image_get_resolution (image, &xres, &yres);
|
2019-08-18 17:04:53 +02:00
|
|
|
|
|
|
|
if ((xres < 1e-5) || (yres < 1e-5))
|
|
|
|
xres = yres = 72.0;
|
|
|
|
|
|
|
|
/* Calculate size of image in inches */
|
2021-04-06 00:47:07 +02:00
|
|
|
width = gimp_image_get_width (image);
|
|
|
|
height = gimp_image_get_height (image);
|
2019-08-18 17:04:53 +02:00
|
|
|
iw = width / xres;
|
|
|
|
ih = height / yres;
|
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
unit = gimp_image_get_unit (image);
|
2019-08-18 17:04:53 +02:00
|
|
|
factor = gimp_unit_get_factor (unit);
|
|
|
|
|
|
|
|
if (factor == 0.0254 ||
|
|
|
|
factor == 0.254 ||
|
|
|
|
factor == 2.54 ||
|
|
|
|
factor == 25.4)
|
|
|
|
{
|
2023-02-21 18:55:53 +00:00
|
|
|
unit_mm = TRUE;
|
2019-08-18 17:04:53 +02:00
|
|
|
}
|
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
if (unit_mm)
|
2019-08-18 17:04:53 +02:00
|
|
|
{
|
|
|
|
iw *= 25.4;
|
|
|
|
ih *= 25.4;
|
|
|
|
}
|
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
g_object_set (config,
|
2024-04-27 16:49:31 +00:00
|
|
|
"unit", unit_mm ? "millimeter" : "inch",
|
2023-02-21 18:55:53 +00:00
|
|
|
"width", iw,
|
|
|
|
"height", ih,
|
|
|
|
NULL);
|
2019-08-18 17:04:53 +02:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* Check if a page is in a given list */
|
|
|
|
static gint
|
2000-01-25 17:46:56 +00:00
|
|
|
page_in_list (gchar *list,
|
|
|
|
guint page_num)
|
|
|
|
{
|
|
|
|
char tmplist[STR_LENGTH], *c0, *c1;
|
|
|
|
int state, start_num, end_num;
|
1997-11-24 22:05:25 +00:00
|
|
|
#define READ_STARTNUM 0
|
|
|
|
#define READ_ENDNUM 1
|
|
|
|
#define CHK_LIST(a,b,c) {int low=(a),high=(b),swp; \
|
|
|
|
if ((low>0) && (high>0)) { \
|
|
|
|
if (low>high) {swp=low; low=high; high=swp;} \
|
|
|
|
if ((low<=(c))&&(high>=(c))) return (1); } }
|
|
|
|
|
2004-11-18 21:10:12 +00:00
|
|
|
if ((list == NULL) || (*list == '\0'))
|
|
|
|
return 1;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-08-14 23:52:38 +02:00
|
|
|
g_strlcpy (tmplist, list, STR_LENGTH);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
|
|
|
c0 = c1 = tmplist;
|
|
|
|
while (*c1) /* Remove all whitespace and break on unsupported characters */
|
|
|
|
{
|
|
|
|
if ((*c1 >= '0') && (*c1 <= '9'))
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
|
|
|
*(c0++) = *c1;
|
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
else if ((*c1 == '-') || (*c1 == ','))
|
2013-01-27 17:52:38 +02:00
|
|
|
{ /* Try to remove double occurrences of these characters */
|
2006-05-08 12:23:32 +00:00
|
|
|
if (c0 == tmplist)
|
|
|
|
{
|
|
|
|
*(c0++) = *c1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (*(c0-1) != *c1)
|
|
|
|
*(c0++) = *c1;
|
|
|
|
}
|
|
|
|
}
|
2004-11-18 21:10:12 +00:00
|
|
|
else
|
|
|
|
break;
|
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
c1++;
|
|
|
|
}
|
2004-11-18 21:10:12 +00:00
|
|
|
|
|
|
|
if (c0 == tmplist)
|
|
|
|
return 1;
|
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
*c0 = '\0';
|
|
|
|
|
|
|
|
/* Now we have a comma separated list like 1-4-1,-3,1- */
|
|
|
|
|
|
|
|
start_num = end_num = -1;
|
|
|
|
state = READ_STARTNUM;
|
|
|
|
for (c0 = tmplist; *c0 != '\0'; c0++)
|
|
|
|
{
|
|
|
|
switch (state)
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
|
|
|
case READ_STARTNUM:
|
|
|
|
if (*c0 == ',')
|
|
|
|
{
|
|
|
|
if ((start_num > 0) && (start_num == (int)page_num))
|
2004-11-18 21:10:12 +00:00
|
|
|
return -1;
|
2006-05-08 12:23:32 +00:00
|
|
|
start_num = -1;
|
|
|
|
}
|
|
|
|
else if (*c0 == '-')
|
|
|
|
{
|
|
|
|
if (start_num < 0) start_num = 1;
|
|
|
|
state = READ_ENDNUM;
|
|
|
|
}
|
|
|
|
else /* '0' - '9' */
|
|
|
|
{
|
|
|
|
if (start_num < 0) start_num = 0;
|
|
|
|
start_num *= 10;
|
|
|
|
start_num += *c0 - '0';
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case READ_ENDNUM:
|
|
|
|
if (*c0 == ',')
|
|
|
|
{
|
|
|
|
if (end_num < 0) end_num = 9999;
|
|
|
|
CHK_LIST (start_num, end_num, (int)page_num);
|
|
|
|
start_num = end_num = -1;
|
|
|
|
state = READ_STARTNUM;
|
|
|
|
}
|
|
|
|
else if (*c0 == '-')
|
|
|
|
{
|
|
|
|
CHK_LIST (start_num, end_num, (int)page_num);
|
|
|
|
start_num = end_num;
|
|
|
|
end_num = -1;
|
|
|
|
}
|
|
|
|
else /* '0' - '9' */
|
|
|
|
{
|
|
|
|
if (end_num < 0) end_num = 0;
|
|
|
|
end_num *= 10;
|
|
|
|
end_num += *c0 - '0';
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
|
|
|
if (state == READ_STARTNUM)
|
|
|
|
{
|
|
|
|
if (start_num > 0)
|
2006-05-08 12:23:32 +00:00
|
|
|
return (start_num == (int) page_num);
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (end_num < 0) end_num = 9999;
|
|
|
|
CHK_LIST (start_num, end_num, (int)page_num);
|
|
|
|
}
|
2004-11-18 21:10:12 +00:00
|
|
|
|
|
|
|
return 0;
|
1997-11-24 22:05:25 +00:00
|
|
|
#undef CHK_LIST
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-08-20 23:26:11 +00:00
|
|
|
/* A function like fgets, but treats single CR-character as line break. */
|
|
|
|
/* As a line break the newline-character is returned. */
|
|
|
|
static char *psfgets (char *s, int size, FILE *stream)
|
|
|
|
|
2004-11-18 21:10:12 +00:00
|
|
|
{
|
|
|
|
int c;
|
|
|
|
char *sptr = s;
|
2000-08-20 23:26:11 +00:00
|
|
|
|
2004-11-18 21:10:12 +00:00
|
|
|
if (size <= 0)
|
|
|
|
return NULL;
|
2000-08-20 23:26:11 +00:00
|
|
|
|
2004-11-18 21:10:12 +00:00
|
|
|
if (size == 1)
|
|
|
|
{
|
|
|
|
*s = '\0';
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = getc (stream);
|
|
|
|
if (c == EOF)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
/* At this point we have space in sptr for at least two characters */
|
|
|
|
if (c == '\n') /* Got end of line (UNIX line end) ? */
|
|
|
|
{
|
|
|
|
*(sptr++) = '\n';
|
|
|
|
break;
|
|
|
|
}
|
2018-05-12 12:13:12 -04:00
|
|
|
else if (c == '\r') /* Got a carriage return. Check next character */
|
2004-11-18 21:10:12 +00:00
|
|
|
{
|
|
|
|
c = getc (stream);
|
|
|
|
if ((c == EOF) || (c == '\n')) /* EOF or DOS line end ? */
|
|
|
|
{
|
|
|
|
*(sptr++) = '\n'; /* Return UNIX line end */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else /* Single carriage return. Return UNIX line end. */
|
|
|
|
{
|
|
|
|
ungetc (c, stream); /* Save the extra character */
|
|
|
|
*(sptr++) = '\n';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else /* no line end character */
|
|
|
|
{
|
|
|
|
*(sptr++) = (char)c;
|
|
|
|
size--;
|
|
|
|
}
|
|
|
|
if (size == 1)
|
|
|
|
break; /* Only space for the nul-character ? */
|
|
|
|
|
|
|
|
c = getc (stream);
|
|
|
|
if (c == EOF)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
*sptr = '\0';
|
|
|
|
|
|
|
|
return s;
|
2000-08-20 23:26:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
/* Get the BoundingBox of a PostScript file. On success, 0 is returned. */
|
|
|
|
/* On failure, -1 is returned. */
|
|
|
|
static gint
|
2019-09-11 21:48:34 +02:00
|
|
|
get_bbox (GFile *file,
|
|
|
|
gint *x0,
|
|
|
|
gint *y0,
|
|
|
|
gint *x1,
|
|
|
|
gint *y1)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2019-09-11 21:48:34 +02:00
|
|
|
char line[1024], *src;
|
|
|
|
FILE *ifp;
|
|
|
|
int retval = -1;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2021-10-01 18:56:12 +02:00
|
|
|
ifp = g_fopen (g_file_peek_path (file), "rb");
|
2019-09-11 21:48:34 +02:00
|
|
|
|
|
|
|
if (! ifp)
|
2004-11-18 21:10:12 +00:00
|
|
|
return -1;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
2000-08-20 23:26:11 +00:00
|
|
|
if (psfgets (line, sizeof (line)-1, ifp) == NULL) break;
|
2000-01-25 17:46:56 +00:00
|
|
|
if ((line[0] != '%') || (line[1] != '%')) continue;
|
|
|
|
src = &(line[2]);
|
|
|
|
while ((*src == ' ') || (*src == '\t')) src++;
|
|
|
|
if (strncmp (src, "BoundingBox", 11) != 0) continue;
|
|
|
|
src += 11;
|
|
|
|
while ((*src == ' ') || (*src == '\t') || (*src == ':')) src++;
|
|
|
|
if (strncmp (src, "(atend)", 7) == 0) continue;
|
|
|
|
if (sscanf (src, "%d%d%d%d", x0, y0, x1, y1) == 4)
|
2006-05-08 12:23:32 +00:00
|
|
|
retval = 0;
|
2000-01-25 17:46:56 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
fclose (ifp);
|
2004-11-18 21:10:12 +00:00
|
|
|
|
|
|
|
return retval;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2024-04-30 01:28:40 +02:00
|
|
|
static gboolean
|
|
|
|
ps_read_header (GFile *file,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
gboolean *is_pdf,
|
|
|
|
gboolean *is_epsf,
|
|
|
|
gint *bbox_x0,
|
|
|
|
gint *bbox_y0,
|
|
|
|
gint *bbox_x1,
|
|
|
|
gint *bbox_y1)
|
|
|
|
{
|
|
|
|
FILE *eps_file;
|
|
|
|
const gchar *filename;
|
|
|
|
gboolean use_bbox = TRUE;
|
|
|
|
gboolean maybe_epsf = FALSE;
|
|
|
|
gboolean has_bbox = FALSE;
|
|
|
|
|
|
|
|
if (config)
|
|
|
|
g_object_get (config, "check-bbox", &use_bbox, NULL);
|
|
|
|
|
|
|
|
/* Check if the file is a PDF. For PDF, we can't set geometry */
|
|
|
|
*is_pdf = FALSE;
|
|
|
|
|
|
|
|
/* Check if it is a EPS-file */
|
|
|
|
*is_epsf = FALSE;
|
|
|
|
|
|
|
|
*bbox_x0 = 0.0;
|
|
|
|
*bbox_y0 = 0.0;
|
|
|
|
*bbox_x1 = 0.0;
|
|
|
|
*bbox_y1 = 0.0;
|
|
|
|
|
|
|
|
filename = gimp_file_get_utf8_name (file);
|
|
|
|
eps_file = g_fopen (filename, "rb");
|
|
|
|
|
|
|
|
if (eps_file)
|
|
|
|
{
|
|
|
|
gchar hdr[512];
|
|
|
|
|
|
|
|
fread (hdr, 1, sizeof(hdr), eps_file);
|
|
|
|
*is_pdf = (strncmp (hdr, "%PDF", 4) == 0);
|
|
|
|
|
|
|
|
if (!*is_pdf) /* Check for EPSF */
|
|
|
|
{
|
|
|
|
char *adobe, *epsf;
|
|
|
|
int ds = 0;
|
|
|
|
static unsigned char doseps[5] = { 0xc5, 0xd0, 0xd3, 0xc6, 0 };
|
|
|
|
|
|
|
|
hdr[sizeof(hdr)-1] = '\0';
|
|
|
|
adobe = strstr (hdr, "PS-Adobe-");
|
|
|
|
epsf = strstr (hdr, "EPSF-");
|
|
|
|
|
|
|
|
if ((adobe != NULL) && (epsf != NULL))
|
|
|
|
ds = epsf - adobe;
|
|
|
|
|
|
|
|
*is_epsf = ((ds >= 11) && (ds <= 15));
|
|
|
|
|
|
|
|
/* Illustrator uses negative values in BoundingBox without marking */
|
|
|
|
/* files as EPSF. Try to handle that. */
|
|
|
|
maybe_epsf =
|
|
|
|
(strstr (hdr, "%%Creator: Adobe Illustrator(R) 8.0") != 0);
|
|
|
|
|
|
|
|
/* Check DOS EPS binary file */
|
|
|
|
if ((!*is_epsf) && (strncmp (hdr, (char *)doseps, 4) == 0))
|
|
|
|
*is_epsf = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose (eps_file);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((!*is_pdf) && (use_bbox)) /* Try the BoundingBox ? */
|
|
|
|
{
|
|
|
|
if (get_bbox (file, bbox_x0, bbox_y0, bbox_x1, bbox_y1) == 0)
|
|
|
|
{
|
|
|
|
has_bbox = TRUE;
|
|
|
|
|
|
|
|
if (maybe_epsf && ((bbox_x0 < 0) || (bbox_y0 < 0)))
|
|
|
|
*is_epsf = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return has_bbox;
|
|
|
|
}
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
/* Open the PostScript file. On failure, NULL is returned. */
|
|
|
|
/* The filepointer returned will give a PNM-file generated */
|
|
|
|
/* by the PostScript-interpreter. */
|
|
|
|
static FILE *
|
2024-04-27 16:49:31 +00:00
|
|
|
ps_open (GFile *file,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
gint *llx,
|
|
|
|
gint *lly,
|
|
|
|
gint *urx,
|
|
|
|
gint *ury,
|
|
|
|
gboolean *is_epsf,
|
|
|
|
gchar **tmp_filename)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2007-05-29 15:29:37 +00:00
|
|
|
const gchar *driver;
|
|
|
|
GPtrArray *cmdA;
|
|
|
|
gchar **pcmdA;
|
|
|
|
FILE *fd_popen = NULL;
|
|
|
|
gint width, height;
|
2024-04-24 01:12:01 +02:00
|
|
|
gdouble resolution;
|
2024-04-27 16:49:31 +00:00
|
|
|
gint pnm_type = 0;
|
|
|
|
gint text_alpha = 0;
|
|
|
|
gint graphics_alpha = 0;
|
2024-04-30 01:28:40 +02:00
|
|
|
gboolean has_bbox;
|
|
|
|
gint bbox_x0 = 0;
|
|
|
|
gint bbox_y0 = 0;
|
|
|
|
gint bbox_x1 = 0;
|
|
|
|
gint bbox_y1 = 0;
|
|
|
|
gint offx = 0;
|
|
|
|
gint offy = 0;
|
2007-05-29 15:29:37 +00:00
|
|
|
gboolean is_pdf;
|
2012-01-22 09:56:08 +05:30
|
|
|
int code;
|
2019-07-09 15:36:13 +02:00
|
|
|
void *instance = NULL;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
if (config)
|
|
|
|
{
|
|
|
|
g_object_get (config,
|
|
|
|
"width", &width,
|
|
|
|
"height", &height,
|
2024-04-24 01:12:01 +02:00
|
|
|
"pixel-density", &resolution,
|
2023-02-21 18:55:53 +00:00
|
|
|
NULL);
|
2024-04-27 16:49:31 +00:00
|
|
|
pnm_type = gimp_procedure_config_get_choice_id (config, "coloring");
|
|
|
|
text_alpha = gimp_procedure_config_get_choice_id (config, "text-alpha-bits");
|
|
|
|
graphics_alpha = gimp_procedure_config_get_choice_id (config, "graphic-alpha-bits");
|
2023-02-21 18:55:53 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
width = 256;
|
|
|
|
height = 256;
|
2024-04-24 01:12:01 +02:00
|
|
|
resolution = 256.0 / 4.0;
|
2023-02-21 18:55:53 +00:00
|
|
|
}
|
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
*llx = *lly = 0;
|
2004-01-25 23:46:24 +00:00
|
|
|
*urx = width - 1;
|
|
|
|
*ury = height - 1;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2024-04-30 01:28:40 +02:00
|
|
|
has_bbox = ps_read_header (file, config, &is_pdf, is_epsf, &bbox_x0, &bbox_y0, &bbox_x1, &bbox_y1);
|
2004-01-25 23:46:24 +00:00
|
|
|
|
2024-04-30 01:28:40 +02:00
|
|
|
if (has_bbox)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2024-04-30 01:28:40 +02:00
|
|
|
if (*is_epsf) /* Handle negative BoundingBox for EPSF */
|
2004-01-25 23:46:24 +00:00
|
|
|
{
|
2024-04-30 01:28:40 +02:00
|
|
|
offx = -bbox_x0; bbox_x1 += offx; bbox_x0 += offx;
|
|
|
|
offy = -bbox_y0; bbox_y1 += offy; bbox_y0 += offy;
|
2004-01-25 23:46:24 +00:00
|
|
|
}
|
|
|
|
|
2024-04-30 01:28:40 +02:00
|
|
|
if (bbox_x0 >= 0 && bbox_y0 >= 0 && bbox_x1 > bbox_x0 && bbox_y1 > bbox_y0)
|
2000-03-25 22:19:17 +00:00
|
|
|
{
|
2024-04-30 01:28:40 +02:00
|
|
|
*llx = (int) (bbox_x0 / 72.0 * resolution + 0.0001);
|
|
|
|
*lly = (int) (bbox_y0 / 72.0 * resolution + 0.0001);
|
|
|
|
/* Use upper bbox values as image size */
|
|
|
|
width = (int) (bbox_x1 / 72.0 * resolution + 0.5);
|
|
|
|
height = (int) (bbox_y1 / 72.0 * resolution + 0.5);
|
|
|
|
/* Pixel coordinates must be one less */
|
|
|
|
*urx = width - 1;
|
|
|
|
*ury = height - 1;
|
|
|
|
if (*urx < *llx) *urx = *llx;
|
|
|
|
if (*ury < *lly) *ury = *lly;
|
2000-03-25 22:19:17 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
2004-01-25 23:46:24 +00:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
switch (pnm_type)
|
2007-05-29 15:29:37 +00:00
|
|
|
{
|
|
|
|
case 4:
|
|
|
|
driver = "pbmraw";
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
driver = "pgmraw";
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
driver = "pnmraw";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
driver = "ppmraw";
|
|
|
|
break;
|
|
|
|
}
|
1999-06-21 00:23:55 +00:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
/* For instance, the Win32 port of ghostscript doesn't work correctly when
|
|
|
|
* using standard output as output file.
|
|
|
|
* Thus, use a real output file.
|
|
|
|
*/
|
2022-05-16 14:31:50 +00:00
|
|
|
if (*is_epsf)
|
|
|
|
{
|
|
|
|
driver = "pngalpha";
|
|
|
|
*tmp_filename = g_file_get_path (gimp_temp_file ("png"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*tmp_filename = g_file_get_path (gimp_temp_file ("pnm"));
|
|
|
|
}
|
2003-03-22 01:12:48 +00:00
|
|
|
|
2004-01-25 23:46:24 +00:00
|
|
|
/* Build command array */
|
|
|
|
cmdA = g_ptr_array_new ();
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2012-01-22 09:56:08 +05:30
|
|
|
g_ptr_array_add (cmdA, g_strdup (g_get_prgname ()));
|
2004-01-25 23:46:24 +00:00
|
|
|
g_ptr_array_add (cmdA, g_strdup_printf ("-sDEVICE=%s", driver));
|
2024-04-24 01:12:01 +02:00
|
|
|
g_ptr_array_add (cmdA, g_strdup_printf ("-r%d", (gint) resolution));
|
2004-01-25 23:46:24 +00:00
|
|
|
|
2005-04-21 10:46:52 +00:00
|
|
|
if (is_pdf)
|
|
|
|
{
|
|
|
|
/* Acrobat Reader honors CropBox over MediaBox, so let's match that
|
|
|
|
* behavior.
|
|
|
|
*/
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("-dUseCropBox"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* For PDF, we can't set geometry */
|
|
|
|
g_ptr_array_add (cmdA, g_strdup_printf ("-g%dx%d", width, height));
|
|
|
|
}
|
2004-01-25 23:46:24 +00:00
|
|
|
|
|
|
|
/* Antialiasing not available for PBM-device */
|
2023-02-21 18:55:53 +00:00
|
|
|
if ((pnm_type != 4) && (text_alpha != 1))
|
2004-01-25 23:46:24 +00:00
|
|
|
g_ptr_array_add (cmdA, g_strdup_printf ("-dTextAlphaBits=%d",
|
2023-02-21 18:55:53 +00:00
|
|
|
text_alpha));
|
|
|
|
if ((pnm_type != 4) && (graphics_alpha != 1))
|
2004-01-25 23:46:24 +00:00
|
|
|
g_ptr_array_add (cmdA, g_strdup_printf ("-dGraphicsAlphaBits=%d",
|
2023-02-21 18:55:53 +00:00
|
|
|
graphics_alpha));
|
2004-01-25 23:46:24 +00:00
|
|
|
g_ptr_array_add (cmdA, g_strdup ("-q"));
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("-dBATCH"));
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("-dNOPAUSE"));
|
|
|
|
|
|
|
|
/* If no additional options specified, use at least -dSAFER */
|
2005-03-04 15:12:29 +00:00
|
|
|
if (g_getenv ("GS_OPTIONS") == NULL)
|
2004-01-25 23:46:24 +00:00
|
|
|
g_ptr_array_add (cmdA, g_strdup ("-dSAFER"));
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2004-01-25 23:46:24 +00:00
|
|
|
/* Output file name */
|
2022-05-16 14:31:50 +00:00
|
|
|
g_ptr_array_add (cmdA, g_strdup_printf ("-sOutputFile=%s", *tmp_filename));
|
2000-03-25 22:19:17 +00:00
|
|
|
|
|
|
|
/* Offset command for gs to get image part with negative x/y-coord. */
|
|
|
|
if ((offx != 0) || (offy != 0))
|
2004-01-25 23:46:24 +00:00
|
|
|
{
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("-c"));
|
|
|
|
g_ptr_array_add (cmdA, g_strdup_printf ("%d", offx));
|
|
|
|
g_ptr_array_add (cmdA, g_strdup_printf ("%d", offy));
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("translate"));
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2004-01-25 23:46:24 +00:00
|
|
|
/* input file name */
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("-f"));
|
2024-04-30 01:28:40 +02:00
|
|
|
g_ptr_array_add (cmdA, g_strdup (gimp_file_get_utf8_name (file)));
|
2004-01-25 23:46:24 +00:00
|
|
|
|
|
|
|
if (*is_epsf)
|
|
|
|
{
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("-c"));
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("showpage"));
|
|
|
|
}
|
|
|
|
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("-c"));
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("quit"));
|
|
|
|
g_ptr_array_add (cmdA, NULL);
|
|
|
|
|
|
|
|
pcmdA = (gchar **) cmdA->pdata;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
#ifdef PS_DEBUG
|
2004-01-25 23:46:24 +00:00
|
|
|
{
|
|
|
|
gchar **p = pcmdA;
|
2012-01-22 09:56:08 +05:30
|
|
|
g_print ("Passing args (argc=%d):\n", cmdA->len - 1);
|
2004-01-25 23:46:24 +00:00
|
|
|
|
|
|
|
while (*p)
|
|
|
|
{
|
|
|
|
g_print ("%s\n", *p);
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
#endif
|
1999-06-21 00:23:55 +00:00
|
|
|
|
2012-01-22 09:56:08 +05:30
|
|
|
code = gsapi_new_instance (&instance, NULL);
|
|
|
|
if (code == 0) {
|
2021-08-07 17:22:27 -04:00
|
|
|
code = gsapi_set_arg_encoding(instance, GS_ARG_ENCODING_UTF8);
|
2012-01-22 09:56:08 +05:30
|
|
|
code = gsapi_init_with_args (instance, cmdA->len - 1, pcmdA);
|
|
|
|
code = gsapi_exit (instance);
|
|
|
|
gsapi_delete_instance (instance);
|
|
|
|
}
|
2004-01-25 23:46:24 +00:00
|
|
|
|
|
|
|
/* Don't care about exit status of ghostscript. */
|
|
|
|
/* Just try to read what it wrote. */
|
2004-10-06 13:18:37 +00:00
|
|
|
|
2022-05-16 14:31:50 +00:00
|
|
|
fd_popen = g_fopen (*tmp_filename, "rb");
|
2004-01-25 23:46:24 +00:00
|
|
|
|
|
|
|
g_ptr_array_free (cmdA, FALSE);
|
|
|
|
g_strfreev (pcmdA);
|
|
|
|
|
|
|
|
return fd_popen;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Close the PNM-File of the PostScript interpreter */
|
|
|
|
static void
|
2022-05-16 14:31:50 +00:00
|
|
|
ps_close (FILE *ifp, gchar *tmp_filename)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
1999-06-21 00:23:55 +00:00
|
|
|
/* If a real outputfile was used, close the file and remove it. */
|
2000-01-25 17:46:56 +00:00
|
|
|
fclose (ifp);
|
2022-05-16 14:31:50 +00:00
|
|
|
g_unlink (tmp_filename);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Read the header of a raw PNM-file and return type (4-6) or -1 on failure */
|
|
|
|
static gint
|
|
|
|
read_pnmraw_type (FILE *ifp,
|
2000-01-25 17:46:56 +00:00
|
|
|
gint *width,
|
|
|
|
gint *height,
|
|
|
|
gint *maxval)
|
|
|
|
{
|
2013-05-15 00:22:38 +05:30
|
|
|
int frst, scnd, thrd;
|
2007-05-29 15:29:37 +00:00
|
|
|
gint pnmtype;
|
|
|
|
gchar line[1024];
|
2000-01-25 17:46:56 +00:00
|
|
|
|
|
|
|
/* GhostScript may write some informational messages infront of the header. */
|
|
|
|
/* We are just looking at a Px\n in the input stream. */
|
|
|
|
frst = getc (ifp);
|
|
|
|
scnd = getc (ifp);
|
|
|
|
thrd = getc (ifp);
|
|
|
|
for (;;)
|
|
|
|
{
|
2004-11-18 21:10:12 +00:00
|
|
|
if (thrd == EOF) return -1;
|
2012-01-22 09:56:08 +05:30
|
|
|
#ifdef G_OS_WIN32
|
2000-01-25 17:46:56 +00:00
|
|
|
if (thrd == '\r') thrd = getc (ifp);
|
1999-05-01 16:10:36 +00:00
|
|
|
#endif
|
2000-01-25 17:46:56 +00:00
|
|
|
if ((thrd == '\n') && (frst == 'P') && (scnd >= '1') && (scnd <= '6'))
|
2006-05-08 12:23:32 +00:00
|
|
|
break;
|
2000-01-25 17:46:56 +00:00
|
|
|
frst = scnd;
|
|
|
|
scnd = thrd;
|
|
|
|
thrd = getc (ifp);
|
|
|
|
}
|
|
|
|
pnmtype = scnd - '0';
|
2018-04-18 20:57:03 +02:00
|
|
|
/* We don't use the ASCII-versions */
|
2004-11-18 21:10:12 +00:00
|
|
|
if ((pnmtype >= 1) && (pnmtype <= 3))
|
|
|
|
return -1;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
|
|
|
/* Read width/height */
|
|
|
|
for (;;)
|
|
|
|
{
|
2004-11-18 21:10:12 +00:00
|
|
|
if (fgets (line, sizeof (line)-1, ifp) == NULL)
|
|
|
|
return -1;
|
|
|
|
if (line[0] != '#')
|
|
|
|
break;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
2004-11-18 21:10:12 +00:00
|
|
|
if (sscanf (line, "%d%d", width, height) != 2)
|
|
|
|
return -1;
|
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
*maxval = 255;
|
|
|
|
|
|
|
|
if (pnmtype != 4) /* Read maxval */
|
|
|
|
{
|
|
|
|
for (;;)
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
|
|
|
if (fgets (line, sizeof (line)-1, ifp) == NULL)
|
2004-11-18 21:10:12 +00:00
|
|
|
return -1;
|
2006-05-08 12:23:32 +00:00
|
|
|
if (line[0] != '#')
|
2004-11-18 21:10:12 +00:00
|
|
|
break;
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
2004-11-18 21:10:12 +00:00
|
|
|
if (sscanf (line, "%d", maxval) != 1)
|
|
|
|
return -1;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
2004-11-18 21:10:12 +00:00
|
|
|
|
|
|
|
return pnmtype;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
/* Create an image. Sets layer, drawable and rgn. Returns image */
|
|
|
|
static GimpImage *
|
2019-09-11 21:48:34 +02:00
|
|
|
create_new_image (GFile *file,
|
2003-11-27 12:28:46 +00:00
|
|
|
guint pagenum,
|
|
|
|
guint width,
|
|
|
|
guint height,
|
2000-08-22 01:26:57 +00:00
|
|
|
GimpImageBaseType type,
|
2019-08-19 15:46:53 +02:00
|
|
|
GimpLayer **layer)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2019-08-19 15:46:53 +02:00
|
|
|
GimpImage *image;
|
2003-11-27 12:28:46 +00:00
|
|
|
GimpImageType gdtype;
|
2005-08-15 08:48:45 +00:00
|
|
|
gchar *tmp;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2013-05-13 17:59:17 +05:30
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case GIMP_GRAY:
|
|
|
|
gdtype = GIMP_GRAY_IMAGE;
|
|
|
|
break;
|
|
|
|
case GIMP_INDEXED:
|
|
|
|
gdtype = GIMP_INDEXED_IMAGE;
|
|
|
|
break;
|
|
|
|
case GIMP_RGB:
|
|
|
|
default:
|
|
|
|
gdtype = GIMP_RGB_IMAGE;
|
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
image = gimp_image_new_with_precision (width, height, type,
|
|
|
|
GIMP_PRECISION_U8_NON_LINEAR);
|
|
|
|
gimp_image_undo_disable (image);
|
2003-11-27 12:28:46 +00:00
|
|
|
|
2005-08-15 08:48:45 +00:00
|
|
|
tmp = g_strdup_printf (_("Page %d"), pagenum);
|
2019-08-19 15:46:53 +02:00
|
|
|
*layer = gimp_layer_new (image, tmp, width, height,
|
|
|
|
gdtype,
|
|
|
|
100,
|
|
|
|
gimp_image_get_default_new_layer_mode (image));
|
2005-08-15 08:48:45 +00:00
|
|
|
g_free (tmp);
|
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
gimp_image_insert_layer (image, *layer, NULL, 0);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
return image;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Skip PNM image generated from PostScript file. */
|
2004-11-18 21:10:12 +00:00
|
|
|
/* Return TRUE on success, FALSE otherwise. */
|
|
|
|
static gboolean
|
1997-11-24 22:05:25 +00:00
|
|
|
skip_ps (FILE *ifp)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2004-11-18 21:10:12 +00:00
|
|
|
guchar buf[8192];
|
|
|
|
gsize len;
|
|
|
|
gint pnmtype, width, height, maxval, bpl;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
pnmtype = read_pnmraw_type (ifp, &width, &height, &maxval);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
if (pnmtype == 4) /* Portable bitmap */
|
2004-11-18 21:10:12 +00:00
|
|
|
bpl = (width + 7) / 8;
|
2000-01-25 17:46:56 +00:00
|
|
|
else if (pnmtype == 5)
|
|
|
|
bpl = width;
|
|
|
|
else if (pnmtype == 6)
|
2004-11-18 21:10:12 +00:00
|
|
|
bpl = width * 3;
|
2000-01-25 17:46:56 +00:00
|
|
|
else
|
2004-11-18 21:10:12 +00:00
|
|
|
return FALSE;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2004-11-18 21:10:12 +00:00
|
|
|
len = bpl * height;
|
|
|
|
while (len)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2004-11-19 13:34:07 +00:00
|
|
|
gsize bytes = fread (buf, 1, MIN (len, sizeof (buf)), ifp);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2004-11-18 21:10:12 +00:00
|
|
|
if (bytes < MIN (len, sizeof (buf)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
len -= bytes;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2004-11-18 21:10:12 +00:00
|
|
|
return TRUE;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Load PNM image generated from PostScript file */
|
2019-08-19 15:46:53 +02:00
|
|
|
static GimpImage *
|
2019-09-11 21:48:34 +02:00
|
|
|
load_ps (GFile *file,
|
|
|
|
guint pagenum,
|
|
|
|
FILE *ifp,
|
|
|
|
gint llx,
|
|
|
|
gint lly,
|
|
|
|
gint urx,
|
|
|
|
gint ury)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2013-05-15 00:22:38 +05:30
|
|
|
guchar *dest;
|
2000-01-25 17:46:56 +00:00
|
|
|
guchar *data, *bitline = NULL, *byteline = NULL, *byteptr, *temp;
|
2019-09-11 21:48:34 +02:00
|
|
|
guchar bit2byte[256*8];
|
|
|
|
int width, height, tile_height, scan_lines, total_scan_lines;
|
|
|
|
int image_width, image_height;
|
|
|
|
int skip_left, skip_bottom;
|
|
|
|
int i, j, pnmtype, maxval, bpp, nread;
|
2000-08-22 01:26:57 +00:00
|
|
|
GimpImageBaseType imagetype;
|
2019-09-11 21:48:34 +02:00
|
|
|
GimpImage *image;
|
|
|
|
GimpLayer *layer;
|
2013-05-13 18:01:35 +05:30
|
|
|
GeglBuffer *buffer = NULL;
|
2019-09-11 21:48:34 +02:00
|
|
|
int err = 0;
|
|
|
|
int e;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
pnmtype = read_pnmraw_type (ifp, &width, &height, &maxval);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
if ((width == urx+1) && (height == ury+1)) /* gs respected BoundingBox ? */
|
|
|
|
{
|
|
|
|
skip_left = llx; skip_bottom = lly;
|
|
|
|
image_width = width - skip_left;
|
|
|
|
image_height = height - skip_bottom;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
skip_left = skip_bottom = 0;
|
|
|
|
image_width = width;
|
|
|
|
image_height = height;
|
|
|
|
}
|
|
|
|
if (pnmtype == 4) /* Portable Bitmap */
|
|
|
|
{
|
2000-08-22 01:26:57 +00:00
|
|
|
imagetype = GIMP_INDEXED;
|
2000-01-25 17:46:56 +00:00
|
|
|
nread = (width+7)/8;
|
|
|
|
bpp = 1;
|
2007-05-29 15:29:37 +00:00
|
|
|
bitline = g_new (guchar, nread);
|
|
|
|
byteline = g_new (guchar, nread * 8);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
|
|
|
/* Get an array for mapping 8 bits in a byte to 8 bytes */
|
|
|
|
temp = bit2byte;
|
|
|
|
for (j = 0; j < 256; j++)
|
2006-05-08 12:23:32 +00:00
|
|
|
for (i = 7; i >= 0; i--)
|
|
|
|
*(temp++) = ((j & (1 << i)) != 0);
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
|
|
|
else if (pnmtype == 5) /* Portable Greymap */
|
|
|
|
{
|
2000-08-22 01:26:57 +00:00
|
|
|
imagetype = GIMP_GRAY;
|
2000-01-25 17:46:56 +00:00
|
|
|
nread = width;
|
|
|
|
bpp = 1;
|
2007-05-29 15:29:37 +00:00
|
|
|
byteline = g_new (guchar, nread);
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
|
|
|
else if (pnmtype == 6) /* Portable Pixmap */
|
|
|
|
{
|
2000-08-22 01:26:57 +00:00
|
|
|
imagetype = GIMP_RGB;
|
2000-01-25 17:46:56 +00:00
|
|
|
nread = width * 3;
|
|
|
|
bpp = 3;
|
2007-05-29 15:29:37 +00:00
|
|
|
byteline = g_new (guchar, nread);
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
2004-11-18 21:10:12 +00:00
|
|
|
else
|
2019-08-19 15:46:53 +02:00
|
|
|
return NULL;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-09-11 21:48:34 +02:00
|
|
|
image = create_new_image (file, pagenum,
|
2019-08-19 15:46:53 +02:00
|
|
|
image_width, image_height, imagetype,
|
|
|
|
&layer);
|
|
|
|
buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer));
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
data = g_malloc (tile_height * image_width * bpp);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
dest = data;
|
|
|
|
total_scan_lines = scan_lines = 0;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
if (pnmtype == 4) /* Read bitimage ? Must be mapped to indexed */
|
2007-05-29 15:29:37 +00:00
|
|
|
{
|
|
|
|
const guchar BWColorMap[2*3] = { 255, 255, 255, 0, 0, 0 };
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2024-09-23 15:17:04 +02:00
|
|
|
gimp_palette_set_colormap (gimp_image_get_palette (image), babl_format ("R'G'B' u8"), (guint8 *) BWColorMap, 2 * 3);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2007-05-29 15:29:37 +00:00
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
|
|
|
e = (fread (bitline, 1, nread, ifp) != nread);
|
2013-05-13 18:01:35 +05:30
|
|
|
if (total_scan_lines >= image_height)
|
|
|
|
continue;
|
2007-05-29 15:29:37 +00:00
|
|
|
err |= e;
|
2013-05-13 18:01:35 +05:30
|
|
|
if (err)
|
|
|
|
break;
|
2006-05-08 12:23:32 +00:00
|
|
|
|
2007-05-29 15:29:37 +00:00
|
|
|
j = width; /* Map 1 byte of bitimage to 8 bytes of indexed image */
|
|
|
|
temp = bitline;
|
|
|
|
byteptr = byteline;
|
|
|
|
while (j >= 8)
|
|
|
|
{
|
|
|
|
memcpy (byteptr, bit2byte + *(temp++)*8, 8);
|
|
|
|
byteptr += 8;
|
|
|
|
j -= 8;
|
|
|
|
}
|
|
|
|
if (j > 0)
|
|
|
|
memcpy (byteptr, bit2byte + *temp*8, j);
|
|
|
|
|
|
|
|
memcpy (dest, byteline+skip_left, image_width);
|
|
|
|
dest += image_width;
|
|
|
|
scan_lines++;
|
|
|
|
total_scan_lines++;
|
2006-05-08 12:23:32 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
if ((scan_lines == tile_height) || ((i + 1) == image_height))
|
2007-05-29 15:29:37 +00:00
|
|
|
{
|
2013-05-13 18:01:35 +05:30
|
|
|
gegl_buffer_set (buffer,
|
|
|
|
GEGL_RECTANGLE (0, i-scan_lines+1,
|
|
|
|
image_width, scan_lines),
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
data,
|
|
|
|
GEGL_AUTO_ROWSTRIDE);
|
2007-05-29 15:29:37 +00:00
|
|
|
scan_lines = 0;
|
|
|
|
dest = data;
|
|
|
|
}
|
2013-05-13 18:01:35 +05:30
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
2014-10-26 18:54:42 +01:00
|
|
|
gimp_progress_update ((gdouble) (i + 1) / (gdouble) image_height);
|
2013-05-13 18:01:35 +05:30
|
|
|
|
|
|
|
if (err)
|
|
|
|
break;
|
2007-05-29 15:29:37 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
|
|
|
else /* Read gray/rgb-image */
|
|
|
|
{
|
|
|
|
for (i = 0; i < height; i++)
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
|
|
|
e = (fread (byteline, bpp, width, ifp) != width);
|
2013-05-13 18:01:35 +05:30
|
|
|
if (total_scan_lines >= image_height)
|
|
|
|
continue;
|
2006-05-08 12:23:32 +00:00
|
|
|
err |= e;
|
2013-05-13 18:01:35 +05:30
|
|
|
if (err)
|
|
|
|
break;
|
2006-05-08 12:23:32 +00:00
|
|
|
|
|
|
|
memcpy (dest, byteline+skip_left*bpp, image_width*bpp);
|
|
|
|
dest += image_width*bpp;
|
|
|
|
scan_lines++;
|
|
|
|
total_scan_lines++;
|
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
if ((scan_lines == tile_height) || ((i + 1) == image_height))
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
2013-05-13 18:01:35 +05:30
|
|
|
gegl_buffer_set (buffer,
|
|
|
|
GEGL_RECTANGLE (0, i-scan_lines+1,
|
|
|
|
image_width, scan_lines),
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
data,
|
|
|
|
GEGL_AUTO_ROWSTRIDE);
|
2006-05-08 12:23:32 +00:00
|
|
|
scan_lines = 0;
|
|
|
|
dest = data;
|
|
|
|
}
|
2013-05-13 18:01:35 +05:30
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
2014-10-26 18:54:42 +01:00
|
|
|
gimp_progress_update ((gdouble) (i + 1) / (gdouble) image_height);
|
2013-05-13 18:01:35 +05:30
|
|
|
|
|
|
|
if (err)
|
|
|
|
break;
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
2011-04-10 19:05:08 +02:00
|
|
|
gimp_progress_update (1.0);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
|
|
|
g_free (data);
|
2007-05-29 15:29:37 +00:00
|
|
|
g_free (byteline);
|
|
|
|
g_free (bitline);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
|
|
|
if (err)
|
|
|
|
g_message ("EOF encountered on reading");
|
|
|
|
|
2013-05-13 18:01:35 +05:30
|
|
|
g_object_unref (buffer);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
return (err ? NULL : image);
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Write out the PostScript file header */
|
2014-10-26 18:54:42 +01:00
|
|
|
static gboolean
|
|
|
|
save_ps_header (GOutputStream *output,
|
|
|
|
GFile *file,
|
2023-02-21 18:55:53 +00:00
|
|
|
GObject *config,
|
2014-10-26 18:54:42 +01:00
|
|
|
GError **error)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2023-02-21 18:55:53 +00:00
|
|
|
gchar *basename = g_path_get_basename (gimp_file_get_utf8_name (file));
|
|
|
|
gboolean eps = FALSE;
|
|
|
|
gboolean level2 = FALSE;
|
|
|
|
time_t cutime = time (NULL);
|
|
|
|
|
|
|
|
g_object_get (config,
|
|
|
|
"eps-flag", &eps,
|
|
|
|
"level", &level2,
|
|
|
|
NULL);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! print (output, error,
|
2023-02-21 18:55:53 +00:00
|
|
|
"%%!PS-Adobe-3.0%s\n", eps ? " EPSF-3.0" : ""))
|
2014-10-26 18:54:42 +01:00
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error,
|
2017-03-21 17:45:50 +01:00
|
|
|
"%%%%Creator: GIMP PostScript file plug-in V %4.2f "
|
2019-08-18 17:04:53 +02:00
|
|
|
"by Peter Kirchgessner\n", VERSION))
|
2014-10-26 18:54:42 +01:00
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error,
|
|
|
|
"%%%%Title: %s\n"
|
|
|
|
"%%%%CreationDate: %s"
|
|
|
|
"%%%%DocumentData: Clean7Bit\n",
|
|
|
|
basename, ctime (&cutime)))
|
|
|
|
goto fail;
|
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
if (eps || level2)
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! print (output, error,"%%%%LanguageLevel: 2\n"))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "%%%%Pages: 1\n"))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
g_free (basename);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
fail:
|
2004-08-08 22:26:17 +00:00
|
|
|
|
|
|
|
g_free (basename);
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
return FALSE;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Write out transformation for image */
|
2014-10-26 18:54:42 +01:00
|
|
|
static gboolean
|
|
|
|
save_ps_setup (GOutputStream *output,
|
2019-08-19 15:46:53 +02:00
|
|
|
GimpDrawable *drawable,
|
2014-10-26 18:54:42 +01:00
|
|
|
gint width,
|
|
|
|
gint height,
|
2023-02-21 18:55:53 +00:00
|
|
|
GObject *config,
|
2014-10-26 18:54:42 +01:00
|
|
|
gint bpp,
|
|
|
|
GError **error)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2023-02-21 18:55:53 +00:00
|
|
|
gdouble config_width;
|
|
|
|
gdouble config_height;
|
|
|
|
gdouble x_offset, y_offset, x_size, y_size;
|
|
|
|
gdouble urx, ury;
|
|
|
|
gdouble width_inch, height_inch;
|
|
|
|
gdouble f1, f2, dx, dy;
|
|
|
|
gint rotation;
|
|
|
|
gint xtrans, ytrans;
|
|
|
|
gint i_urx, i_ury;
|
|
|
|
gint preview_size;
|
|
|
|
gboolean unit_mm;
|
|
|
|
gboolean keep_ratio;
|
|
|
|
gboolean show_preview;
|
|
|
|
gboolean level2;
|
|
|
|
gchar tmpbuf1[G_ASCII_DTOSTR_BUF_SIZE];
|
|
|
|
gchar tmpbuf2[G_ASCII_DTOSTR_BUF_SIZE];
|
2000-01-25 17:46:56 +00:00
|
|
|
|
|
|
|
/* initialize */
|
2023-02-21 18:55:53 +00:00
|
|
|
g_object_get (config,
|
|
|
|
"width", &config_width,
|
|
|
|
"height", &config_height,
|
|
|
|
"x-offset", &x_offset,
|
|
|
|
"y-offset", &y_offset,
|
|
|
|
"keep-ratio", &keep_ratio,
|
|
|
|
"level", &level2,
|
|
|
|
"rotation", &rotation,
|
|
|
|
"show-preview", &show_preview,
|
|
|
|
"preview", &preview_size,
|
|
|
|
NULL);
|
2024-04-27 16:49:31 +00:00
|
|
|
unit_mm = gimp_procedure_config_get_choice_id (GIMP_PROCEDURE_CONFIG (config),
|
|
|
|
"unit");
|
2000-01-25 17:46:56 +00:00
|
|
|
|
|
|
|
dx = 0.0;
|
|
|
|
dy = 0.0;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
width_inch = fabs (config_width);
|
|
|
|
height_inch = fabs (config_height);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
if (unit_mm)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
|
|
|
x_offset /= 25.4; y_offset /= 25.4;
|
|
|
|
width_inch /= 25.4; height_inch /= 25.4;
|
|
|
|
}
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
if (keep_ratio) /* Proportions to keep ? */
|
2000-01-25 17:46:56 +00:00
|
|
|
{ /* Fit the image into the allowed size */
|
2023-02-21 18:55:53 +00:00
|
|
|
f1 = width_inch / (gint) width;
|
|
|
|
f2 = height_inch / (gint) height;
|
2000-01-25 17:46:56 +00:00
|
|
|
if (f1 < f2)
|
2014-10-26 18:54:42 +01:00
|
|
|
height_inch = width_inch * (gdouble) height / (gdouble) width;
|
2000-01-25 17:46:56 +00:00
|
|
|
else
|
2014-10-26 18:54:42 +01:00
|
|
|
width_inch = fabs (height_inch) * (gdouble) width / (gdouble) height;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
if ((rotation == 0) || (rotation == 180))
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
x_size = width_inch;
|
|
|
|
y_size = height_inch;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
else
|
2014-10-26 18:54:42 +01:00
|
|
|
{
|
|
|
|
y_size = width_inch;
|
|
|
|
x_size = height_inch;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2002-10-08 10:53:10 +00:00
|
|
|
/* Round up upper right corner only for non-integer values */
|
2014-10-26 18:54:42 +01:00
|
|
|
urx = (x_offset + x_size) * 72.0;
|
|
|
|
ury = (y_offset + y_size) * 72.0;
|
|
|
|
i_urx = (gint) urx;
|
|
|
|
i_ury = (gint) ury;
|
|
|
|
if (urx != (gdouble) i_urx) i_urx++; /* Check for non-integer value */
|
|
|
|
if (ury != (gdouble) i_ury) i_ury++;
|
|
|
|
|
|
|
|
if (! print (output, error,
|
|
|
|
"%%%%BoundingBox: %d %d %d %d\n"
|
|
|
|
"%%%%EndComments\n",
|
|
|
|
(gint) (x_offset * 72.0), (gint) (y_offset * 72.0), i_urx, i_ury))
|
|
|
|
return FALSE;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
if (show_preview && (preview_size > 0))
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2023-02-21 18:55:53 +00:00
|
|
|
if (! save_ps_preview (output, drawable, config, error))
|
2014-10-26 18:54:42 +01:00
|
|
|
return FALSE;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
1997-12-26 07:08:20 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! print (output, error,
|
|
|
|
"%%%%BeginProlog\n"
|
|
|
|
"%% Use own dictionary to avoid conflicts\n"
|
|
|
|
"10 dict begin\n"
|
|
|
|
"%%%%EndProlog\n"
|
|
|
|
"%%%%Page: 1 1\n"
|
|
|
|
"%% Translate for offset\n"
|
|
|
|
"%s %s translate\n",
|
|
|
|
g_ascii_dtostr (tmpbuf1, sizeof (tmpbuf1), x_offset * 72.0),
|
|
|
|
g_ascii_dtostr (tmpbuf2, sizeof (tmpbuf2), y_offset * 72.0)))
|
|
|
|
return FALSE;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* Calculate translation to startpoint of first scanline */
|
2023-02-21 18:55:53 +00:00
|
|
|
switch (rotation)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
case 0: dx = 0.0; dy = y_size * 72.0;
|
2000-01-25 17:46:56 +00:00
|
|
|
break;
|
1997-11-24 22:05:25 +00:00
|
|
|
case 90: dx = dy = 0.0;
|
2000-01-25 17:46:56 +00:00
|
|
|
break;
|
2014-10-26 18:54:42 +01:00
|
|
|
case 180: dx = x_size * 72.0; dy = 0.0;
|
2000-01-25 17:46:56 +00:00
|
|
|
break;
|
2014-10-26 18:54:42 +01:00
|
|
|
case 270: dx = x_size * 72.0; dy = y_size * 72.0;
|
2000-01-25 17:46:56 +00:00
|
|
|
break;
|
|
|
|
}
|
2014-10-26 18:54:42 +01:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
if ((dx != 0.0) || (dy != 0.0))
|
2002-12-16 19:24:05 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! print (output, error,
|
|
|
|
"%% Translate to begin of first scanline\n"
|
|
|
|
"%s %s translate\n",
|
|
|
|
g_ascii_dtostr (tmpbuf1, sizeof (tmpbuf1), dx),
|
|
|
|
g_ascii_dtostr (tmpbuf2, sizeof (tmpbuf2), dy)))
|
|
|
|
return FALSE;
|
2002-12-16 19:24:05 +00:00
|
|
|
}
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
if (rotation)
|
|
|
|
if (! print (output, error, "%d rotate\n", (gint) rotation))
|
2014-10-26 18:54:42 +01:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (! print (output, error,
|
|
|
|
"%s %s scale\n",
|
|
|
|
g_ascii_dtostr (tmpbuf1, sizeof (tmpbuf1), 72.0 * width_inch),
|
|
|
|
g_ascii_dtostr (tmpbuf2, sizeof (tmpbuf2), -72.0 * height_inch)))
|
|
|
|
return FALSE;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* Write the PostScript procedures to read the image */
|
2023-02-21 18:55:53 +00:00
|
|
|
if (! level2)
|
2014-10-26 18:54:42 +01:00
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"%% Variable to keep one line of raster data\n"))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (bpp == 1)
|
|
|
|
{
|
|
|
|
if (! print (output, error,
|
2023-02-21 18:55:53 +00:00
|
|
|
"/scanline %d string def\n", ((gint) width + 7) / 8))
|
2014-10-26 18:54:42 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (! print (output, error,
|
2023-02-21 18:55:53 +00:00
|
|
|
"/scanline %d %d mul string def\n",
|
|
|
|
(gint) width, bpp / 8))
|
2014-10-26 18:54:42 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! print (output, error,
|
|
|
|
"%% Image geometry\n%d %d %d\n"
|
|
|
|
"%% Transformation matrix\n",
|
2023-02-21 18:55:53 +00:00
|
|
|
(gint) width, (gint) height, (bpp == 1) ? 1 : 8))
|
2014-10-26 18:54:42 +01:00
|
|
|
return FALSE;
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
xtrans = ytrans = 0;
|
2023-02-21 18:55:53 +00:00
|
|
|
if (config_width < 0.0)
|
|
|
|
{
|
|
|
|
width = -width;
|
|
|
|
xtrans = -width;
|
|
|
|
}
|
|
|
|
if (config_height < 0.0)
|
|
|
|
{
|
|
|
|
height = -height;
|
|
|
|
ytrans = -height;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! print (output, error,
|
2023-02-21 18:55:53 +00:00
|
|
|
"[ %d 0 0 %d %d %d ]\n", (gint) width, (gint) height, xtrans, ytrans))
|
2014-10-26 18:54:42 +01:00
|
|
|
return FALSE;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
save_ps_trailer (GOutputStream *output,
|
|
|
|
GError **error)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
return print (output, error,
|
|
|
|
"%%%%Trailer\n"
|
|
|
|
"end\n%%%%EOF\n");
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2013-06-06 23:26:16 +02:00
|
|
|
/* Do a Floyd-Steinberg dithering on a grayscale scanline. */
|
1997-12-26 07:08:20 +00:00
|
|
|
/* linecount must keep the counter for the actual scanline (0, 1, 2, ...). */
|
|
|
|
/* If linecount is less than zero, all used memory is freed. */
|
|
|
|
|
|
|
|
static void
|
2006-08-29 13:32:22 +00:00
|
|
|
dither_grey (const guchar *grey,
|
|
|
|
guchar *bw,
|
|
|
|
gint npix,
|
|
|
|
gint linecount)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
static gboolean do_init_arrays = TRUE;
|
|
|
|
static gint *fs_error = NULL;
|
|
|
|
static gint limit[1278];
|
|
|
|
static gint east_error[256];
|
|
|
|
static gint seast_error[256];
|
|
|
|
static gint south_error[256];
|
|
|
|
static gint swest_error[256];
|
2006-08-29 13:32:22 +00:00
|
|
|
|
2013-05-15 00:22:38 +05:30
|
|
|
const guchar *greyptr;
|
2014-10-26 18:54:42 +01:00
|
|
|
guchar *bwptr, mask;
|
|
|
|
gint *fse;
|
|
|
|
gint x, greyval, fse_inline;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
|
|
|
if (linecount <= 0)
|
|
|
|
{
|
2006-08-29 13:32:22 +00:00
|
|
|
g_free (fs_error);
|
|
|
|
|
|
|
|
if (linecount < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
fs_error = g_new0 (gint, npix + 2);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
|
|
|
/* Initialize some arrays that speed up dithering */
|
|
|
|
if (do_init_arrays)
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
2006-08-29 13:32:22 +00:00
|
|
|
gint i;
|
|
|
|
|
|
|
|
do_init_arrays = FALSE;
|
|
|
|
|
|
|
|
for (i = 0, x = -511; x <= 766; i++, x++)
|
|
|
|
limit[i] = (x < 0) ? 0 : ((x > 255) ? 255 : x);
|
|
|
|
|
2006-05-08 12:23:32 +00:00
|
|
|
for (greyval = 0; greyval < 256; greyval++)
|
|
|
|
{
|
2006-08-29 13:32:22 +00:00
|
|
|
east_error[greyval] = (greyval < 128) ?
|
|
|
|
((greyval * 79) >> 8) : (((greyval - 255) * 79) >> 8);
|
|
|
|
seast_error[greyval] = (greyval < 128) ?
|
|
|
|
((greyval * 34) >> 8) : (((greyval - 255) * 34) >> 8);
|
|
|
|
south_error[greyval] = (greyval < 128) ?
|
|
|
|
((greyval * 56) >> 8) : (((greyval - 255) * 56) >> 8);
|
|
|
|
swest_error[greyval] = (greyval < 128) ?
|
|
|
|
((greyval * 12) >> 8) : (((greyval - 255) * 12) >> 8);
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
|
|
|
|
2006-08-29 13:32:22 +00:00
|
|
|
g_return_if_fail (fs_error != NULL);
|
|
|
|
|
|
|
|
memset (bw, 0, (npix + 7) / 8); /* Initialize with white */
|
2000-01-25 17:46:56 +00:00
|
|
|
|
|
|
|
greyptr = grey;
|
|
|
|
bwptr = bw;
|
|
|
|
mask = 0x80;
|
2006-08-29 13:32:22 +00:00
|
|
|
|
|
|
|
fse_inline = fs_error[1];
|
|
|
|
|
|
|
|
for (x = 0, fse = fs_error + 1; x < npix; x++, fse++)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2006-08-29 13:32:22 +00:00
|
|
|
greyval =
|
|
|
|
limit[*(greyptr++) + fse_inline + 512]; /* 0 <= greyval <= 255 */
|
|
|
|
|
|
|
|
if (greyval < 128)
|
|
|
|
*bwptr |= mask; /* Set a black pixel */
|
2000-01-25 17:46:56 +00:00
|
|
|
|
|
|
|
/* Error distribution */
|
|
|
|
fse_inline = east_error[greyval] + fse[1];
|
|
|
|
fse[1] = seast_error[greyval];
|
|
|
|
fse[0] += south_error[greyval];
|
|
|
|
fse[-1] += swest_error[greyval];
|
|
|
|
|
|
|
|
mask >>= 1; /* Get mask for next b/w-pixel */
|
2006-08-29 13:32:22 +00:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
if (!mask)
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
|
|
|
mask = 0x80;
|
|
|
|
bwptr++;
|
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
1997-12-26 07:08:20 +00:00
|
|
|
}
|
|
|
|
|
2012-09-10 12:22:12 -04:00
|
|
|
/* Write a device independent screen preview */
|
2014-10-26 18:54:42 +01:00
|
|
|
static gboolean
|
|
|
|
save_ps_preview (GOutputStream *output,
|
2019-08-19 15:46:53 +02:00
|
|
|
GimpDrawable *drawable,
|
2023-02-21 18:55:53 +00:00
|
|
|
GObject *config,
|
2014-10-26 18:54:42 +01:00
|
|
|
GError **error)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2013-05-14 19:43:19 +05:30
|
|
|
GimpImageType drawable_type;
|
|
|
|
GeglBuffer *buffer = NULL;
|
|
|
|
const Babl *format;
|
2014-10-26 18:54:42 +01:00
|
|
|
gint bpp;
|
|
|
|
guchar *bwptr, *greyptr;
|
|
|
|
gint width, height, x, y, nbsl, out_count;
|
|
|
|
gint nchar_pl = 72, src_y;
|
|
|
|
gdouble f1, f2;
|
|
|
|
guchar *grey, *bw, *src_row, *src_ptr;
|
|
|
|
guchar *cmap;
|
|
|
|
gint ncols, cind;
|
2023-02-21 18:55:53 +00:00
|
|
|
gint preview_size;
|
|
|
|
|
|
|
|
g_object_get (config,
|
|
|
|
"preview", &preview_size,
|
|
|
|
NULL);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
if (preview_size <= 0)
|
2014-10-26 18:54:42 +01:00
|
|
|
return TRUE;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
buffer = gimp_drawable_get_buffer (drawable);
|
2013-05-14 19:43:19 +05:30
|
|
|
cmap = NULL;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
drawable_type = gimp_drawable_type (drawable);
|
2013-05-14 19:43:19 +05:30
|
|
|
switch (drawable_type)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2013-05-14 19:43:19 +05:30
|
|
|
case GIMP_GRAY_IMAGE:
|
|
|
|
format = babl_format ("Y' u8");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_INDEXED_IMAGE:
|
2024-09-23 15:17:04 +02:00
|
|
|
cmap = gimp_palette_get_colormap (gimp_image_get_palette (gimp_item_get_image (GIMP_ITEM (drawable))),
|
|
|
|
babl_format ("R'G'B' u8"), &ncols, NULL);
|
2019-08-19 15:46:53 +02:00
|
|
|
format = gimp_drawable_get_format (drawable);
|
2013-05-14 19:43:19 +05:30
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_RGB_IMAGE:
|
|
|
|
default:
|
|
|
|
format = babl_format ("R'G'B' u8");
|
|
|
|
break;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
2013-05-14 19:43:19 +05:30
|
|
|
|
|
|
|
bpp = babl_format_get_bytes_per_pixel (format);
|
|
|
|
|
|
|
|
width = gegl_buffer_get_width (buffer);
|
|
|
|
height = gegl_buffer_get_height (buffer);
|
|
|
|
|
|
|
|
/* Calculate size of preview */
|
2023-02-21 18:55:53 +00:00
|
|
|
if ((width > preview_size) ||
|
|
|
|
(height > preview_size))
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2023-02-21 18:55:53 +00:00
|
|
|
f1 = (gdouble) preview_size / (gdouble) width;
|
|
|
|
f2 = (gdouble) preview_size / (gdouble) height;
|
2007-05-29 15:29:37 +00:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
if (f1 < f2)
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
2023-02-21 18:55:53 +00:00
|
|
|
width = preview_size;
|
2013-05-14 19:43:19 +05:30
|
|
|
height *= f1;
|
|
|
|
if (height <= 0)
|
|
|
|
height = 1;
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
else
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
2023-02-21 18:55:53 +00:00
|
|
|
height = preview_size;
|
2013-05-14 19:43:19 +05:30
|
|
|
width *= f1;
|
|
|
|
if (width <= 0)
|
|
|
|
width = 1;
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
nbsl = (width + 7) / 8; /* Number of bytes per scanline in bitmap */
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
grey = g_new (guchar, width);
|
|
|
|
bw = g_new (guchar, nbsl);
|
2013-05-14 19:43:19 +05:30
|
|
|
src_row = g_new (guchar, gegl_buffer_get_width (buffer) * bpp);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! print (output, error,
|
|
|
|
"%%%%BeginPreview: %d %d 1 %d\n",
|
|
|
|
width, height,
|
|
|
|
((nbsl * 2 + nchar_pl - 1) / nchar_pl) * height))
|
|
|
|
goto fail;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
|
|
|
for (y = 0; y < height; y++)
|
|
|
|
{
|
2013-05-14 19:43:19 +05:30
|
|
|
/* Get a scanline from the input image and scale it to the desired
|
|
|
|
width */
|
|
|
|
src_y = (y * gegl_buffer_get_height (buffer)) / height;
|
|
|
|
gegl_buffer_get (buffer,
|
|
|
|
GEGL_RECTANGLE (0, src_y,
|
|
|
|
gegl_buffer_get_width (buffer), 1),
|
|
|
|
1.0, format, src_row,
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
|
|
|
greyptr = grey;
|
2013-05-14 19:43:19 +05:30
|
|
|
if (bpp == 3) /* RGB-image */
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
|
|
|
for (x = 0; x < width; x++)
|
|
|
|
{ /* Convert to grey */
|
2013-05-14 19:43:19 +05:30
|
|
|
src_ptr = src_row + ((x * gegl_buffer_get_width (buffer)) / width) * 3;
|
2006-05-08 12:23:32 +00:00
|
|
|
*(greyptr++) = (3*src_ptr[0] + 6*src_ptr[1] + src_ptr[2]) / 10;
|
|
|
|
}
|
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
else if (cmap) /* Indexed image */
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
|
|
|
for (x = 0; x < width; x++)
|
|
|
|
{
|
2013-05-14 19:43:19 +05:30
|
|
|
src_ptr = src_row + ((x * gegl_buffer_get_width (buffer)) / width);
|
2013-06-06 23:26:16 +02:00
|
|
|
cind = *src_ptr; /* Get color index and convert to grey */
|
2006-05-08 12:23:32 +00:00
|
|
|
src_ptr = (cind >= ncols) ? cmap : (cmap + 3*cind);
|
|
|
|
*(greyptr++) = (3*src_ptr[0] + 6*src_ptr[1] + src_ptr[2]) / 10;
|
|
|
|
}
|
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
else /* Grey image */
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
|
|
|
for (x = 0; x < width; x++)
|
2013-05-14 19:43:19 +05:30
|
|
|
*(greyptr++) = *(src_row + ((x * gegl_buffer_get_width (buffer)) / width));
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2013-06-06 23:26:16 +02:00
|
|
|
/* Now we have a grayscale line for the desired width. */
|
2000-01-25 17:46:56 +00:00
|
|
|
/* Dither it to b/w */
|
|
|
|
dither_grey (grey, bw, width, y);
|
|
|
|
|
|
|
|
/* Write out the b/w line */
|
|
|
|
out_count = 0;
|
|
|
|
bwptr = bw;
|
|
|
|
for (x = 0; x < nbsl; x++)
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
if (out_count == 0)
|
|
|
|
if (! print (output, error, "%% "))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "%02x", *(bwptr++)))
|
|
|
|
goto fail;
|
|
|
|
|
2006-05-08 12:23:32 +00:00
|
|
|
out_count += 2;
|
|
|
|
if (out_count >= nchar_pl)
|
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
goto fail;
|
|
|
|
|
2006-05-08 12:23:32 +00:00
|
|
|
out_count = 0;
|
|
|
|
}
|
|
|
|
}
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
goto fail;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2003-06-13 14:37:00 +00:00
|
|
|
if ((y % 20) == 0)
|
2014-10-26 18:54:42 +01:00
|
|
|
gimp_progress_update ((gdouble) y / (gdouble) height);
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2011-04-10 19:05:08 +02:00
|
|
|
gimp_progress_update (1.0);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! print (output, error, "%%%%EndPreview\n"))
|
|
|
|
goto fail;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
|
|
|
dither_grey (grey, bw, width, -1);
|
|
|
|
g_free (src_row);
|
|
|
|
g_free (bw);
|
|
|
|
g_free (grey);
|
|
|
|
|
2013-05-14 19:43:19 +05:30
|
|
|
g_object_unref (buffer);
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
|
|
|
|
g_free (src_row);
|
|
|
|
g_free (bw);
|
|
|
|
g_free (grey);
|
|
|
|
|
|
|
|
g_object_unref (buffer);
|
|
|
|
|
|
|
|
return FALSE;
|
1997-12-26 07:08:20 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
static gboolean
|
|
|
|
save_gray (GOutputStream *output,
|
2019-08-19 15:46:53 +02:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2023-02-21 18:55:53 +00:00
|
|
|
GObject *config,
|
2014-10-26 18:54:42 +01:00
|
|
|
GError **error)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
GeglBuffer *buffer = NULL;
|
|
|
|
const Babl *format;
|
2023-02-21 18:55:53 +00:00
|
|
|
gboolean level2;
|
2014-10-26 18:54:42 +01:00
|
|
|
gint bpp;
|
|
|
|
gint height, width, i, j;
|
|
|
|
gint tile_height;
|
|
|
|
guchar *data;
|
|
|
|
guchar *src;
|
|
|
|
guchar *packb = NULL;
|
2023-02-21 18:55:53 +00:00
|
|
|
|
|
|
|
g_object_get (config,
|
|
|
|
"level", &level2,
|
|
|
|
NULL);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
buffer = gimp_drawable_get_buffer (drawable);
|
2013-05-14 14:24:00 +05:30
|
|
|
format = babl_format ("Y' u8");
|
2014-10-26 18:54:42 +01:00
|
|
|
bpp = babl_format_get_bytes_per_pixel (format);
|
|
|
|
width = gegl_buffer_get_width (buffer);
|
2013-05-14 14:24:00 +05:30
|
|
|
height = gegl_buffer_get_height (buffer);
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
|
|
|
|
/* allocate a buffer for retrieving information from the pixel region */
|
2013-05-14 14:24:00 +05:30
|
|
|
src = data = (guchar *) g_malloc (tile_height * width * bpp);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* Set up transformation in PostScript */
|
2023-02-21 18:55:53 +00:00
|
|
|
if (! save_ps_setup (output, drawable, width, height, config, 1 * 8, error))
|
2014-10-26 18:54:42 +01:00
|
|
|
goto fail;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* Write read image procedure */
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! level2)
|
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"{ currentfile scanline readhexstring pop }\n"))
|
|
|
|
goto fail;
|
|
|
|
}
|
2000-01-22 22:26:20 +00:00
|
|
|
else
|
2014-10-26 18:54:42 +01:00
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"currentfile /ASCII85Decode filter /RunLengthDecode filter\n"))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
ascii85_init ();
|
|
|
|
|
|
|
|
/* Allocate buffer for packbits data. Worst case: Less than 1% increase */
|
|
|
|
packb = (guchar *) g_malloc ((width * 105) / 100 + 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! ps_begin_data (output, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "image\n"))
|
|
|
|
goto fail;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
#define GET_GRAY_TILE(begin) \
|
2014-10-26 18:54:42 +01:00
|
|
|
{ gint scan_lines; \
|
1997-11-24 22:05:25 +00:00
|
|
|
scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i); \
|
2013-05-14 14:24:00 +05:30
|
|
|
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, i, width, scan_lines), \
|
|
|
|
1.0, format, begin, \
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); \
|
1997-11-24 22:05:25 +00:00
|
|
|
src = begin; }
|
|
|
|
|
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
if ((i % tile_height) == 0)
|
|
|
|
GET_GRAY_TILE (data); /* Get more data */
|
|
|
|
|
|
|
|
if (! level2)
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! print (output, error, "%c", hex[(*src) >> 4]))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "%c", hex[(*(src++)) & 0x0f]))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (((j + 1) % 39) == 0)
|
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
goto fail;
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
else
|
2014-10-26 18:54:42 +01:00
|
|
|
{
|
|
|
|
gint nout;
|
2000-03-10 17:27:25 +00:00
|
|
|
|
|
|
|
compress_packbits (width, src, &nout, packb);
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
if (! ascii85_nout (output, nout, packb, error))
|
|
|
|
goto fail;
|
|
|
|
|
2000-03-10 17:27:25 +00:00
|
|
|
src += width;
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
2003-06-13 14:37:00 +00:00
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
2014-10-26 18:54:42 +01:00
|
|
|
gimp_progress_update ((gdouble) i / (gdouble) height);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2011-04-10 19:05:08 +02:00
|
|
|
gimp_progress_update (1.0);
|
2003-06-13 14:37:00 +00:00
|
|
|
|
2000-03-10 17:27:25 +00:00
|
|
|
if (level2)
|
2003-06-13 14:37:00 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
/* Write EOD of RunLengthDecode filter */
|
|
|
|
if (! ascii85_out (output, 128, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! ascii85_done (output, error))
|
|
|
|
goto fail;
|
2003-06-13 14:37:00 +00:00
|
|
|
}
|
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! ps_end_data (output, error))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (! print (output, error, "showpage\n"))
|
|
|
|
goto fail;
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
g_free (data);
|
2014-10-26 18:54:42 +01:00
|
|
|
g_free (packb);
|
|
|
|
|
|
|
|
g_object_unref (buffer);
|
|
|
|
|
|
|
|
return TRUE;
|
2003-06-13 14:37:00 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
fail:
|
|
|
|
|
|
|
|
g_free (data);
|
|
|
|
g_free (packb);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2013-05-14 14:24:00 +05:30
|
|
|
g_object_unref (buffer);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
return FALSE;
|
2004-11-18 21:10:12 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
#undef GET_GRAY_TILE
|
|
|
|
}
|
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
static gboolean
|
|
|
|
save_bw (GOutputStream *output,
|
2019-08-19 15:46:53 +02:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2023-02-21 18:55:53 +00:00
|
|
|
GObject *config,
|
2014-10-26 18:54:42 +01:00
|
|
|
GError **error)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
GeglBuffer *buffer = NULL;
|
|
|
|
const Babl *format;
|
2023-02-21 18:55:53 +00:00
|
|
|
gboolean level2;
|
2014-10-26 18:54:42 +01:00
|
|
|
gint bpp;
|
|
|
|
gint height, width, i, j;
|
|
|
|
gint ncols, nbsl, nwrite;
|
|
|
|
gint tile_height;
|
|
|
|
guchar *cmap, *ct;
|
|
|
|
guchar *data, *src;
|
|
|
|
guchar *packb = NULL;
|
|
|
|
guchar *scanline, *dst, mask;
|
|
|
|
guchar *hex_scanline;
|
2023-02-21 18:55:53 +00:00
|
|
|
|
|
|
|
g_object_get (config,
|
|
|
|
"level", &level2,
|
|
|
|
NULL);
|
1999-01-03 22:41:12 +00:00
|
|
|
|
2024-09-23 15:17:04 +02:00
|
|
|
cmap = gimp_palette_get_colormap (gimp_image_get_palette (image), babl_format ("R'G'B' u8"), &ncols, NULL);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
buffer = gimp_drawable_get_buffer (drawable);
|
|
|
|
format = gimp_drawable_get_format (drawable);
|
2014-10-26 18:54:42 +01:00
|
|
|
bpp = babl_format_get_bytes_per_pixel (format);
|
|
|
|
width = gegl_buffer_get_width (buffer);
|
2013-05-14 19:43:19 +05:30
|
|
|
height = gegl_buffer_get_height (buffer);
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
|
|
|
|
/* allocate a buffer for retrieving information from the pixel region */
|
2013-05-14 19:43:19 +05:30
|
|
|
src = data = g_new (guchar, tile_height * width * bpp);
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
nbsl = (width + 7) / 8;
|
|
|
|
|
|
|
|
scanline = g_new (guchar, nbsl + 1);
|
2003-07-03 13:26:06 +00:00
|
|
|
hex_scanline = g_new (guchar, (nbsl + 1) * 2);
|
1999-01-03 22:41:12 +00:00
|
|
|
|
|
|
|
/* Set up transformation in PostScript */
|
2023-02-21 18:55:53 +00:00
|
|
|
if (! save_ps_setup (output, drawable, width, height, config, 1, error))
|
2014-10-26 18:54:42 +01:00
|
|
|
goto fail;
|
1999-01-03 22:41:12 +00:00
|
|
|
|
|
|
|
/* Write read image procedure */
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! level2)
|
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"{ currentfile scanline readhexstring pop }\n"))
|
|
|
|
goto fail;
|
|
|
|
}
|
2000-01-22 22:26:20 +00:00
|
|
|
else
|
2014-10-26 18:54:42 +01:00
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"currentfile /ASCII85Decode filter /RunLengthDecode filter\n"))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
ascii85_init ();
|
|
|
|
|
|
|
|
/* Allocate buffer for packbits data. Worst case: Less than 1% increase */
|
|
|
|
packb = g_new (guchar, ((nbsl+1) * 105) / 100 + 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! ps_begin_data (output, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "image\n"))
|
|
|
|
goto fail;
|
1999-01-03 22:41:12 +00:00
|
|
|
|
|
|
|
#define GET_BW_TILE(begin) \
|
2014-10-26 18:54:42 +01:00
|
|
|
{ gint scan_lines; \
|
1999-01-03 22:41:12 +00:00
|
|
|
scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i); \
|
2013-05-14 19:43:19 +05:30
|
|
|
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, i, width, scan_lines), \
|
|
|
|
1.0, format, begin, \
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); \
|
1999-01-03 22:41:12 +00:00
|
|
|
src = begin; }
|
|
|
|
|
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
if ((i % tile_height) == 0)
|
|
|
|
GET_BW_TILE (data); /* Get more data */
|
|
|
|
|
2000-01-22 22:26:20 +00:00
|
|
|
dst = scanline;
|
2000-01-25 17:46:56 +00:00
|
|
|
memset (dst, 0, nbsl);
|
|
|
|
mask = 0x80;
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
/* Build a bitmap for a scanline */
|
|
|
|
for (j = 0; j < width; j++)
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
|
|
|
ct = cmap + *(src++)*3;
|
|
|
|
if (ct[0] || ct[1] || ct[2])
|
|
|
|
*dst |= mask;
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
if (mask == 0x01)
|
|
|
|
{
|
|
|
|
mask = 0x80; dst++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mask >>= 1;
|
|
|
|
}
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
if (! level2)
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
|
|
|
/* Convert to hexstring */
|
|
|
|
for (j = 0; j < nbsl; j++)
|
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
hex_scanline[j * 2] = (guchar) hex[scanline[j] >> 4];
|
|
|
|
hex_scanline[j * 2 + 1] = (guchar) hex[scanline[j] & 0x0f];
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2006-05-08 12:23:32 +00:00
|
|
|
/* Write out hexstring */
|
|
|
|
j = nbsl * 2;
|
|
|
|
dst = hex_scanline;
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2006-05-08 12:23:32 +00:00
|
|
|
while (j > 0)
|
|
|
|
{
|
|
|
|
nwrite = (j > 78) ? 78 : j;
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
if (! g_output_stream_write_all (output,
|
|
|
|
dst, nwrite, NULL,
|
|
|
|
NULL, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
goto fail;
|
|
|
|
|
2006-05-08 12:23:32 +00:00
|
|
|
j -= nwrite;
|
|
|
|
dst += nwrite;
|
|
|
|
}
|
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
else
|
2014-10-26 18:54:42 +01:00
|
|
|
{
|
|
|
|
gint nout;
|
2000-03-10 17:27:25 +00:00
|
|
|
|
|
|
|
compress_packbits (nbsl, scanline, &nout, packb);
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
if (! ascii85_nout (output, nout, packb, error))
|
|
|
|
goto fail;
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
2003-06-13 14:37:00 +00:00
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
2014-10-26 18:54:42 +01:00
|
|
|
gimp_progress_update ((gdouble) i / (gdouble) height);
|
1999-01-03 22:41:12 +00:00
|
|
|
}
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2011-04-10 19:05:08 +02:00
|
|
|
gimp_progress_update (1.0);
|
2003-06-13 14:37:00 +00:00
|
|
|
|
2000-03-10 17:27:25 +00:00
|
|
|
if (level2)
|
2003-06-13 14:37:00 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
/* Write EOD of RunLengthDecode filter */
|
|
|
|
if (! ascii85_out (output, 128, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! ascii85_done (output, error))
|
|
|
|
goto fail;
|
2003-06-13 14:37:00 +00:00
|
|
|
}
|
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! ps_end_data (output, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "showpage\n"))
|
|
|
|
goto fail;
|
1999-01-03 22:41:12 +00:00
|
|
|
|
|
|
|
g_free (hex_scanline);
|
|
|
|
g_free (scanline);
|
|
|
|
g_free (data);
|
2014-10-26 18:54:42 +01:00
|
|
|
g_free (packb);
|
2003-06-13 14:37:00 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
g_object_unref (buffer);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
|
|
|
|
g_free (hex_scanline);
|
|
|
|
g_free (scanline);
|
|
|
|
g_free (data);
|
|
|
|
g_free (packb);
|
1999-01-03 22:41:12 +00:00
|
|
|
|
2013-05-14 19:43:19 +05:30
|
|
|
g_object_unref (buffer);
|
1999-01-03 22:41:12 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
return FALSE;
|
2004-11-18 21:10:12 +00:00
|
|
|
|
1999-01-03 22:41:12 +00:00
|
|
|
#undef GET_BW_TILE
|
|
|
|
}
|
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
static gboolean
|
|
|
|
save_index (GOutputStream *output,
|
2019-08-19 15:46:53 +02:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2023-02-21 18:55:53 +00:00
|
|
|
GObject *config,
|
2014-10-26 18:54:42 +01:00
|
|
|
GError **error)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
GeglBuffer *buffer = NULL;
|
|
|
|
const Babl *format;
|
2023-02-21 18:55:53 +00:00
|
|
|
gboolean level2;
|
2014-10-26 18:54:42 +01:00
|
|
|
gint bpp;
|
|
|
|
gint height, width, i, j;
|
|
|
|
gint ncols, bw;
|
|
|
|
gint tile_height;
|
|
|
|
guchar *cmap, *cmap_start;
|
|
|
|
guchar *data, *src;
|
|
|
|
guchar *packb = NULL;
|
|
|
|
guchar *plane = NULL;
|
|
|
|
gchar coltab[256 * 6], *ct;
|
2023-02-21 18:55:53 +00:00
|
|
|
|
|
|
|
g_object_get (config,
|
|
|
|
"level", &level2,
|
|
|
|
NULL);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2024-09-23 15:17:04 +02:00
|
|
|
cmap = cmap_start = gimp_palette_get_colormap (gimp_image_get_palette (image), babl_format ("R'G'B' u8"), &ncols, NULL);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
ct = coltab;
|
1999-01-03 22:41:12 +00:00
|
|
|
bw = 1;
|
1997-11-24 22:05:25 +00:00
|
|
|
for (j = 0; j < 256; j++)
|
|
|
|
{
|
2000-01-25 17:46:56 +00:00
|
|
|
if (j >= ncols)
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
2008-12-03 16:07:32 +00:00
|
|
|
memset (ct, 0, 6);
|
2006-05-08 12:23:32 +00:00
|
|
|
ct += 6;
|
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
else
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
bw &= ((cmap[0] == 0) && (cmap[1] == 0) && (cmap[2] == 0)) ||
|
|
|
|
((cmap[0] == 255) && (cmap[1] == 255) && (cmap[2] == 255));
|
|
|
|
|
|
|
|
*(ct++) = (guchar) hex[(*cmap) >> 4];
|
|
|
|
*(ct++) = (guchar) hex[(*(cmap++)) & 0x0f];
|
|
|
|
*(ct++) = (guchar) hex[(*cmap) >> 4];
|
|
|
|
*(ct++) = (guchar) hex[(*(cmap++)) & 0x0f];
|
|
|
|
*(ct++) = (guchar) hex[(*cmap) >> 4];
|
|
|
|
*(ct++) = (guchar) hex[(*(cmap++)) & 0x0f];
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2004-11-18 21:10:12 +00:00
|
|
|
if (bw)
|
2023-02-21 18:55:53 +00:00
|
|
|
return save_bw (output, image, drawable, config, error);
|
1999-01-03 22:41:12 +00:00
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
buffer = gimp_drawable_get_buffer (drawable);
|
|
|
|
format = gimp_drawable_get_format (drawable);
|
2014-10-26 18:54:42 +01:00
|
|
|
bpp = babl_format_get_bytes_per_pixel (format);
|
|
|
|
width = gegl_buffer_get_width (buffer);
|
2013-05-14 19:43:19 +05:30
|
|
|
height = gegl_buffer_get_height (buffer);
|
|
|
|
|
1999-01-03 22:41:12 +00:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
|
|
|
|
/* allocate a buffer for retrieving information from the pixel region */
|
2014-10-26 18:54:42 +01:00
|
|
|
src = data = (guchar *) g_malloc (tile_height * width * bpp);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* Set up transformation in PostScript */
|
2023-02-21 18:55:53 +00:00
|
|
|
if (! save_ps_setup (output, drawable, width, height, config, 3 * 8, error))
|
2014-10-26 18:54:42 +01:00
|
|
|
goto fail;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* Write read image procedure */
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! level2)
|
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"{ currentfile scanline readhexstring pop } false 3\n"))
|
|
|
|
goto fail;
|
|
|
|
}
|
2000-01-22 22:26:20 +00:00
|
|
|
else
|
2014-10-26 18:54:42 +01:00
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"%% Strings to hold RGB-samples per scanline\n"
|
|
|
|
"/rstr %d string def\n"
|
|
|
|
"/gstr %d string def\n"
|
|
|
|
"/bstr %d string def\n",
|
|
|
|
width, width, width))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error,
|
|
|
|
"{currentfile /ASCII85Decode filter /RunLengthDecode filter\
|
|
|
|
rstr readstring pop}\n"
|
|
|
|
"{currentfile /ASCII85Decode filter /RunLengthDecode filter\
|
|
|
|
gstr readstring pop}\n"
|
|
|
|
"{currentfile /ASCII85Decode filter /RunLengthDecode filter\
|
|
|
|
bstr readstring pop}\n"
|
|
|
|
"true 3\n"))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
/* Allocate buffer for packbits data. Worst case: Less than 1% increase */
|
|
|
|
packb = (guchar *) g_malloc ((width * 105) / 100 + 2);
|
|
|
|
plane = (guchar *) g_malloc (width);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! ps_begin_data (output, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "colorimage\n"))
|
|
|
|
goto fail;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
#define GET_INDEX_TILE(begin) \
|
2014-10-26 18:54:42 +01:00
|
|
|
{ gint scan_lines; \
|
1997-11-24 22:05:25 +00:00
|
|
|
scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i); \
|
2013-05-14 19:43:19 +05:30
|
|
|
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, i, width, scan_lines), \
|
|
|
|
1.0, format, begin, \
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); \
|
1997-11-24 22:05:25 +00:00
|
|
|
src = begin; }
|
|
|
|
|
|
|
|
for (i = 0; i < height; i++)
|
2000-01-22 22:26:20 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
if ((i % tile_height) == 0)
|
|
|
|
GET_INDEX_TILE (data); /* Get more data */
|
|
|
|
|
|
|
|
if (! level2)
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! g_output_stream_write_all (output,
|
|
|
|
coltab + (*(src++)) * 6, 6, NULL,
|
|
|
|
NULL, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (((j + 1) % 13) == 0)
|
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
goto fail;
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
goto fail;
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
else
|
2014-10-26 18:54:42 +01:00
|
|
|
{
|
|
|
|
gint rgb;
|
2000-03-10 17:27:25 +00:00
|
|
|
|
|
|
|
for (rgb = 0; rgb < 3; rgb++)
|
2014-10-26 18:54:42 +01:00
|
|
|
{
|
|
|
|
guchar *src_ptr = src;
|
|
|
|
guchar *plane_ptr = plane;
|
|
|
|
gint nout;
|
|
|
|
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
*(plane_ptr++) = cmap_start[3 * *(src_ptr++) + rgb];
|
|
|
|
|
|
|
|
compress_packbits (width, plane, &nout, packb);
|
|
|
|
|
|
|
|
ascii85_init ();
|
|
|
|
|
|
|
|
if (! ascii85_nout (output, nout, packb, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
/* Write EOD of RunLengthDecode filter */
|
|
|
|
if (! ascii85_out (output, 128, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! ascii85_done (output, error))
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2000-03-10 17:27:25 +00:00
|
|
|
src += width;
|
|
|
|
}
|
2003-06-13 14:37:00 +00:00
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
2014-10-26 18:54:42 +01:00
|
|
|
gimp_progress_update ((gdouble) i / (gdouble) height);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2011-04-10 19:05:08 +02:00
|
|
|
gimp_progress_update (1.0);
|
2003-06-13 14:37:00 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! ps_end_data (output, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "showpage\n"))
|
|
|
|
goto fail;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
g_free (data);
|
2014-10-26 18:54:42 +01:00
|
|
|
g_free (packb);
|
|
|
|
g_free (plane);
|
|
|
|
|
|
|
|
g_object_unref (buffer);
|
|
|
|
|
|
|
|
return TRUE;
|
2003-06-13 14:37:00 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
fail:
|
2003-06-13 14:37:00 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
g_free (data);
|
|
|
|
g_free (packb);
|
|
|
|
g_free (plane);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2013-05-14 19:43:19 +05:30
|
|
|
g_object_unref (buffer);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
return FALSE;
|
2004-11-18 21:10:12 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
#undef GET_INDEX_TILE
|
|
|
|
}
|
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
static gboolean
|
|
|
|
save_rgb (GOutputStream *output,
|
2019-08-19 15:46:53 +02:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2023-02-21 18:55:53 +00:00
|
|
|
GObject *config,
|
2014-10-26 18:54:42 +01:00
|
|
|
GError **error)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
GeglBuffer *buffer = NULL;
|
|
|
|
const Babl *format;
|
2023-02-21 18:55:53 +00:00
|
|
|
gboolean level2;
|
2014-10-26 18:54:42 +01:00
|
|
|
gint bpp;
|
|
|
|
gint height, width, tile_height;
|
|
|
|
gint i, j;
|
|
|
|
guchar *data, *src;
|
|
|
|
guchar *packb = NULL;
|
|
|
|
guchar *plane = NULL;
|
2023-02-21 18:55:53 +00:00
|
|
|
|
|
|
|
g_object_get (config,
|
|
|
|
"level", &level2,
|
|
|
|
NULL);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-19 15:46:53 +02:00
|
|
|
buffer = gimp_drawable_get_buffer (drawable);
|
2013-05-14 14:24:00 +05:30
|
|
|
format = babl_format ("R'G'B' u8");
|
2014-10-26 18:54:42 +01:00
|
|
|
bpp = babl_format_get_bytes_per_pixel (format);
|
|
|
|
width = gegl_buffer_get_width (buffer);
|
2013-05-14 14:24:00 +05:30
|
|
|
height = gegl_buffer_get_height (buffer);
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
|
|
|
|
/* allocate a buffer for retrieving information from the pixel region */
|
2013-05-14 14:24:00 +05:30
|
|
|
src = data = g_new (guchar, tile_height * width * bpp);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* Set up transformation in PostScript */
|
2023-02-21 18:55:53 +00:00
|
|
|
if (! save_ps_setup (output, drawable, width, height, config, 3 * 8, error))
|
2014-10-26 18:54:42 +01:00
|
|
|
goto fail;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* Write read image procedure */
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! level2)
|
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"{ currentfile scanline readhexstring pop } false 3\n"))
|
|
|
|
goto fail;
|
|
|
|
}
|
2000-01-22 22:26:20 +00:00
|
|
|
else
|
2014-10-26 18:54:42 +01:00
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"%% Strings to hold RGB-samples per scanline\n"
|
|
|
|
"/rstr %d string def\n"
|
|
|
|
"/gstr %d string def\n"
|
|
|
|
"/bstr %d string def\n",
|
|
|
|
width, width, width))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error,
|
|
|
|
"{currentfile /ASCII85Decode filter /RunLengthDecode filter\
|
|
|
|
rstr readstring pop}\n"
|
|
|
|
"{currentfile /ASCII85Decode filter /RunLengthDecode filter\
|
|
|
|
gstr readstring pop}\n"
|
|
|
|
"{currentfile /ASCII85Decode filter /RunLengthDecode filter\
|
|
|
|
bstr readstring pop}\n"
|
|
|
|
"true 3\n"))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
/* Allocate buffer for packbits data. Worst case: Less than 1% increase */
|
|
|
|
packb = g_new (guchar, (width * 105) / 100 + 2);
|
|
|
|
plane = g_new (guchar, width);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! ps_begin_data (output, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "colorimage\n"))
|
|
|
|
goto fail;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
#define GET_RGB_TILE(begin) \
|
2014-10-26 18:54:42 +01:00
|
|
|
{ gint scan_lines; \
|
1997-11-24 22:05:25 +00:00
|
|
|
scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i); \
|
2013-05-14 14:24:00 +05:30
|
|
|
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, i, width, scan_lines), \
|
|
|
|
1.0, format, begin, \
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); \
|
1997-11-24 22:05:25 +00:00
|
|
|
src = begin; }
|
|
|
|
|
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
if ((i % tile_height) == 0)
|
|
|
|
GET_RGB_TILE (data); /* Get more data */
|
|
|
|
|
|
|
|
if (! level2)
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! print (output, error, "%c",
|
|
|
|
hex[(*src) >> 4])) /* Red */
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "%c",
|
|
|
|
hex[(*(src++)) & 0x0f]))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "%c",
|
|
|
|
hex[(*src) >> 4])) /* Green */
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "%c",
|
|
|
|
hex[(*(src++)) & 0x0f]))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "%c",
|
|
|
|
hex[(*src) >> 4])) /* Blue */
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "%c",
|
|
|
|
hex[(*(src++)) & 0x0f]))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (((j+1) % 13) == 0)
|
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
goto fail;
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
goto fail;
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
else
|
2014-10-26 18:54:42 +01:00
|
|
|
{
|
|
|
|
gint rgb;
|
2000-03-10 17:27:25 +00:00
|
|
|
|
|
|
|
for (rgb = 0; rgb < 3; rgb++)
|
2006-05-08 12:23:32 +00:00
|
|
|
{
|
2014-10-26 18:54:42 +01:00
|
|
|
guchar *src_ptr = src + rgb;
|
|
|
|
guchar *plane_ptr = plane;
|
|
|
|
gint nout;
|
|
|
|
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
|
|
|
*(plane_ptr++) = *src_ptr;
|
|
|
|
src_ptr += 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
compress_packbits (width, plane, &nout, packb);
|
|
|
|
|
|
|
|
ascii85_init ();
|
|
|
|
|
|
|
|
if (! ascii85_nout (output, nout, packb, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
/* Write EOD of RunLengthDecode filter */
|
|
|
|
if (! ascii85_out (output, 128, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! ascii85_done (output, error))
|
|
|
|
goto fail;
|
2000-03-10 17:27:25 +00:00
|
|
|
}
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
src += 3 * width;
|
2006-05-08 12:23:32 +00:00
|
|
|
}
|
2003-06-13 14:37:00 +00:00
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
2014-10-26 18:54:42 +01:00
|
|
|
gimp_progress_update ((gdouble) i / (gdouble) height);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
2014-10-26 18:54:42 +01:00
|
|
|
|
2011-04-10 19:05:08 +02:00
|
|
|
gimp_progress_update (1.0);
|
2003-06-13 14:37:00 +00:00
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
if (! ps_end_data (output, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "showpage\n"))
|
|
|
|
goto fail;
|
2003-06-13 14:37:00 +00:00
|
|
|
|
2007-05-29 15:29:37 +00:00
|
|
|
g_free (data);
|
|
|
|
g_free (packb);
|
|
|
|
g_free (plane);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2013-05-14 14:24:00 +05:30
|
|
|
g_object_unref (buffer);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2004-11-18 21:10:12 +00:00
|
|
|
return TRUE;
|
2014-10-26 18:54:42 +01:00
|
|
|
|
|
|
|
fail:
|
|
|
|
|
|
|
|
g_free (data);
|
|
|
|
g_free (packb);
|
|
|
|
g_free (plane);
|
|
|
|
|
|
|
|
g_object_unref (buffer);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
#undef GET_RGB_TILE
|
|
|
|
}
|
|
|
|
|
2014-10-26 18:54:42 +01:00
|
|
|
static gboolean
|
|
|
|
print (GOutputStream *output,
|
|
|
|
GError **error,
|
|
|
|
const gchar *format,
|
|
|
|
...)
|
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
gboolean success;
|
|
|
|
|
|
|
|
va_start (args, format);
|
|
|
|
success = g_output_stream_vprintf (output, NULL, NULL,
|
|
|
|
error, format, args);
|
|
|
|
va_end (args);
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
/* Load interface functions */
|
|
|
|
|
2005-08-15 08:48:45 +00:00
|
|
|
static gint32
|
2019-09-11 21:48:34 +02:00
|
|
|
count_ps_pages (GFile *file)
|
2005-08-15 08:48:45 +00:00
|
|
|
{
|
2007-05-29 15:29:37 +00:00
|
|
|
FILE *psfile;
|
|
|
|
gchar *extension;
|
|
|
|
gchar buf[1024];
|
2005-08-15 08:48:45 +00:00
|
|
|
gint32 num_pages = 0;
|
|
|
|
gint32 showpage_count = 0;
|
|
|
|
|
2021-10-01 18:56:12 +02:00
|
|
|
extension = strrchr (g_file_peek_path (file), '.');
|
2007-05-29 15:29:37 +00:00
|
|
|
if (extension)
|
|
|
|
{
|
|
|
|
extension = g_ascii_strdown (extension + 1, -1);
|
|
|
|
|
|
|
|
if (strcmp (extension, "eps") == 0)
|
|
|
|
{
|
|
|
|
g_free (extension);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (extension);
|
|
|
|
}
|
2005-08-15 08:48:45 +00:00
|
|
|
|
2021-10-01 18:56:12 +02:00
|
|
|
psfile = g_fopen (g_file_peek_path (file), "r");
|
2019-09-11 21:48:34 +02:00
|
|
|
|
2005-08-15 08:48:45 +00:00
|
|
|
if (psfile == NULL)
|
|
|
|
{
|
|
|
|
g_message (_("Could not open '%s' for reading: %s"),
|
2019-09-11 21:48:34 +02:00
|
|
|
gimp_file_get_utf8_name (file), g_strerror (errno));
|
2005-08-15 08:48:45 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (num_pages == 0 && !feof (psfile))
|
|
|
|
{
|
2007-05-29 15:29:37 +00:00
|
|
|
fgets (buf, sizeof (buf), psfile);
|
2005-08-15 08:48:45 +00:00
|
|
|
|
2007-05-29 15:29:37 +00:00
|
|
|
if (strncmp (buf + 2, "Pages:", 6) == 0)
|
|
|
|
sscanf (buf + strlen ("%%Pages:"), "%d", &num_pages);
|
|
|
|
else if (strncmp (buf, "showpage", 8) == 0)
|
2005-08-15 08:48:45 +00:00
|
|
|
showpage_count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (feof (psfile) && num_pages < 1 && showpage_count > 0)
|
|
|
|
num_pages = showpage_count;
|
|
|
|
|
|
|
|
fclose (psfile);
|
|
|
|
|
|
|
|
return num_pages;
|
|
|
|
}
|
|
|
|
|
2004-05-19 17:53:21 +00:00
|
|
|
static gboolean
|
2024-06-08 18:37:38 +02:00
|
|
|
load_dialog (GFile *file,
|
|
|
|
GimpVectorLoadData extracted_data,
|
|
|
|
GimpProcedure *procedure,
|
|
|
|
GObject *config)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2014-06-22 23:01:31 +02:00
|
|
|
GtkWidget *dialog;
|
|
|
|
GtkWidget *hbox;
|
|
|
|
GtkWidget *vbox;
|
|
|
|
GtkWidget *target = NULL;
|
|
|
|
GtkWidget *selector = NULL;
|
|
|
|
gint32 page_count;
|
|
|
|
gchar *range = NULL;
|
|
|
|
gboolean run;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-09-11 21:48:34 +02:00
|
|
|
page_count = count_ps_pages (file);
|
2005-08-15 08:48:45 +00:00
|
|
|
|
2019-09-20 19:39:00 +02:00
|
|
|
gimp_ui_init (PLUG_IN_BINARY);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2024-04-24 01:12:01 +02:00
|
|
|
dialog = gimp_vector_load_procedure_dialog_new (GIMP_VECTOR_LOAD_PROCEDURE (procedure),
|
|
|
|
GIMP_PROCEDURE_CONFIG (config),
|
2024-06-08 18:37:38 +02:00
|
|
|
&extracted_data, NULL);
|
2000-01-08 15:23:28 +00:00
|
|
|
|
2005-08-15 08:48:45 +00:00
|
|
|
if (page_count > 1)
|
|
|
|
{
|
|
|
|
selector = gimp_page_selector_new ();
|
2023-02-21 18:55:53 +00:00
|
|
|
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
|
|
|
|
selector, TRUE, TRUE, 0);
|
2005-08-15 08:48:45 +00:00
|
|
|
gimp_page_selector_set_n_pages (GIMP_PAGE_SELECTOR (selector),
|
2006-05-08 12:23:32 +00:00
|
|
|
page_count);
|
2005-08-15 08:48:45 +00:00
|
|
|
gimp_page_selector_set_target (GIMP_PAGE_SELECTOR (selector),
|
2006-05-08 12:23:32 +00:00
|
|
|
ps_pagemode);
|
2005-10-28 14:57:32 +00:00
|
|
|
|
2024-04-27 16:49:31 +00:00
|
|
|
gtk_widget_set_visible (selector, TRUE);
|
2005-10-28 14:57:32 +00:00
|
|
|
|
|
|
|
g_signal_connect_swapped (selector, "activate",
|
|
|
|
G_CALLBACK (gtk_window_activate_default),
|
|
|
|
dialog);
|
2005-08-15 08:48:45 +00:00
|
|
|
}
|
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
vbox = gimp_procedure_dialog_fill_box (GIMP_PROCEDURE_DIALOG (dialog),
|
|
|
|
"rendering-box",
|
|
|
|
"check-bbox",
|
|
|
|
NULL);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2017-12-13 20:35:41 +01:00
|
|
|
if (page_count == 0)
|
2005-08-15 08:48:45 +00:00
|
|
|
{
|
2023-02-21 18:55:53 +00:00
|
|
|
GtkWidget *grid;
|
|
|
|
GtkWidget *entry = NULL;
|
|
|
|
|
|
|
|
grid = gtk_grid_new ();
|
|
|
|
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
|
|
|
|
gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), grid, FALSE, FALSE, 0);
|
2024-04-27 16:49:31 +00:00
|
|
|
gtk_widget_set_visible (grid, TRUE);
|
2023-02-21 18:55:53 +00:00
|
|
|
|
|
|
|
entry = gimp_procedure_dialog_get_widget (GIMP_PROCEDURE_DIALOG (dialog),
|
|
|
|
"pages", GTK_TYPE_ENTRY);
|
2005-08-15 08:48:45 +00:00
|
|
|
gtk_widget_set_size_request (entry, 80, -1);
|
2023-02-21 18:55:53 +00:00
|
|
|
gimp_grid_attach_aligned (GTK_GRID (grid), 0, 0,
|
2018-05-08 23:06:26 +02:00
|
|
|
_("Pages:"), 0.0, 0.5,
|
|
|
|
entry, 1);
|
2005-08-15 08:48:45 +00:00
|
|
|
|
|
|
|
gimp_help_set_help_data (GTK_WIDGET (entry),
|
2023-02-21 18:55:53 +00:00
|
|
|
_("Pages to load (e.g.: 1-4 or 1,3,5-7)"),
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
target = gimp_enum_combo_box_new (GIMP_TYPE_PAGE_SELECTOR_TARGET);
|
2005-08-15 08:48:45 +00:00
|
|
|
gtk_combo_box_set_active (GTK_COMBO_BOX (target), (int) ps_pagemode);
|
2023-02-21 18:55:53 +00:00
|
|
|
gimp_grid_attach_aligned (GTK_GRID (grid), 0, 1,
|
2018-05-08 23:06:26 +02:00
|
|
|
_("Open as"), 0.0, 0.5,
|
|
|
|
target, 1);
|
2005-08-15 08:48:45 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
/* Dialog formatting */
|
|
|
|
hbox = gimp_procedure_dialog_fill_box (GIMP_PROCEDURE_DIALOG (dialog),
|
|
|
|
"ps-top-row",
|
|
|
|
"rendering-box",
|
|
|
|
NULL);
|
|
|
|
gtk_box_set_spacing (GTK_BOX (hbox), 12);
|
2011-09-30 12:17:53 +02:00
|
|
|
gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE);
|
2023-02-21 18:55:53 +00:00
|
|
|
gtk_widget_set_margin_bottom (hbox, 12);
|
|
|
|
gtk_orientable_set_orientation (GTK_ORIENTABLE (hbox),
|
|
|
|
GTK_ORIENTATION_HORIZONTAL);
|
|
|
|
|
2024-04-27 16:49:31 +00:00
|
|
|
vbox = gimp_procedure_dialog_fill_box (GIMP_PROCEDURE_DIALOG (dialog),
|
2023-02-21 18:55:53 +00:00
|
|
|
"ps-bottom-row",
|
2024-04-24 01:12:01 +02:00
|
|
|
"coloring",
|
2023-02-21 18:55:53 +00:00
|
|
|
"text-alpha-bits",
|
2024-04-27 16:49:31 +00:00
|
|
|
"graphic-alpha-bits",
|
2023-02-21 18:55:53 +00:00
|
|
|
NULL);
|
2024-04-27 16:49:31 +00:00
|
|
|
gtk_box_set_spacing (GTK_BOX (vbox), 12);
|
|
|
|
gtk_box_set_homogeneous (GTK_BOX (vbox), TRUE);
|
|
|
|
gtk_widget_set_margin_bottom (vbox, 12);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
gimp_procedure_dialog_fill (GIMP_PROCEDURE_DIALOG (dialog),
|
|
|
|
"ps-top-row",
|
|
|
|
"ps-bottom-row",
|
|
|
|
NULL);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2024-04-27 16:49:31 +00:00
|
|
|
gtk_widget_set_visible (dialog, TRUE);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
run = gimp_procedure_dialog_run (GIMP_PROCEDURE_DIALOG (dialog));
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2005-10-28 14:57:32 +00:00
|
|
|
if (selector)
|
2005-08-15 08:48:45 +00:00
|
|
|
{
|
|
|
|
range = gimp_page_selector_get_selected_range (GIMP_PAGE_SELECTOR (selector));
|
|
|
|
|
|
|
|
if (strlen (range) < 1)
|
|
|
|
{
|
|
|
|
gimp_page_selector_select_all (GIMP_PAGE_SELECTOR (selector));
|
|
|
|
range = gimp_page_selector_get_selected_range (GIMP_PAGE_SELECTOR (selector));
|
|
|
|
}
|
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
g_object_set (config,
|
|
|
|
"pages", range,
|
|
|
|
NULL);
|
2005-08-15 08:48:45 +00:00
|
|
|
ps_pagemode = gimp_page_selector_get_target (GIMP_PAGE_SELECTOR (selector));
|
|
|
|
}
|
2017-12-13 20:35:41 +01:00
|
|
|
else if (page_count == 0)
|
2005-08-15 08:48:45 +00:00
|
|
|
{
|
|
|
|
ps_pagemode = gtk_combo_box_get_active (GTK_COMBO_BOX (target));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-02-21 18:55:53 +00:00
|
|
|
g_object_set (config,
|
|
|
|
"pages", "1",
|
|
|
|
NULL);
|
2005-08-15 08:48:45 +00:00
|
|
|
ps_pagemode = GIMP_PAGE_SELECTOR_TARGET_IMAGES;
|
|
|
|
}
|
|
|
|
|
2003-11-06 15:27:05 +00:00
|
|
|
gtk_widget_destroy (dialog);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2003-11-06 15:27:05 +00:00
|
|
|
return run;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* Save interface functions */
|
|
|
|
|
2004-05-19 17:53:21 +00:00
|
|
|
static gboolean
|
2023-02-21 18:55:53 +00:00
|
|
|
save_dialog (GimpProcedure *procedure,
|
|
|
|
GObject *config,
|
|
|
|
GimpImage *image)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2014-06-22 23:01:31 +02:00
|
|
|
GtkWidget *dialog;
|
2023-02-21 18:55:53 +00:00
|
|
|
GtkListStore *store;
|
2014-06-22 23:01:31 +02:00
|
|
|
GtkWidget *toggle;
|
2024-04-27 16:49:31 +00:00
|
|
|
GtkWidget *combo;
|
|
|
|
GtkWidget *widget;
|
2014-06-22 23:01:31 +02:00
|
|
|
GtkWidget *hbox, *vbox;
|
|
|
|
gboolean run;
|
2000-01-08 15:23:28 +00:00
|
|
|
|
2024-04-20 03:08:57 +00:00
|
|
|
dialog = gimp_export_procedure_dialog_new (GIMP_EXPORT_PROCEDURE (procedure),
|
|
|
|
GIMP_PROCEDURE_CONFIG (config),
|
|
|
|
image);
|
1997-12-26 07:08:20 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
/* Image Size */
|
|
|
|
/* Width/Height/X-/Y-offset labels */
|
2023-02-21 18:55:53 +00:00
|
|
|
toggle = gimp_procedure_dialog_get_widget (GIMP_PROCEDURE_DIALOG (dialog),
|
|
|
|
"keep-ratio", G_TYPE_NONE);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2001-12-31 00:21:10 +00:00
|
|
|
gimp_help_set_help_data (toggle,
|
2006-08-29 13:32:22 +00:00
|
|
|
_("When toggled, the resulting image will be "
|
|
|
|
"scaled to fit into the given size without "
|
|
|
|
"changing the aspect ratio."),
|
2006-05-08 12:23:32 +00:00
|
|
|
"#keep_aspect_ratio"),
|
2001-12-31 00:21:10 +00:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
gimp_procedure_dialog_get_label (GIMP_PROCEDURE_DIALOG (dialog),
|
2023-07-18 00:06:26 +02:00
|
|
|
"image-title", _("Image Size"),
|
|
|
|
FALSE, FALSE);
|
2001-12-31 00:21:10 +00:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
gimp_procedure_dialog_fill_box (GIMP_PROCEDURE_DIALOG (dialog), "image-box",
|
|
|
|
"width", "height", "x-offset", "y-offset",
|
|
|
|
"keep-ratio", NULL);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
gimp_procedure_dialog_fill_frame (GIMP_PROCEDURE_DIALOG (dialog),
|
|
|
|
"image-frame", "image-title",
|
|
|
|
FALSE, "image-box");
|
2001-12-31 00:21:10 +00:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
/* Unit */
|
2024-04-27 16:49:31 +00:00
|
|
|
widget = gimp_procedure_dialog_get_widget (GIMP_PROCEDURE_DIALOG (dialog),
|
|
|
|
"unit", G_TYPE_NONE);
|
|
|
|
combo = gimp_label_string_widget_get_widget (GIMP_LABEL_STRING_WIDGET (widget));
|
|
|
|
g_signal_connect (combo, "changed",
|
|
|
|
G_CALLBACK (save_unit_changed_update),
|
2023-02-21 18:55:53 +00:00
|
|
|
config);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* Rotation */
|
2023-02-21 18:55:53 +00:00
|
|
|
store = gimp_int_store_new (_("_0"), 0,
|
|
|
|
_("_90"), 90,
|
|
|
|
_("_180"), 180,
|
|
|
|
_("_270"), 270,
|
|
|
|
NULL);
|
|
|
|
gimp_procedure_dialog_get_int_radio (GIMP_PROCEDURE_DIALOG (dialog),
|
|
|
|
"rotation", GIMP_INT_STORE (store));
|
|
|
|
|
|
|
|
/* Output */
|
|
|
|
gimp_procedure_dialog_get_label (GIMP_PROCEDURE_DIALOG (dialog),
|
2023-07-18 00:06:26 +02:00
|
|
|
"output-title", _("Output"),
|
|
|
|
FALSE, FALSE);
|
2023-02-21 18:55:53 +00:00
|
|
|
|
|
|
|
gimp_procedure_dialog_set_sensitive (GIMP_PROCEDURE_DIALOG (dialog),
|
|
|
|
"preview",
|
|
|
|
TRUE, config, "show-preview", FALSE);
|
|
|
|
|
|
|
|
|
|
|
|
gimp_procedure_dialog_fill_box (GIMP_PROCEDURE_DIALOG (dialog), "output-box",
|
|
|
|
"level", "eps-flag", "show-preview", "preview",
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
gimp_procedure_dialog_fill_frame (GIMP_PROCEDURE_DIALOG (dialog),
|
|
|
|
"output-frame", "output-title",
|
|
|
|
FALSE, "output-box");
|
|
|
|
|
|
|
|
/* Dialog Formatting */
|
|
|
|
vbox = gimp_procedure_dialog_fill_box (GIMP_PROCEDURE_DIALOG (dialog), "left-column",
|
|
|
|
"image-frame", "unit",
|
|
|
|
NULL);
|
|
|
|
gtk_box_set_spacing (GTK_BOX (vbox), 12);
|
|
|
|
vbox = gimp_procedure_dialog_fill_box (GIMP_PROCEDURE_DIALOG (dialog), "right-column",
|
|
|
|
"rotation", "output-frame",
|
|
|
|
NULL);
|
|
|
|
gtk_box_set_spacing (GTK_BOX (vbox), 12);
|
|
|
|
hbox = gimp_procedure_dialog_fill_box (GIMP_PROCEDURE_DIALOG (dialog), "ps-hbox",
|
|
|
|
"left-column", "right-column",
|
|
|
|
NULL);
|
|
|
|
gtk_box_set_spacing (GTK_BOX (hbox), 12);
|
|
|
|
gtk_orientable_set_orientation (GTK_ORIENTABLE (hbox),
|
|
|
|
GTK_ORIENTATION_HORIZONTAL);
|
|
|
|
|
|
|
|
gimp_procedure_dialog_fill (GIMP_PROCEDURE_DIALOG (dialog),
|
|
|
|
"ps-hbox",
|
|
|
|
NULL);
|
|
|
|
|
2024-04-27 16:49:31 +00:00
|
|
|
gtk_widget_set_visible (dialog, TRUE);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2023-02-21 18:55:53 +00:00
|
|
|
run = gimp_procedure_dialog_run (GIMP_PROCEDURE_DIALOG (dialog));
|
2003-11-06 15:27:05 +00:00
|
|
|
|
|
|
|
gtk_widget_destroy (dialog);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2003-11-06 15:27:05 +00:00
|
|
|
return run;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
static void
|
2024-04-27 16:49:31 +00:00
|
|
|
save_unit_changed_update (GtkWidget *widget,
|
|
|
|
gpointer data)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2023-02-21 18:55:53 +00:00
|
|
|
GimpProcedureConfig *config = GIMP_PROCEDURE_CONFIG (data);
|
|
|
|
gdouble factor;
|
|
|
|
gboolean unit_mm;
|
|
|
|
gdouble width;
|
|
|
|
gdouble height;
|
|
|
|
gdouble x_offset;
|
|
|
|
gdouble y_offset;
|
|
|
|
|
|
|
|
g_object_get (config,
|
|
|
|
"width", &width,
|
|
|
|
"height", &height,
|
|
|
|
"x-offset", &x_offset,
|
|
|
|
"y-offset", &y_offset,
|
|
|
|
NULL);
|
2024-04-27 16:49:31 +00:00
|
|
|
unit_mm = gimp_procedure_config_get_choice_id (config, "unit");
|
2023-02-21 18:55:53 +00:00
|
|
|
|
|
|
|
if (unit_mm)
|
|
|
|
factor = 25.4;
|
|
|
|
else
|
|
|
|
factor = 1.0 / 25.4;
|
|
|
|
|
|
|
|
g_object_set (config,
|
|
|
|
"width", width * factor,
|
|
|
|
"height", height * factor,
|
|
|
|
"x-offset", x_offset * factor,
|
|
|
|
"y-offset", y_offset * factor,
|
|
|
|
NULL);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|