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
|
|
|
|
* SUN raster reading and writing code Copyright (C) 1996 Peter Kirchgessner
|
1999-11-24 23:58:46 +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
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* This program was written using pages 625-629 of the book
|
|
|
|
* "Encyclopedia of Graphics File Formats", Murray/van Ryper,
|
|
|
|
* O'Reilly & Associates Inc.
|
1999-11-24 23:58:46 +00:00
|
|
|
* Bug reports or suggestions should be e-mailed to peter@kirchgessner.net
|
1997-11-24 22:05:25 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* Event history:
|
|
|
|
* V 1.00, PK, 25-Jul-96: First try
|
|
|
|
* V 1.90, PK, 15-Mar-97: Upgrade to work with GIMP V0.99
|
|
|
|
* V 1.91, PK, 05-Apr-97: Return all arguments, even in case of an error
|
|
|
|
* V 1.92, PK, 18-May-97: Ignore EOF-error on reading image data
|
|
|
|
* V 1.93, PK, 05-Oct-97: Parse rc file
|
|
|
|
* V 1.94, PK, 12-Oct-97: No progress bars for non-interactive mode
|
1997-12-26 07:08:20 +00:00
|
|
|
* V 1.95, nn, 20-Dec-97: Initialize some variable
|
1999-11-24 23:58:46 +00:00
|
|
|
* V 1.96, PK, 21-Nov-99: Internationalization
|
2000-12-21 16:33:49 +00:00
|
|
|
* V 1.97, PK, 20-Dec-00: Recognize extensions .rs and .ras too
|
1997-11-24 22:05:25 +00:00
|
|
|
*/
|
|
|
|
|
1999-06-28 17:54:19 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
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-08 15:23:28 +00:00
|
|
|
|
|
|
|
#include <libgimp/gimp.h>
|
|
|
|
#include <libgimp/gimpui.h>
|
|
|
|
|
1999-11-24 23:58:46 +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 19:39:02 +00:00
|
|
|
#define LOAD_PROC "file-sunras-load"
|
2024-04-13 15:10:25 +00:00
|
|
|
#define EXPORT_PROC "file-sunras-export"
|
2008-08-11 10:06:13 +00:00
|
|
|
#define PLUG_IN_BINARY "file-sunras"
|
2011-04-08 20:31:34 +02:00
|
|
|
#define PLUG_IN_ROLE "gimp-file-sunras"
|
2005-08-15 19:39:02 +00:00
|
|
|
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
typedef int WRITE_FUN(void*,size_t,size_t,FILE*);
|
|
|
|
|
2000-05-01 20:22:55 +00:00
|
|
|
typedef gulong L_CARD32;
|
|
|
|
typedef gushort L_CARD16;
|
|
|
|
typedef guchar L_CARD8;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* Fileheader of SunRaster files */
|
2000-01-25 17:46:56 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
1997-11-24 22:05:25 +00:00
|
|
|
L_CARD32 l_ras_magic; /* Magic Number */
|
|
|
|
L_CARD32 l_ras_width; /* Width */
|
|
|
|
L_CARD32 l_ras_height; /* Height */
|
|
|
|
L_CARD32 l_ras_depth; /* Number of bits per pixel (1,8,24,32) */
|
|
|
|
L_CARD32 l_ras_length; /* Length of image data (but may also be 0) */
|
|
|
|
L_CARD32 l_ras_type; /* Encoding */
|
|
|
|
L_CARD32 l_ras_maptype; /* Type of colormap */
|
|
|
|
L_CARD32 l_ras_maplength;/* Number of bytes for colormap */
|
|
|
|
} L_SUNFILEHEADER;
|
|
|
|
|
|
|
|
/* Sun-raster magic */
|
|
|
|
#define RAS_MAGIC 0x59a66a95
|
|
|
|
|
|
|
|
#define RAS_TYPE_STD 1 /* Standard uncompressed format */
|
|
|
|
#define RAS_TYPE_RLE 2 /* Runlength compression format */
|
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
2000-05-01 20:22:55 +00:00
|
|
|
gint val; /* The value that is to be repeated */
|
|
|
|
gint n; /* How many times it is repeated */
|
1997-11-24 22:05:25 +00:00
|
|
|
} RLEBUF;
|
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
|
|
|
|
typedef struct _Sunras Sunras;
|
|
|
|
typedef struct _SunrasClass SunrasClass;
|
|
|
|
|
|
|
|
struct _Sunras
|
|
|
|
{
|
|
|
|
GimpPlugIn parent_instance;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _SunrasClass
|
|
|
|
{
|
|
|
|
GimpPlugInClass parent_class;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#define SUNRAS_TYPE (sunras_get_type ())
|
2023-10-18 18:29:37 +02:00
|
|
|
#define SUNRAS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SUNRAS_TYPE, Sunras))
|
2019-08-25 15:12:48 +02:00
|
|
|
|
|
|
|
GType sunras_get_type (void) G_GNUC_CONST;
|
|
|
|
|
2023-08-06 02:56:44 +02:00
|
|
|
static GList * sunras_query_procedures (GimpPlugIn *plug_in);
|
|
|
|
static GimpProcedure * sunras_create_procedure (GimpPlugIn *plug_in,
|
|
|
|
const gchar *name);
|
|
|
|
|
|
|
|
static GimpValueArray * sunras_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 * sunras_export (GimpProcedure *procedure,
|
2023-08-06 02:56:44 +02:00
|
|
|
GimpRunMode run_mode,
|
|
|
|
GimpImage *image,
|
|
|
|
GFile *file,
|
|
|
|
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,
|
|
|
|
GObject *config,
|
|
|
|
GError **error);
|
|
|
|
|
|
|
|
static void set_color_table (GimpImage *image,
|
|
|
|
L_SUNFILEHEADER *sunhdr,
|
|
|
|
const guchar *suncolmap);
|
|
|
|
static GimpImage * create_new_image (GFile *file,
|
|
|
|
guint width,
|
|
|
|
guint height,
|
|
|
|
GimpImageBaseType type,
|
|
|
|
GimpLayer **layer,
|
|
|
|
GeglBuffer **buffer);
|
|
|
|
|
|
|
|
static GimpImage * load_sun_d1 (GFile *file,
|
|
|
|
FILE *ifp,
|
|
|
|
L_SUNFILEHEADER *sunhdr,
|
|
|
|
guchar *suncolmap);
|
|
|
|
static GimpImage * load_sun_d8 (GFile *file,
|
|
|
|
FILE *ifp,
|
|
|
|
L_SUNFILEHEADER *sunhdr,
|
|
|
|
guchar *suncolmap);
|
|
|
|
static GimpImage * load_sun_d24 (GFile *file,
|
|
|
|
FILE *ifp,
|
|
|
|
L_SUNFILEHEADER *sunhdr,
|
|
|
|
guchar *suncolmap);
|
|
|
|
static GimpImage * load_sun_d32 (GFile *file,
|
|
|
|
FILE *ifp,
|
|
|
|
L_SUNFILEHEADER *sunhdr,
|
|
|
|
guchar *suncolmap);
|
|
|
|
|
|
|
|
static L_CARD32 read_card32 (FILE *ifp,
|
|
|
|
int *err);
|
|
|
|
|
|
|
|
static void write_card32 (FILE *ofp,
|
|
|
|
L_CARD32 c);
|
|
|
|
|
|
|
|
static void byte2bit (guchar *byteline,
|
|
|
|
int width,
|
|
|
|
guchar *bitline,
|
|
|
|
gboolean invert);
|
|
|
|
|
|
|
|
static void rle_startread (FILE *ifp);
|
|
|
|
static int rle_fread (char *ptr,
|
|
|
|
int sz,
|
|
|
|
int nelem,
|
|
|
|
FILE *ifp);
|
|
|
|
static int rle_fgetc (FILE *ifp);
|
1997-11-24 22:05:25 +00:00
|
|
|
#define rle_getc(fp) ((rlebuf.n > 0) ? (rlebuf.n)--,rlebuf.val : rle_fgetc (fp))
|
|
|
|
|
2023-08-06 02:56:44 +02:00
|
|
|
static void rle_startwrite (FILE *ofp);
|
|
|
|
static int rle_fwrite (char *ptr,
|
|
|
|
int sz,
|
|
|
|
int nelem,
|
|
|
|
FILE *ofp);
|
|
|
|
static int rle_fputc (int val,
|
|
|
|
FILE *ofp);
|
|
|
|
static int rle_putrun (int n,
|
|
|
|
int val,
|
|
|
|
FILE *ofp);
|
|
|
|
static void rle_endwrite (FILE *ofp);
|
1997-11-24 22:05:25 +00:00
|
|
|
#define rle_putc rle_fputc
|
|
|
|
|
2023-08-06 02:56:44 +02:00
|
|
|
static void read_sun_header (FILE *ifp,
|
|
|
|
L_SUNFILEHEADER *sunhdr);
|
|
|
|
static void write_sun_header (FILE *ofp,
|
|
|
|
L_SUNFILEHEADER *sunhdr);
|
|
|
|
static void read_sun_cols (FILE *ifp,
|
|
|
|
L_SUNFILEHEADER *sunhdr,
|
|
|
|
guchar *colormap);
|
|
|
|
static void write_sun_cols (FILE *ofp,
|
|
|
|
L_SUNFILEHEADER *sunhdr,
|
|
|
|
guchar *colormap);
|
|
|
|
|
|
|
|
static gint save_index (FILE *ofp,
|
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
gboolean grey,
|
|
|
|
gint rle);
|
|
|
|
static gint save_rgb (FILE *ofp,
|
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
gint rle);
|
|
|
|
|
|
|
|
static gboolean save_dialog (GimpImage *image,
|
|
|
|
GimpProcedure *procedure,
|
|
|
|
GObject *config);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
/* Portability kludge */
|
2023-08-06 02:56:44 +02:00
|
|
|
static int my_fwrite (void *ptr,
|
|
|
|
int size,
|
|
|
|
int nmemb,
|
|
|
|
FILE *stream);
|
2019-08-25 15:12:48 +02:00
|
|
|
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (Sunras, sunras, GIMP_TYPE_PLUG_IN)
|
|
|
|
|
|
|
|
GIMP_MAIN (SUNRAS_TYPE)
|
2022-05-26 00:59:36 +02:00
|
|
|
DEFINE_STD_SET_I18N
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
static int read_msb_first = 1;
|
|
|
|
static RLEBUF rlebuf;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
static void
|
|
|
|
sunras_class_init (SunrasClass *klass)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2019-08-25 15:12:48 +02:00
|
|
|
GimpPlugInClass *plug_in_class = GIMP_PLUG_IN_CLASS (klass);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
plug_in_class->query_procedures = sunras_query_procedures;
|
|
|
|
plug_in_class->create_procedure = sunras_create_procedure;
|
2022-05-26 00:59:36 +02:00
|
|
|
plug_in_class->set_i18n = STD_SET_I18N;
|
2019-08-25 15:12:48 +02:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
static void
|
|
|
|
sunras_init (Sunras *sunras)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2019-08-25 15:12:48 +02:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
static GList *
|
|
|
|
sunras_query_procedures (GimpPlugIn *plug_in)
|
|
|
|
{
|
|
|
|
GList *list = NULL;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-25 15:12:48 +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));
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
return list;
|
|
|
|
}
|
2014-01-01 22:28:08 +01:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
static GimpProcedure *
|
|
|
|
sunras_create_procedure (GimpPlugIn *plug_in,
|
2019-09-25 23:26:28 +02:00
|
|
|
const gchar *name)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2019-08-25 15:12:48 +02:00
|
|
|
GimpProcedure *procedure = NULL;
|
|
|
|
|
|
|
|
if (! strcmp (name, LOAD_PROC))
|
|
|
|
{
|
2023-08-06 03:21:27 +02:00
|
|
|
procedure = gimp_load_procedure_new (plug_in, name,
|
|
|
|
GIMP_PDB_PROC_TYPE_PLUGIN,
|
|
|
|
sunras_load, NULL, NULL);
|
2019-08-25 15:12:48 +02:00
|
|
|
|
2022-07-04 22:50:53 +02:00
|
|
|
gimp_procedure_set_menu_label (procedure, _("SUN Rasterfile image"));
|
2019-08-25 15:12:48 +02:00
|
|
|
|
|
|
|
gimp_procedure_set_documentation (procedure,
|
|
|
|
"Load file of the SunRaster file format",
|
|
|
|
"Load file of the SunRaster file format",
|
|
|
|
name);
|
|
|
|
gimp_procedure_set_attribution (procedure,
|
|
|
|
"Peter Kirchgessner",
|
|
|
|
"Peter Kirchgessner",
|
|
|
|
"1996");
|
|
|
|
|
|
|
|
gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"image/x-sun-raster");
|
|
|
|
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
|
meson, configure, plug-ins: image/x-sun-raster is a supported MimeTypes.
Also ".sun" is a possible (and common) file name extension for Sun
Raster images, according to various sources and samples I found (these
samples with .sun extension also opened fine in GIMP, so it's not just a
subvariant which we may not handle or something of the sort). This one
is not so important though as we also register magic bytes for detection
(which is the proper way), but it can still be useful, mostly for
exporting (as we will direct to the SunRaster plug-in if someone tried
to export a file with .sun extension, since no other file format uses
this extension AFAICS).
There is no functional change, I just had a look at this plug-in while
handling !428 and realized this format was not present in the MimeType
list (which is used to generate the desktop file, in order to have
proper mime types, not detection based on extension only, unlike
Windows in !428).
2021-04-04 15:44:26 +02:00
|
|
|
"im1,im8,im24,im32,rs,ras,sun");
|
2019-08-25 15:12:48 +02:00
|
|
|
gimp_file_procedure_set_magics (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"0,long,0x59a66a95");
|
|
|
|
}
|
2024-04-13 15:10:25 +00:00
|
|
|
else if (! strcmp (name, EXPORT_PROC))
|
2019-08-25 15:12:48 +02:00
|
|
|
{
|
2024-04-20 03:08:57 +00:00
|
|
|
procedure = gimp_export_procedure_new (plug_in, name,
|
|
|
|
GIMP_PDB_PROC_TYPE_PLUGIN,
|
|
|
|
FALSE, sunras_export, NULL, NULL);
|
2019-08-25 15:12:48 +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, _("SUN Rasterfile image"));
|
2019-08-25 15:12:48 +02:00
|
|
|
|
|
|
|
gimp_procedure_set_documentation (procedure,
|
|
|
|
"Export file in the SunRaster file "
|
|
|
|
"format",
|
|
|
|
"SUNRAS exporting handles all image "
|
|
|
|
"types except those with alpha "
|
|
|
|
"channels.",
|
|
|
|
name);
|
|
|
|
gimp_procedure_set_attribution (procedure,
|
|
|
|
"Peter Kirchgessner",
|
|
|
|
"Peter Kirchgessner",
|
|
|
|
"1996");
|
|
|
|
|
2023-05-20 14:30:41 +00:00
|
|
|
gimp_file_procedure_set_format_name (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
_("SUNRAS"));
|
2019-08-25 15:12:48 +02:00
|
|
|
gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"image/x-sun-raster");
|
|
|
|
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
|
meson, configure, plug-ins: image/x-sun-raster is a supported MimeTypes.
Also ".sun" is a possible (and common) file name extension for Sun
Raster images, according to various sources and samples I found (these
samples with .sun extension also opened fine in GIMP, so it's not just a
subvariant which we may not handle or something of the sort). This one
is not so important though as we also register magic bytes for detection
(which is the proper way), but it can still be useful, mostly for
exporting (as we will direct to the SunRaster plug-in if someone tried
to export a file with .sun extension, since no other file format uses
this extension AFAICS).
There is no functional change, I just had a look at this plug-in while
handling !428 and realized this format was not present in the MimeType
list (which is used to generate the desktop file, in order to have
proper mime types, not detection based on extension only, unlike
Windows in !428).
2021-04-04 15:44:26 +02:00
|
|
|
"im1,im8,im24,im32,rs,ras,sun");
|
2019-08-25 15:12:48 +02:00
|
|
|
|
2024-06-12 16:53:12 +00:00
|
|
|
gimp_procedure_add_int_argument (procedure, "rle",
|
|
|
|
_("Data Formatting"),
|
|
|
|
_("Use standard (0) or Run-Length Encoded (1) output"),
|
|
|
|
0, 1, 1,
|
|
|
|
G_PARAM_READWRITE);
|
2019-08-25 15:12:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return procedure;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
static GimpValueArray *
|
2023-08-06 02:56:44 +02:00
|
|
|
sunras_load (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
|
|
|
GFile *file,
|
|
|
|
GimpMetadata *metadata,
|
|
|
|
GimpMetadataLoadFlags *flags,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
gpointer run_data)
|
2019-08-25 15:12:48 +02:00
|
|
|
{
|
|
|
|
GimpValueArray *return_vals;
|
|
|
|
GimpImage *image;
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
gegl_init (NULL, NULL);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-09-11 21:48:34 +02:00
|
|
|
image = load_image (file, &error);
|
2019-08-25 15:12:48 +02:00
|
|
|
|
|
|
|
if (! image)
|
|
|
|
return gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_EXECUTION_ERROR,
|
|
|
|
error);
|
|
|
|
|
|
|
|
return_vals = gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_SUCCESS,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
GIMP_VALUES_SET_IMAGE (return_vals, 1, image);
|
|
|
|
|
|
|
|
return return_vals;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GimpValueArray *
|
2024-04-13 15:10:25 +00:00
|
|
|
sunras_export (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
|
|
|
GimpImage *image,
|
|
|
|
GFile *file,
|
|
|
|
GimpMetadata *metadata,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
gpointer run_data)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2023-07-21 18:08:00 +02:00
|
|
|
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
|
2024-04-30 04:25:51 +00:00
|
|
|
GimpExportReturn export = GIMP_EXPORT_IGNORE;
|
2024-04-30 13:50:24 +00:00
|
|
|
GList *drawables;
|
2023-07-21 18:08:00 +02:00
|
|
|
GError *error = NULL;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
gegl_init (NULL, NULL);
|
2003-03-25 16:38:19 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
switch (run_mode)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2019-08-25 15:12:48 +02:00
|
|
|
case GIMP_RUN_INTERACTIVE:
|
|
|
|
case GIMP_RUN_WITH_LAST_VALS:
|
2019-09-20 19:39:00 +02:00
|
|
|
gimp_ui_init (PLUG_IN_BINARY);
|
2019-08-25 15:12:48 +02:00
|
|
|
|
2024-04-30 13:50:24 +00:00
|
|
|
export = gimp_export_image (&image, "SUNRAS",
|
2019-08-25 15:12:48 +02:00
|
|
|
GIMP_EXPORT_CAN_HANDLE_RGB |
|
|
|
|
GIMP_EXPORT_CAN_HANDLE_GRAY |
|
|
|
|
GIMP_EXPORT_CAN_HANDLE_INDEXED);
|
|
|
|
break;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
default:
|
|
|
|
break;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
2024-04-30 13:50:24 +00:00
|
|
|
drawables = gimp_image_list_layers (image);
|
2020-04-14 11:46:17 +02:00
|
|
|
|
2019-09-25 23:26:28 +02:00
|
|
|
if (run_mode == GIMP_RUN_INTERACTIVE)
|
|
|
|
{
|
2023-05-20 14:30:41 +00:00
|
|
|
if (! save_dialog (image, procedure, G_OBJECT (config)))
|
2019-08-25 15:12:48 +02:00
|
|
|
status = GIMP_PDB_CANCEL;
|
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
if (status == GIMP_PDB_SUCCESS)
|
|
|
|
{
|
2024-04-30 13:50:24 +00:00
|
|
|
if (! export_image (file, image, drawables->data, G_OBJECT (config),
|
2024-04-13 15:10:25 +00:00
|
|
|
&error))
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
2019-08-25 15:12:48 +02:00
|
|
|
status = GIMP_PDB_EXECUTION_ERROR;
|
2008-10-20 06:04:39 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
|
|
|
|
2024-04-30 13:50:24 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
if (export == GIMP_EXPORT_EXPORT)
|
2024-04-30 13:50:24 +00:00
|
|
|
gimp_image_delete (image);
|
2008-08-18 19:35:55 +00:00
|
|
|
|
2024-04-30 13:50:24 +00:00
|
|
|
g_list_free (drawables);
|
2019-08-25 15:12:48 +02:00
|
|
|
return gimp_procedure_new_return_values (procedure, status, error);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2019-08-25 15:12:48 +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-08-25 15:12:48 +02:00
|
|
|
GimpImage *image;
|
2014-01-01 22:28:08 +01:00
|
|
|
FILE *ifp;
|
|
|
|
L_SUNFILEHEADER sunhdr;
|
|
|
|
guchar *suncolmap = 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 22:58:14 +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:35:55 +00:00
|
|
|
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
|
|
|
|
_("Could not open '%s' for reading: %s"),
|
2019-09-11 21:48:34 +02:00
|
|
|
gimp_file_get_utf8_name (file), g_strerror (errno));
|
2019-08-25 15:12:48 +02:00
|
|
|
return NULL;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
read_msb_first = 1; /* SUN raster is always most significant byte first */
|
|
|
|
|
|
|
|
read_sun_header (ifp, &sunhdr);
|
|
|
|
if (sunhdr.l_ras_magic != RAS_MAGIC)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2008-08-18 19:35:55 +00:00
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("Could not open '%s' as SUN-raster-file"),
|
2019-09-11 21:48:34 +02:00
|
|
|
gimp_file_get_utf8_name (file));
|
2000-01-25 17:46:56 +00:00
|
|
|
fclose (ifp);
|
2019-08-25 15:12:48 +02:00
|
|
|
return NULL;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2016-10-31 01:08:38 +01:00
|
|
|
if (sunhdr.l_ras_type > 5)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2008-08-18 19:35:55 +00:00
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
"%s",
|
|
|
|
_("The type of this SUN-rasterfile is not supported"));
|
1997-11-24 22:05:25 +00:00
|
|
|
fclose (ifp);
|
2019-08-25 15:12:48 +02:00
|
|
|
return NULL;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2016-10-31 01:08:38 +01:00
|
|
|
if (sunhdr.l_ras_maplength > (256 * 3))
|
2007-07-06 09:01:38 +00:00
|
|
|
{
|
2007-08-14 14:15:03 +00:00
|
|
|
g_message ("Map lengths greater than 256 entries are unsupported by GIMP.");
|
|
|
|
gimp_quit ();
|
2007-07-06 09:01:38 +00:00
|
|
|
}
|
|
|
|
|
2013-06-06 23:26:16 +02:00
|
|
|
/* Is there a RGB colormap ? */
|
2000-01-25 17:46:56 +00:00
|
|
|
if ((sunhdr.l_ras_maptype == 1) && (sunhdr.l_ras_maplength > 0))
|
|
|
|
{
|
2000-01-30 13:25:54 +00:00
|
|
|
suncolmap = g_new (guchar, sunhdr.l_ras_maplength);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2000-01-30 13:25:54 +00:00
|
|
|
read_sun_cols (ifp, &sunhdr, suncolmap);
|
1997-11-24 22:05:25 +00:00
|
|
|
#ifdef DEBUG
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2008-10-20 06:04:39 +00:00
|
|
|
int j, ncols;
|
2021-10-01 22:58:14 +02:00
|
|
|
printf ("File %s\n", g_file_peek_path (file));
|
2008-10-20 06:04:39 +00:00
|
|
|
ncols = sunhdr.l_ras_maplength/3;
|
|
|
|
for (j=0; j < ncols; j++)
|
|
|
|
printf ("Entry 0x%08x: 0x%04x, 0x%04x, 0x%04x\n",
|
|
|
|
j,suncolmap[j],suncolmap[j+ncols],suncolmap[j+2*ncols]);
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
2000-01-30 13:25:54 +00:00
|
|
|
#endif
|
|
|
|
if (sunhdr.l_ras_magic != RAS_MAGIC)
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
|
|
|
g_message (_("Could not read color entries from '%s'"),
|
2019-09-11 21:48:34 +02:00
|
|
|
gimp_file_get_utf8_name (file));
|
2008-10-20 06:04:39 +00:00
|
|
|
fclose (ifp);
|
2010-11-09 16:03:47 -02:00
|
|
|
g_free (suncolmap);
|
2019-08-25 15:12:48 +02:00
|
|
|
return NULL;
|
2008-10-20 06:04:39 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
else if (sunhdr.l_ras_maplength > 0)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2000-01-30 13:25:54 +00:00
|
|
|
g_message (_("Type of colormap not supported"));
|
2000-01-25 17:46:56 +00:00
|
|
|
fseek (ifp, (sizeof (L_SUNFILEHEADER)/sizeof (L_CARD32))
|
2008-10-20 06:04:39 +00:00
|
|
|
*4 + sunhdr.l_ras_maplength, SEEK_SET);
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
2003-06-13 14:37:00 +00:00
|
|
|
|
2007-07-04 23:32:15 +00:00
|
|
|
if (sunhdr.l_ras_width <= 0)
|
|
|
|
{
|
|
|
|
g_message (_("'%s':\nNo image width specified"),
|
2019-09-11 21:48:34 +02:00
|
|
|
gimp_file_get_utf8_name (file));
|
2007-07-04 23:32:15 +00:00
|
|
|
fclose (ifp);
|
2019-08-25 15:12:48 +02:00
|
|
|
return NULL;
|
2007-07-04 23:32:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (sunhdr.l_ras_width > GIMP_MAX_IMAGE_SIZE)
|
|
|
|
{
|
|
|
|
g_message (_("'%s':\nImage width is larger than GIMP can handle"),
|
2019-09-11 21:48:34 +02:00
|
|
|
gimp_file_get_utf8_name (file));
|
2007-07-04 23:32:15 +00:00
|
|
|
fclose (ifp);
|
2019-08-25 15:12:48 +02:00
|
|
|
return NULL;
|
2007-07-04 23:32:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (sunhdr.l_ras_height <= 0)
|
|
|
|
{
|
|
|
|
g_message (_("'%s':\nNo image height specified"),
|
2019-09-11 21:48:34 +02:00
|
|
|
gimp_file_get_utf8_name (file));
|
2007-07-04 23:32:15 +00:00
|
|
|
fclose (ifp);
|
2019-08-25 15:12:48 +02:00
|
|
|
return NULL;
|
2007-07-04 23:32:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (sunhdr.l_ras_height > GIMP_MAX_IMAGE_SIZE)
|
|
|
|
{
|
|
|
|
g_message (_("'%s':\nImage height is larger than GIMP can handle"),
|
2019-09-11 21:48:34 +02:00
|
|
|
gimp_file_get_utf8_name (file));
|
2007-07-04 23:32:15 +00:00
|
|
|
fclose (ifp);
|
2019-08-25 15:12:48 +02:00
|
|
|
return NULL;
|
2007-07-04 23:32:15 +00:00
|
|
|
}
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
switch (sunhdr.l_ras_depth)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
1997-11-24 22:05:25 +00:00
|
|
|
case 1: /* bitmap */
|
2019-09-11 21:48:34 +02:00
|
|
|
image = load_sun_d1 (file, ifp, &sunhdr, suncolmap);
|
1997-11-24 22:05:25 +00:00
|
|
|
break;
|
|
|
|
|
2013-06-06 23:26:16 +02:00
|
|
|
case 8: /* 256 colors */
|
2019-09-11 21:48:34 +02:00
|
|
|
image = load_sun_d8 (file, ifp, &sunhdr, suncolmap);
|
1997-11-24 22:05:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 24: /* True color */
|
2019-09-11 21:48:34 +02:00
|
|
|
image = load_sun_d24 (file, ifp, &sunhdr, suncolmap);
|
1997-11-24 22:05:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 32: /* True color with extra byte */
|
2019-09-11 21:48:34 +02:00
|
|
|
image = load_sun_d32 (file, ifp, &sunhdr, suncolmap);
|
1997-11-24 22:05:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2019-08-25 15:12:48 +02:00
|
|
|
image = NULL;
|
2000-01-25 17:46:56 +00:00
|
|
|
break;
|
|
|
|
}
|
2011-04-10 19:05:08 +02:00
|
|
|
gimp_progress_update (1.0);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
fclose (ifp);
|
|
|
|
|
2000-01-30 13:25:54 +00:00
|
|
|
g_free (suncolmap);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
if (! image)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
|
|
|
g_message (_("This image depth is not supported"));
|
2019-08-25 15:12:48 +02:00
|
|
|
return NULL;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
return image;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2008-08-18 19:35:55 +00:00
|
|
|
static gboolean
|
2024-04-13 15:10:25 +00:00
|
|
|
export_image (GFile *file,
|
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GObject *config,
|
|
|
|
GError **error)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
FILE *ofp;
|
|
|
|
GimpImageType drawable_type;
|
2023-03-21 18:54:15 +00:00
|
|
|
gint rle;
|
2014-01-01 22:28:08 +01:00
|
|
|
gboolean retval;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
drawable_type = gimp_drawable_type (drawable);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-09-25 23:26:28 +02:00
|
|
|
g_object_get (config,
|
|
|
|
"rle", &rle,
|
|
|
|
NULL);
|
|
|
|
|
2016-02-16 02:35:43 +01:00
|
|
|
/* Make sure we're not exporting an image with an alpha channel */
|
2019-08-25 15:12:48 +02:00
|
|
|
if (gimp_drawable_has_alpha (drawable))
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2008-08-20 14:00:44 +00:00
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
2016-02-16 02:35:43 +01:00
|
|
|
_("SUNRAS export cannot handle images with alpha channels"));
|
2000-01-25 17:46:56 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
switch (drawable_type)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2000-08-22 01:26:57 +00:00
|
|
|
case GIMP_INDEXED_IMAGE:
|
|
|
|
case GIMP_GRAY_IMAGE:
|
|
|
|
case GIMP_RGB_IMAGE:
|
1997-11-24 22:05:25 +00:00
|
|
|
break;
|
|
|
|
default:
|
2000-01-25 17:46:56 +00:00
|
|
|
g_message (_("Can't operate on unknown image types"));
|
2014-01-01 22:28:08 +01:00
|
|
|
return FALSE;
|
1997-11-24 22:05:25 +00:00
|
|
|
break;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2016-02-16 02:35:43 +01:00
|
|
|
gimp_progress_init_printf (_("Exporting '%s'"),
|
2019-09-11 21:48:34 +02:00
|
|
|
gimp_file_get_utf8_name (file));
|
2014-07-23 16:39:00 +02:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
/* Open the output file. */
|
2021-10-01 22:58:14 +02:00
|
|
|
ofp = g_fopen (g_file_peek_path (file), "wb");
|
2019-09-11 21:48:34 +02:00
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
if (! ofp)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
2008-08-18 19:35:55 +00:00
|
|
|
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
|
|
|
|
_("Could not open '%s' for writing: %s"),
|
2019-09-11 21:48:34 +02:00
|
|
|
gimp_file_get_utf8_name (file), g_strerror (errno));
|
2003-06-13 14:37:00 +00:00
|
|
|
return FALSE;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2000-08-22 01:26:57 +00:00
|
|
|
if (drawable_type == GIMP_INDEXED_IMAGE)
|
2019-08-25 15:12:48 +02:00
|
|
|
{
|
2019-09-25 23:26:28 +02:00
|
|
|
retval = save_index (ofp, image, drawable, FALSE, rle);
|
2019-08-25 15:12:48 +02:00
|
|
|
}
|
2000-08-22 01:26:57 +00:00
|
|
|
else if (drawable_type == GIMP_GRAY_IMAGE)
|
2019-08-25 15:12:48 +02:00
|
|
|
{
|
2019-09-25 23:26:28 +02:00
|
|
|
retval = save_index (ofp, image, drawable, TRUE, rle);
|
2019-08-25 15:12:48 +02:00
|
|
|
}
|
2000-08-22 01:26:57 +00:00
|
|
|
else if (drawable_type == GIMP_RGB_IMAGE)
|
2019-08-25 15:12:48 +02:00
|
|
|
{
|
2019-09-25 23:26:28 +02:00
|
|
|
retval = save_rgb (ofp, image, drawable, rle);
|
2019-08-25 15:12:48 +02:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
else
|
2019-08-25 15:12:48 +02:00
|
|
|
{
|
|
|
|
retval = FALSE;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
fclose (ofp);
|
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
return retval;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
static L_CARD32
|
|
|
|
read_card32 (FILE *ifp,
|
2008-10-20 06:04:39 +00:00
|
|
|
gint *err)
|
2000-01-25 17:46:56 +00:00
|
|
|
{
|
|
|
|
L_CARD32 c;
|
|
|
|
|
|
|
|
if (read_msb_first)
|
|
|
|
{
|
|
|
|
c = (((L_CARD32)(getc (ifp))) << 24);
|
|
|
|
c |= (((L_CARD32)(getc (ifp))) << 16);
|
|
|
|
c |= (((L_CARD32)(getc (ifp))) << 8);
|
|
|
|
c |= ((L_CARD32)(*err = getc (ifp)));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
c = ((L_CARD32)(getc (ifp)));
|
|
|
|
c |= (((L_CARD32)(getc (ifp))) << 8);
|
|
|
|
c |= (((L_CARD32)(getc (ifp))) << 16);
|
|
|
|
c |= (((L_CARD32)(*err = getc (ifp))) << 24);
|
|
|
|
}
|
|
|
|
|
|
|
|
*err = (*err < 0);
|
2014-01-01 22:28:08 +01:00
|
|
|
|
|
|
|
return c;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-06 15:27:05 +00:00
|
|
|
static void
|
1999-10-14 02:11:52 +00:00
|
|
|
write_card32 (FILE *ofp,
|
2008-10-20 06:04:39 +00:00
|
|
|
L_CARD32 c)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2000-01-25 17:46:56 +00:00
|
|
|
putc ((int)((c >> 24) & 0xff), ofp);
|
|
|
|
putc ((int)((c >> 16) & 0xff), ofp);
|
|
|
|
putc ((int)((c >> 8) & 0xff), ofp);
|
|
|
|
putc ((int)((c) & 0xff), ofp);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Convert n bytes of 0/1 to a line of bits */
|
2003-11-06 15:27:05 +00:00
|
|
|
static void
|
2004-11-26 03:52:01 +00:00
|
|
|
byte2bit (guchar *byteline,
|
2008-10-20 06:04:39 +00:00
|
|
|
gint width,
|
|
|
|
guchar *bitline,
|
|
|
|
gboolean invert)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
guchar bitval;
|
2000-01-25 17:46:56 +00:00
|
|
|
guchar rest[8];
|
1997-11-24 22:05:25 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
while (width >= 8)
|
|
|
|
{
|
|
|
|
bitval = 0;
|
|
|
|
if (*(byteline++)) bitval |= 0x80;
|
|
|
|
if (*(byteline++)) bitval |= 0x40;
|
|
|
|
if (*(byteline++)) bitval |= 0x20;
|
|
|
|
if (*(byteline++)) bitval |= 0x10;
|
|
|
|
if (*(byteline++)) bitval |= 0x08;
|
|
|
|
if (*(byteline++)) bitval |= 0x04;
|
|
|
|
if (*(byteline++)) bitval |= 0x02;
|
|
|
|
if (*(byteline++)) bitval |= 0x01;
|
|
|
|
*(bitline++) = invert ? ~bitval : bitval;
|
|
|
|
width -= 8;
|
|
|
|
}
|
|
|
|
if (width > 0)
|
|
|
|
{
|
|
|
|
memset (rest, 0, 8);
|
|
|
|
memcpy (rest, byteline, width);
|
|
|
|
bitval = 0;
|
|
|
|
byteline = rest;
|
|
|
|
if (*(byteline++)) bitval |= 0x80;
|
|
|
|
if (*(byteline++)) bitval |= 0x40;
|
|
|
|
if (*(byteline++)) bitval |= 0x20;
|
|
|
|
if (*(byteline++)) bitval |= 0x10;
|
|
|
|
if (*(byteline++)) bitval |= 0x08;
|
|
|
|
if (*(byteline++)) bitval |= 0x04;
|
|
|
|
if (*(byteline++)) bitval |= 0x02;
|
|
|
|
*bitline = invert ? ~bitval : bitval;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Start reading Runlength Encoded Data */
|
2003-11-06 15:27:05 +00:00
|
|
|
static void
|
1999-10-14 02:11:52 +00:00
|
|
|
rle_startread (FILE *ifp)
|
2014-01-01 22:28:08 +01:00
|
|
|
{
|
|
|
|
/* Clear RLE-buffer */
|
1997-11-24 22:05:25 +00:00
|
|
|
rlebuf.val = rlebuf.n = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Read uncompressed elements from RLE-stream */
|
2000-01-25 17:46:56 +00:00
|
|
|
static gint
|
|
|
|
rle_fread (gchar *ptr,
|
2008-10-20 06:04:39 +00:00
|
|
|
gint sz,
|
|
|
|
gint nelem,
|
|
|
|
FILE *ifp)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
|
|
|
int elem_read, cnt, val, err = 0;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (elem_read = 0; elem_read < nelem; elem_read++)
|
|
|
|
{
|
|
|
|
for (cnt = 0; cnt < sz; cnt++)
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
|
|
|
val = rle_getc (ifp);
|
2014-01-01 22:28:08 +01:00
|
|
|
|
|
|
|
if (val < 0)
|
|
|
|
{
|
|
|
|
err = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-10-20 06:04:39 +00:00
|
|
|
*(ptr++) = (char)val;
|
|
|
|
}
|
2014-01-01 22:28:08 +01:00
|
|
|
|
|
|
|
if (err)
|
|
|
|
break;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2014-01-01 22:28:08 +01:00
|
|
|
|
|
|
|
return elem_read;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Get one byte of uncompressed data from RLE-stream */
|
2000-01-25 17:46:56 +00:00
|
|
|
static gint
|
1999-10-14 02:11:52 +00:00
|
|
|
rle_fgetc (FILE *ifp)
|
|
|
|
{
|
|
|
|
int flag, runcnt, runval;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (rlebuf.n > 0) /* Something in the buffer ? */
|
|
|
|
{
|
|
|
|
(rlebuf.n)--;
|
2014-01-01 22:28:08 +01:00
|
|
|
return rlebuf.val;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Nothing in the buffer. We have to read something */
|
2014-01-01 22:28:08 +01:00
|
|
|
if ((flag = getc (ifp)) < 0) return -1;
|
|
|
|
if (flag != 0x0080) return flag; /* Single byte run ? */
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
if ((runcnt = getc (ifp)) < 0) return -1;
|
|
|
|
if (runcnt == 0) return 0x0080; /* Single 0x80 ? */
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* The run */
|
2014-01-01 22:28:08 +01:00
|
|
|
if ((runval = getc (ifp)) < 0) return -1;
|
1999-10-14 02:11:52 +00:00
|
|
|
rlebuf.n = runcnt;
|
|
|
|
rlebuf.val = runval;
|
2014-01-01 22:28:08 +01:00
|
|
|
|
|
|
|
return runval;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Start writing Runlength Encoded Data */
|
2003-11-06 15:27:05 +00:00
|
|
|
static void
|
1999-10-14 02:11:52 +00:00
|
|
|
rle_startwrite (FILE *ofp)
|
2014-01-01 22:28:08 +01:00
|
|
|
{
|
|
|
|
/* Clear RLE-buffer */
|
1997-11-24 22:05:25 +00:00
|
|
|
rlebuf.val = rlebuf.n = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Write uncompressed elements to RLE-stream */
|
2000-01-25 17:46:56 +00:00
|
|
|
static gint
|
|
|
|
rle_fwrite (gchar *ptr,
|
2008-10-20 06:04:39 +00:00
|
|
|
gint sz,
|
|
|
|
gint nelem,
|
|
|
|
FILE *ofp)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
int elem_write, cnt, val, err = 0;
|
2000-01-25 17:46:56 +00:00
|
|
|
guchar *pixels = (unsigned char *)ptr;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (elem_write = 0; elem_write < nelem; elem_write++)
|
|
|
|
{
|
|
|
|
for (cnt = 0; cnt < sz; cnt++)
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
|
|
|
val = rle_fputc (*(pixels++), ofp);
|
2014-01-01 22:28:08 +01:00
|
|
|
if (val < 0)
|
|
|
|
{
|
|
|
|
err = 1;
|
|
|
|
break;
|
|
|
|
}
|
2008-10-20 06:04:39 +00:00
|
|
|
}
|
2014-01-01 22:28:08 +01:00
|
|
|
|
|
|
|
if (err)
|
|
|
|
break;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2014-01-01 22:28:08 +01:00
|
|
|
|
|
|
|
return elem_write;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Write uncompressed character to RLE-stream */
|
2000-01-25 17:46:56 +00:00
|
|
|
static gint
|
|
|
|
rle_fputc (gint val,
|
2008-10-20 06:04:39 +00:00
|
|
|
FILE *ofp)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
|
|
|
int retval;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (rlebuf.n == 0) /* Nothing in the buffer ? Save the value */
|
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
rlebuf.n = 1;
|
|
|
|
rlebuf.val = val;
|
|
|
|
|
|
|
|
return val;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Something in the buffer */
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (rlebuf.val == val) /* Same value in the buffer ? */
|
|
|
|
{
|
|
|
|
(rlebuf.n)++;
|
|
|
|
if (rlebuf.n == 257) /* Can not be encoded in a single run ? */
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
|
|
|
retval = rle_putrun (256, rlebuf.val, ofp);
|
2014-01-01 22:28:08 +01:00
|
|
|
if (retval < 0)
|
|
|
|
return retval;
|
|
|
|
|
2008-10-20 06:04:39 +00:00
|
|
|
rlebuf.n -= 256;
|
|
|
|
}
|
2014-01-01 22:28:08 +01:00
|
|
|
|
|
|
|
return val;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Something different in the buffer ? Write out the run */
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
retval = rle_putrun (rlebuf.n, rlebuf.val, ofp);
|
2014-01-01 22:28:08 +01:00
|
|
|
if (retval < 0)
|
|
|
|
return retval;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Save the new value */
|
2014-01-01 22:28:08 +01:00
|
|
|
rlebuf.n = 1;
|
|
|
|
rlebuf.val = val;
|
|
|
|
|
|
|
|
return val;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Write out a run with 0 < n < 257 */
|
2003-11-06 15:27:05 +00:00
|
|
|
static gint
|
2000-01-25 17:46:56 +00:00
|
|
|
rle_putrun (gint n,
|
2008-10-20 06:04:39 +00:00
|
|
|
gint val,
|
|
|
|
FILE *ofp)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
|
|
|
int retval, flag = 0x80;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Useful to write a 3 byte run ? */
|
|
|
|
if ((n > 2) || ((n == 2) && (val == flag)))
|
|
|
|
{
|
|
|
|
putc (flag, ofp);
|
|
|
|
putc (n-1, ofp);
|
|
|
|
retval = putc (val, ofp);
|
|
|
|
}
|
|
|
|
else if (n == 2) /* Write two single runs (could not be value 0x80) */
|
|
|
|
{
|
|
|
|
putc (val, ofp);
|
|
|
|
retval = putc (val, ofp);
|
|
|
|
}
|
|
|
|
else /* Write a single run */
|
|
|
|
{
|
|
|
|
if (val == flag)
|
2008-10-20 06:04:39 +00:00
|
|
|
retval = putc (flag, ofp), putc (0x00, ofp);
|
1999-10-14 02:11:52 +00:00
|
|
|
else
|
2008-10-20 06:04:39 +00:00
|
|
|
retval = putc (val, ofp);
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
return (retval < 0) ? retval : val;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* End writing Runlength Encoded Data */
|
2003-11-06 15:27:05 +00:00
|
|
|
static void
|
|
|
|
rle_endwrite (FILE *ofp)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
1999-10-14 02:11:52 +00:00
|
|
|
if (rlebuf.n > 0)
|
|
|
|
{
|
|
|
|
rle_putrun (rlebuf.n, rlebuf.val, ofp);
|
|
|
|
rlebuf.val = rlebuf.n = 0; /* Clear RLE-buffer */
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
1999-10-14 02:11:52 +00:00
|
|
|
read_sun_header (FILE *ifp,
|
1997-11-24 22:05:25 +00:00
|
|
|
L_SUNFILEHEADER *sunhdr)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
int j, err;
|
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
|
|
|
cp = (L_CARD32 *)sunhdr;
|
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 */
|
2014-01-01 22:28:08 +01:00
|
|
|
for (j = 0; j < sizeof (L_SUNFILEHEADER) / sizeof(sunhdr->l_ras_magic); j++)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
|
|
|
*(cp++) = read_card32 (ifp, &err);
|
2014-01-01 22:28:08 +01:00
|
|
|
if (err)
|
|
|
|
break;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
if (err)
|
|
|
|
sunhdr->l_ras_magic = 0; /* Not a valid SUN-raster file */
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Write out a SUN-fileheader */
|
|
|
|
|
|
|
|
static void
|
1999-10-14 02:11:52 +00:00
|
|
|
write_sun_header (FILE *ofp,
|
1997-11-24 22:05:25 +00:00
|
|
|
L_SUNFILEHEADER *sunhdr)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
int j, hdr_entries;
|
1999-10-14 02:11:52 +00:00
|
|
|
L_CARD32 *cp;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
hdr_entries = sizeof (L_SUNFILEHEADER) / sizeof(sunhdr->l_ras_magic);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
cp = (L_CARD32 *)sunhdr;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Write out all 32-bit values of the header and check for byte order */
|
2011-10-06 08:49:21 +05:30
|
|
|
for (j = 0; j < hdr_entries; j++)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
|
|
|
write_card32 (ofp, *(cp++));
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-06 23:26:16 +02:00
|
|
|
/* Read the sun colormap */
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
static void
|
1999-10-14 02:11:52 +00:00
|
|
|
read_sun_cols (FILE *ifp,
|
1997-11-24 22:05:25 +00:00
|
|
|
L_SUNFILEHEADER *sunhdr,
|
2000-01-25 17:46:56 +00:00
|
|
|
guchar *colormap)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
|
|
|
int ncols, err = 0;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Read in SUN-raster Colormap */
|
|
|
|
ncols = sunhdr->l_ras_maplength / 3;
|
|
|
|
if (ncols <= 0)
|
|
|
|
err = 1;
|
|
|
|
else
|
|
|
|
err = (fread (colormap, 3, ncols, ifp) != ncols);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
if (err)
|
|
|
|
sunhdr->l_ras_magic = 0; /* Not a valid SUN-raster file */
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-06 23:26:16 +02:00
|
|
|
/* Write a sun colormap */
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
static void
|
1999-10-14 02:11:52 +00:00
|
|
|
write_sun_cols (FILE *ofp,
|
1997-11-24 22:05:25 +00:00
|
|
|
L_SUNFILEHEADER *sunhdr,
|
2000-01-25 17:46:56 +00:00
|
|
|
guchar *colormap)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
|
|
|
int ncols;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
ncols = sunhdr->l_ras_maplength / 3;
|
|
|
|
fwrite (colormap, 3, ncols, ofp);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-06 23:26:16 +02:00
|
|
|
/* Set a GIMP colortable using the sun colormap */
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
static void
|
2019-08-25 15:12:48 +02:00
|
|
|
set_color_table (GimpImage *image,
|
2008-10-20 06:04:39 +00:00
|
|
|
L_SUNFILEHEADER *sunhdr,
|
|
|
|
const guchar *suncolmap)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2007-04-27 11:50:00 +00:00
|
|
|
guchar ColorMap[256 * 3];
|
|
|
|
gint ncols, j;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
ncols = sunhdr->l_ras_maplength / 3;
|
2007-04-27 11:50:00 +00:00
|
|
|
if (ncols <= 0)
|
|
|
|
return;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2007-04-27 11:50:00 +00:00
|
|
|
for (j = 0; j < MIN (ncols, 256); j++)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2007-04-27 11:50:00 +00:00
|
|
|
ColorMap[j * 3 + 0] = suncolmap[j];
|
|
|
|
ColorMap[j * 3 + 1] = suncolmap[j + ncols];
|
|
|
|
ColorMap[j * 3 + 2] = suncolmap[j + 2 * ncols];
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
#ifdef DEBUG
|
1999-10-14 02:11:52 +00:00
|
|
|
printf ("Set GIMP colortable:\n");
|
|
|
|
for (j = 0; j < ncols; j++)
|
|
|
|
printf ("%3d: 0x%02x 0x%02x 0x%02x\n", j,
|
2008-10-20 06:04:39 +00:00
|
|
|
ColorMap[j*3], ColorMap[j*3+1], ColorMap[j*3+2]);
|
1997-11-24 22:05:25 +00:00
|
|
|
#endif
|
2007-04-27 11:50:00 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
gimp_image_set_colormap (image, ColorMap, ncols);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-08-25 15:12:48 +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,
|
|
|
|
GimpImageBaseType type,
|
2019-08-25 15:12:48 +02:00
|
|
|
GimpLayer **layer,
|
2014-01-01 22:28:08 +01:00
|
|
|
GeglBuffer **buffer)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2019-08-25 15:12:48 +02:00
|
|
|
GimpImage *image;
|
|
|
|
GimpImageType gdtype;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2000-08-22 01:26:57 +00:00
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case GIMP_RGB:
|
|
|
|
gdtype = GIMP_RGB_IMAGE;
|
|
|
|
break;
|
2003-11-06 15:27:05 +00:00
|
|
|
case GIMP_GRAY:
|
2000-08-22 01:26:57 +00:00
|
|
|
gdtype = GIMP_GRAY_IMAGE;
|
|
|
|
break;
|
|
|
|
case GIMP_INDEXED:
|
|
|
|
gdtype = GIMP_INDEXED_IMAGE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_warning ("Unsupported image type");
|
2019-08-25 15:12:48 +02:00
|
|
|
return NULL;
|
2000-08-22 01:26:57 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
image = gimp_image_new (width, height, type);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-08-25 15:12:48 +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);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
*buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (*layer));
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
return image;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Load SUN-raster-file with depth 1 */
|
2019-08-25 15:12:48 +02:00
|
|
|
static GimpImage *
|
2019-09-11 21:48:34 +02:00
|
|
|
load_sun_d1 (GFile *file,
|
1999-10-14 02:11:52 +00:00
|
|
|
FILE *ifp,
|
1997-11-24 22:05:25 +00:00
|
|
|
L_SUNFILEHEADER *sunhdr,
|
2000-01-25 17:46:56 +00:00
|
|
|
guchar *suncolmap)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
int pix8;
|
|
|
|
int width, height, linepad, scan_lines, tile_height;
|
|
|
|
int i, j;
|
|
|
|
guchar *dest, *data;
|
2019-08-25 15:12:48 +02:00
|
|
|
GimpImage *image;
|
|
|
|
GimpLayer *layer;
|
2014-01-01 22:28:08 +01:00
|
|
|
GeglBuffer *buffer;
|
|
|
|
guchar bit2byte[256 * 8];
|
|
|
|
L_SUNFILEHEADER sun_bwhdr;
|
|
|
|
guchar sun_bwcolmap[6] = { 255,0,255,0,255,0 };
|
|
|
|
int err = 0;
|
|
|
|
gboolean rle = (sunhdr->l_ras_type == RAS_TYPE_RLE);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
width = sunhdr->l_ras_width;
|
|
|
|
height = sunhdr->l_ras_height;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-09-11 21:48:34 +02:00
|
|
|
image = create_new_image (file, width, height, GIMP_INDEXED,
|
2019-08-25 15:12:48 +02:00
|
|
|
&layer, &buffer);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
data = g_malloc (tile_height * width);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2013-06-06 23:26:16 +02:00
|
|
|
if (suncolmap != NULL) /* Set up the specified color map */
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2019-08-25 15:12:48 +02:00
|
|
|
set_color_table (image, sunhdr, suncolmap);
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2013-06-06 23:26:16 +02:00
|
|
|
else /* No colormap available. Set up a dummy b/w-colormap */
|
|
|
|
{ /* Copy the original header and simulate b/w-colormap */
|
1999-10-14 02:11:52 +00:00
|
|
|
memcpy ((char *)&sun_bwhdr,(char *)sunhdr,sizeof (L_SUNFILEHEADER));
|
|
|
|
sun_bwhdr.l_ras_maptype = 2;
|
|
|
|
sun_bwhdr.l_ras_maplength = 6;
|
2019-08-25 15:12:48 +02:00
|
|
|
set_color_table (image, &sun_bwhdr, sun_bwcolmap);
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* Get an array for mapping 8 bits in a byte to 8 bytes */
|
|
|
|
dest = bit2byte;
|
|
|
|
for (j = 0; j < 256; j++)
|
|
|
|
for (i = 7; i >= 0; i--)
|
|
|
|
*(dest++) = ((j & (1 << i)) != 0);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
linepad = (((sunhdr->l_ras_width+7)/8) % 2); /* Check for 16bit align */
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
if (rle)
|
|
|
|
rle_startread (ifp);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
dest = data;
|
|
|
|
scan_lines = 0;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
|
|
|
j = width;
|
|
|
|
while (j >= 8)
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
|
|
|
pix8 = rle ? rle_getc (ifp) : getc (ifp);
|
|
|
|
if (pix8 < 0) { err = 1; pix8 = 0; }
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2008-10-20 06:04:39 +00:00
|
|
|
memcpy (dest, bit2byte + pix8*8, 8);
|
|
|
|
dest += 8;
|
|
|
|
j -= 8;
|
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (j > 0)
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
|
|
|
pix8 = rle ? rle_getc (ifp) : getc (ifp);
|
|
|
|
if (pix8 < 0) { err = 1; pix8 = 0; }
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2008-10-20 06:04:39 +00:00
|
|
|
memcpy (dest, bit2byte + pix8*8, j);
|
|
|
|
dest += j;
|
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (linepad)
|
2008-10-20 06:04:39 +00:00
|
|
|
err |= ((rle ? rle_getc (ifp) : getc (ifp)) < 0);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
scan_lines++;
|
2000-01-25 17:46:56 +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 ((double)(i+1) / (double)height);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if ((scan_lines == tile_height) || ((i+1) == height))
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, i - scan_lines + 1,
|
|
|
|
width, scan_lines), 0,
|
|
|
|
NULL, data, GEGL_AUTO_ROWSTRIDE);
|
2008-10-20 06:04:39 +00:00
|
|
|
scan_lines = 0;
|
|
|
|
dest = data;
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
g_free (data);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (err)
|
2000-01-25 17:46:56 +00:00
|
|
|
g_message (_("EOF encountered on reading"));
|
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
g_object_unref (buffer);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
return image;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Load SUN-raster-file with depth 8 */
|
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
static GimpImage *
|
2019-09-11 21:48:34 +02:00
|
|
|
load_sun_d8 (GFile *file,
|
1999-10-14 02:11:52 +00:00
|
|
|
FILE *ifp,
|
1997-11-24 22:05:25 +00:00
|
|
|
L_SUNFILEHEADER *sunhdr,
|
2000-01-25 17:46:56 +00:00
|
|
|
guchar *suncolmap)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
int width, height, linepad, i, j;
|
|
|
|
gboolean grayscale;
|
|
|
|
gint ncols;
|
|
|
|
int scan_lines, tile_height;
|
|
|
|
guchar *dest, *data;
|
2019-08-25 15:12:48 +02:00
|
|
|
GimpImage *image;
|
|
|
|
GimpLayer *layer;
|
2014-01-01 22:28:08 +01:00
|
|
|
GeglBuffer *buffer;
|
|
|
|
int err = 0;
|
|
|
|
gboolean rle = (sunhdr->l_ras_type == RAS_TYPE_RLE);
|
|
|
|
|
|
|
|
width = sunhdr->l_ras_width;
|
1999-10-14 02:11:52 +00:00
|
|
|
height = sunhdr->l_ras_height;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2013-06-06 23:26:16 +02:00
|
|
|
/* This could also be a grayscale image. Check it */
|
1999-10-14 02:11:52 +00:00
|
|
|
ncols = sunhdr->l_ras_maplength / 3;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
grayscale = TRUE; /* Also grayscale if no colormap present */
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if ((ncols > 0) && (suncolmap != NULL))
|
|
|
|
{
|
|
|
|
for (j = 0; j < ncols; j++)
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
if ((suncolmap[j] != j) ||
|
|
|
|
(suncolmap[j + ncols] != j) ||
|
|
|
|
(suncolmap[j + 2 * ncols] != j))
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
grayscale = FALSE;
|
2008-10-20 06:04:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-09-11 21:48:34 +02:00
|
|
|
image = create_new_image (file, width, height,
|
2019-08-25 15:12:48 +02:00
|
|
|
grayscale ? GIMP_GRAY : GIMP_INDEXED,
|
|
|
|
&layer, &buffer);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
data = g_malloc (tile_height * width);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2013-06-06 23:26:16 +02:00
|
|
|
if (!grayscale)
|
2019-08-25 15:12:48 +02:00
|
|
|
set_color_table (image, sunhdr, suncolmap);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
linepad = (sunhdr->l_ras_width % 2);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
if (rle)
|
|
|
|
rle_startread (ifp); /* Initialize RLE-buffer */
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
dest = data;
|
|
|
|
scan_lines = 0;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
|
|
|
memset ((char *)dest, 0, width);
|
|
|
|
err |= ((rle ? rle_fread ((char *)dest, 1, width, ifp)
|
1997-11-24 22:05:25 +00:00
|
|
|
: fread ((char *)dest, 1, width, ifp)) != width);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (linepad)
|
2008-10-20 06:04:39 +00:00
|
|
|
err |= ((rle ? rle_getc (ifp) : getc (ifp)) < 0);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
dest += width;
|
|
|
|
scan_lines++;
|
2000-01-25 17:46:56 +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 ((double)(i+1) / (double)height);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if ((scan_lines == tile_height) || ((i+1) == height))
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, i - scan_lines + 1,
|
|
|
|
width, scan_lines), 0,
|
|
|
|
NULL, data, GEGL_AUTO_ROWSTRIDE);
|
2008-10-20 06:04:39 +00:00
|
|
|
scan_lines = 0;
|
|
|
|
dest = data;
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
g_free (data);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (err)
|
2000-01-25 17:46:56 +00:00
|
|
|
g_message (_("EOF encountered on reading"));
|
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
g_object_unref (buffer);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
return image;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Load SUN-raster-file with depth 24 */
|
2019-08-25 15:12:48 +02:00
|
|
|
static GimpImage *
|
2019-09-11 21:48:34 +02:00
|
|
|
load_sun_d24 (GFile *file,
|
1999-10-14 02:11:52 +00:00
|
|
|
FILE *ifp,
|
|
|
|
L_SUNFILEHEADER *sunhdr,
|
2000-01-25 17:46:56 +00:00
|
|
|
guchar *suncolmap)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
guchar *dest, blue;
|
|
|
|
guchar *data;
|
|
|
|
int width, height, linepad, tile_height, scan_lines;
|
|
|
|
int i, j;
|
2019-08-25 15:12:48 +02:00
|
|
|
GimpImage *image;
|
|
|
|
GimpLayer *layer;
|
2014-01-01 22:28:08 +01:00
|
|
|
GeglBuffer *buffer;
|
|
|
|
int err = 0;
|
|
|
|
gboolean rle = (sunhdr->l_ras_type == RAS_TYPE_RLE);
|
|
|
|
|
|
|
|
width = sunhdr->l_ras_width;
|
1999-10-14 02:11:52 +00:00
|
|
|
height = sunhdr->l_ras_height;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-09-11 21:48:34 +02:00
|
|
|
image = create_new_image (file, width, height, GIMP_RGB,
|
2019-08-25 15:12:48 +02:00
|
|
|
&layer, &buffer);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
data = g_malloc (tile_height * width * 3);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
linepad = ((sunhdr->l_ras_width*3) % 2);
|
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
if (rle)
|
|
|
|
rle_startread (ifp); /* Initialize RLE-buffer */
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
dest = data;
|
|
|
|
scan_lines = 0;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
|
|
|
memset ((char *)dest, 0, 3*width);
|
|
|
|
err |= ((rle ? rle_fread ((char *)dest, 3, width, ifp)
|
1997-11-24 22:05:25 +00:00
|
|
|
: fread ((char *)dest, 3, width, ifp)) != width);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (linepad)
|
2008-10-20 06:04:39 +00:00
|
|
|
err |= ((rle ? rle_getc (ifp) : getc (ifp)) < 0);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (sunhdr->l_ras_type == 3) /* RGB-format ? That is what GIMP wants */
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
dest += width * 3;
|
2008-10-20 06:04:39 +00:00
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
else /* We have BGR format. Correct it */
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
|
|
|
blue = *dest;
|
|
|
|
*dest = *(dest+2);
|
|
|
|
*(dest+2) = blue;
|
|
|
|
dest += 3;
|
|
|
|
}
|
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
scan_lines++;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2003-06-13 14:37:00 +00:00
|
|
|
if ((i % 20) == 0)
|
2014-01-01 22:28:08 +01:00
|
|
|
gimp_progress_update ((double)(i + 1) / (double)height);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
if ((scan_lines == tile_height) || ((i + 1) == height))
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, i - scan_lines + 1,
|
|
|
|
width, scan_lines), 0,
|
|
|
|
NULL, data, GEGL_AUTO_ROWSTRIDE);
|
2008-10-20 06:04:39 +00:00
|
|
|
scan_lines = 0;
|
|
|
|
dest = data;
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
g_free (data);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (err)
|
2000-01-25 17:46:56 +00:00
|
|
|
g_message (_("EOF encountered on reading"));
|
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
g_object_unref (buffer);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
return image;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Load SUN-raster-file with depth 32 */
|
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
static GimpImage *
|
2019-09-11 21:48:34 +02:00
|
|
|
load_sun_d32 (GFile *file,
|
1999-10-14 02:11:52 +00:00
|
|
|
FILE *ifp,
|
1997-11-24 22:05:25 +00:00
|
|
|
L_SUNFILEHEADER *sunhdr,
|
2000-01-25 17:46:56 +00:00
|
|
|
guchar *suncolmap)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
guchar *dest, blue;
|
|
|
|
guchar *data;
|
|
|
|
int width, height, tile_height, scan_lines;
|
|
|
|
int i, j;
|
2019-08-25 15:12:48 +02:00
|
|
|
GimpImage *image;
|
|
|
|
GimpLayer *layer;
|
2014-01-01 22:28:08 +01:00
|
|
|
GeglBuffer *buffer;
|
|
|
|
int err = 0;
|
|
|
|
int cerr;
|
|
|
|
gboolean rle = (sunhdr->l_ras_type == RAS_TYPE_RLE);
|
|
|
|
|
|
|
|
width = sunhdr->l_ras_width;
|
1999-10-14 02:11:52 +00:00
|
|
|
height = sunhdr->l_ras_height;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
/* initialize */
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
cerr = 0;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-09-11 21:48:34 +02:00
|
|
|
image = create_new_image (file, width, height, GIMP_RGB,
|
2019-08-25 15:12:48 +02:00
|
|
|
&layer, &buffer);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
data = g_malloc (tile_height * width * 3);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
if (rle)
|
|
|
|
rle_startread (ifp); /* Initialize RLE-buffer */
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
dest = data;
|
|
|
|
scan_lines = 0;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
|
|
|
if (rle)
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
|
|
|
rle_getc (ifp); /* Skip unused byte */
|
|
|
|
*(dest++) = rle_getc (ifp);
|
|
|
|
*(dest++) = rle_getc (ifp);
|
|
|
|
*(dest++) = (cerr = (rle_getc (ifp)));
|
|
|
|
}
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
else
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
|
|
|
getc (ifp); /* Skip unused byte */
|
|
|
|
*(dest++) = getc (ifp);
|
|
|
|
*(dest++) = getc (ifp);
|
|
|
|
*(dest++) = (cerr = (getc (ifp)));
|
|
|
|
}
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
err |= (cerr < 0);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (sunhdr->l_ras_type != 3) /* BGR format ? Correct it */
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
|
|
|
dest -= 3;
|
|
|
|
blue = *dest;
|
|
|
|
*dest = *(dest+2);
|
|
|
|
*(dest+2) = blue;
|
|
|
|
}
|
|
|
|
dest += width*3;
|
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
scan_lines++;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2003-06-13 14:37:00 +00:00
|
|
|
if ((i % 20) == 0)
|
2014-01-01 22:28:08 +01:00
|
|
|
gimp_progress_update ((double)(i + 1) / (double)height);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
if ((scan_lines == tile_height) || ((i + 1) == height))
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, i - scan_lines + 1,
|
|
|
|
width, scan_lines), 0,
|
|
|
|
NULL, data, GEGL_AUTO_ROWSTRIDE);
|
2008-10-20 06:04:39 +00:00
|
|
|
scan_lines = 0;
|
|
|
|
dest = data;
|
|
|
|
}
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
g_free (data);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
if (err)
|
2000-01-25 17:46:56 +00:00
|
|
|
g_message (_("EOF encountered on reading"));
|
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
g_object_unref (buffer);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
return image;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
static gboolean
|
|
|
|
save_index (FILE *ofp,
|
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
gboolean grey,
|
2023-03-21 18:54:15 +00:00
|
|
|
gint rle)
|
2003-11-06 15:27:05 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
int height, width, linepad, i, j;
|
|
|
|
int ncols, bw, is_bw, is_wb, bpl;
|
|
|
|
int tile_height;
|
|
|
|
long tmp = 0;
|
|
|
|
guchar *cmap, *bwline = NULL;
|
|
|
|
guchar *data, *src;
|
1997-11-24 22:05:25 +00:00
|
|
|
L_SUNFILEHEADER sunhdr;
|
2014-01-01 22:28:08 +01:00
|
|
|
guchar sun_colormap[256*3];
|
|
|
|
static guchar sun_bwmap[6] = { 0, 255, 0, 255, 0, 255 };
|
|
|
|
static guchar sun_wbmap[6] = { 255, 0, 255, 0, 255, 0 };
|
|
|
|
unsigned char *suncolmap = sun_colormap;
|
|
|
|
GeglBuffer *buffer;
|
|
|
|
const Babl *format;
|
|
|
|
WRITE_FUN *write_fun;
|
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
buffer = gimp_drawable_get_buffer (drawable);
|
2014-01-01 22:28:08 +01:00
|
|
|
|
|
|
|
width = gegl_buffer_get_width (buffer);
|
|
|
|
height = gegl_buffer_get_height (buffer);
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
if (grey)
|
|
|
|
format = babl_format ("Y' u8");
|
|
|
|
else
|
|
|
|
format = gegl_buffer_get_format (buffer);
|
|
|
|
|
|
|
|
/* allocate a buffer for retrieving information from the buffer */
|
|
|
|
src = data = g_malloc (tile_height * width *
|
|
|
|
babl_format_get_bytes_per_pixel (format));
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* Fill SUN-color map */
|
|
|
|
if (grey)
|
|
|
|
{
|
1999-10-14 02:11:52 +00:00
|
|
|
ncols = 256;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (j = 0; j < ncols; j++)
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
suncolmap[j] = j;
|
|
|
|
suncolmap[j + ncols] = j;
|
|
|
|
suncolmap[j + ncols * 2] = j;
|
2008-10-20 06:04:39 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-05-23 23:37:46 +02:00
|
|
|
cmap = gimp_image_get_colormap (image, NULL, &ncols);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (j = 0; j < ncols; j++)
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
suncolmap[j] = *(cmap++);
|
|
|
|
suncolmap[j + ncols] = *(cmap++);
|
|
|
|
suncolmap[j + ncols * 2] = *(cmap++);
|
2008-10-20 06:04:39 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2013-06-06 23:26:16 +02:00
|
|
|
bw = (ncols == 2); /* Maybe this is a two-color image */
|
1997-11-24 22:05:25 +00:00
|
|
|
if (bw)
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
bwline = g_malloc ((width + 7) / 8);
|
|
|
|
if (bwline == NULL)
|
|
|
|
bw = 0;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
is_bw = is_wb = 0;
|
|
|
|
if (bw) /* The Sun-OS imagetool generates index 0 for white and */
|
2013-06-06 23:26:16 +02:00
|
|
|
{ /* index 1 for black. Do the same without colortable. */
|
1999-10-14 02:11:52 +00:00
|
|
|
is_bw = (memcmp (suncolmap, sun_bwmap, 6) == 0);
|
|
|
|
is_wb = (memcmp (suncolmap, sun_wbmap, 6) == 0);
|
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
/* Number of data bytes per line */
|
|
|
|
bpl = bw ? (width+7)/8 : width;
|
|
|
|
linepad = bpl % 2;
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
/* Fill in the SUN header */
|
2014-01-01 22:28:08 +01:00
|
|
|
sunhdr.l_ras_magic = RAS_MAGIC;
|
|
|
|
sunhdr.l_ras_width = width;
|
1997-11-24 22:05:25 +00:00
|
|
|
sunhdr.l_ras_height = height;
|
2014-01-01 22:28:08 +01:00
|
|
|
sunhdr.l_ras_depth = bw ? 1 : 8;
|
|
|
|
sunhdr.l_ras_length = (bpl + linepad) * height;
|
|
|
|
sunhdr.l_ras_type = rle ? RAS_TYPE_RLE : RAS_TYPE_STD;
|
|
|
|
|
2013-06-06 23:26:16 +02:00
|
|
|
if (is_bw || is_wb) /* No colortable for real b/w images */
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2013-06-06 23:26:16 +02:00
|
|
|
sunhdr.l_ras_maptype = 0; /* No colormap */
|
|
|
|
sunhdr.l_ras_maplength = 0; /* Length of colormap */
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
else
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2013-06-06 23:26:16 +02:00
|
|
|
sunhdr.l_ras_maptype = 1; /* RGB colormap */
|
|
|
|
sunhdr.l_ras_maplength = ncols*3; /* Length of colormap */
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
write_sun_header (ofp, &sunhdr);
|
|
|
|
|
|
|
|
if (sunhdr.l_ras_maplength > 0)
|
|
|
|
write_sun_cols (ofp, &sunhdr, suncolmap);
|
|
|
|
|
|
|
|
#define GET_INDEX_TILE(begin) \
|
|
|
|
{int scan_lines; \
|
|
|
|
scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i); \
|
2014-01-01 22:28:08 +01:00
|
|
|
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, i, width, scan_lines), 1.0, \
|
|
|
|
format, begin, \
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); \
|
1997-11-24 22:05:25 +00:00
|
|
|
src = begin; }
|
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
if (rle)
|
|
|
|
{
|
|
|
|
write_fun = (WRITE_FUN *) &rle_fwrite;
|
|
|
|
rle_startwrite (ofp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
write_fun = (WRITE_FUN *) &my_fwrite;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2013-06-06 23:26:16 +02:00
|
|
|
if (bw) /* Two color image */
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
1999-10-14 02:11:52 +00:00
|
|
|
for (i = 0; i < height; i++)
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
if ((i % tile_height) == 0)
|
|
|
|
GET_INDEX_TILE (data); /* Get more data */
|
|
|
|
|
2008-10-20 06:04:39 +00:00
|
|
|
byte2bit (src, width, bwline, is_bw);
|
|
|
|
(*write_fun) (bwline, bpl, 1, ofp);
|
2014-01-01 22:28:08 +01:00
|
|
|
if (linepad)
|
|
|
|
(*write_fun) ((char *)&tmp, linepad, 1, ofp);
|
2008-10-20 06:04:39 +00:00
|
|
|
src += width;
|
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
|
|
|
gimp_progress_update ((double) i / (double) height);
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
2013-06-06 23:26:16 +02:00
|
|
|
else /* Color or grey-image */
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
1999-10-14 02:11:52 +00:00
|
|
|
for (i = 0; i < height; i++)
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
if ((i % tile_height) == 0)
|
|
|
|
GET_INDEX_TILE (data); /* Get more data */
|
|
|
|
|
2008-10-20 06:04:39 +00:00
|
|
|
(*write_fun) ((char *)src, width, 1, ofp);
|
2014-01-01 22:28:08 +01:00
|
|
|
if (linepad)
|
|
|
|
(*write_fun) ((char *)&tmp, linepad, 1, ofp);
|
2008-10-20 06:04:39 +00:00
|
|
|
src += width;
|
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
|
|
|
gimp_progress_update ((double) i / (double) height);
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
#undef GET_INDEX_TILE
|
|
|
|
|
2003-11-06 15:27:05 +00:00
|
|
|
if (rle)
|
1999-10-14 02:11:52 +00:00
|
|
|
rle_endwrite (ofp);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
g_free (data);
|
|
|
|
|
2003-11-06 15:27:05 +00:00
|
|
|
if (bwline)
|
1999-10-14 02:11:52 +00:00
|
|
|
g_free (bwline);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
g_object_unref (buffer);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
if (ferror (ofp))
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2004-05-23 21:12:29 +00:00
|
|
|
g_message (_("Write error occurred"));
|
2014-01-01 22:28:08 +01:00
|
|
|
return FALSE;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2014-01-01 22:28:08 +01:00
|
|
|
|
|
|
|
return TRUE;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
static gboolean
|
|
|
|
save_rgb (FILE *ofp,
|
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2023-03-21 18:54:15 +00:00
|
|
|
gint rle)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
int height, width, tile_height, linepad;
|
|
|
|
int i, j, bpp;
|
|
|
|
guchar *data, *src;
|
|
|
|
L_SUNFILEHEADER sunhdr;
|
|
|
|
GeglBuffer *buffer;
|
|
|
|
const Babl *format;
|
|
|
|
|
2019-08-25 15:12:48 +02:00
|
|
|
buffer = gimp_drawable_get_buffer (drawable);
|
2014-01-01 22:28:08 +01:00
|
|
|
|
|
|
|
width = gegl_buffer_get_width (buffer);
|
|
|
|
height = gegl_buffer_get_height (buffer);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
tile_height = gimp_tile_height ();
|
2014-01-01 22:28:08 +01:00
|
|
|
|
|
|
|
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 */
|
2014-01-01 22:28:08 +01:00
|
|
|
src = data = g_malloc (tile_height * width *
|
|
|
|
babl_format_get_bytes_per_pixel (format));
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
/* #define SUNRAS_32 */
|
|
|
|
#ifdef SUNRAS_32
|
|
|
|
bpp = 4;
|
|
|
|
#else
|
|
|
|
bpp = 3;
|
|
|
|
#endif
|
|
|
|
linepad = (width * bpp) % 2;
|
|
|
|
|
|
|
|
/* Fill in the SUN header */
|
2014-01-01 22:28:08 +01:00
|
|
|
sunhdr.l_ras_magic = RAS_MAGIC;
|
|
|
|
sunhdr.l_ras_width = width;
|
|
|
|
sunhdr.l_ras_height = height;
|
|
|
|
sunhdr.l_ras_depth = 8 * bpp;
|
|
|
|
sunhdr.l_ras_length = (width * bpp + linepad) * height;
|
|
|
|
sunhdr.l_ras_type = rle ? RAS_TYPE_RLE : RAS_TYPE_STD;
|
|
|
|
sunhdr.l_ras_maptype = 0; /* No colormap */
|
2013-06-06 23:26:16 +02:00
|
|
|
sunhdr.l_ras_maplength = 0; /* Length of colormap */
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
write_sun_header (ofp, &sunhdr);
|
|
|
|
|
|
|
|
#define GET_RGB_TILE(begin) \
|
|
|
|
{int scan_lines; \
|
|
|
|
scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i); \
|
2014-01-01 22:28:08 +01:00
|
|
|
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, i, width, scan_lines), 1.0, \
|
|
|
|
format, begin, \
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); \
|
1997-11-24 22:05:25 +00:00
|
|
|
src = begin; }
|
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
if (! rle)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
1999-10-14 02:11:52 +00:00
|
|
|
for (i = 0; i < height; i++)
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
if ((i % tile_height) == 0)
|
|
|
|
GET_RGB_TILE (data); /* Get more data */
|
|
|
|
|
2008-10-20 06:04:39 +00:00
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
|
|
|
if (bpp == 4) putc (0, ofp); /* Dummy */
|
2014-01-01 22:28:08 +01:00
|
|
|
putc (*(src + 2), ofp); /* Blue */
|
|
|
|
putc (*(src + 1), ofp); /* Green */
|
|
|
|
putc (*src, ofp); /* Red */
|
2008-10-20 06:04:39 +00:00
|
|
|
src += 3;
|
|
|
|
}
|
2014-01-01 22:28:08 +01:00
|
|
|
|
2008-10-20 06:04:39 +00:00
|
|
|
for (j = 0; j < linepad; j++)
|
|
|
|
putc (0, ofp);
|
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
|
|
|
gimp_progress_update ((double) i / (double) height);
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
else /* Write runlength encoded */
|
|
|
|
{
|
1999-10-14 02:11:52 +00:00
|
|
|
rle_startwrite (ofp);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
for (i = 0; i < height; i++)
|
2008-10-20 06:04:39 +00:00
|
|
|
{
|
2014-01-01 22:28:08 +01:00
|
|
|
if ((i % tile_height) == 0)
|
|
|
|
GET_RGB_TILE (data); /* Get more data */
|
|
|
|
|
2008-10-20 06:04:39 +00:00
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
|
|
|
if (bpp == 4) rle_putc (0, ofp); /* Dummy */
|
2014-01-01 22:28:08 +01:00
|
|
|
rle_putc (*(src + 2), ofp); /* Blue */
|
|
|
|
rle_putc (*(src + 1), ofp); /* Green */
|
|
|
|
rle_putc (*src, ofp); /* Red */
|
2008-10-20 06:04:39 +00:00
|
|
|
src += 3;
|
|
|
|
}
|
2014-01-01 22:28:08 +01:00
|
|
|
|
2008-10-20 06:04:39 +00:00
|
|
|
for (j = 0; j < linepad; j++)
|
|
|
|
rle_putc (0, ofp);
|
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
|
|
|
gimp_progress_update ((double) i / (double) height);
|
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1999-10-14 02:11:52 +00:00
|
|
|
rle_endwrite (ofp);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
2014-01-01 22:28:08 +01:00
|
|
|
|
|
|
|
#undef GET_RGB_TILE
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
g_free (data);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2014-01-01 22:28:08 +01:00
|
|
|
g_object_unref (buffer);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
if (ferror (ofp))
|
1999-10-14 02:11:52 +00:00
|
|
|
{
|
2004-05-23 21:12:29 +00:00
|
|
|
g_message (_("Write error occurred"));
|
2014-01-01 22:28:08 +01:00
|
|
|
return FALSE;
|
1999-10-14 02:11:52 +00:00
|
|
|
}
|
2014-01-01 22:28:08 +01:00
|
|
|
|
|
|
|
return TRUE;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Save interface functions */
|
|
|
|
|
2004-05-19 23:54:40 +00:00
|
|
|
static gboolean
|
2023-05-20 14:30:41 +00:00
|
|
|
save_dialog (GimpImage *image,
|
|
|
|
GimpProcedure *procedure,
|
2019-09-25 23:26:28 +02:00
|
|
|
GObject *config)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2023-03-21 18:54:15 +00:00
|
|
|
GtkWidget *dialog;
|
|
|
|
GtkListStore *store;
|
|
|
|
gboolean run;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2024-04-20 03:08:57 +00:00
|
|
|
dialog = gimp_export_procedure_dialog_new (GIMP_EXPORT_PROCEDURE (procedure),
|
|
|
|
GIMP_PROCEDURE_CONFIG (config),
|
|
|
|
image);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2023-03-21 18:54:15 +00:00
|
|
|
store = gimp_int_store_new (_("S_tandard"), FALSE,
|
|
|
|
_("R_un-Length Encoded"), TRUE,
|
|
|
|
NULL);
|
|
|
|
gimp_procedure_dialog_get_int_radio (GIMP_PROCEDURE_DIALOG (dialog),
|
|
|
|
"rle", GIMP_INT_STORE (store));
|
2002-01-03 17:55:00 +00:00
|
|
|
|
2023-03-21 18:54:15 +00:00
|
|
|
gimp_procedure_dialog_fill (GIMP_PROCEDURE_DIALOG (dialog),
|
|
|
|
NULL);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2005-09-09 18:38:00 +00:00
|
|
|
gtk_widget_show (dialog);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-09-25 23:26:28 +02:00
|
|
|
run = gimp_procedure_dialog_run (GIMP_PROCEDURE_DIALOG (dialog));
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2005-09-09 18:38:00 +00:00
|
|
|
gtk_widget_destroy (dialog);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2003-11-06 15:27:05 +00:00
|
|
|
return run;
|
1999-10-14 11:35:08 +00:00
|
|
|
}
|
|
|
|
|
2003-11-06 15:27:05 +00:00
|
|
|
static int
|
|
|
|
my_fwrite (void *ptr,
|
2008-10-20 06:04:39 +00:00
|
|
|
int size,
|
|
|
|
int nmemb,
|
|
|
|
FILE *stream)
|
1998-03-25 02:41:09 +00:00
|
|
|
{
|
2000-05-01 20:22:55 +00:00
|
|
|
return fwrite (ptr, size, nmemb, stream);
|
1998-03-25 02:41:09 +00:00
|
|
|
}
|