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
|
|
|
|
* XWD reading and writing code Copyright (C) 1996 Peter Kirchgessner
|
2000-03-10 17:27:25 +00:00
|
|
|
* (email: peter@kirchgessner.net, WWW: http://www.kirchgessner.net)
|
1997-11-24 22:05:25 +00:00
|
|
|
*
|
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
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2001-07-02 23:18:10 +00:00
|
|
|
* XWD-input/output was written by Peter Kirchgessner (peter@kirchgessner.net)
|
1997-11-24 22:05:25 +00:00
|
|
|
* Examples from mainly used UNIX-systems have been used for testing.
|
|
|
|
* If a file does not work, please return a small (!!) compressed example.
|
|
|
|
* Currently the following formats are supported:
|
|
|
|
* pixmap_format | pixmap_depth | bits_per_pixel
|
|
|
|
* ---------------------------------------------
|
|
|
|
* 0 | 1 | 1
|
|
|
|
* 1 | 1,...,24 | 1
|
|
|
|
* 2 | 1 | 1
|
|
|
|
* 2 | 1,...,8 | 8
|
|
|
|
* 2 | 1,...,16 | 16
|
|
|
|
* 2 | 1,...,24 | 24
|
2012-08-07 15:56:58 +02:00
|
|
|
* 2 | 1,...,32 | 32
|
1997-11-24 22:05:25 +00:00
|
|
|
*/
|
|
|
|
/* Event history:
|
2018-05-25 15:01:25 +02:00
|
|
|
* PK = Peter Kirchgessner, ME = Mattias Engdegård
|
1997-11-24 22:05:25 +00:00
|
|
|
* V 1.00, PK, xx-Aug-96: First try
|
|
|
|
* V 1.01, PK, 03-Sep-96: Check for bitmap_bit_order
|
|
|
|
* V 1.90, PK, 17-Mar-97: Upgrade to work with GIMP V0.99
|
|
|
|
* Use visual class 3 to write indexed image
|
|
|
|
* Set gimp b/w-colormap if no xwdcolormap present
|
|
|
|
* V 1.91, PK, 05-Apr-97: Return all arguments, even in case of an error
|
|
|
|
* V 1.92, PK, 12-Oct-97: No progress bars for non-interactive mode
|
1998-04-11 22:07:00 +00:00
|
|
|
* V 1.93, PK, 11-Apr-98: Fix problem with overwriting memory
|
2000-03-10 17:27:25 +00:00
|
|
|
* V 1.94, ME, 27-Feb-00: Remove superfluous little-endian support (format is
|
|
|
|
specified as big-endian). Trim magic header
|
2001-07-02 23:18:10 +00:00
|
|
|
* V 1.95, PK, 02-Jul-01: Fix problem with 8 bit image
|
1997-11-24 22:05:25 +00:00
|
|
|
*/
|
|
|
|
|
1999-05-29 16:35:47 +00:00
|
|
|
#include "config.h"
|
1999-06-28 17:54:19 +00:00
|
|
|
|
2003-06-13 14:37:00 +00:00
|
|
|
#include <errno.h>
|
1997-11-24 22:05:25 +00:00
|
|
|
#include <string.h>
|
1999-06-28 17:54:19 +00:00
|
|
|
|
2005-03-04 15:12:29 +00:00
|
|
|
#include <glib/gstdio.h>
|
2000-01-25 17:46:56 +00:00
|
|
|
|
|
|
|
#include <libgimp/gimp.h>
|
|
|
|
#include <libgimp/gimpui.h>
|
|
|
|
|
1999-05-29 16:35:47 +00:00
|
|
|
#include "libgimp/stdplugins-intl.h"
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2000-05-01 20:22:55 +00:00
|
|
|
|
2005-08-15 22:42:34 +00:00
|
|
|
#define LOAD_PROC "file-xwd-load"
|
2024-04-13 15:10:25 +00:00
|
|
|
#define EXPORT_PROC "file-xwd-export"
|
2008-08-11 10:06:13 +00:00
|
|
|
#define PLUG_IN_BINARY "file-xwd"
|
2011-04-08 20:31:34 +02:00
|
|
|
#define PLUG_IN_ROLE "gimp-file-xwd"
|
2005-08-15 22:42:34 +00:00
|
|
|
|
|
|
|
|
2023-07-11 18:17:42 -04:00
|
|
|
typedef guint32 L_CARD32;
|
2000-05-01 20:22:55 +00:00
|
|
|
typedef gushort L_CARD16;
|
|
|
|
typedef guchar L_CARD8;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
1997-11-24 22:05:25 +00:00
|
|
|
L_CARD32 l_header_size; /* Header size */
|
|
|
|
|
|
|
|
L_CARD32 l_file_version; /* File version (7) */
|
|
|
|
L_CARD32 l_pixmap_format; /* Image type */
|
|
|
|
L_CARD32 l_pixmap_depth; /* Number of planes */
|
|
|
|
L_CARD32 l_pixmap_width; /* Image width */
|
|
|
|
L_CARD32 l_pixmap_height; /* Image height */
|
|
|
|
L_CARD32 l_xoffset; /* x-offset (0 ?) */
|
|
|
|
L_CARD32 l_byte_order; /* Byte ordering */
|
|
|
|
|
|
|
|
L_CARD32 l_bitmap_unit;
|
|
|
|
L_CARD32 l_bitmap_bit_order; /* Bit order */
|
|
|
|
L_CARD32 l_bitmap_pad;
|
|
|
|
L_CARD32 l_bits_per_pixel; /* Number of bits per pixel */
|
|
|
|
|
|
|
|
L_CARD32 l_bytes_per_line; /* Number of bytes per scanline */
|
|
|
|
L_CARD32 l_visual_class; /* Visual class */
|
|
|
|
L_CARD32 l_red_mask; /* Red mask */
|
|
|
|
L_CARD32 l_green_mask; /* Green mask */
|
|
|
|
L_CARD32 l_blue_mask; /* Blue mask */
|
|
|
|
L_CARD32 l_bits_per_rgb; /* Number of bits per RGB-part */
|
2004-09-07 12:08:03 +00:00
|
|
|
L_CARD32 l_colormap_entries; /* Number of colors in color table (?) */
|
1997-11-24 22:05:25 +00:00
|
|
|
L_CARD32 l_ncolors; /* Number of xwdcolor structures */
|
|
|
|
L_CARD32 l_window_width; /* Window width */
|
|
|
|
L_CARD32 l_window_height; /* Window height */
|
|
|
|
L_CARD32 l_window_x; /* Window position x */
|
|
|
|
L_CARD32 l_window_y; /* Window position y */
|
|
|
|
L_CARD32 l_window_bdrwidth;/* Window border width */
|
|
|
|
} L_XWDFILEHEADER;
|
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
2004-09-07 12:08:03 +00:00
|
|
|
L_CARD32 l_pixel; /* Color index */
|
1997-11-24 22:05:25 +00:00
|
|
|
L_CARD16 l_red, l_green, l_blue; /* RGB-values */
|
|
|
|
L_CARD8 l_flags, l_pad;
|
|
|
|
} L_XWDCOLOR;
|
|
|
|
|
|
|
|
|
|
|
|
/* Some structures for mapping up to 32bit-pixel */
|
|
|
|
/* values which are kept in the XWD-Colormap */
|
|
|
|
|
|
|
|
#define MAPPERBITS 12
|
|
|
|
#define MAPPERMASK ((1 << MAPPERBITS)-1)
|
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
1999-10-14 02:11:52 +00:00
|
|
|
L_CARD32 pixel_val;
|
2000-01-25 17:46:56 +00:00
|
|
|
guchar red;
|
|
|
|
guchar green;
|
|
|
|
guchar blue;
|
1997-11-24 22:05:25 +00:00
|
|
|
} PMAP;
|
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
gint npixel; /* Number of pixel values in map */
|
|
|
|
guchar pixel_in_map[1 << MAPPERBITS];
|
|
|
|
PMAP pmap[256];
|
1997-11-24 22:05:25 +00:00
|
|
|
} PIXEL_MAP;
|
|
|
|
|
|
|
|
#define XWDHDR_PAD 0 /* Total number of padding bytes for XWD header */
|
|
|
|
#define XWDCOL_PAD 0 /* Total number of padding bytes for each XWD color */
|
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
|
|
|
|
typedef struct _Xwd Xwd;
|
|
|
|
typedef struct _XwdClass XwdClass;
|
|
|
|
|
|
|
|
struct _Xwd
|
|
|
|
{
|
|
|
|
GimpPlugIn parent_instance;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _XwdClass
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2019-08-24 16:46:40 +02:00
|
|
|
GimpPlugInClass parent_class;
|
1997-11-24 22:05:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
#define XWD_TYPE (xwd_get_type ())
|
2023-10-18 18:29:37 +02:00
|
|
|
#define XWD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XWD_TYPE, Xwd))
|
2019-08-24 16:46:40 +02:00
|
|
|
|
|
|
|
GType xwd_get_type (void) G_GNUC_CONST;
|
|
|
|
|
2023-08-06 02:56:44 +02:00
|
|
|
static GList * xwd_query_procedures (GimpPlugIn *plug_in);
|
|
|
|
static GimpProcedure * xwd_create_procedure (GimpPlugIn *plug_in,
|
|
|
|
const gchar *name);
|
|
|
|
|
|
|
|
static GimpValueArray * xwd_load (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
|
|
|
GFile *file,
|
|
|
|
GimpMetadata *metadata,
|
|
|
|
GimpMetadataLoadFlags *flags,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
gpointer run_data);
|
2024-04-13 15:10:25 +00:00
|
|
|
static GimpValueArray * xwd_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,
|
|
|
|
GError **error);
|
2024-04-13 15:10:25 +00:00
|
|
|
static gboolean export_image (GFile *file,
|
2023-08-06 02:56:44 +02:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GError **error);
|
|
|
|
static GimpImage * create_new_image (GFile *file,
|
|
|
|
guint width,
|
|
|
|
guint height,
|
|
|
|
GimpImageBaseType type,
|
|
|
|
GimpImageType gdtype,
|
|
|
|
GimpLayer **layer,
|
|
|
|
GeglBuffer **buffer);
|
|
|
|
|
|
|
|
static int set_pixelmap (gint ncols,
|
|
|
|
L_XWDCOLOR *xwdcol,
|
|
|
|
PIXEL_MAP *pixelmap);
|
|
|
|
static gboolean get_pixelmap (L_CARD32 pixelval,
|
|
|
|
PIXEL_MAP *pixelmap,
|
|
|
|
guchar *red,
|
|
|
|
guchar *green,
|
|
|
|
guchar *glue);
|
|
|
|
|
|
|
|
static void set_bw_color_table (GimpImage *image);
|
|
|
|
static void set_color_table (GimpImage *image,
|
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
|
|
|
L_XWDCOLOR *xwdcolmap);
|
|
|
|
|
|
|
|
static GimpImage * load_xwd_f2_d1_b1 (GFile *file,
|
|
|
|
FILE *ifp,
|
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
|
|
|
L_XWDCOLOR *xwdcolmap,
|
|
|
|
GError **error);
|
|
|
|
static GimpImage * load_xwd_f2_d8_b8 (GFile *file,
|
|
|
|
FILE *ifp,
|
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
|
|
|
L_XWDCOLOR *xwdcolmap,
|
|
|
|
GError **error);
|
|
|
|
static GimpImage * load_xwd_f2_d16_b16 (GFile *file,
|
|
|
|
FILE *ifp,
|
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
|
|
|
L_XWDCOLOR *xwdcolmap,
|
|
|
|
GError **error);
|
|
|
|
static GimpImage * load_xwd_f2_d24_b32 (GFile *file,
|
|
|
|
FILE *ifp,
|
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
|
|
|
L_XWDCOLOR *xwdcolmap,
|
|
|
|
GError **error);
|
|
|
|
static GimpImage * load_xwd_f2_d32_b32 (GFile *file,
|
|
|
|
FILE *ifp,
|
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
|
|
|
L_XWDCOLOR *xwdcolmap,
|
|
|
|
GError **error);
|
|
|
|
static GimpImage * load_xwd_f1_d24_b1 (GFile *file,
|
|
|
|
FILE *ifp,
|
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
|
|
|
L_XWDCOLOR *xwdcolmap,
|
|
|
|
GError **error);
|
|
|
|
|
|
|
|
static L_CARD32 read_card32 (FILE *ifp,
|
|
|
|
gint *err);
|
|
|
|
static L_CARD16 read_card16 (FILE *ifp,
|
|
|
|
gint *err);
|
|
|
|
static L_CARD8 read_card8 (FILE *ifp,
|
|
|
|
gint *err);
|
|
|
|
|
|
|
|
static gboolean write_card32 (GOutputStream *output,
|
|
|
|
L_CARD32 c,
|
|
|
|
GError **error);
|
|
|
|
static gboolean write_card16 (GOutputStream *output,
|
|
|
|
L_CARD32 c,
|
|
|
|
GError **error);
|
|
|
|
static gboolean write_card8 (GOutputStream *output,
|
|
|
|
L_CARD32 c,
|
|
|
|
GError **error);
|
|
|
|
|
|
|
|
static void read_xwd_header (FILE *ifp,
|
|
|
|
L_XWDFILEHEADER *xwdhdr);
|
|
|
|
|
|
|
|
static gboolean write_xwd_header (GOutputStream *output,
|
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
|
|
|
GError **error);
|
|
|
|
|
|
|
|
static void read_xwd_cols (FILE *ifp,
|
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
|
|
|
L_XWDCOLOR *xwdcolmap,
|
|
|
|
GError **error);
|
|
|
|
|
|
|
|
static gboolean write_xwd_cols (GOutputStream *output,
|
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
|
|
|
L_XWDCOLOR *colormap,
|
|
|
|
GError **error);
|
|
|
|
|
|
|
|
static gint save_index (GOutputStream *output,
|
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
gboolean gray,
|
|
|
|
GError **error);
|
|
|
|
static gint save_rgb (GOutputStream *output,
|
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GError **error);
|
2019-08-24 16:46:40 +02:00
|
|
|
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (Xwd, xwd, GIMP_TYPE_PLUG_IN)
|
|
|
|
|
|
|
|
GIMP_MAIN (XWD_TYPE)
|
2022-05-26 00:59:36 +02:00
|
|
|
DEFINE_STD_SET_I18N
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
static void
|
2019-08-24 16:46:40 +02:00
|
|
|
xwd_class_init (XwdClass *klass)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2019-08-24 16:46:40 +02:00
|
|
|
GimpPlugInClass *plug_in_class = GIMP_PLUG_IN_CLASS (klass);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
plug_in_class->query_procedures = xwd_query_procedures;
|
|
|
|
plug_in_class->create_procedure = xwd_create_procedure;
|
2022-05-26 00:59:36 +02:00
|
|
|
plug_in_class->set_i18n = STD_SET_I18N;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-08-24 16:46:40 +02:00
|
|
|
xwd_init (Xwd *xwd)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2019-08-24 16:46:40 +02:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
static GList *
|
|
|
|
xwd_query_procedures (GimpPlugIn *plug_in)
|
|
|
|
{
|
|
|
|
GList *list = NULL;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
list = g_list_append (list, g_strdup (LOAD_PROC));
|
2024-04-13 15:10:25 +00:00
|
|
|
list = g_list_append (list, g_strdup (EXPORT_PROC));
|
2003-03-25 16:38:19 +00:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
return list;
|
|
|
|
}
|
2002-01-15 18:35:29 +00:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
static GimpProcedure *
|
|
|
|
xwd_create_procedure (GimpPlugIn *plug_in,
|
|
|
|
const gchar *name)
|
|
|
|
{
|
|
|
|
GimpProcedure *procedure = NULL;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
if (! strcmp (name, LOAD_PROC))
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2023-08-06 03:21:27 +02:00
|
|
|
procedure = gimp_load_procedure_new (plug_in, name,
|
|
|
|
GIMP_PDB_PROC_TYPE_PLUGIN,
|
|
|
|
xwd_load, NULL, NULL);
|
2019-08-24 16:46:40 +02:00
|
|
|
|
2022-07-04 22:50:53 +02:00
|
|
|
gimp_procedure_set_menu_label (procedure, _("X window dump"));
|
2019-08-24 16:46:40 +02:00
|
|
|
|
|
|
|
gimp_procedure_set_documentation (procedure,
|
|
|
|
"Loads files in the XWD (X Window Dump) "
|
|
|
|
"format",
|
|
|
|
"Loads files in the XWD (X Window Dump) "
|
|
|
|
"format. XWD image files are produced "
|
|
|
|
"by the program xwd. Xwd is an X Window "
|
|
|
|
"System window dumping utility.",
|
|
|
|
name);
|
|
|
|
gimp_procedure_set_attribution (procedure,
|
|
|
|
"Peter Kirchgessner",
|
|
|
|
"Peter Kirchgessner",
|
|
|
|
"1996");
|
|
|
|
|
|
|
|
gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"image/x-xwindowdump");
|
|
|
|
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"xwd");
|
|
|
|
gimp_file_procedure_set_magics (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"4,long,0x00000007");
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
2024-04-13 15:10:25 +00:00
|
|
|
else if (! strcmp (name, EXPORT_PROC))
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2024-04-20 03:08:57 +00:00
|
|
|
procedure = gimp_export_procedure_new (plug_in, name,
|
|
|
|
GIMP_PDB_PROC_TYPE_PLUGIN,
|
|
|
|
FALSE, xwd_export, NULL, NULL);
|
2019-08-24 16:46:40 +02:00
|
|
|
|
|
|
|
gimp_procedure_set_image_types (procedure, "RGB, GRAY, INDEXED");
|
|
|
|
|
2022-07-04 22:50:53 +02:00
|
|
|
gimp_procedure_set_menu_label (procedure, _("X window dump"));
|
2019-08-24 16:46:40 +02:00
|
|
|
|
|
|
|
gimp_procedure_set_documentation (procedure,
|
|
|
|
"Exports files in the XWD (X Window "
|
|
|
|
"Dump) format",
|
|
|
|
"XWD exporting handles all image "
|
|
|
|
"types except those with alpha channels.",
|
|
|
|
name);
|
|
|
|
gimp_procedure_set_attribution (procedure,
|
|
|
|
"Peter Kirchgessner",
|
|
|
|
"Peter Kirchgessner",
|
|
|
|
"1996");
|
|
|
|
|
|
|
|
gimp_file_procedure_set_handles_remote (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
TRUE);
|
|
|
|
gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"image/x-xwindowdump");
|
|
|
|
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"xwd");
|
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);
|
2019-08-24 16:46:40 +02:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
return procedure;
|
|
|
|
}
|
2013-11-10 00:18:48 +01:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
static GimpValueArray *
|
2023-08-06 02:56:44 +02:00
|
|
|
xwd_load (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
|
|
|
GFile *file,
|
|
|
|
GimpMetadata *metadata,
|
|
|
|
GimpMetadataLoadFlags *flags,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
gpointer run_data)
|
2019-08-24 16:46:40 +02:00
|
|
|
{
|
|
|
|
GimpValueArray *return_vals;
|
|
|
|
GimpImage *image;
|
|
|
|
GError *error = NULL;
|
2013-11-10 00:18:48 +01:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
gegl_init (NULL, NULL);
|
2004-09-07 12:08:03 +00:00
|
|
|
|
2019-09-11 21:48:34 +02:00
|
|
|
image = load_image (file, &error);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
if (! image)
|
|
|
|
return gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_EXECUTION_ERROR,
|
|
|
|
error);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
return_vals = gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_SUCCESS,
|
|
|
|
NULL);
|
2015-10-18 14:26:25 +02:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
GIMP_VALUES_SET_IMAGE (return_vals, 1, image);
|
2015-10-18 14:26:25 +02:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
return return_vals;
|
|
|
|
}
|
2004-09-07 12:08:03 +00:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
static GimpValueArray *
|
2024-04-13 15:10:25 +00:00
|
|
|
xwd_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-24 16:46:40 +02:00
|
|
|
{
|
2023-07-20 23:58:41 +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;
|
|
|
|
GError *error = NULL;
|
2019-08-24 16:46:40 +02:00
|
|
|
|
|
|
|
gegl_init (NULL, NULL);
|
|
|
|
|
2024-05-06 18:38:12 +00:00
|
|
|
export = gimp_export_options_get_image (options, &image);
|
2024-04-30 13:50:24 +00:00
|
|
|
drawables = gimp_image_list_layers (image);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2024-04-30 13:50:24 +00:00
|
|
|
if (! export_image (file, image, drawables->data, &error))
|
2024-07-14 20:12:57 +00:00
|
|
|
status = GIMP_PDB_EXECUTION_ERROR;
|
2008-08-18 19:08:54 +00:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
if (export == GIMP_EXPORT_EXPORT)
|
2024-04-30 13:50:24 +00:00
|
|
|
gimp_image_delete (image);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2024-04-30 13:50:24 +00:00
|
|
|
g_list_free (drawables);
|
2019-08-24 16:46:40 +02:00
|
|
|
return gimp_procedure_new_return_values (procedure, status, error);
|
|
|
|
}
|
2015-10-18 14:26:25 +02:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
static GimpImage *
|
2019-09-11 21:48:34 +02:00
|
|
|
load_image (GFile *file,
|
|
|
|
GError **error)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2019-09-11 21:48:34 +02:00
|
|
|
FILE *ifp;
|
2004-09-07 12:08:03 +00:00
|
|
|
gint depth, bpp;
|
2019-08-24 16:46:40 +02:00
|
|
|
GimpImage *image = NULL;
|
2004-09-07 12:08:03 +00:00
|
|
|
L_XWDFILEHEADER xwdhdr;
|
|
|
|
L_XWDCOLOR *xwdcolmap = NULL;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
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
|
|
|
|
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)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2008-08-18 19:08:54 +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));
|
2013-11-26 10:49:42 +01:00
|
|
|
goto out;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
read_xwd_header (ifp, &xwdhdr);
|
2023-07-11 18:17:42 -04:00
|
|
|
|
|
|
|
#ifdef XWD_DEBUG
|
|
|
|
/* Write info about header */
|
|
|
|
g_printerr ("XWD header:\n\t"
|
|
|
|
"Header size: %u, filer version: %u, image type: %u\n\t"
|
|
|
|
"Depth: %u, Width: %u, Height: %u\n\t"
|
|
|
|
"X-offset: %u, byte order: %u, bitmap unit: %u, bit order: %u\n\t"
|
|
|
|
"bitmap pad: %u, bits per pixel: %u, bytes per line: %u\n\t"
|
|
|
|
"visual class: %u, Masks: red %x, green %x, blue %x, bits per rgb: %u\n\t"
|
|
|
|
"Number of colors: %u, color map entries: %u\n\t"
|
|
|
|
"Window width: %u, height: %u, x: %u, y: %u, border width: %u"
|
|
|
|
"\n", xwdhdr.l_header_size, xwdhdr.l_file_version, xwdhdr.l_pixmap_format,
|
|
|
|
xwdhdr.l_pixmap_depth, xwdhdr.l_pixmap_width, xwdhdr.l_pixmap_height,
|
|
|
|
xwdhdr.l_xoffset, xwdhdr.l_byte_order, xwdhdr.l_bitmap_unit,
|
|
|
|
xwdhdr.l_bitmap_bit_order, xwdhdr.l_bitmap_pad, xwdhdr.l_bits_per_pixel,
|
|
|
|
xwdhdr.l_bytes_per_line, xwdhdr.l_visual_class,
|
|
|
|
xwdhdr.l_red_mask, xwdhdr.l_green_mask, xwdhdr.l_blue_mask,
|
|
|
|
xwdhdr.l_bits_per_rgb, xwdhdr.l_ncolors, xwdhdr.l_colormap_entries,
|
|
|
|
xwdhdr.l_window_width, xwdhdr.l_window_height,
|
|
|
|
xwdhdr.l_window_x, xwdhdr.l_window_y, xwdhdr.l_window_bdrwidth);
|
|
|
|
#endif
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
if (xwdhdr.l_file_version != 7)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2008-08-18 19:08:54 +00:00
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("Could not read XWD header from '%s'"),
|
2019-09-11 21:48:34 +02:00
|
|
|
gimp_file_get_utf8_name (file));
|
2013-11-26 10:49:42 +01:00
|
|
|
goto out;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2001-07-02 23:18:10 +00:00
|
|
|
#ifdef XWD_COL_WAIT_DEBUG
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
|
|
|
int k = 1;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2001-07-02 23:18:10 +00:00
|
|
|
while (k)
|
|
|
|
k = k;
|
2004-09-07 12:08:03 +00:00
|
|
|
}
|
2001-07-02 23:18:10 +00:00
|
|
|
#endif
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
/* Position to start of XWDColor structures */
|
2023-07-11 18:17:42 -04:00
|
|
|
if (fseek (ifp, (long)xwdhdr.l_header_size, SEEK_SET) != 0)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("'%s':\nSeek error"),
|
|
|
|
gimp_file_get_utf8_name (file));
|
|
|
|
goto out;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2024-09-23 15:17:04 +02:00
|
|
|
/* Guard against insanely huge color maps -- gimp_palette_set_colormap() only
|
2013-11-14 14:29:01 +01:00
|
|
|
* accepts colormaps with 0..256 colors anyway. */
|
|
|
|
if (xwdhdr.l_colormap_entries > 256)
|
|
|
|
{
|
2023-07-11 18:17:42 -04:00
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("'%s':\nIllegal number of colormap entries: %u"),
|
|
|
|
gimp_file_get_utf8_name (file),
|
|
|
|
xwdhdr.l_colormap_entries);
|
2013-11-26 10:49:42 +01:00
|
|
|
goto out;
|
2013-11-14 14:29:01 +01:00
|
|
|
}
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
if (xwdhdr.l_colormap_entries > 0)
|
|
|
|
{
|
2013-11-26 10:49:42 +01:00
|
|
|
if (xwdhdr.l_colormap_entries < xwdhdr.l_ncolors)
|
|
|
|
{
|
2023-07-11 18:17:42 -04:00
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("'%s':\nNumber of colormap entries < number of colors"),
|
|
|
|
gimp_file_get_utf8_name (file));
|
2013-11-26 10:49:42 +01:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2001-12-06 02:28:58 +00:00
|
|
|
xwdcolmap = g_new (L_XWDCOLOR, xwdhdr.l_colormap_entries);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2023-07-11 18:17:42 -04:00
|
|
|
read_xwd_cols (ifp, &xwdhdr, xwdcolmap, error);
|
|
|
|
if (error && *error)
|
|
|
|
goto out;
|
2004-09-07 12:08:03 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
#ifdef XWD_COL_DEBUG
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2003-06-13 14:37:00 +00:00
|
|
|
int j;
|
2021-10-01 18:56:12 +02:00
|
|
|
g_printf ("File %s\n", g_file_peek_path (file));
|
2004-09-07 12:08:03 +00:00
|
|
|
for (j = 0; j < xwdhdr.l_colormap_entries; j++)
|
2018-08-12 19:21:44 +02:00
|
|
|
g_printf ("Entry 0x%08lx: 0x%04lx, 0x%04lx, 0x%04lx, %d\n",
|
|
|
|
(long)xwdcolmap[j].l_pixel,(long)xwdcolmap[j].l_red,
|
|
|
|
(long)xwdcolmap[j].l_green,(long)xwdcolmap[j].l_blue,
|
|
|
|
(int)xwdcolmap[j].l_flags);
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
2003-06-13 14:37:00 +00:00
|
|
|
#endif
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2003-06-13 14:37:00 +00:00
|
|
|
if (xwdhdr.l_file_version != 7)
|
|
|
|
{
|
2023-07-11 18:17:42 -04:00
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("Can't read color entries"));
|
2013-11-26 10:49:42 +01:00
|
|
|
goto out;
|
2003-06-13 14:37:00 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2007-07-04 23:32:15 +00:00
|
|
|
if (xwdhdr.l_pixmap_width <= 0)
|
|
|
|
{
|
2023-07-11 18:17:42 -04:00
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("'%s':\nNo image width specified"),
|
|
|
|
gimp_file_get_utf8_name (file));
|
2013-11-26 10:49:42 +01:00
|
|
|
goto out;
|
2007-07-04 23:32:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (xwdhdr.l_pixmap_width > GIMP_MAX_IMAGE_SIZE
|
|
|
|
|| xwdhdr.l_bytes_per_line > GIMP_MAX_IMAGE_SIZE * 3)
|
|
|
|
{
|
2023-07-11 18:17:42 -04:00
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("'%s':\nImage width is larger than GIMP can handle"),
|
|
|
|
gimp_file_get_utf8_name (file));
|
2013-11-26 10:49:42 +01:00
|
|
|
goto out;
|
2007-07-04 23:32:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (xwdhdr.l_pixmap_height <= 0)
|
|
|
|
{
|
2023-07-11 18:17:42 -04:00
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("'%s':\nNo image height specified"),
|
|
|
|
gimp_file_get_utf8_name (file));
|
2013-11-26 10:49:42 +01:00
|
|
|
goto out;
|
2007-07-04 23:32:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (xwdhdr.l_pixmap_height > GIMP_MAX_IMAGE_SIZE)
|
|
|
|
{
|
2023-07-11 18:17:42 -04:00
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("'%s':\nImage height is larger than GIMP can handle"),
|
|
|
|
gimp_file_get_utf8_name (file));
|
2013-11-26 10:49:42 +01:00
|
|
|
goto out;
|
2007-07-04 23:32:15 +00:00
|
|
|
}
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
depth = xwdhdr.l_pixmap_depth;
|
2004-09-07 12:08:03 +00:00
|
|
|
bpp = xwdhdr.l_bits_per_pixel;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
switch (xwdhdr.l_pixmap_format)
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
1997-11-24 22:05:25 +00:00
|
|
|
case 0: /* Single plane bitmap */
|
|
|
|
if ((depth == 1) && (bpp == 1))
|
2004-09-07 12:08:03 +00:00
|
|
|
{ /* Can be performed by format 2 loader */
|
2023-07-11 18:17:42 -04:00
|
|
|
image = load_xwd_f2_d1_b1 (file, ifp, &xwdhdr, xwdcolmap, error);
|
2004-09-07 12:08:03 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 1: /* Single plane pixmap */
|
|
|
|
if ((depth <= 24) && (bpp == 1))
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
2023-07-11 18:17:42 -04:00
|
|
|
image = load_xwd_f1_d24_b1 (file, ifp, &xwdhdr, xwdcolmap, error);
|
2004-09-07 12:08:03 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
break;
|
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
case 2: /* Multiplane pixmaps */
|
|
|
|
if ((depth == 1) && (bpp == 1))
|
|
|
|
{
|
2023-07-11 18:17:42 -04:00
|
|
|
image = load_xwd_f2_d1_b1 (file, ifp, &xwdhdr, xwdcolmap, error);
|
2004-09-07 12:08:03 +00:00
|
|
|
}
|
|
|
|
else if ((depth <= 8) && (bpp == 8))
|
|
|
|
{
|
2023-07-11 18:17:42 -04:00
|
|
|
image = load_xwd_f2_d8_b8 (file, ifp, &xwdhdr, xwdcolmap, error);
|
2004-09-07 12:08:03 +00:00
|
|
|
}
|
|
|
|
else if ((depth <= 16) && (bpp == 16))
|
|
|
|
{
|
2023-07-11 18:17:42 -04:00
|
|
|
if (xwdcolmap)
|
|
|
|
image = load_xwd_f2_d16_b16 (file, ifp, &xwdhdr, xwdcolmap, error);
|
2004-09-07 12:08:03 +00:00
|
|
|
}
|
|
|
|
else if ((depth <= 24) && ((bpp == 24) || (bpp == 32)))
|
|
|
|
{
|
2023-07-11 18:17:42 -04:00
|
|
|
image = load_xwd_f2_d24_b32 (file, ifp, &xwdhdr, xwdcolmap, error);
|
2004-09-07 12:08:03 +00:00
|
|
|
}
|
2012-08-07 15:56:58 +02:00
|
|
|
else if ((depth <= 32) && (bpp == 32))
|
|
|
|
{
|
2023-07-11 18:17:42 -04:00
|
|
|
image = load_xwd_f2_d32_b32 (file, ifp, &xwdhdr, xwdcolmap, error);
|
2012-08-07 15:56:58 +02:00
|
|
|
}
|
2004-09-07 12:08:03 +00:00
|
|
|
break;
|
|
|
|
}
|
2011-04-10 19:05:08 +02:00
|
|
|
gimp_progress_update (1.0);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
if (! image && ! (error && *error))
|
2008-08-18 19:08:54 +00:00
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("XWD-file %s has format %d, depth %d and bits per pixel %d. "
|
|
|
|
"Currently this is not supported."),
|
2019-09-11 21:48:34 +02:00
|
|
|
gimp_file_get_utf8_name (file),
|
2008-08-18 19:08:54 +00:00
|
|
|
(gint) xwdhdr.l_pixmap_format, depth, bpp);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2013-11-26 10:49:42 +01:00
|
|
|
out:
|
|
|
|
if (ifp)
|
2019-08-24 16:46:40 +02:00
|
|
|
fclose (ifp);
|
2013-11-26 10:49:42 +01:00
|
|
|
|
|
|
|
if (xwdcolmap)
|
2019-08-24 16:46:40 +02:00
|
|
|
g_free (xwdcolmap);
|
2013-11-26 10:49:42 +01:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
return image;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
static gboolean
|
2024-04-13 15:10:25 +00:00
|
|
|
export_image (GFile *file,
|
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GError **error)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2015-10-18 14:26:25 +02:00
|
|
|
GOutputStream *output;
|
2004-09-07 12:08:03 +00:00
|
|
|
GimpImageType drawable_type;
|
2015-10-18 14:26:25 +02:00
|
|
|
gboolean success;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-24 16:46:40 +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-24 16:46:40 +02:00
|
|
|
if (gimp_drawable_has_alpha (drawable))
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2015-10-18 14:26:25 +02:00
|
|
|
g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
2016-02-16 02:35:43 +01:00
|
|
|
_("Cannot export images with alpha channels."));
|
1999-10-14 02:11:52 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
switch (drawable_type)
|
1999-10-14 02:11:52 +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;
|
|
|
|
default:
|
2003-11-15 13:53:33 +00:00
|
|
|
g_message (_("Cannot operate on unknown image types."));
|
2004-09-07 12:08:03 +00:00
|
|
|
return FALSE;
|
1997-11-24 22:05:25 +00:00
|
|
|
break;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2016-02-16 02:35:43 +01:00
|
|
|
gimp_progress_init_printf (_("Exporting '%s'"),
|
2015-10-18 14:26:25 +02:00
|
|
|
gimp_file_get_utf8_name (file));
|
2014-07-23 16:39:00 +02:00
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
output = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, 0, NULL, error));
|
|
|
|
if (! output)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2015-10-18 14:26:25 +02:00
|
|
|
g_prefix_error (error,
|
|
|
|
_("Could not open '%s' for writing: "),
|
|
|
|
gimp_file_get_utf8_name (file));
|
2003-06-13 14:37:00 +00:00
|
|
|
return FALSE;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2011-10-06 19:35:21 +05:30
|
|
|
switch (drawable_type)
|
|
|
|
{
|
|
|
|
case GIMP_INDEXED_IMAGE:
|
2019-08-24 16:46:40 +02:00
|
|
|
success = save_index (output, image, drawable, FALSE, error);
|
2011-10-06 19:35:21 +05:30
|
|
|
break;
|
2015-10-18 14:26:25 +02:00
|
|
|
|
2011-10-06 19:35:21 +05:30
|
|
|
case GIMP_GRAY_IMAGE:
|
2019-08-24 16:46:40 +02:00
|
|
|
success = save_index (output, image, drawable, TRUE, error);
|
2011-10-06 19:35:21 +05:30
|
|
|
break;
|
2015-10-18 14:26:25 +02:00
|
|
|
|
2011-10-06 19:35:21 +05:30
|
|
|
case GIMP_RGB_IMAGE:
|
2019-08-24 16:46:40 +02:00
|
|
|
success = save_rgb (output, image, drawable, error);
|
2011-10-06 19:35:21 +05:30
|
|
|
break;
|
2015-10-18 14:26:25 +02:00
|
|
|
|
2011-10-06 19:35:21 +05:30
|
|
|
default:
|
2015-10-18 14:26:25 +02:00
|
|
|
success = FALSE;
|
|
|
|
break;
|
2011-10-06 19:35:21 +05:30
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
if (success && ! g_output_stream_close (output, NULL, error))
|
|
|
|
{
|
|
|
|
g_prefix_error (error,
|
2016-02-16 02:35:43 +01:00
|
|
|
_("Error exporting '%s': "),
|
2015-10-18 14:26:25 +02:00
|
|
|
gimp_file_get_utf8_name (file));
|
|
|
|
success = FALSE;
|
|
|
|
}
|
2018-11-27 12:27:20 +01:00
|
|
|
else if (! success)
|
|
|
|
{
|
|
|
|
GCancellable *cancellable;
|
|
|
|
|
|
|
|
cancellable = g_cancellable_new ();
|
|
|
|
g_cancellable_cancel (cancellable);
|
|
|
|
g_output_stream_close (output, cancellable, NULL);
|
|
|
|
g_object_unref (cancellable);
|
|
|
|
}
|
2011-04-10 19:05:08 +02:00
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
g_object_unref (output);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
gimp_progress_update (1.0);
|
|
|
|
|
|
|
|
return success;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-06 15:27:05 +00:00
|
|
|
static L_CARD32
|
1999-10-14 02:11:52 +00:00
|
|
|
read_card32 (FILE *ifp,
|
2004-09-07 12:08:03 +00:00
|
|
|
int *err)
|
1997-11-24 22:05:25 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
|
|
|
L_CARD32 c;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
c = (((L_CARD32) (getc (ifp))) << 24);
|
|
|
|
c |= (((L_CARD32) (getc (ifp))) << 16);
|
|
|
|
c |= (((L_CARD32) (getc (ifp))) << 8);
|
|
|
|
c |= ((L_CARD32) (*err = getc (ifp)));
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
*err = (*err < 0);
|
2004-09-07 12:08:03 +00:00
|
|
|
|
|
|
|
return c;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2003-11-06 15:27:05 +00:00
|
|
|
static L_CARD16
|
1999-10-14 02:11:52 +00:00
|
|
|
read_card16 (FILE *ifp,
|
2004-09-07 12:08:03 +00:00
|
|
|
int *err)
|
1997-11-24 22:05:25 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
|
|
|
L_CARD16 c;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
c = (((L_CARD16) (getc (ifp))) << 8);
|
|
|
|
c |= ((L_CARD16) (*err = getc (ifp)));
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
*err = (*err < 0);
|
2004-09-07 12:08:03 +00:00
|
|
|
|
|
|
|
return c;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2003-11-06 15:27:05 +00:00
|
|
|
static L_CARD8
|
1999-10-14 02:11:52 +00:00
|
|
|
read_card8 (FILE *ifp,
|
2004-09-07 12:08:03 +00:00
|
|
|
int *err)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
|
|
|
L_CARD8 c;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
c = ((L_CARD8) (*err = getc (ifp)));
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
*err = (*err < 0);
|
2004-09-07 12:08:03 +00:00
|
|
|
|
|
|
|
return c;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
|
|
|
|
static gboolean
|
|
|
|
write_card32 (GOutputStream *output,
|
|
|
|
L_CARD32 c,
|
|
|
|
GError **error)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2015-10-18 14:26:25 +02:00
|
|
|
guchar buffer[4];
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
buffer[0] = (c >> 24) & 0xff;
|
|
|
|
buffer[1] = (c >> 16) & 0xff;
|
|
|
|
buffer[2] = (c >> 8) & 0xff;
|
|
|
|
buffer[3] = (c) & 0xff;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
return g_output_stream_write_all (output, buffer, 4,
|
|
|
|
NULL, NULL, error);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
static gboolean
|
|
|
|
write_card16 (GOutputStream *output,
|
|
|
|
L_CARD32 c,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
guchar buffer[2];
|
|
|
|
|
|
|
|
buffer[0] = (c >> 8) & 0xff;
|
|
|
|
buffer[1] = (c) & 0xff;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
return g_output_stream_write_all (output, buffer, 2,
|
|
|
|
NULL, NULL, error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
write_card8 (GOutputStream *output,
|
|
|
|
L_CARD32 c,
|
|
|
|
GError **error)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2015-10-18 14:26:25 +02:00
|
|
|
guchar buffer[1];
|
|
|
|
|
|
|
|
buffer[0] = c & 0xff;
|
|
|
|
|
|
|
|
return g_output_stream_write_all (output, buffer, 1,
|
|
|
|
NULL, NULL, error);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
1999-10-14 02:11:52 +00:00
|
|
|
read_xwd_header (FILE *ifp,
|
1997-11-24 22:05:25 +00:00
|
|
|
L_XWDFILEHEADER *xwdhdr)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2004-09-07 12:08:03 +00:00
|
|
|
gint j, err;
|
1999-10-14 02:11:52 +00:00
|
|
|
L_CARD32 *cp;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
cp = (L_CARD32 *) xwdhdr;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Read in all 32-bit values of the header and check for byte order */
|
2004-09-07 12:08:03 +00:00
|
|
|
for (j = 0; j < sizeof (L_XWDFILEHEADER) / sizeof(xwdhdr->l_file_version); j++)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
|
|
|
*(cp++) = read_card32 (ifp, &err);
|
2004-09-07 12:08:03 +00:00
|
|
|
|
|
|
|
if (err)
|
|
|
|
break;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
if (err)
|
|
|
|
xwdhdr->l_file_version = 0; /* Not a valid XWD-file */
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Write out an XWD-fileheader. The header size is calculated here */
|
2015-10-18 14:26:25 +02:00
|
|
|
static gboolean
|
2023-07-11 18:17:42 -04:00
|
|
|
write_xwd_header (GOutputStream *output,
|
2015-10-18 14:26:25 +02:00
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
|
|
|
GError **error)
|
1997-11-24 22:05:25 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2004-09-07 12:08:03 +00:00
|
|
|
gint j, hdrpad, hdr_entries;
|
1999-10-14 02:11:52 +00:00
|
|
|
L_CARD32 *cp;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
hdrpad = XWDHDR_PAD;
|
2004-09-07 12:08:03 +00:00
|
|
|
hdr_entries = sizeof (L_XWDFILEHEADER) / sizeof(xwdhdr->l_file_version);
|
1999-10-14 02:11:52 +00:00
|
|
|
xwdhdr->l_header_size = hdr_entries * 4 + hdrpad;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
cp = (L_CARD32 *) xwdhdr;
|
1999-10-14 02:11:52 +00:00
|
|
|
|
|
|
|
/* Write out all 32-bit values of the header and check for byte order */
|
2004-09-07 12:08:03 +00:00
|
|
|
for (j = 0; j < sizeof (L_XWDFILEHEADER) / sizeof(xwdhdr->l_file_version); j++)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2015-10-18 14:26:25 +02:00
|
|
|
if (! write_card32 (output, *(cp++), error))
|
|
|
|
return FALSE;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Add padding bytes after XWD header */
|
|
|
|
for (j = 0; j < hdrpad; j++)
|
2015-10-18 14:26:25 +02:00
|
|
|
if (! write_card8 (output, (L_CARD32) 0, error))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2023-07-11 18:17:42 -04:00
|
|
|
read_xwd_cols (FILE *ifp,
|
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
|
|
|
L_XWDCOLOR *colormap,
|
|
|
|
GError **error)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2004-09-07 12:08:03 +00:00
|
|
|
gint j, err = 0;
|
|
|
|
gint flag_is_bad, index_is_bad;
|
|
|
|
gint indexed = (xwdhdr->l_pixmap_depth <= 8);
|
|
|
|
glong colmappos = ftell (ifp);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Read in XWD-Color structures (the usual case) */
|
|
|
|
flag_is_bad = index_is_bad = 0;
|
|
|
|
for (j = 0; j < xwdhdr->l_ncolors; j++)
|
|
|
|
{
|
|
|
|
colormap[j].l_pixel = read_card32 (ifp, &err);
|
|
|
|
|
|
|
|
colormap[j].l_red = read_card16 (ifp, &err);
|
|
|
|
colormap[j].l_green = read_card16 (ifp, &err);
|
|
|
|
colormap[j].l_blue = read_card16 (ifp, &err);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
colormap[j].l_flags = read_card8 (ifp, &err);
|
|
|
|
colormap[j].l_pad = read_card8 (ifp, &err);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (indexed && (colormap[j].l_pixel > 255))
|
2004-09-07 12:08:03 +00:00
|
|
|
index_is_bad++;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
if (err)
|
|
|
|
break;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (err) /* Not a valid XWD-file ? */
|
|
|
|
xwdhdr->l_file_version = 0;
|
|
|
|
if (err || ((flag_is_bad == 0) && (index_is_bad == 0)))
|
|
|
|
return;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Read in XWD-Color structures (with 4 bytes inserted infront of RGB) */
|
2023-07-11 18:17:42 -04:00
|
|
|
if (fseek (ifp, colmappos, SEEK_SET) != 0)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("Seek error"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
flag_is_bad = index_is_bad = 0;
|
|
|
|
for (j = 0; j < xwdhdr->l_ncolors; j++)
|
|
|
|
{
|
|
|
|
colormap[j].l_pixel = read_card32 (ifp, &err);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
read_card32 (ifp, &err); /* Empty bytes on Alpha OSF */
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
colormap[j].l_red = read_card16 (ifp, &err);
|
|
|
|
colormap[j].l_green = read_card16 (ifp, &err);
|
|
|
|
colormap[j].l_blue = read_card16 (ifp, &err);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
colormap[j].l_flags = read_card8 (ifp, &err);
|
|
|
|
colormap[j].l_pad = read_card8 (ifp, &err);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (indexed && (colormap[j].l_pixel > 255))
|
2004-09-07 12:08:03 +00:00
|
|
|
index_is_bad++;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
if (err)
|
|
|
|
break;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (err) /* Not a valid XWD-file ? */
|
|
|
|
xwdhdr->l_file_version = 0;
|
|
|
|
if (err || ((flag_is_bad == 0) && (index_is_bad == 0)))
|
|
|
|
return;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Read in XWD-Color structures (with 2 bytes inserted infront of RGB) */
|
2023-07-11 18:17:42 -04:00
|
|
|
if (fseek (ifp, colmappos, SEEK_SET) !=0)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("Seek error"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
flag_is_bad = index_is_bad = 0;
|
|
|
|
for (j = 0; j < xwdhdr->l_ncolors; j++)
|
|
|
|
{
|
|
|
|
colormap[j].l_pixel = read_card32 (ifp, &err);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
read_card16 (ifp, &err); /* Empty bytes (from where ?) */
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
colormap[j].l_red = read_card16 (ifp, &err);
|
|
|
|
colormap[j].l_green = read_card16 (ifp, &err);
|
|
|
|
colormap[j].l_blue = read_card16 (ifp, &err);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
colormap[j].l_flags = read_card8 (ifp, &err);
|
|
|
|
colormap[j].l_pad = read_card8 (ifp, &err);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* if ((colormap[j].l_flags == 0) || (colormap[j].l_flags > 7))
|
2004-09-07 12:08:03 +00:00
|
|
|
flag_is_bad++; */
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (indexed && (colormap[j].l_pixel > 255))
|
2004-09-07 12:08:03 +00:00
|
|
|
index_is_bad++;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
if (err)
|
|
|
|
break;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (err) /* Not a valid XWD-file ? */
|
|
|
|
xwdhdr->l_file_version = 0;
|
|
|
|
if (err || ((flag_is_bad == 0) && (index_is_bad == 0)))
|
|
|
|
return;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Read in XWD-Color structures (every value is 8 bytes from a CRAY) */
|
2023-07-11 18:17:42 -04:00
|
|
|
if (fseek (ifp, colmappos, SEEK_SET) != 0)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("Seek error"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
flag_is_bad = index_is_bad = 0;
|
|
|
|
for (j = 0; j < xwdhdr->l_ncolors; j++)
|
|
|
|
{
|
|
|
|
read_card32 (ifp, &err);
|
|
|
|
colormap[j].l_pixel = read_card32 (ifp, &err);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
read_card32 (ifp, &err);
|
|
|
|
colormap[j].l_red = read_card32 (ifp, &err);
|
|
|
|
read_card32 (ifp, &err);
|
|
|
|
colormap[j].l_green = read_card32 (ifp, &err);
|
|
|
|
read_card32 (ifp, &err);
|
|
|
|
colormap[j].l_blue = read_card32 (ifp, &err);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* The flag byte is kept in the first byte */
|
|
|
|
colormap[j].l_flags = read_card8 (ifp, &err);
|
|
|
|
colormap[j].l_pad = read_card8 (ifp, &err);
|
|
|
|
read_card16 (ifp, &err);
|
|
|
|
read_card32 (ifp, &err);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
if (indexed && (colormap[j].l_pixel > 255))
|
|
|
|
index_is_bad++;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
if (err)
|
|
|
|
break;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (flag_is_bad || index_is_bad)
|
|
|
|
{
|
2018-08-12 19:21:44 +02:00
|
|
|
g_printf ("xwd: Warning. Error in XWD-color-structure (");
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2018-08-12 19:21:44 +02:00
|
|
|
if (flag_is_bad) g_printf ("flag");
|
|
|
|
if (index_is_bad) g_printf ("index");
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2018-08-12 19:21:44 +02:00
|
|
|
g_printf (")\n");
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2004-09-07 12:08:03 +00:00
|
|
|
|
|
|
|
if (err)
|
|
|
|
xwdhdr->l_file_version = 0; /* Not a valid XWD-file */
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
static gboolean
|
|
|
|
write_xwd_cols (GOutputStream *output,
|
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
|
|
|
L_XWDCOLOR *colormap,
|
|
|
|
GError **error)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2015-10-18 14:26:25 +02:00
|
|
|
gint j;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (j = 0; j < xwdhdr->l_colormap_entries; j++)
|
|
|
|
{
|
1997-11-24 22:05:25 +00:00
|
|
|
#ifdef CRAY
|
2015-10-18 14:26:25 +02:00
|
|
|
if (! (write_card32 (output, (L_CARD32)0, error) &&
|
|
|
|
write_card32 (output, colormap[j].l_pixel, error) &&
|
|
|
|
write_card32 (output, (L_CARD32)0, error) &&
|
|
|
|
write_card32 (output, (L_CARD32)colormap[j].l_red, error) &&
|
|
|
|
write_card32 (output, (L_CARD32)0, error) &&
|
|
|
|
write_card32 (output, (L_CARD32)colormap[j].l_green, error) &&
|
|
|
|
write_card32 (output, (L_CARD32)0, error) &&
|
|
|
|
write_card32 (output, (L_CARD32)colormap[j].l_blue, error) &&
|
|
|
|
write_card8 (output, (L_CARD32)colormap[j].l_flags, error) &&
|
|
|
|
write_card8 (output, (L_CARD32)colormap[j].l_pad, error) &&
|
|
|
|
write_card16 (output, (L_CARD32)0, error) &&
|
|
|
|
write_card32 (output, (L_CARD32)0, error)))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
#else
|
|
|
|
#ifdef __alpha
|
2015-10-18 14:26:25 +02:00
|
|
|
if (! (write_card32 (output, colormap[j].l_pixel, error) &&
|
|
|
|
write_card32 (output, (L_CARD32)0, error) &&
|
|
|
|
write_card16 (output, (L_CARD32)colormap[j].l_red, error) &&
|
|
|
|
write_card16 (output, (L_CARD32)colormap[j].l_green, error) &&
|
|
|
|
write_card16 (output, (L_CARD32)colormap[j].l_blue, error) &&
|
|
|
|
write_card8 (output, (L_CARD32)colormap[j].l_flags, error) &&
|
|
|
|
write_card8 (output, (L_CARD32)colormap[j].l_pad, error)))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
#else
|
2015-10-18 14:26:25 +02:00
|
|
|
if (! (write_card32 (output, colormap[j].l_pixel, error) &&
|
|
|
|
write_card16 (output, (L_CARD32)colormap[j].l_red, error) &&
|
|
|
|
write_card16 (output, (L_CARD32)colormap[j].l_green, error) &&
|
|
|
|
write_card16 (output, (L_CARD32)colormap[j].l_blue, error) &&
|
|
|
|
write_card8 (output, (L_CARD32)colormap[j].l_flags, error) &&
|
|
|
|
write_card8 (output, (L_CARD32)colormap[j].l_pad, error)))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
#endif
|
|
|
|
#endif
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
return TRUE;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
/* Create a map for mapping up to 32 bit pixelvalues to RGB.
|
|
|
|
* Returns number of colors kept in the map (up to 256)
|
|
|
|
*/
|
2004-09-07 12:08:03 +00:00
|
|
|
static gint
|
|
|
|
set_pixelmap (int ncols,
|
|
|
|
L_XWDCOLOR *xwdcol,
|
|
|
|
PIXEL_MAP *pixelmap)
|
1997-11-24 22:05:25 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2004-09-07 12:08:03 +00:00
|
|
|
gint i, j, k, maxcols;
|
1999-10-14 02:11:52 +00:00
|
|
|
L_CARD32 pixel_val;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
memset ((gchar *) pixelmap, 0, sizeof (PIXEL_MAP));
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
maxcols = 0;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (j = 0; j < ncols; j++) /* For each entry of the XWD colormap */
|
|
|
|
{
|
|
|
|
pixel_val = xwdcol[j].l_pixel;
|
|
|
|
for (k = 0; k < maxcols; k++) /* Where to insert in list ? */
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
|
|
|
if (pixel_val <= pixelmap->pmap[k].pixel_val)
|
|
|
|
break;
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
if ((k < maxcols) && (pixel_val == pixelmap->pmap[k].pixel_val))
|
2004-09-07 12:08:03 +00:00
|
|
|
break; /* It was already in list */
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
if (k >= 256)
|
|
|
|
break;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (k < maxcols) /* Must move entries to the back ? */
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
|
|
|
for (i = maxcols-1; i >= k; i--)
|
|
|
|
memcpy ((char *)&(pixelmap->pmap[i+1]),(char *)&(pixelmap->pmap[i]),
|
|
|
|
sizeof (PMAP));
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
pixelmap->pmap[k].pixel_val = pixel_val;
|
|
|
|
pixelmap->pmap[k].red = xwdcol[j].l_red >> 8;
|
|
|
|
pixelmap->pmap[k].green = xwdcol[j].l_green >> 8;
|
|
|
|
pixelmap->pmap[k].blue = xwdcol[j].l_blue >> 8;
|
|
|
|
pixelmap->pixel_in_map[pixel_val & MAPPERMASK] = 1;
|
|
|
|
maxcols++;
|
|
|
|
}
|
|
|
|
pixelmap->npixel = maxcols;
|
1997-11-24 22:05:25 +00:00
|
|
|
#ifdef XWD_COL_DEBUG
|
2018-08-12 19:21:44 +02:00
|
|
|
g_printf ("Colors in pixelmap: %d\n",pixelmap->npixel);
|
1999-10-14 02:11:52 +00:00
|
|
|
for (j=0; j<pixelmap->npixel; j++)
|
2018-08-12 19:21:44 +02:00
|
|
|
g_printf ("Pixelvalue 0x%08lx, 0x%02x 0x%02x 0x%02x\n",
|
|
|
|
pixelmap->pmap[j].pixel_val,
|
|
|
|
pixelmap->pmap[j].red,pixelmap->pmap[j].green,
|
|
|
|
pixelmap->pmap[j].blue);
|
1999-10-14 02:11:52 +00:00
|
|
|
for (j=0; j<=MAPPERMASK; j++)
|
2018-08-12 19:21:44 +02:00
|
|
|
g_printf ("0x%08lx: %d\n",(long)j,pixelmap->pixel_in_map[j]);
|
1997-11-24 22:05:25 +00:00
|
|
|
#endif
|
2004-09-07 12:08:03 +00:00
|
|
|
|
|
|
|
return pixelmap->npixel;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
/* Search a pixel value in the pixel map. Returns FALSE if the
|
|
|
|
* pixelval was not found in map. Returns TRUE if found.
|
|
|
|
*/
|
2004-09-07 12:08:03 +00:00
|
|
|
static gboolean
|
|
|
|
get_pixelmap (L_CARD32 pixelval,
|
|
|
|
PIXEL_MAP *pixelmap,
|
|
|
|
guchar *red,
|
|
|
|
guchar *green,
|
|
|
|
guchar *blue)
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
|
|
|
register PMAP *low, *high, *middle;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
if (pixelmap->npixel == 0)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(pixelmap->pixel_in_map[pixelval & MAPPERMASK]))
|
|
|
|
return FALSE;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
low = &(pixelmap->pmap[0]);
|
|
|
|
high = &(pixelmap->pmap[pixelmap->npixel-1]);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Do a binary search on the array */
|
|
|
|
while (low < high)
|
|
|
|
{
|
|
|
|
middle = low + ((high - low)/2);
|
|
|
|
if (pixelval <= middle->pixel_val)
|
2004-09-07 12:08:03 +00:00
|
|
|
high = middle;
|
1999-10-14 02:11:52 +00:00
|
|
|
else
|
2004-09-07 12:08:03 +00:00
|
|
|
low = middle+1;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (pixelval == low->pixel_val)
|
|
|
|
{
|
|
|
|
*red = low->red; *green = low->green; *blue = low->blue;
|
2004-09-07 12:08:03 +00:00
|
|
|
return TRUE;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2004-09-07 12:08:03 +00:00
|
|
|
|
|
|
|
return FALSE;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-06 15:27:05 +00:00
|
|
|
static void
|
2019-08-24 16:46:40 +02:00
|
|
|
set_bw_color_table (GimpImage *image)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2024-09-22 01:24:25 +02:00
|
|
|
static guchar BWColorMap[2*3] = { 255, 255, 255, 0, 0, 0 };
|
|
|
|
GimpPalette *palette = gimp_image_get_palette (image);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
#ifdef XWD_COL_DEBUG
|
2018-08-12 19:21:44 +02:00
|
|
|
g_printf ("Set GIMP b/w-colortable:\n");
|
1997-11-24 22:05:25 +00:00
|
|
|
#endif
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2024-09-22 17:11:03 +02:00
|
|
|
gimp_palette_set_colormap (palette, babl_format ("R'G'B' u8"), BWColorMap, 2 * 3);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-07-02 23:18:10 +00:00
|
|
|
/* Initialize an 8-bit colortable from the mask-values of the XWD-header */
|
2003-11-06 15:27:05 +00:00
|
|
|
static void
|
2004-09-07 12:08:03 +00:00
|
|
|
init_color_table256 (L_XWDFILEHEADER *xwdhdr,
|
|
|
|
guchar *ColorMap)
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2001-07-02 23:18:10 +00:00
|
|
|
{
|
2004-09-07 12:08:03 +00:00
|
|
|
gint i, j, k, cuind;
|
|
|
|
gint redshift, greenshift, blueshift;
|
|
|
|
gint maxred, maxgreen, maxblue;
|
2001-07-02 23:18:10 +00:00
|
|
|
|
|
|
|
/* Assume: the bit masks for red/green/blue are grouped together
|
|
|
|
* Example: redmask = 0xe0, greenmask = 0x1c, bluemask = 0x03
|
|
|
|
* We need to know where to place the RGB-values (shifting)
|
|
|
|
* and the maximum value for each component.
|
|
|
|
*/
|
|
|
|
redshift = greenshift = blueshift = 0;
|
2004-09-07 12:08:03 +00:00
|
|
|
if ((maxred = xwdhdr->l_red_mask) == 0)
|
|
|
|
return;
|
2001-07-02 23:18:10 +00:00
|
|
|
|
|
|
|
/* Shift the redmask to the rightmost bit position to get
|
|
|
|
* maximum value for red.
|
|
|
|
*/
|
|
|
|
while ((maxred & 1) == 0)
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
|
|
|
redshift++;
|
|
|
|
maxred >>= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((maxgreen = xwdhdr->l_green_mask) == 0)
|
|
|
|
return;
|
|
|
|
|
2001-07-02 23:18:10 +00:00
|
|
|
while ((maxgreen & 1) == 0)
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
|
|
|
greenshift++;
|
|
|
|
maxgreen >>= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((maxblue = xwdhdr->l_blue_mask) == 0)
|
|
|
|
return;
|
|
|
|
|
2001-07-02 23:18:10 +00:00
|
|
|
while ((maxblue & 1) == 0)
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
|
|
|
blueshift++;
|
|
|
|
maxblue >>= 1;
|
|
|
|
}
|
2001-07-02 23:18:10 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
memset ((gchar *) ColorMap, 0, 256 * 3);
|
2001-07-02 23:18:10 +00:00
|
|
|
|
|
|
|
for (i = 0; i <= maxred; i++)
|
|
|
|
for (j = 0; j <= maxgreen; j++)
|
|
|
|
for (k = 0; k <= maxblue; k++)
|
|
|
|
{
|
2004-09-07 12:08:03 +00:00
|
|
|
cuind = (i << redshift) | (j << greenshift) | (k << blueshift);
|
|
|
|
|
|
|
|
if (cuind < 256)
|
|
|
|
{
|
|
|
|
ColorMap[cuind*3] = (i * 255)/maxred;
|
|
|
|
ColorMap[cuind*3+1] = (j * 255)/maxgreen;
|
|
|
|
ColorMap[cuind*3+2] = (k * 255)/maxblue;
|
|
|
|
}
|
2001-07-02 23:18:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-06 15:27:05 +00:00
|
|
|
static void
|
2019-08-24 16:46:40 +02:00
|
|
|
set_color_table (GimpImage *image,
|
2004-09-07 12:08:03 +00:00
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
|
|
|
L_XWDCOLOR *xwdcolmap)
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2004-09-07 12:08:03 +00:00
|
|
|
gint ncols, i, j;
|
|
|
|
guchar ColorMap[256 * 3];
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
ncols = xwdhdr->l_colormap_entries;
|
2003-11-06 15:27:05 +00:00
|
|
|
if (xwdhdr->l_ncolors < ncols)
|
1999-10-14 02:11:52 +00:00
|
|
|
ncols = xwdhdr->l_ncolors;
|
2003-11-06 15:27:05 +00:00
|
|
|
if (ncols <= 0)
|
1999-10-14 02:11:52 +00:00
|
|
|
return;
|
2003-11-06 15:27:05 +00:00
|
|
|
if (ncols > 256)
|
1999-10-14 02:11:52 +00:00
|
|
|
ncols = 256;
|
2001-07-02 23:18:10 +00:00
|
|
|
|
|
|
|
/* Initialize color table for all 256 entries from mask-values */
|
|
|
|
init_color_table256 (xwdhdr, ColorMap);
|
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (j = 0; j < ncols; j++)
|
|
|
|
{
|
|
|
|
i = xwdcolmap[j].l_pixel;
|
|
|
|
if ((i >= 0) && (i < 256))
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
|
|
|
ColorMap[i*3] = (xwdcolmap[j].l_red) >> 8;
|
|
|
|
ColorMap[i*3+1] = (xwdcolmap[j].l_green) >> 8;
|
|
|
|
ColorMap[i*3+2] = (xwdcolmap[j].l_blue) >> 8;
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
#ifdef XWD_COL_DEBUG
|
2018-08-12 19:21:44 +02:00
|
|
|
g_printf ("Set GIMP colortable:\n");
|
2001-07-02 23:18:10 +00:00
|
|
|
for (j = 0; j < 256; j++)
|
2018-08-12 19:21:44 +02:00
|
|
|
g_printf ("%3d: 0x%02x 0x%02x 0x%02x\n", j,
|
|
|
|
ColorMap[j*3], ColorMap[j*3+1], ColorMap[j*3+2]);
|
1997-11-24 22:05:25 +00:00
|
|
|
#endif
|
2004-09-07 12:08:03 +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"), ColorMap, 256 * 3);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-07-02 23:18:10 +00:00
|
|
|
|
|
|
|
|
2019-08-24 16:46:40 +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,
|
2000-12-13 18:53:35 +00:00
|
|
|
guint width,
|
|
|
|
guint height,
|
2000-08-22 01:26:57 +00:00
|
|
|
GimpImageBaseType type,
|
2012-08-07 15:56:58 +02:00
|
|
|
GimpImageType gdtype,
|
2019-08-24 16:46:40 +02:00
|
|
|
GimpLayer **layer,
|
2013-08-31 02:57:02 +02:00
|
|
|
GeglBuffer **buffer)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2019-08-24 16:46:40 +02:00
|
|
|
GimpImage *image;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
image = gimp_image_new (width, height, type);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
*layer = gimp_layer_new (image, "Background", width, height,
|
|
|
|
gdtype,
|
|
|
|
100,
|
|
|
|
gimp_image_get_default_new_layer_mode (image));
|
|
|
|
gimp_image_insert_layer (image, *layer, NULL, 0);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
*buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (*layer));
|
2004-09-07 12:08:03 +00:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
return image;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Load XWD with pixmap_format 2, pixmap_depth 1, bits_per_pixel 1 */
|
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
static GimpImage *
|
2019-09-11 21:48:34 +02:00
|
|
|
load_xwd_f2_d1_b1 (GFile *file,
|
1999-10-14 02:11:52 +00:00
|
|
|
FILE *ifp,
|
1997-11-24 22:05:25 +00:00
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
2023-07-11 18:17:42 -04:00
|
|
|
L_XWDCOLOR *xwdcolmap,
|
|
|
|
GError **error)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2004-09-07 12:08:03 +00:00
|
|
|
register int pix8;
|
|
|
|
register guchar *dest, *src;
|
|
|
|
guchar c1, c2, c3, c4;
|
2011-10-03 13:08:17 +05:30
|
|
|
gint width, height, scan_lines, tile_height;
|
2004-09-07 12:08:03 +00:00
|
|
|
gint i, j, ncols;
|
2005-03-04 15:12:29 +00:00
|
|
|
gchar *temp;
|
2004-09-07 12:08:03 +00:00
|
|
|
guchar bit2byte[256 * 8];
|
|
|
|
guchar *data, *scanline;
|
|
|
|
gint err = 0;
|
2019-08-24 16:46:40 +02:00
|
|
|
GimpImage *image;
|
|
|
|
GimpLayer *layer;
|
2013-08-31 02:57:02 +02:00
|
|
|
GeglBuffer *buffer;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
#ifdef XWD_DEBUG
|
2023-07-11 18:17:42 -04:00
|
|
|
g_printf ("load_xwd_f2_d1_b1 (%s)\n", gimp_file_get_utf8_name (file));
|
1997-11-24 22:05:25 +00:00
|
|
|
#endif
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
width = xwdhdr->l_pixmap_width;
|
1999-10-14 02:11:52 +00:00
|
|
|
height = xwdhdr->l_pixmap_height;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2019-09-11 21:48:34 +02:00
|
|
|
image = create_new_image (file, width, height, GIMP_INDEXED,
|
2019-08-24 16:46:40 +02:00
|
|
|
GIMP_INDEXED_IMAGE, &layer, &buffer);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
data = g_malloc (tile_height * width);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
scanline = g_new (guchar, xwdhdr->l_bytes_per_line + 8);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
ncols = xwdhdr->l_colormap_entries;
|
2004-09-07 12:08:03 +00:00
|
|
|
if (xwdhdr->l_ncolors < ncols)
|
|
|
|
ncols = xwdhdr->l_ncolors;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (ncols < 2)
|
2019-08-24 16:46:40 +02:00
|
|
|
set_bw_color_table (image);
|
1999-10-14 02:11:52 +00:00
|
|
|
else
|
2019-08-24 16:46:40 +02:00
|
|
|
set_color_table (image, xwdhdr, xwdcolmap);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
temp = (gchar *) bit2byte;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Get an array for mapping 8 bits in a byte to 8 bytes */
|
|
|
|
if (!xwdhdr->l_bitmap_bit_order)
|
|
|
|
{
|
|
|
|
for (j = 0; j < 256; j++)
|
2004-09-07 12:08:03 +00:00
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
*(temp++) = ((j & (1 << i)) != 0);
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (j = 0; j < 256; j++)
|
2004-09-07 12:08:03 +00:00
|
|
|
for (i = 7; i >= 0; i--)
|
|
|
|
*(temp++) = ((j & (1 << i)) != 0);
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
dest = data;
|
|
|
|
scan_lines = 0;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
|
|
|
if (fread (scanline, xwdhdr->l_bytes_per_line, 1, ifp) != 1)
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
|
|
|
err = 1;
|
|
|
|
break;
|
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Need to check byte order ? */
|
|
|
|
if (xwdhdr->l_bitmap_bit_order != xwdhdr->l_byte_order)
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
|
|
|
src = scanline;
|
|
|
|
switch (xwdhdr->l_bitmap_unit)
|
|
|
|
{
|
|
|
|
case 16:
|
|
|
|
j = xwdhdr->l_bytes_per_line;
|
|
|
|
while (j > 0)
|
|
|
|
{
|
|
|
|
c1 = src[0]; c2 = src[1];
|
|
|
|
*(src++) = c2; *(src++) = c1;
|
|
|
|
j -= 2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 32:
|
|
|
|
j = xwdhdr->l_bytes_per_line;
|
|
|
|
while (j > 0)
|
|
|
|
{
|
|
|
|
c1 = src[0]; c2 = src[1]; c3 = src[2]; c4 = src[3];
|
|
|
|
*(src++) = c4; *(src++) = c3; *(src++) = c2; *(src++) = c1;
|
|
|
|
j -= 4;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
src = scanline;
|
|
|
|
j = width;
|
|
|
|
while (j >= 8)
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
|
|
|
pix8 = *(src++);
|
|
|
|
memcpy (dest, bit2byte + pix8*8, 8);
|
|
|
|
dest += 8;
|
|
|
|
j -= 8;
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
if (j > 0)
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
|
|
|
pix8 = *(src++);
|
|
|
|
memcpy (dest, bit2byte + pix8*8, j);
|
|
|
|
dest += j;
|
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
scan_lines++;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2003-06-13 14:37:00 +00:00
|
|
|
if ((i % 20) == 0)
|
2004-09-07 12:08:03 +00:00
|
|
|
gimp_progress_update ((double)(i+1) / (double)height);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if ((scan_lines == tile_height) || ((i+1) == height))
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
2013-08-31 02:57:02 +02:00
|
|
|
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, i - scan_lines + 1,
|
|
|
|
width, scan_lines), 0,
|
|
|
|
NULL, data, GEGL_AUTO_ROWSTRIDE);
|
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
scan_lines = 0;
|
|
|
|
dest = data;
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2004-09-07 12:08:03 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
g_free (data);
|
|
|
|
g_free (scanline);
|
2023-07-11 18:17:42 -04:00
|
|
|
g_object_unref (buffer);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (err)
|
2023-07-11 18:17:42 -04:00
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("EOF encountered on reading"));
|
|
|
|
return NULL;
|
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2023-07-11 18:17:42 -04:00
|
|
|
return image;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Load XWD with pixmap_format 2, pixmap_depth 8, bits_per_pixel 8 */
|
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
static GimpImage *
|
2019-09-11 21:48:34 +02:00
|
|
|
load_xwd_f2_d8_b8 (GFile *file,
|
1999-10-14 02:11:52 +00:00
|
|
|
FILE *ifp,
|
1997-11-24 22:05:25 +00:00
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
2023-07-11 18:17:42 -04:00
|
|
|
L_XWDCOLOR *xwdcolmap,
|
|
|
|
GError **error)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2013-08-31 02:57:02 +02:00
|
|
|
gint width, height, linepad, tile_height, scan_lines;
|
|
|
|
gint i, j, ncols;
|
|
|
|
gint grayscale;
|
|
|
|
guchar *dest, *data;
|
|
|
|
gint err = 0;
|
2019-08-24 16:46:40 +02:00
|
|
|
GimpImage *image;
|
|
|
|
GimpLayer *layer;
|
2013-08-31 02:57:02 +02:00
|
|
|
GeglBuffer *buffer;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
#ifdef XWD_DEBUG
|
2023-07-11 18:17:42 -04:00
|
|
|
g_printf ("load_xwd_f2_d8_b8 (%s)\n", gimp_file_get_utf8_name (file));
|
1997-11-24 22:05:25 +00:00
|
|
|
#endif
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
width = xwdhdr->l_pixmap_width;
|
1999-10-14 02:11:52 +00:00
|
|
|
height = xwdhdr->l_pixmap_height;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
/* This could also be a grayscale image. Check it */
|
|
|
|
grayscale = 0;
|
1999-10-14 02:11:52 +00:00
|
|
|
if ((xwdhdr->l_ncolors == 256) && (xwdhdr->l_colormap_entries == 256))
|
|
|
|
{
|
|
|
|
for (j = 0; j < 256; j++)
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
|
|
|
if ((xwdcolmap[j].l_pixel != j)
|
|
|
|
|| ((xwdcolmap[j].l_red >> 8) != j)
|
|
|
|
|| ((xwdcolmap[j].l_green >> 8) != j)
|
|
|
|
|| ((xwdcolmap[j].l_blue >> 8) != j))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
grayscale = (j == 256);
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2019-09-11 21:48:34 +02:00
|
|
|
image = create_new_image (file, width, height,
|
2019-08-24 16:46:40 +02:00
|
|
|
grayscale ? GIMP_GRAY : GIMP_INDEXED,
|
|
|
|
grayscale ? GIMP_GRAY_IMAGE : GIMP_INDEXED_IMAGE,
|
|
|
|
&layer, &buffer);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
data = g_malloc (tile_height * width);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
if (!grayscale)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
|
|
|
ncols = xwdhdr->l_colormap_entries;
|
|
|
|
if (xwdhdr->l_ncolors < ncols) ncols = xwdhdr->l_ncolors;
|
|
|
|
if (ncols < 2)
|
2019-08-24 16:46:40 +02:00
|
|
|
set_bw_color_table (image);
|
1999-10-14 02:11:52 +00:00
|
|
|
else
|
2019-08-24 16:46:40 +02:00
|
|
|
set_color_table (image, xwdhdr, xwdcolmap);
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
linepad = xwdhdr->l_bytes_per_line - xwdhdr->l_pixmap_width;
|
2004-09-07 12:08:03 +00:00
|
|
|
if (linepad < 0)
|
|
|
|
linepad = 0;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
dest = data;
|
|
|
|
scan_lines = 0;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
|
|
|
if (fread (dest, 1, width, ifp) != width)
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
|
|
|
err = 1;
|
|
|
|
break;
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
dest += width;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (j = 0; j < linepad; j++)
|
2023-07-11 18:17:42 -04:00
|
|
|
if (getc (ifp) < 0)
|
|
|
|
{
|
|
|
|
err = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (err)
|
|
|
|
break;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
scan_lines++;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2003-06-13 14:37:00 +00:00
|
|
|
if ((i % 20) == 0)
|
2004-09-07 12:08:03 +00:00
|
|
|
gimp_progress_update ((gdouble) (i + 1) / (gdouble) height);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if ((scan_lines == tile_height) || ((i+1) == height))
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
2013-08-31 02:57:02 +02:00
|
|
|
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, i - scan_lines + 1,
|
|
|
|
width, scan_lines), 0,
|
|
|
|
NULL, data, GEGL_AUTO_ROWSTRIDE);
|
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
scan_lines = 0;
|
|
|
|
dest = data;
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2004-09-07 12:08:03 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
g_free (data);
|
2023-07-11 18:17:42 -04:00
|
|
|
g_object_unref (buffer);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (err)
|
2023-07-11 18:17:42 -04:00
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("EOF encountered on reading"));
|
|
|
|
return NULL;
|
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2023-07-11 18:17:42 -04:00
|
|
|
return image;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Load XWD with pixmap_format 2, pixmap_depth up to 16, bits_per_pixel 16 */
|
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
static GimpImage *
|
2019-09-11 21:48:34 +02:00
|
|
|
load_xwd_f2_d16_b16 (GFile *file,
|
2003-07-02 13:00:16 +00:00
|
|
|
FILE *ifp,
|
1997-11-24 22:05:25 +00:00
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
2023-07-11 18:17:42 -04:00
|
|
|
L_XWDCOLOR *xwdcolmap,
|
|
|
|
GError **error)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2004-09-07 12:08:03 +00:00
|
|
|
register guchar *dest, lsbyte_first;
|
|
|
|
gint width, height, linepad, i, j, c0, c1, ncols;
|
|
|
|
gint red, green, blue, redval, greenval, blueval;
|
|
|
|
gint maxred, maxgreen, maxblue;
|
|
|
|
gint tile_height, scan_lines;
|
2023-07-11 18:17:42 -04:00
|
|
|
guint32 redmask, greenmask, bluemask;
|
2004-09-07 12:08:03 +00:00
|
|
|
guint redshift, greenshift, blueshift;
|
2023-07-11 18:17:42 -04:00
|
|
|
guint32 maxval;
|
2004-09-07 12:08:03 +00:00
|
|
|
guchar *ColorMap, *cm, *data;
|
|
|
|
gint err = 0;
|
2019-08-24 16:46:40 +02:00
|
|
|
GimpImage *image;
|
|
|
|
GimpLayer *layer;
|
2013-08-31 02:57:02 +02:00
|
|
|
GeglBuffer *buffer;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
#ifdef XWD_DEBUG
|
2023-07-11 18:17:42 -04:00
|
|
|
g_printf ("load_xwd_f2_d16_b16 (%s)\n", gimp_file_get_utf8_name (file));
|
1997-11-24 22:05:25 +00:00
|
|
|
#endif
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
width = xwdhdr->l_pixmap_width;
|
1999-10-14 02:11:52 +00:00
|
|
|
height = xwdhdr->l_pixmap_height;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2019-09-11 21:48:34 +02:00
|
|
|
image = create_new_image (file, width, height, GIMP_RGB,
|
2019-08-24 16:46:40 +02:00
|
|
|
GIMP_RGB_IMAGE, &layer, &buffer);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
data = g_malloc (tile_height * width * 3);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Get memory for mapping 16 bit XWD-pixel to GIMP-RGB */
|
|
|
|
maxval = 0x10000 * 3;
|
2004-09-07 12:08:03 +00:00
|
|
|
ColorMap = g_new0 (guchar, maxval);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
redmask = xwdhdr->l_red_mask;
|
|
|
|
greenmask = xwdhdr->l_green_mask;
|
|
|
|
bluemask = xwdhdr->l_blue_mask;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* How to shift RGB to be right aligned ? */
|
|
|
|
/* (We rely on the the mask bits are grouped and not mixed) */
|
|
|
|
redshift = greenshift = blueshift = 0;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
while (((1 << redshift) & redmask) == 0) redshift++;
|
1999-10-14 02:11:52 +00:00
|
|
|
while (((1 << greenshift) & greenmask) == 0) greenshift++;
|
2004-09-07 12:08:03 +00:00
|
|
|
while (((1 << blueshift) & bluemask) == 0) blueshift++;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* The bits_per_rgb may not be correct. Use redmask instead */
|
|
|
|
maxred = 0; while (redmask >> (redshift + maxred)) maxred++;
|
|
|
|
maxred = (1 << maxred) - 1;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
maxgreen = 0; while (greenmask >> (greenshift + maxgreen)) maxgreen++;
|
|
|
|
maxgreen = (1 << maxgreen) - 1;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
maxblue = 0; while (bluemask >> (blueshift + maxblue)) maxblue++;
|
|
|
|
maxblue = (1 << maxblue) - 1;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Built up the array to map XWD-pixel value to GIMP-RGB */
|
|
|
|
for (red = 0; red <= maxred; red++)
|
|
|
|
{
|
|
|
|
redval = (red * 255) / maxred;
|
|
|
|
for (green = 0; green <= maxgreen; green++)
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
|
|
|
greenval = (green * 255) / maxgreen;
|
|
|
|
for (blue = 0; blue <= maxblue; blue++)
|
|
|
|
{
|
|
|
|
blueval = (blue * 255) / maxblue;
|
|
|
|
cm = ColorMap + ((red << redshift) + (green << greenshift)
|
|
|
|
+ (blue << blueshift)) * 3;
|
|
|
|
*(cm++) = redval;
|
|
|
|
*(cm++) = greenval;
|
|
|
|
*cm = blueval;
|
|
|
|
}
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Now look what was written to the XWD-Colormap */
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
ncols = xwdhdr->l_colormap_entries;
|
2004-09-07 12:08:03 +00:00
|
|
|
if (xwdhdr->l_ncolors < ncols)
|
|
|
|
ncols = xwdhdr->l_ncolors;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (j = 0; j < ncols; j++)
|
|
|
|
{
|
|
|
|
cm = ColorMap + xwdcolmap[j].l_pixel * 3;
|
|
|
|
*(cm++) = (xwdcolmap[j].l_red >> 8);
|
|
|
|
*(cm++) = (xwdcolmap[j].l_green >> 8);
|
|
|
|
*cm = (xwdcolmap[j].l_blue >> 8);
|
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* What do we have to consume after a line has finished ? */
|
|
|
|
linepad = xwdhdr->l_bytes_per_line
|
|
|
|
- (xwdhdr->l_pixmap_width*xwdhdr->l_bits_per_pixel)/8;
|
|
|
|
if (linepad < 0) linepad = 0;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
lsbyte_first = (xwdhdr->l_byte_order == 0);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
dest = data;
|
|
|
|
scan_lines = 0;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
|
|
|
for (j = 0; j < width; j++)
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
|
|
|
c0 = getc (ifp);
|
|
|
|
c1 = getc (ifp);
|
|
|
|
if (c1 < 0)
|
|
|
|
{
|
|
|
|
err = 1;
|
|
|
|
break;
|
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
if (lsbyte_first)
|
|
|
|
c0 = c0 | (c1 << 8);
|
|
|
|
else
|
|
|
|
c0 = (c0 << 8) | c1;
|
|
|
|
|
|
|
|
cm = ColorMap + c0 * 3;
|
|
|
|
*(dest++) = *(cm++);
|
|
|
|
*(dest++) = *(cm++);
|
|
|
|
*(dest++) = *cm;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (err)
|
|
|
|
break;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (j = 0; j < linepad; j++)
|
2023-07-11 18:17:42 -04:00
|
|
|
if (getc (ifp) < 0)
|
|
|
|
{
|
|
|
|
err = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (err)
|
|
|
|
break;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
scan_lines++;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2003-06-13 14:37:00 +00:00
|
|
|
if ((i % 20) == 0)
|
2004-09-07 12:08:03 +00:00
|
|
|
gimp_progress_update ((double)(i+1) / (double)height);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if ((scan_lines == tile_height) || ((i+1) == height))
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
2013-08-31 02:57:02 +02:00
|
|
|
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, i - scan_lines + 1,
|
|
|
|
width, scan_lines), 0,
|
|
|
|
NULL, data, GEGL_AUTO_ROWSTRIDE);
|
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
scan_lines = 0;
|
|
|
|
dest = data;
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
|
|
|
g_free (data);
|
|
|
|
g_free (ColorMap);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2013-08-31 02:57:02 +02:00
|
|
|
g_object_unref (buffer);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2023-07-11 18:17:42 -04:00
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("EOF encountered on reading"));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return image;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Load XWD with pixmap_format 2, pixmap_depth up to 24, bits_per_pixel 24/32 */
|
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
static GimpImage *
|
2019-09-11 21:48:34 +02:00
|
|
|
load_xwd_f2_d24_b32 (GFile *file,
|
2012-11-08 00:16:31 +01:00
|
|
|
FILE *ifp,
|
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
|
|
|
L_XWDCOLOR *xwdcolmap,
|
|
|
|
GError **error)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2004-09-07 12:08:03 +00:00
|
|
|
register guchar *dest, lsbyte_first;
|
|
|
|
gint width, height, linepad, i, j, c0, c1, c2, c3;
|
|
|
|
gint tile_height, scan_lines;
|
|
|
|
L_CARD32 pixelval;
|
|
|
|
gint red, green, blue, ncols;
|
2023-07-11 18:17:42 -04:00
|
|
|
guint32 maxred, maxgreen, maxblue;
|
|
|
|
guint32 redmask, greenmask, bluemask;
|
2004-09-07 12:08:03 +00:00
|
|
|
guint redshift, greenshift, blueshift;
|
|
|
|
guchar redmap[256], greenmap[256], bluemap[256];
|
|
|
|
guchar *data;
|
|
|
|
PIXEL_MAP pixel_map;
|
|
|
|
gint err = 0;
|
2019-08-24 16:46:40 +02:00
|
|
|
GimpImage *image;
|
|
|
|
GimpLayer *layer;
|
2013-08-31 02:57:02 +02:00
|
|
|
GeglBuffer *buffer;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
#ifdef XWD_DEBUG
|
2023-07-11 18:17:42 -04:00
|
|
|
g_printf ("load_xwd_f2_d24_b32 (%s)\n", gimp_file_get_utf8_name (file));
|
1997-11-24 22:05:25 +00:00
|
|
|
#endif
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2023-07-11 18:26:05 -04:00
|
|
|
/* issue #8082: depth and bits per pixel is 24, but 4 bytes are used per pixel */
|
|
|
|
if (xwdhdr->l_bits_per_pixel == 24)
|
|
|
|
{
|
|
|
|
if (xwdhdr->l_bytes_per_line / xwdhdr->l_pixmap_width == 4 &&
|
|
|
|
xwdhdr->l_bytes_per_line % xwdhdr->l_pixmap_width == 0)
|
|
|
|
xwdhdr->l_bits_per_pixel = 32;
|
|
|
|
}
|
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
width = xwdhdr->l_pixmap_width;
|
1999-10-14 02:11:52 +00:00
|
|
|
height = xwdhdr->l_pixmap_height;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
redmask = xwdhdr->l_red_mask;
|
|
|
|
greenmask = xwdhdr->l_green_mask;
|
|
|
|
bluemask = xwdhdr->l_blue_mask;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
if (redmask == 0) redmask = 0xff0000;
|
1999-10-14 02:11:52 +00:00
|
|
|
if (greenmask == 0) greenmask = 0x00ff00;
|
2004-09-07 12:08:03 +00:00
|
|
|
if (bluemask == 0) bluemask = 0x0000ff;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* How to shift RGB to be right aligned ? */
|
|
|
|
/* (We rely on the the mask bits are grouped and not mixed) */
|
|
|
|
redshift = greenshift = blueshift = 0;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
while (((1 << redshift) & redmask) == 0) redshift++;
|
1999-10-14 02:11:52 +00:00
|
|
|
while (((1 << greenshift) & greenmask) == 0) greenshift++;
|
2004-09-07 12:08:03 +00:00
|
|
|
while (((1 << blueshift) & bluemask) == 0) blueshift++;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* The bits_per_rgb may not be correct. Use redmask instead */
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
maxred = 0; while (redmask >> (redshift + maxred)) maxred++;
|
|
|
|
maxred = (1 << maxred) - 1;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
maxgreen = 0; while (greenmask >> (greenshift + maxgreen)) maxgreen++;
|
|
|
|
maxgreen = (1 << maxgreen) - 1;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
maxblue = 0; while (bluemask >> (blueshift + maxblue)) maxblue++;
|
|
|
|
maxblue = (1 << maxblue) - 1;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2023-07-11 18:17:42 -04:00
|
|
|
if (maxred == 0 || maxred >= sizeof (redmap) ||
|
|
|
|
maxgreen == 0 || maxgreen >= sizeof (greenmap) ||
|
|
|
|
maxblue == 0 || maxblue >= sizeof (bluemap))
|
2012-11-08 00:16:31 +01:00
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("XWD-file %s is corrupt."),
|
2019-09-11 21:48:34 +02:00
|
|
|
gimp_file_get_utf8_name (file));
|
2019-08-24 16:46:40 +02:00
|
|
|
return NULL;
|
2012-11-08 00:16:31 +01:00
|
|
|
}
|
|
|
|
|
2019-09-11 21:48:34 +02:00
|
|
|
image = create_new_image (file, width, height, GIMP_RGB,
|
2019-08-24 16:46:40 +02:00
|
|
|
GIMP_RGB_IMAGE, &layer, &buffer);
|
2012-11-08 00:16:31 +01:00
|
|
|
|
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
data = g_malloc (tile_height * width * 3);
|
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Set map-arrays for red, green, blue */
|
|
|
|
for (red = 0; red <= maxred; red++)
|
|
|
|
redmap[red] = (red * 255) / maxred;
|
|
|
|
for (green = 0; green <= maxgreen; green++)
|
|
|
|
greenmap[green] = (green * 255) / maxgreen;
|
|
|
|
for (blue = 0; blue <= maxblue; blue++)
|
|
|
|
bluemap[blue] = (blue * 255) / maxblue;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
ncols = xwdhdr->l_colormap_entries;
|
2011-10-08 18:38:14 +05:30
|
|
|
if (xwdhdr->l_ncolors < ncols)
|
|
|
|
ncols = xwdhdr->l_ncolors;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2011-10-08 18:37:58 +05:30
|
|
|
set_pixelmap (ncols, xwdcolmap, &pixel_map);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* What do we have to consume after a line has finished ? */
|
|
|
|
linepad = xwdhdr->l_bytes_per_line
|
|
|
|
- (xwdhdr->l_pixmap_width*xwdhdr->l_bits_per_pixel)/8;
|
|
|
|
if (linepad < 0) linepad = 0;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
lsbyte_first = (xwdhdr->l_byte_order == 0);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
dest = data;
|
|
|
|
scan_lines = 0;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (xwdhdr->l_bits_per_pixel == 32)
|
|
|
|
{
|
|
|
|
for (i = 0; i < height; i++)
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
|
|
|
c0 = getc (ifp);
|
|
|
|
c1 = getc (ifp);
|
|
|
|
c2 = getc (ifp);
|
|
|
|
c3 = getc (ifp);
|
|
|
|
if (c3 < 0)
|
|
|
|
{
|
|
|
|
err = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (lsbyte_first)
|
|
|
|
pixelval = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
|
|
|
|
else
|
|
|
|
pixelval = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3;
|
|
|
|
|
|
|
|
if (get_pixelmap (pixelval, &pixel_map, dest, dest+1, dest+2))
|
|
|
|
{
|
|
|
|
dest += 3;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*(dest++) = redmap[(pixelval & redmask) >> redshift];
|
|
|
|
*(dest++) = greenmap[(pixelval & greenmask) >> greenshift];
|
|
|
|
*(dest++) = bluemap[(pixelval & bluemask) >> blueshift];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
scan_lines++;
|
|
|
|
|
|
|
|
if (err)
|
|
|
|
break;
|
|
|
|
|
|
|
|
for (j = 0; j < linepad; j++)
|
2023-07-11 18:17:42 -04:00
|
|
|
if (getc (ifp) < 0)
|
|
|
|
{
|
|
|
|
err = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (err)
|
|
|
|
break;
|
2004-09-07 12:08:03 +00:00
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
|
|
|
gimp_progress_update ((gdouble) (i + 1) / (gdouble) height);
|
|
|
|
|
|
|
|
if ((scan_lines == tile_height) || ((i+1) == height))
|
|
|
|
{
|
2013-08-31 02:57:02 +02:00
|
|
|
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, i - scan_lines + 1,
|
|
|
|
width, scan_lines), 0,
|
|
|
|
NULL, data, GEGL_AUTO_ROWSTRIDE);
|
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
scan_lines = 0;
|
|
|
|
dest = data;
|
|
|
|
}
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
|
|
|
else /* 24 bits per pixel */
|
|
|
|
{
|
|
|
|
for (i = 0; i < height; i++)
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
|
|
|
c0 = getc (ifp);
|
|
|
|
c1 = getc (ifp);
|
|
|
|
c2 = getc (ifp);
|
|
|
|
if (c2 < 0)
|
|
|
|
{
|
|
|
|
err = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (lsbyte_first)
|
|
|
|
pixelval = c0 | (c1 << 8) | (c2 << 16);
|
|
|
|
else
|
|
|
|
pixelval = (c0 << 16) | (c1 << 8) | c2;
|
|
|
|
|
|
|
|
if (get_pixelmap (pixelval, &pixel_map, dest, dest+1, dest+2))
|
|
|
|
{
|
|
|
|
dest += 3;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*(dest++) = redmap[(pixelval & redmask) >> redshift];
|
|
|
|
*(dest++) = greenmap[(pixelval & greenmask) >> greenshift];
|
|
|
|
*(dest++) = bluemap[(pixelval & bluemask) >> blueshift];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
scan_lines++;
|
|
|
|
|
|
|
|
if (err)
|
|
|
|
break;
|
|
|
|
|
|
|
|
for (j = 0; j < linepad; j++)
|
2023-07-11 18:17:42 -04:00
|
|
|
if (getc (ifp) < 0)
|
|
|
|
{
|
|
|
|
err = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (err)
|
|
|
|
break;
|
2004-09-07 12:08:03 +00:00
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
|
|
|
gimp_progress_update ((gdouble) (i + 1) / (gdouble) height);
|
|
|
|
|
|
|
|
if ((scan_lines == tile_height) || ((i+1) == height))
|
|
|
|
{
|
2013-08-31 02:57:02 +02:00
|
|
|
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, i - scan_lines + 1,
|
|
|
|
width, scan_lines), 0,
|
|
|
|
NULL, data, GEGL_AUTO_ROWSTRIDE);
|
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
scan_lines = 0;
|
|
|
|
dest = data;
|
|
|
|
}
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2004-09-07 12:08:03 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
g_free (data);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2013-08-31 02:57:02 +02:00
|
|
|
g_object_unref (buffer);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2023-07-11 18:17:42 -04:00
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("EOF encountered on reading"));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return image;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2012-08-07 15:56:58 +02:00
|
|
|
/* Load XWD with pixmap_format 2, pixmap_depth up to 32, bits_per_pixel 32 */
|
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
static GimpImage *
|
2019-09-11 21:48:34 +02:00
|
|
|
load_xwd_f2_d32_b32 (GFile *file,
|
2012-08-07 15:56:58 +02:00
|
|
|
FILE *ifp,
|
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
2023-07-11 18:17:42 -04:00
|
|
|
L_XWDCOLOR *xwdcolmap,
|
|
|
|
GError **error)
|
2012-08-07 15:56:58 +02:00
|
|
|
{
|
|
|
|
register guchar *dest, lsbyte_first;
|
|
|
|
gint width, height, linepad, i, j, c0, c1, c2, c3;
|
|
|
|
gint tile_height, scan_lines;
|
|
|
|
L_CARD32 pixelval;
|
|
|
|
gint red, green, blue, alpha, ncols;
|
2023-07-11 18:17:42 -04:00
|
|
|
guint32 maxred, maxgreen, maxblue, maxalpha;
|
|
|
|
guint32 redmask, greenmask, bluemask, alphamask;
|
2012-08-07 15:56:58 +02:00
|
|
|
guint redshift, greenshift, blueshift, alphashift;
|
|
|
|
guchar redmap[256], greenmap[256], bluemap[256], alphamap[256];
|
|
|
|
guchar *data;
|
|
|
|
PIXEL_MAP pixel_map;
|
|
|
|
gint err = 0;
|
2019-08-24 16:46:40 +02:00
|
|
|
GimpImage *image;
|
|
|
|
GimpLayer *layer;
|
2013-08-31 02:57:02 +02:00
|
|
|
GeglBuffer *buffer;
|
2012-08-07 15:56:58 +02:00
|
|
|
|
|
|
|
#ifdef XWD_DEBUG
|
2023-07-11 18:17:42 -04:00
|
|
|
g_printf ("load_xwd_f2_d32_b32 (%s)\n", gimp_file_get_utf8_name (file));
|
2012-08-07 15:56:58 +02:00
|
|
|
#endif
|
|
|
|
|
2023-07-11 18:17:42 -04:00
|
|
|
if (! xwdcolmap)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("'%s':\nInvalid color map"),
|
|
|
|
gimp_file_get_utf8_name (file));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-07 15:56:58 +02:00
|
|
|
width = xwdhdr->l_pixmap_width;
|
|
|
|
height = xwdhdr->l_pixmap_height;
|
|
|
|
|
2019-09-11 21:48:34 +02:00
|
|
|
image = create_new_image (file, width, height, GIMP_RGB,
|
2019-08-24 16:46:40 +02:00
|
|
|
GIMP_RGBA_IMAGE, &layer, &buffer);
|
2012-08-07 15:56:58 +02:00
|
|
|
|
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
data = g_malloc (tile_height * width * 4);
|
|
|
|
|
|
|
|
redmask = xwdhdr->l_red_mask;
|
|
|
|
greenmask = xwdhdr->l_green_mask;
|
|
|
|
bluemask = xwdhdr->l_blue_mask;
|
|
|
|
|
|
|
|
if (redmask == 0) redmask = 0xff0000;
|
|
|
|
if (greenmask == 0) greenmask = 0x00ff00;
|
|
|
|
if (bluemask == 0) bluemask = 0x0000ff;
|
|
|
|
alphamask = 0xffffffff & ~(redmask | greenmask | bluemask);
|
|
|
|
|
|
|
|
/* How to shift RGB to be right aligned ? */
|
|
|
|
/* (We rely on the the mask bits are grouped and not mixed) */
|
|
|
|
redshift = greenshift = blueshift = alphashift = 0;
|
|
|
|
|
|
|
|
while (((1 << redshift) & redmask) == 0) redshift++;
|
|
|
|
while (((1 << greenshift) & greenmask) == 0) greenshift++;
|
|
|
|
while (((1 << blueshift) & bluemask) == 0) blueshift++;
|
|
|
|
while (((1 << alphashift) & alphamask) == 0) alphashift++;
|
|
|
|
|
|
|
|
/* The bits_per_rgb may not be correct. Use redmask instead */
|
|
|
|
|
|
|
|
maxred = 0; while (redmask >> (redshift + maxred)) maxred++;
|
|
|
|
maxred = (1 << maxred) - 1;
|
|
|
|
|
|
|
|
maxgreen = 0; while (greenmask >> (greenshift + maxgreen)) maxgreen++;
|
|
|
|
maxgreen = (1 << maxgreen) - 1;
|
|
|
|
|
|
|
|
maxblue = 0; while (bluemask >> (blueshift + maxblue)) maxblue++;
|
|
|
|
maxblue = (1 << maxblue) - 1;
|
|
|
|
|
|
|
|
maxalpha = 0; while (alphamask >> (alphashift + maxalpha)) maxalpha++;
|
|
|
|
maxalpha = (1 << maxalpha) - 1;
|
|
|
|
|
2023-07-11 18:17:42 -04:00
|
|
|
if (maxred == 0 || maxred >= sizeof (redmap) ||
|
|
|
|
maxgreen == 0 || maxgreen >= sizeof (greenmap) ||
|
|
|
|
maxblue == 0 || maxblue >= sizeof (bluemap) ||
|
|
|
|
maxalpha == 0 || maxalpha >= sizeof (alphamap))
|
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("XWD-file %s is corrupt."),
|
|
|
|
gimp_file_get_utf8_name (file));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-07 15:56:58 +02:00
|
|
|
/* Set map-arrays for red, green, blue */
|
|
|
|
for (red = 0; red <= maxred; red++)
|
|
|
|
redmap[red] = (red * 255) / maxred;
|
|
|
|
for (green = 0; green <= maxgreen; green++)
|
|
|
|
greenmap[green] = (green * 255) / maxgreen;
|
|
|
|
for (blue = 0; blue <= maxblue; blue++)
|
|
|
|
bluemap[blue] = (blue * 255) / maxblue;
|
|
|
|
for (alpha = 0; alpha <= maxalpha; alpha++)
|
|
|
|
alphamap[alpha] = (alpha * 255) / maxalpha;
|
|
|
|
|
|
|
|
ncols = xwdhdr->l_colormap_entries;
|
|
|
|
if (xwdhdr->l_ncolors < ncols)
|
|
|
|
ncols = xwdhdr->l_ncolors;
|
|
|
|
|
|
|
|
set_pixelmap (ncols, xwdcolmap, &pixel_map);
|
|
|
|
|
|
|
|
/* What do we have to consume after a line has finished ? */
|
|
|
|
linepad = xwdhdr->l_bytes_per_line
|
|
|
|
- (xwdhdr->l_pixmap_width*xwdhdr->l_bits_per_pixel)/8;
|
|
|
|
if (linepad < 0) linepad = 0;
|
|
|
|
|
|
|
|
lsbyte_first = (xwdhdr->l_byte_order == 0);
|
|
|
|
|
|
|
|
dest = data;
|
|
|
|
scan_lines = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
|
|
|
c0 = getc (ifp);
|
|
|
|
c1 = getc (ifp);
|
|
|
|
c2 = getc (ifp);
|
|
|
|
c3 = getc (ifp);
|
|
|
|
if (c3 < 0)
|
|
|
|
{
|
|
|
|
err = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (lsbyte_first)
|
|
|
|
pixelval = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
|
|
|
|
else
|
|
|
|
pixelval = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3;
|
|
|
|
|
|
|
|
if (get_pixelmap (pixelval, &pixel_map, dest, dest+1, dest+2))
|
|
|
|
{
|
|
|
|
/* FIXME: is it always transparent or encoded in an unknown way? */
|
|
|
|
*(dest+3) = 0x00;
|
|
|
|
dest += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*(dest++) = redmap[(pixelval & redmask) >> redshift];
|
|
|
|
*(dest++) = greenmap[(pixelval & greenmask) >> greenshift];
|
|
|
|
*(dest++) = bluemap[(pixelval & bluemask) >> blueshift];
|
|
|
|
*(dest++) = alphamap[(pixelval & alphamask) >> alphashift];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
scan_lines++;
|
|
|
|
|
|
|
|
if (err)
|
|
|
|
break;
|
|
|
|
|
|
|
|
for (j = 0; j < linepad; j++)
|
2023-07-11 18:17:42 -04:00
|
|
|
if (getc (ifp) < 0)
|
|
|
|
{
|
|
|
|
err = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (err)
|
|
|
|
break;
|
2012-08-07 15:56:58 +02:00
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
|
|
|
gimp_progress_update ((gdouble) (i + 1) / (gdouble) height);
|
|
|
|
|
|
|
|
if ((scan_lines == tile_height) || ((i+1) == height))
|
|
|
|
{
|
2013-08-31 02:57:02 +02:00
|
|
|
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, i - scan_lines + 1,
|
|
|
|
width, scan_lines), 0,
|
|
|
|
NULL, data, GEGL_AUTO_ROWSTRIDE);
|
|
|
|
|
2012-08-07 15:56:58 +02:00
|
|
|
scan_lines = 0;
|
|
|
|
dest = data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (data);
|
|
|
|
|
2013-08-31 02:57:02 +02:00
|
|
|
g_object_unref (buffer);
|
2012-08-07 15:56:58 +02:00
|
|
|
|
2023-07-11 18:17:42 -04:00
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("EOF encountered on reading"));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return image;
|
2012-08-07 15:56:58 +02:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* Load XWD with pixmap_format 1, pixmap_depth up to 24, bits_per_pixel 1 */
|
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
static GimpImage *
|
2019-09-11 21:48:34 +02:00
|
|
|
load_xwd_f1_d24_b1 (GFile *file,
|
2012-11-08 00:16:31 +01:00
|
|
|
FILE *ifp,
|
|
|
|
L_XWDFILEHEADER *xwdhdr,
|
|
|
|
L_XWDCOLOR *xwdcolmap,
|
|
|
|
GError **error)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2004-09-07 12:08:03 +00:00
|
|
|
register guchar *dest, outmask, inmask, do_reverse;
|
2011-10-11 10:04:43 +05:30
|
|
|
gint width, height, i, j, plane, fromright;
|
2004-09-07 12:08:03 +00:00
|
|
|
gint tile_height, tile_start, tile_end;
|
|
|
|
gint indexed, bytes_per_pixel;
|
|
|
|
gint maxred, maxgreen, maxblue;
|
|
|
|
gint red, green, blue, ncols, standard_rgb;
|
2023-07-11 18:17:42 -04:00
|
|
|
goffset data_offset, plane_offset, tile_offset;
|
|
|
|
guint32 redmask, greenmask, bluemask;
|
2004-09-07 12:08:03 +00:00
|
|
|
guint redshift, greenshift, blueshift;
|
2023-07-11 18:17:42 -04:00
|
|
|
guint32 g;
|
2004-09-07 12:08:03 +00:00
|
|
|
guchar redmap[256], greenmap[256], bluemap[256];
|
|
|
|
guchar bit_reverse[256];
|
|
|
|
guchar *xwddata, *xwdin, *data;
|
|
|
|
L_CARD32 pixelval;
|
|
|
|
PIXEL_MAP pixel_map;
|
|
|
|
gint err = 0;
|
2019-08-24 16:46:40 +02:00
|
|
|
GimpImage *image;
|
|
|
|
GimpLayer *layer;
|
2013-08-31 02:57:02 +02:00
|
|
|
GeglBuffer *buffer;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
#ifdef XWD_DEBUG
|
2023-07-11 18:17:42 -04:00
|
|
|
g_printf ("load_xwd_f1_d24_b1 (%s)\n", gimp_file_get_utf8_name (file));
|
1997-11-24 22:05:25 +00:00
|
|
|
#endif
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
xwddata = g_malloc (xwdhdr->l_bytes_per_line);
|
2004-09-07 12:08:03 +00:00
|
|
|
if (xwddata == NULL)
|
2019-08-24 16:46:40 +02:00
|
|
|
return NULL;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
width = xwdhdr->l_pixmap_width;
|
|
|
|
height = xwdhdr->l_pixmap_height;
|
|
|
|
indexed = (xwdhdr->l_pixmap_depth <= 8);
|
1999-10-14 02:11:52 +00:00
|
|
|
bytes_per_pixel = (indexed ? 1 : 3);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (j = 0; j < 256; j++) /* Create an array for reversing bits */
|
|
|
|
{
|
|
|
|
inmask = 0;
|
|
|
|
for (i = 0; i < 8; i++)
|
2004-09-07 12:08:03 +00:00
|
|
|
{
|
|
|
|
inmask <<= 1;
|
|
|
|
if (j & (1 << i)) inmask |= 1;
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
bit_reverse[j] = inmask;
|
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
redmask = xwdhdr->l_red_mask;
|
|
|
|
greenmask = xwdhdr->l_green_mask;
|
|
|
|
bluemask = xwdhdr->l_blue_mask;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
if (redmask == 0) redmask = 0xff0000;
|
1999-10-14 02:11:52 +00:00
|
|
|
if (greenmask == 0) greenmask = 0x00ff00;
|
2004-09-07 12:08:03 +00:00
|
|
|
if (bluemask == 0) bluemask = 0x0000ff;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
standard_rgb = (redmask == 0xff0000) && (greenmask == 0x00ff00)
|
|
|
|
&& (bluemask == 0x0000ff);
|
|
|
|
redshift = greenshift = blueshift = 0;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
if (!standard_rgb) /* Do we need to re-map the pixel-values ? */
|
|
|
|
{
|
|
|
|
/* How to shift RGB to be right aligned ? */
|
|
|
|
/* (We rely on the the mask bits are grouped and not mixed) */
|
|
|
|
|
|
|
|
while (((1 << redshift) & redmask) == 0) redshift++;
|
|
|
|
while (((1 << greenshift) & greenmask) == 0) greenshift++;
|
|
|
|
while (((1 << blueshift) & bluemask) == 0) blueshift++;
|
|
|
|
|
|
|
|
/* The bits_per_rgb may not be correct. Use redmask instead */
|
|
|
|
|
|
|
|
maxred = 0; while (redmask >> (redshift + maxred)) maxred++;
|
|
|
|
maxred = (1 << maxred) - 1;
|
|
|
|
|
|
|
|
maxgreen = 0; while (greenmask >> (greenshift + maxgreen)) maxgreen++;
|
|
|
|
maxgreen = (1 << maxgreen) - 1;
|
|
|
|
|
|
|
|
maxblue = 0; while (bluemask >> (blueshift + maxblue)) maxblue++;
|
|
|
|
maxblue = (1 << maxblue) - 1;
|
|
|
|
|
2023-07-11 18:17:42 -04:00
|
|
|
if (maxred == 0 || maxred >= sizeof (redmap) ||
|
|
|
|
maxgreen == 0 || maxgreen >= sizeof (greenmap) ||
|
|
|
|
maxblue == 0 || maxblue >= sizeof (bluemap))
|
2012-11-08 00:16:31 +01:00
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("XWD-file %s is corrupt."),
|
2019-09-11 21:48:34 +02:00
|
|
|
gimp_file_get_utf8_name (file));
|
2019-08-24 16:46:40 +02:00
|
|
|
return NULL;
|
2012-11-08 00:16:31 +01:00
|
|
|
}
|
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
/* Set map-arrays for red, green, blue */
|
|
|
|
for (red = 0; red <= maxred; red++)
|
|
|
|
redmap[red] = (red * 255) / maxred;
|
|
|
|
for (green = 0; green <= maxgreen; green++)
|
|
|
|
greenmap[green] = (green * 255) / maxgreen;
|
|
|
|
for (blue = 0; blue <= maxblue; blue++)
|
|
|
|
bluemap[blue] = (blue * 255) / maxblue;
|
|
|
|
}
|
|
|
|
|
2019-09-11 21:48:34 +02:00
|
|
|
image = create_new_image (file, width, height,
|
2019-08-24 16:46:40 +02:00
|
|
|
indexed ? GIMP_INDEXED : GIMP_RGB,
|
|
|
|
indexed ? GIMP_INDEXED_IMAGE : GIMP_RGB_IMAGE,
|
|
|
|
&layer, &buffer);
|
2012-11-08 00:16:31 +01:00
|
|
|
|
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
data = g_malloc (tile_height * width * bytes_per_pixel);
|
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
ncols = xwdhdr->l_colormap_entries;
|
|
|
|
if (xwdhdr->l_ncolors < ncols)
|
|
|
|
ncols = xwdhdr->l_ncolors;
|
|
|
|
|
|
|
|
if (indexed)
|
|
|
|
{
|
|
|
|
if (ncols < 2)
|
2019-08-24 16:46:40 +02:00
|
|
|
set_bw_color_table (image);
|
2004-09-07 12:08:03 +00:00
|
|
|
else
|
2019-08-24 16:46:40 +02:00
|
|
|
set_color_table (image, xwdhdr, xwdcolmap);
|
2004-09-07 12:08:03 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-10-08 18:37:58 +05:30
|
|
|
set_pixelmap (ncols, xwdcolmap, &pixel_map);
|
2004-09-07 12:08:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
do_reverse = !xwdhdr->l_bitmap_bit_order;
|
|
|
|
|
|
|
|
/* This is where the image data starts within the file */
|
|
|
|
data_offset = ftell (ifp);
|
|
|
|
|
|
|
|
for (tile_start = 0; tile_start < height; tile_start += tile_height)
|
|
|
|
{
|
|
|
|
memset (data, 0, width*tile_height*bytes_per_pixel);
|
|
|
|
|
|
|
|
tile_end = tile_start + tile_height - 1;
|
|
|
|
if (tile_end >= height)
|
|
|
|
tile_end = height - 1;
|
|
|
|
|
|
|
|
for (plane = 0; plane < xwdhdr->l_pixmap_depth; plane++)
|
|
|
|
{
|
|
|
|
dest = data; /* Position to start of tile within the plane */
|
|
|
|
plane_offset = data_offset + plane*height*xwdhdr->l_bytes_per_line;
|
|
|
|
tile_offset = plane_offset + tile_start*xwdhdr->l_bytes_per_line;
|
2023-07-11 18:17:42 -04:00
|
|
|
if (fseek (ifp, tile_offset, SEEK_SET) != 0)
|
|
|
|
{
|
|
|
|
err = 1;
|
|
|
|
break;
|
|
|
|
}
|
2004-09-07 12:08:03 +00:00
|
|
|
|
|
|
|
/* Place the last plane at the least significant bit */
|
|
|
|
|
|
|
|
if (indexed) /* Only 1 byte per pixel */
|
|
|
|
{
|
|
|
|
fromright = xwdhdr->l_pixmap_depth-1-plane;
|
|
|
|
outmask = (1 << fromright);
|
|
|
|
}
|
|
|
|
else /* 3 bytes per pixel */
|
|
|
|
{
|
|
|
|
fromright = xwdhdr->l_pixmap_depth-1-plane;
|
|
|
|
dest += 2 - fromright/8;
|
|
|
|
outmask = (1 << (fromright % 8));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = tile_start; i <= tile_end; i++)
|
|
|
|
{
|
|
|
|
if (fread (xwddata,xwdhdr->l_bytes_per_line,1,ifp) != 1)
|
|
|
|
{
|
|
|
|
err = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
xwdin = xwddata;
|
|
|
|
|
|
|
|
/* Handle bitmap unit */
|
|
|
|
if (xwdhdr->l_bitmap_unit == 16)
|
|
|
|
{
|
|
|
|
if (xwdhdr->l_bitmap_bit_order != xwdhdr->l_byte_order)
|
|
|
|
{
|
|
|
|
j = xwdhdr->l_bytes_per_line/2;
|
|
|
|
while (j--)
|
|
|
|
{
|
|
|
|
inmask = xwdin[0]; xwdin[0] = xwdin[1]; xwdin[1] = inmask;
|
|
|
|
xwdin += 2;
|
|
|
|
}
|
|
|
|
xwdin = xwddata;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (xwdhdr->l_bitmap_unit == 32)
|
|
|
|
{
|
|
|
|
if (xwdhdr->l_bitmap_bit_order != xwdhdr->l_byte_order)
|
|
|
|
{
|
|
|
|
j = xwdhdr->l_bytes_per_line/4;
|
|
|
|
while (j--)
|
|
|
|
{
|
|
|
|
inmask = xwdin[0]; xwdin[0] = xwdin[3]; xwdin[3] = inmask;
|
|
|
|
inmask = xwdin[1]; xwdin[1] = xwdin[2]; xwdin[2] = inmask;
|
|
|
|
xwdin += 4;
|
|
|
|
}
|
|
|
|
xwdin = xwddata;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g = inmask = 0;
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
|
|
|
if (!inmask)
|
|
|
|
{
|
|
|
|
g = *(xwdin++);
|
|
|
|
if (do_reverse)
|
|
|
|
g = bit_reverse[g];
|
|
|
|
inmask = 0x80;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g & inmask)
|
|
|
|
*dest |= outmask;
|
|
|
|
dest += bytes_per_pixel;
|
|
|
|
|
|
|
|
inmask >>= 1;
|
|
|
|
}
|
|
|
|
}
|
2023-07-11 18:17:42 -04:00
|
|
|
if (err)
|
|
|
|
break;
|
2004-09-07 12:08:03 +00:00
|
|
|
}
|
2023-07-11 18:17:42 -04:00
|
|
|
if (err)
|
|
|
|
break;
|
2004-09-07 12:08:03 +00:00
|
|
|
|
|
|
|
/* For indexed images, the mapping to colors is done by the color table. */
|
|
|
|
/* Otherwise we must do the mapping by ourself. */
|
|
|
|
if (!indexed)
|
|
|
|
{
|
|
|
|
dest = data;
|
|
|
|
for (i = tile_start; i <= tile_end; i++)
|
|
|
|
{
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
|
|
|
pixelval = (*dest << 16) | (*(dest+1) << 8) | *(dest+2);
|
|
|
|
|
|
|
|
if (get_pixelmap (pixelval, &pixel_map, dest, dest+1, dest+2)
|
|
|
|
|| standard_rgb)
|
|
|
|
{
|
|
|
|
dest += 3;
|
|
|
|
}
|
|
|
|
else /* We have to map RGB to 0,...,255 */
|
|
|
|
{
|
|
|
|
*(dest++) = redmap[(pixelval & redmask) >> redshift];
|
|
|
|
*(dest++) = greenmap[(pixelval & greenmask) >> greenshift];
|
|
|
|
*(dest++) = bluemap[(pixelval & bluemask) >> blueshift];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_progress_update ((gdouble) tile_end / (gdouble) height);
|
|
|
|
|
2013-08-31 02:57:02 +02:00
|
|
|
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, tile_start,
|
|
|
|
width, tile_end-tile_start+1), 0,
|
|
|
|
NULL, data, GEGL_AUTO_ROWSTRIDE);
|
2004-09-07 12:08:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
g_free (data);
|
|
|
|
g_free (xwddata);
|
|
|
|
|
2013-08-31 02:57:02 +02:00
|
|
|
g_object_unref (buffer);
|
2004-09-07 12:08:03 +00:00
|
|
|
|
2023-07-11 18:17:42 -04:00
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("EOF encountered on reading"));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return image;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
static gboolean
|
|
|
|
save_index (GOutputStream *output,
|
2019-08-24 16:46:40 +02:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2015-10-18 14:26:25 +02:00
|
|
|
gboolean gray,
|
|
|
|
GError **error)
|
2003-11-06 15:27:05 +00:00
|
|
|
{
|
2015-10-18 14:26:25 +02:00
|
|
|
gint height, width;
|
|
|
|
gint linepad;
|
|
|
|
gint tile_height;
|
|
|
|
gint i, j;
|
2004-09-07 12:08:03 +00:00
|
|
|
gint ncolors, vclass;
|
2023-07-11 18:17:42 -04:00
|
|
|
gsize tmp = 0;
|
2004-09-07 12:08:03 +00:00
|
|
|
guchar *data, *src, *cmap;
|
|
|
|
L_XWDFILEHEADER xwdhdr;
|
|
|
|
L_XWDCOLOR xwdcolmap[256];
|
2013-08-31 02:57:02 +02:00
|
|
|
const Babl *format;
|
|
|
|
GeglBuffer *buffer;
|
2015-10-18 14:26:25 +02:00
|
|
|
gboolean success = TRUE;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
#ifdef XWD_DEBUG
|
2018-08-12 19:21:44 +02:00
|
|
|
g_printf ("save_index ()\n");
|
1997-11-24 22:05:25 +00:00
|
|
|
#endif
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
buffer = gimp_drawable_get_buffer (drawable);
|
2015-10-18 14:26:25 +02:00
|
|
|
width = gegl_buffer_get_width (buffer);
|
|
|
|
height = gegl_buffer_get_height (buffer);
|
|
|
|
tile_height = gimp_tile_height ();
|
2004-09-07 12:08:03 +00:00
|
|
|
|
2013-08-31 02:57:02 +02:00
|
|
|
if (gray)
|
|
|
|
format = babl_format ("Y' u8");
|
|
|
|
else
|
|
|
|
format = gegl_buffer_get_format (buffer);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
/* allocate a buffer for retrieving information from the pixel region */
|
2013-08-31 02:57:02 +02:00
|
|
|
src = data = g_new (guchar,
|
|
|
|
tile_height * width *
|
|
|
|
babl_format_get_bytes_per_pixel (format));
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
linepad = width % 4;
|
2015-10-18 14:26:25 +02:00
|
|
|
if (linepad)
|
|
|
|
linepad = 4 - linepad;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* Fill XWD-color map */
|
2004-09-07 12:08:03 +00:00
|
|
|
if (gray)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
1999-10-14 02:11:52 +00:00
|
|
|
vclass = 0;
|
|
|
|
ncolors = 256;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (j = 0; j < ncolors; j++)
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
|
|
|
xwdcolmap[j].l_pixel = j;
|
|
|
|
xwdcolmap[j].l_red = (j << 8) | j;
|
|
|
|
xwdcolmap[j].l_green = (j << 8) | j;
|
|
|
|
xwdcolmap[j].l_blue = (j << 8) | j;
|
|
|
|
xwdcolmap[j].l_flags = 7;
|
|
|
|
xwdcolmap[j].l_pad = 0;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-10-14 02:11:52 +00:00
|
|
|
vclass = 3;
|
2024-09-23 15:17:04 +02:00
|
|
|
cmap = gimp_palette_get_colormap (gimp_image_get_palette (image), babl_format ("R'G'B' u8"), &ncolors, NULL);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (j = 0; j < ncolors; j++)
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
|
|
|
xwdcolmap[j].l_pixel = j;
|
|
|
|
xwdcolmap[j].l_red = ((*cmap) << 8) | *cmap; cmap++;
|
|
|
|
xwdcolmap[j].l_green = ((*cmap) << 8) | *cmap; cmap++;
|
|
|
|
xwdcolmap[j].l_blue = ((*cmap) << 8) | *cmap; cmap++;
|
|
|
|
xwdcolmap[j].l_flags = 7;
|
|
|
|
xwdcolmap[j].l_pad = 0;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
/* Fill in the XWD header (header_size is evaluated by write_xwd_hdr ()) */
|
2004-09-07 12:08:03 +00:00
|
|
|
xwdhdr.l_header_size = 0;
|
|
|
|
xwdhdr.l_file_version = 7;
|
|
|
|
xwdhdr.l_pixmap_format = 2;
|
|
|
|
xwdhdr.l_pixmap_depth = 8;
|
|
|
|
xwdhdr.l_pixmap_width = width;
|
|
|
|
xwdhdr.l_pixmap_height = height;
|
|
|
|
xwdhdr.l_xoffset = 0;
|
|
|
|
xwdhdr.l_byte_order = 1;
|
|
|
|
xwdhdr.l_bitmap_unit = 32;
|
1997-11-24 22:05:25 +00:00
|
|
|
xwdhdr.l_bitmap_bit_order = 1;
|
2004-09-07 12:08:03 +00:00
|
|
|
xwdhdr.l_bitmap_pad = 32;
|
|
|
|
xwdhdr.l_bits_per_pixel = 8;
|
|
|
|
xwdhdr.l_bytes_per_line = width + linepad;
|
|
|
|
xwdhdr.l_visual_class = vclass;
|
|
|
|
xwdhdr.l_red_mask = 0x000000;
|
|
|
|
xwdhdr.l_green_mask = 0x000000;
|
|
|
|
xwdhdr.l_blue_mask = 0x000000;
|
|
|
|
xwdhdr.l_bits_per_rgb = 8;
|
1997-11-24 22:05:25 +00:00
|
|
|
xwdhdr.l_colormap_entries = ncolors;
|
2004-09-07 12:08:03 +00:00
|
|
|
xwdhdr.l_ncolors = ncolors;
|
|
|
|
xwdhdr.l_window_width = width;
|
|
|
|
xwdhdr.l_window_height = height;
|
|
|
|
xwdhdr.l_window_x = 64;
|
|
|
|
xwdhdr.l_window_y = 64;
|
|
|
|
xwdhdr.l_window_bdrwidth = 0;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
success = (write_xwd_header (output, &xwdhdr, error) &&
|
|
|
|
write_xwd_cols (output, &xwdhdr, xwdcolmap, error));
|
|
|
|
if (! success)
|
|
|
|
goto out;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
for (i = 0; i < height; i++)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
|
|
|
if ((i % tile_height) == 0) /* Get more data */
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
2004-09-07 12:08:03 +00:00
|
|
|
gint scan_lines = (i + tile_height - 1 < height) ? tile_height : (height - i);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2013-08-31 02:57:02 +02:00
|
|
|
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, i, width, scan_lines), 1.0,
|
|
|
|
format, data,
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
src = data;
|
2008-10-20 06:04:39 +00:00
|
|
|
}
|
2004-09-07 12:08:03 +00:00
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
success = g_output_stream_write_all (output, src, width,
|
|
|
|
NULL, NULL, error);
|
|
|
|
if (! success)
|
|
|
|
goto out;
|
2004-09-07 12:08:03 +00:00
|
|
|
|
|
|
|
if (linepad)
|
2015-10-18 14:26:25 +02:00
|
|
|
{
|
|
|
|
success = g_output_stream_write_all (output, &tmp, linepad,
|
|
|
|
NULL, NULL, error);
|
|
|
|
if (! success)
|
|
|
|
goto out;
|
|
|
|
}
|
2004-09-07 12:08:03 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
src += width;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2003-06-13 14:37:00 +00:00
|
|
|
if ((i % 20) == 0)
|
2008-10-20 06:04:39 +00:00
|
|
|
gimp_progress_update ((gdouble) i / (gdouble) height);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
2004-09-07 12:08:03 +00:00
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
out:
|
1997-11-24 22:05:25 +00:00
|
|
|
g_free (data);
|
2013-08-31 02:57:02 +02:00
|
|
|
g_object_unref (buffer);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
return success;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
static gboolean
|
|
|
|
save_rgb (GOutputStream *output,
|
2019-08-24 16:46:40 +02:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2015-10-18 14:26:25 +02:00
|
|
|
GError **error)
|
2003-11-06 15:27:05 +00:00
|
|
|
{
|
2015-10-18 14:26:25 +02:00
|
|
|
gint height, width;
|
|
|
|
gint linepad;
|
|
|
|
gint tile_height;
|
|
|
|
gint i;
|
2023-07-11 18:17:42 -04:00
|
|
|
gsize tmp = 0;
|
2004-09-07 12:08:03 +00:00
|
|
|
guchar *data, *src;
|
|
|
|
L_XWDFILEHEADER xwdhdr;
|
2013-08-31 02:57:02 +02:00
|
|
|
const Babl *format;
|
|
|
|
GeglBuffer *buffer;
|
2015-10-18 14:26:25 +02:00
|
|
|
gboolean success = TRUE;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
#ifdef XWD_DEBUG
|
2018-08-12 19:21:44 +02:00
|
|
|
g_printf ("save_rgb ()\n");
|
1997-11-24 22:05:25 +00:00
|
|
|
#endif
|
|
|
|
|
2019-08-24 16:46:40 +02:00
|
|
|
buffer = gimp_drawable_get_buffer (drawable);
|
2015-10-18 14:26:25 +02:00
|
|
|
width = gegl_buffer_get_width (buffer);
|
|
|
|
height = gegl_buffer_get_height (buffer);
|
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
format = babl_format ("R'G'B' u8");
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* allocate a buffer for retrieving information from the pixel region */
|
2013-08-31 02:57:02 +02:00
|
|
|
src = data = g_new (guchar,
|
|
|
|
tile_height * width *
|
|
|
|
babl_format_get_bytes_per_pixel (format));
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
linepad = (width * 3) % 4;
|
2004-09-07 12:08:03 +00:00
|
|
|
if (linepad)
|
|
|
|
linepad = 4 - linepad;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* Fill in the XWD header (header_size is evaluated by write_xwd_hdr ()) */
|
2004-09-07 12:08:03 +00:00
|
|
|
xwdhdr.l_header_size = 0;
|
|
|
|
xwdhdr.l_file_version = 7;
|
|
|
|
xwdhdr.l_pixmap_format = 2;
|
|
|
|
xwdhdr.l_pixmap_depth = 24;
|
|
|
|
xwdhdr.l_pixmap_width = width;
|
|
|
|
xwdhdr.l_pixmap_height = height;
|
|
|
|
xwdhdr.l_xoffset = 0;
|
|
|
|
xwdhdr.l_byte_order = 1;
|
|
|
|
|
|
|
|
xwdhdr.l_bitmap_unit = 32;
|
1997-11-24 22:05:25 +00:00
|
|
|
xwdhdr.l_bitmap_bit_order = 1;
|
2004-09-07 12:08:03 +00:00
|
|
|
xwdhdr.l_bitmap_pad = 32;
|
|
|
|
xwdhdr.l_bits_per_pixel = 24;
|
|
|
|
|
|
|
|
xwdhdr.l_bytes_per_line = width * 3 + linepad;
|
|
|
|
xwdhdr.l_visual_class = 5;
|
|
|
|
xwdhdr.l_red_mask = 0xff0000;
|
|
|
|
xwdhdr.l_green_mask = 0x00ff00;
|
|
|
|
xwdhdr.l_blue_mask = 0x0000ff;
|
|
|
|
xwdhdr.l_bits_per_rgb = 8;
|
1997-11-24 22:05:25 +00:00
|
|
|
xwdhdr.l_colormap_entries = 0;
|
2004-09-07 12:08:03 +00:00
|
|
|
xwdhdr.l_ncolors = 0;
|
|
|
|
xwdhdr.l_window_width = width;
|
|
|
|
xwdhdr.l_window_height = height;
|
|
|
|
xwdhdr.l_window_x = 64;
|
|
|
|
xwdhdr.l_window_y = 64;
|
|
|
|
xwdhdr.l_window_bdrwidth = 0;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
success = write_xwd_header (output, &xwdhdr, error);
|
|
|
|
if (! success)
|
|
|
|
goto out;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
for (i = 0; i < height; i++)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
|
|
|
if ((i % tile_height) == 0) /* Get more data */
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
2004-09-07 12:08:03 +00:00
|
|
|
gint scan_lines = (i + tile_height - 1 < height) ? tile_height : (height - i);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2013-08-31 02:57:02 +02:00
|
|
|
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, i, width, scan_lines), 1.0,
|
|
|
|
format, data,
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
|
|
|
|
2004-09-07 12:08:03 +00:00
|
|
|
src = data;
|
2008-10-20 06:04:39 +00:00
|
|
|
}
|
2004-09-07 12:08:03 +00:00
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
success = g_output_stream_write_all (output, src, width * 3,
|
|
|
|
NULL, NULL, error);
|
|
|
|
if (! success)
|
|
|
|
goto out;
|
2004-09-07 12:08:03 +00:00
|
|
|
|
|
|
|
if (linepad)
|
2015-10-18 14:26:25 +02:00
|
|
|
{
|
|
|
|
success = g_output_stream_write_all (output, &tmp, linepad,
|
|
|
|
NULL, NULL, error);
|
|
|
|
if (! success)
|
|
|
|
goto out;
|
|
|
|
}
|
2004-09-07 12:08:03 +00:00
|
|
|
|
|
|
|
src += width * 3;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2003-06-13 14:37:00 +00:00
|
|
|
if ((i % 20) == 0)
|
2008-10-20 06:04:39 +00:00
|
|
|
gimp_progress_update ((gdouble) i / (gdouble) height);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
2004-09-07 12:08:03 +00:00
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
out:
|
1997-11-24 22:05:25 +00:00
|
|
|
g_free (data);
|
2013-08-31 02:57:02 +02:00
|
|
|
g_object_unref (buffer);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2015-10-18 14:26:25 +02:00
|
|
|
return success;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|