2015-12-03 01:02:43 +01:00
|
|
|
/* tiff loading for GIMP
|
|
|
|
* -Peter Mattis
|
|
|
|
*
|
|
|
|
* The TIFF loading code has been completely revamped by Nick Lamb
|
|
|
|
* njl195@zepler.org.uk -- 18 May 1998
|
|
|
|
* And it now gains support for tiles (and doubtless a zillion bugs)
|
|
|
|
* njl195@zepler.org.uk -- 12 June 1999
|
|
|
|
* LZW patent fuss continues :(
|
|
|
|
* njl195@zepler.org.uk -- 20 April 2000
|
|
|
|
* The code for this filter is based on "tifftopnm" and "pnmtotiff",
|
|
|
|
* 2 programs that are a part of the netpbm package.
|
|
|
|
* khk@khk.net -- 13 May 2000
|
|
|
|
* Added support for ICCPROFILE tiff tag. If this tag is present in a
|
|
|
|
* TIFF file, then a parasite is created and vice versa.
|
|
|
|
* peter@kirchgessner.net -- 29 Oct 2002
|
|
|
|
* Progress bar only when run interactive
|
|
|
|
* Added support for layer offsets - pablo.dangelo@web.de -- 7 Jan 2004
|
|
|
|
* Honor EXTRASAMPLES tag while loading images with alphachannel
|
|
|
|
* pablo.dangelo@web.de -- 16 Jan 2004
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* tifftopnm.c - converts a Tagged Image File to a portable anymap
|
|
|
|
*
|
|
|
|
* Derived by Jef Poskanzer from tif2ras.c, which is:
|
|
|
|
*
|
|
|
|
* Copyright (c) 1990 by Sun Microsystems, Inc.
|
|
|
|
*
|
|
|
|
* Author: Patrick J. Naughton
|
|
|
|
* naughton@wind.sun.com
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software and its
|
|
|
|
* documentation for any purpose and without fee is hereby granted,
|
|
|
|
* provided that the above copyright notice appear in all copies and that
|
|
|
|
* both that copyright notice and this permission notice appear in
|
|
|
|
* supporting documentation.
|
|
|
|
*
|
|
|
|
* This file is provided AS IS with no warranties of any kind. The author
|
|
|
|
* shall have no liability with respect to the infringement of copyrights,
|
|
|
|
* trade secrets or any patents by this file or any part thereof. In no
|
|
|
|
* event will the author be liable for any lost revenue or profits or
|
|
|
|
* other special, indirect and consequential damages.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <tiffio.h>
|
|
|
|
|
|
|
|
#include <libgimp/gimp.h>
|
|
|
|
#include <libgimp/gimpui.h>
|
|
|
|
|
2020-05-18 00:13:21 +02:00
|
|
|
#include "file-tiff.h"
|
2022-03-11 15:05:06 +01:00
|
|
|
#include "file-tiff-io.h"
|
2015-12-03 01:02:43 +01:00
|
|
|
#include "file-tiff-load.h"
|
2024-04-21 16:36:01 +02:00
|
|
|
#include "file-tiff-export.h"
|
2015-12-03 01:02:43 +01:00
|
|
|
|
|
|
|
#include "libgimp/stdplugins-intl.h"
|
|
|
|
|
|
|
|
|
2024-04-13 15:10:25 +00:00
|
|
|
#define EXPORT_PROC "file-tiff-export"
|
2015-12-03 01:02:43 +01:00
|
|
|
#define PLUG_IN_BINARY "file-tiff"
|
|
|
|
|
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
typedef struct _Tiff Tiff;
|
|
|
|
typedef struct _TiffClass TiffClass;
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
struct _Tiff
|
|
|
|
{
|
|
|
|
GimpPlugIn parent_instance;
|
|
|
|
};
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
struct _TiffClass
|
2015-12-03 01:02:43 +01:00
|
|
|
{
|
2019-08-16 22:55:16 +02:00
|
|
|
GimpPlugInClass parent_class;
|
2015-12-03 01:02:43 +01:00
|
|
|
};
|
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
|
|
|
|
#define TIFF_TYPE (tiff_get_type ())
|
2023-10-18 18:29:37 +02:00
|
|
|
#define TIFF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TIFF_TYPE, Tiff))
|
2019-08-16 22:55:16 +02:00
|
|
|
|
2024-11-01 19:13:02 +01:00
|
|
|
GType tiff_get_type (void) G_GNUC_CONST;
|
|
|
|
|
|
|
|
static GList * tiff_query_procedures (GimpPlugIn *plug_in);
|
|
|
|
static GimpProcedure * tiff_create_procedure (GimpPlugIn *plug_in,
|
|
|
|
const gchar *name);
|
|
|
|
|
|
|
|
static GimpValueArray * tiff_load (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
|
|
|
GFile *file,
|
|
|
|
GimpMetadata *metadata,
|
|
|
|
GimpMetadataLoadFlags *flags,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
gpointer run_data);
|
|
|
|
static GimpValueArray * tiff_export (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
|
|
|
GimpImage *image,
|
|
|
|
GFile *file,
|
|
|
|
GimpExportOptions *options,
|
|
|
|
GimpMetadata *metadata,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
gpointer run_data);
|
|
|
|
static GimpPDBStatusType tiff_export_rec (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
|
|
|
GimpImage *orig_image,
|
|
|
|
GFile *file,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
GimpExportOptions *options,
|
|
|
|
GimpMetadata *metadata,
|
|
|
|
gboolean retried,
|
|
|
|
GError **error);
|
|
|
|
static GimpExportCapabilities export_edit_options (GimpProcedure *procedure,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
GimpExportOptions *options,
|
|
|
|
gpointer create_data);
|
|
|
|
|
|
|
|
static gboolean image_is_monochrome (GimpImage *image);
|
|
|
|
static gboolean image_is_multi_layer (GimpImage *image);
|
2019-08-16 22:55:16 +02:00
|
|
|
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (Tiff, tiff, GIMP_TYPE_PLUG_IN)
|
|
|
|
|
|
|
|
GIMP_MAIN (TIFF_TYPE)
|
2022-05-26 00:59:36 +02:00
|
|
|
DEFINE_STD_SET_I18N
|
2019-08-16 22:55:16 +02:00
|
|
|
|
|
|
|
|
2015-12-03 01:02:43 +01:00
|
|
|
static void
|
2019-08-16 22:55:16 +02:00
|
|
|
tiff_class_init (TiffClass *klass)
|
2015-12-03 01:02:43 +01:00
|
|
|
{
|
2019-08-16 22:55:16 +02:00
|
|
|
GimpPlugInClass *plug_in_class = GIMP_PLUG_IN_CLASS (klass);
|
|
|
|
|
|
|
|
plug_in_class->query_procedures = tiff_query_procedures;
|
|
|
|
plug_in_class->create_procedure = tiff_create_procedure;
|
2022-05-26 00:59:36 +02:00
|
|
|
plug_in_class->set_i18n = STD_SET_I18N;
|
2015-12-03 01:02:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-08-16 22:55:16 +02:00
|
|
|
tiff_init (Tiff *tiff)
|
2015-12-03 01:02:43 +01:00
|
|
|
{
|
2019-08-16 22:55:16 +02:00
|
|
|
}
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
static GList *
|
|
|
|
tiff_query_procedures (GimpPlugIn *plug_in)
|
|
|
|
{
|
|
|
|
GList *list = NULL;
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2019-08-16 22:55:16 +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));
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
return list;
|
|
|
|
}
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
static GimpProcedure *
|
|
|
|
tiff_create_procedure (GimpPlugIn *plug_in,
|
|
|
|
const gchar *name)
|
|
|
|
{
|
|
|
|
GimpProcedure *procedure = NULL;
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
if (! strcmp (name, LOAD_PROC))
|
2015-12-03 01:02:43 +01:00
|
|
|
{
|
2023-08-06 03:21:27 +02:00
|
|
|
procedure = gimp_load_procedure_new (plug_in, name,
|
|
|
|
GIMP_PDB_PROC_TYPE_PLUGIN,
|
|
|
|
tiff_load, NULL, NULL);
|
2019-08-16 22:55:16 +02:00
|
|
|
|
2022-07-04 22:50:53 +02:00
|
|
|
gimp_procedure_set_menu_label (procedure, _("TIFF or BigTIFF image"));
|
2019-08-16 22:55:16 +02:00
|
|
|
|
|
|
|
gimp_procedure_set_documentation (procedure,
|
2024-05-31 04:34:51 +00:00
|
|
|
_("Loads files of the TIFF and BigTIFF file formats"),
|
|
|
|
_("Loads files of the Tag Image File Format (TIFF) and "
|
|
|
|
"its 64-bit offsets variant (BigTIFF)"),
|
2019-08-16 22:55:16 +02:00
|
|
|
name);
|
|
|
|
gimp_procedure_set_attribution (procedure,
|
|
|
|
"Spencer Kimball, Peter Mattis & Nick Lamb",
|
|
|
|
"Nick Lamb <njl195@zepler.org.uk>",
|
|
|
|
"1995-1996,1998-2003");
|
|
|
|
|
2019-08-19 12:05:12 +02:00
|
|
|
gimp_file_procedure_set_handles_remote (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
TRUE);
|
2019-08-16 22:55:16 +02:00
|
|
|
gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"image/tiff");
|
|
|
|
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"tif,tiff");
|
|
|
|
gimp_file_procedure_set_magics (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"0,string,II*\\0,0,string,MM\\0*");
|
2023-10-26 21:26:21 +02:00
|
|
|
|
|
|
|
/* TODO: the 2 below AUX arguments should likely be real arguments, but I
|
|
|
|
* just wanted to get rid of gimp_get_data/gimp_set_data() usage at first
|
|
|
|
* and didn't dig much into proper and full usage. Since it's always
|
|
|
|
* possible to add arguments, but not to remove them, I prefer to make
|
|
|
|
* them AUX for now and leave it as further exercise to decide whether it
|
|
|
|
* should be part of the PDB API.
|
|
|
|
*/
|
2024-06-12 16:53:12 +00:00
|
|
|
gimp_procedure_add_enum_aux_argument (procedure, "target",
|
|
|
|
"Open _pages as", NULL,
|
|
|
|
GIMP_TYPE_PAGE_SELECTOR_TARGET,
|
|
|
|
GIMP_PAGE_SELECTOR_TARGET_LAYERS,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_boolean_aux_argument (procedure, "keep-empty-space",
|
|
|
|
_("_Keep empty space around imported layers"),
|
|
|
|
NULL, TRUE, GIMP_PARAM_READWRITE);
|
2019-08-16 22:55:16 +02:00
|
|
|
}
|
2024-04-13 15:10:25 +00:00
|
|
|
else if (! strcmp (name, EXPORT_PROC))
|
2019-08-16 22:55:16 +02:00
|
|
|
{
|
2024-04-20 03:08:57 +00:00
|
|
|
procedure = gimp_export_procedure_new (plug_in, name,
|
|
|
|
GIMP_PDB_PROC_TYPE_PLUGIN,
|
|
|
|
TRUE, tiff_export, NULL, NULL);
|
2019-08-16 22:55:16 +02:00
|
|
|
|
|
|
|
gimp_procedure_set_image_types (procedure, "*");
|
|
|
|
|
2022-07-04 22:50:53 +02:00
|
|
|
gimp_procedure_set_menu_label (procedure, _("TIFF or BigTIFF image"));
|
2019-08-16 22:55:16 +02:00
|
|
|
|
|
|
|
gimp_procedure_set_documentation (procedure,
|
2024-05-31 04:34:51 +00:00
|
|
|
_("Exports files in the TIFF or BigTIFF file formats"),
|
|
|
|
_("Exports files in the Tag Image File Format (TIFF) or "
|
|
|
|
"its 64-bit offsets variant (BigTIFF) able to support "
|
|
|
|
"much bigger file sizes"),
|
2019-08-16 22:55:16 +02:00
|
|
|
name);
|
|
|
|
gimp_procedure_set_attribution (procedure,
|
|
|
|
"Spencer Kimball & Peter Mattis",
|
|
|
|
"Spencer Kimball & Peter Mattis",
|
|
|
|
"1995-1996,2000-2003");
|
|
|
|
|
2019-08-19 12:05:12 +02:00
|
|
|
gimp_file_procedure_set_handles_remote (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
TRUE);
|
2020-12-17 02:02:14 +01:00
|
|
|
gimp_file_procedure_set_format_name (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
_("TIFF"));
|
2019-08-16 22:55:16 +02:00
|
|
|
gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"image/tiff");
|
|
|
|
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"tif,tiff");
|
|
|
|
|
2024-05-06 18:38:12 +00:00
|
|
|
/* TIFF capabilities are so dependent on export settings, we can't assign
|
|
|
|
* defaults until we know how the user wants to export it */
|
|
|
|
gimp_export_procedure_set_capabilities (GIMP_EXPORT_PROCEDURE (procedure),
|
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
|
|
|
0, export_edit_options, NULL, NULL);
|
2024-05-06 18:38:12 +00:00
|
|
|
|
2024-06-12 16:53:12 +00:00
|
|
|
gimp_procedure_add_boolean_argument (procedure, "bigtiff",
|
|
|
|
_("Export in _BigTIFF variant file format"),
|
|
|
|
_("The BigTIFF variant file format uses 64-bit offsets, "
|
|
|
|
"hence supporting over 4GiB files and bigger"),
|
|
|
|
FALSE,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_choice_argument (procedure, "compression",
|
|
|
|
_("Co_mpression"),
|
|
|
|
_("Compression type"),
|
|
|
|
gimp_choice_new_with_values ("none", GIMP_COMPRESSION_NONE, _("None"), NULL,
|
|
|
|
"lzw", GIMP_COMPRESSION_LZW, _("LZW"), NULL,
|
|
|
|
"packbits", GIMP_COMPRESSION_PACKBITS, _("Pack Bits"), NULL,
|
|
|
|
"adobe_deflate", GIMP_COMPRESSION_ADOBE_DEFLATE, _("Deflate"), NULL,
|
|
|
|
"jpeg", GIMP_COMPRESSION_JPEG, _("JPEG"), NULL,
|
|
|
|
"ccittfax3", GIMP_COMPRESSION_CCITTFAX3, _("CCITT Group 3 fax"), NULL,
|
|
|
|
"ccittfax4", GIMP_COMPRESSION_CCITTFAX4, _("CCITT Group 4 fax"), NULL,
|
|
|
|
NULL),
|
|
|
|
"none", G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_boolean_argument (procedure, "save-transparent-pixels",
|
|
|
|
_("Save color _values from transparent pixels"),
|
|
|
|
_("Keep the color data masked by an alpha channel "
|
|
|
|
"intact (do not store premultiplied components)"),
|
|
|
|
TRUE,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_boolean_argument (procedure, "cmyk",
|
|
|
|
_("Export as CMY_K"),
|
|
|
|
_("Create a CMYK TIFF image using the soft-proofing color profile"),
|
|
|
|
FALSE,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_boolean_aux_argument (procedure, "save-layers",
|
|
|
|
_("Save La_yers"),
|
|
|
|
_("Save Layers"),
|
|
|
|
TRUE,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_boolean_aux_argument (procedure, "crop-layers",
|
|
|
|
_("Crop L_ayers"),
|
|
|
|
_("Crop Layers"),
|
|
|
|
TRUE,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_boolean_aux_argument (procedure, "save-geotiff",
|
|
|
|
_("Save _GeoTIFF data"),
|
|
|
|
_("Save GeoTIFF data"),
|
|
|
|
TRUE,
|
|
|
|
G_PARAM_READWRITE);
|
2020-11-21 22:27:27 +01:00
|
|
|
|
2024-04-20 03:08:57 +00:00
|
|
|
gimp_export_procedure_set_support_exif (GIMP_EXPORT_PROCEDURE (procedure), TRUE);
|
|
|
|
gimp_export_procedure_set_support_iptc (GIMP_EXPORT_PROCEDURE (procedure), TRUE);
|
|
|
|
gimp_export_procedure_set_support_xmp (GIMP_EXPORT_PROCEDURE (procedure), TRUE);
|
2020-11-21 22:27:27 +01:00
|
|
|
#ifdef TIFFTAG_ICCPROFILE
|
2024-04-20 03:08:57 +00:00
|
|
|
gimp_export_procedure_set_support_profile (GIMP_EXPORT_PROCEDURE (procedure), TRUE);
|
2020-11-21 22:27:27 +01:00
|
|
|
#endif
|
2024-04-20 03:08:57 +00:00
|
|
|
gimp_export_procedure_set_support_thumbnail (GIMP_EXPORT_PROCEDURE (procedure), TRUE);
|
|
|
|
gimp_export_procedure_set_support_comment (GIMP_EXPORT_PROCEDURE (procedure), TRUE);
|
2019-08-16 22:55:16 +02:00
|
|
|
}
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
return procedure;
|
|
|
|
}
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
static GimpValueArray *
|
2023-08-05 19:07:04 +02:00
|
|
|
tiff_load (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
|
|
|
GFile *file,
|
|
|
|
GimpMetadata *metadata,
|
|
|
|
GimpMetadataLoadFlags *flags,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
gpointer run_data)
|
2019-08-16 22:55:16 +02:00
|
|
|
{
|
|
|
|
GimpValueArray *return_vals;
|
|
|
|
GimpPDBStatusType status;
|
2022-12-19 16:29:41 +00:00
|
|
|
GimpImage *image = NULL;
|
|
|
|
gboolean resolution_loaded = FALSE;
|
|
|
|
gboolean profile_loaded = FALSE;
|
|
|
|
gboolean ps_metadata_loaded = FALSE;
|
2019-08-16 22:55:16 +02:00
|
|
|
GError *error = NULL;
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
gegl_init (NULL, NULL);
|
2019-04-16 10:04:16 +02:00
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
if (run_mode == GIMP_RUN_INTERACTIVE)
|
2019-09-20 19:39:00 +02:00
|
|
|
gimp_ui_init (PLUG_IN_BINARY);
|
2019-04-16 10:04:16 +02:00
|
|
|
|
2024-05-31 04:34:51 +00:00
|
|
|
status = load_image (procedure,
|
|
|
|
file, run_mode, &image,
|
2019-08-16 22:55:16 +02:00
|
|
|
&resolution_loaded,
|
|
|
|
&profile_loaded,
|
2022-12-19 16:29:41 +00:00
|
|
|
&ps_metadata_loaded,
|
2023-10-26 21:26:21 +02:00
|
|
|
config, &error);
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2019-08-17 10:52:05 +02:00
|
|
|
if (!image)
|
2019-08-16 22:55:16 +02:00
|
|
|
return gimp_procedure_new_return_values (procedure, status, error);
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2023-08-05 19:07:04 +02:00
|
|
|
if (resolution_loaded)
|
|
|
|
*flags &= ~GIMP_METADATA_LOAD_RESOLUTION;
|
2019-08-16 22:55:16 +02:00
|
|
|
|
2023-08-05 19:07:04 +02:00
|
|
|
if (profile_loaded)
|
|
|
|
*flags &= ~GIMP_METADATA_LOAD_COLORSPACE;
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
return_vals = gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_SUCCESS,
|
|
|
|
NULL);
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2019-08-20 01:03:38 +02:00
|
|
|
GIMP_VALUES_SET_IMAGE (return_vals, 1, image);
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
return return_vals;
|
|
|
|
}
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
static GimpValueArray *
|
2024-04-13 15:10:25 +00:00
|
|
|
tiff_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-16 22:55:16 +02:00
|
|
|
{
|
2024-04-30 13:50:24 +00:00
|
|
|
GError *error = NULL;
|
2023-07-20 23:16:27 +02:00
|
|
|
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
gegl_init (NULL, NULL);
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
switch (run_mode)
|
|
|
|
{
|
|
|
|
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-16 22:55:16 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2024-05-06 18:38:12 +00:00
|
|
|
status = tiff_export_rec (procedure, run_mode, image, file,
|
|
|
|
config, options, metadata, FALSE, &error);
|
2022-03-11 15:05:06 +01:00
|
|
|
|
|
|
|
return gimp_procedure_new_return_values (procedure, status, error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static GimpPDBStatusType
|
2024-04-13 15:10:25 +00:00
|
|
|
tiff_export_rec (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
|
|
|
GimpImage *orig_image,
|
|
|
|
GFile *file,
|
|
|
|
GimpProcedureConfig *config,
|
2024-05-06 18:38:12 +00:00
|
|
|
GimpExportOptions *options,
|
2024-04-13 15:10:25 +00:00
|
|
|
GimpMetadata *metadata,
|
|
|
|
gboolean retried,
|
|
|
|
GError **error)
|
2022-03-11 15:05:06 +01:00
|
|
|
{
|
|
|
|
GimpImage *image = orig_image;
|
2024-04-30 13:50:24 +00:00
|
|
|
GList *drawables = gimp_image_list_layers (image);
|
|
|
|
gint n_drawables = g_list_length (drawables);
|
2022-03-11 15:05:06 +01:00
|
|
|
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
|
2024-04-30 04:25:51 +00:00
|
|
|
GimpExportReturn export = GIMP_EXPORT_IGNORE;
|
2022-03-11 15:05:06 +01:00
|
|
|
gboolean bigtiff = FALSE;
|
|
|
|
|
2020-05-18 00:13:21 +02:00
|
|
|
if (run_mode == GIMP_RUN_INTERACTIVE)
|
2019-08-16 22:55:16 +02:00
|
|
|
{
|
2020-05-18 00:13:21 +02:00
|
|
|
if (! save_dialog (orig_image, procedure, G_OBJECT (config),
|
2024-04-30 13:50:24 +00:00
|
|
|
n_drawables == 1 ? gimp_drawable_has_alpha (drawables->data) : TRUE,
|
2022-03-11 15:05:06 +01:00
|
|
|
image_is_monochrome (orig_image),
|
|
|
|
gimp_image_get_base_type (orig_image) == GIMP_INDEXED,
|
|
|
|
image_is_multi_layer (orig_image),
|
|
|
|
retried))
|
2015-12-03 01:02:43 +01:00
|
|
|
{
|
2022-03-11 15:05:06 +01:00
|
|
|
return GIMP_PDB_CANCEL;
|
2019-06-28 22:33:12 +02:00
|
|
|
}
|
2015-12-03 01:02:43 +01:00
|
|
|
}
|
2019-08-16 22:55:16 +02:00
|
|
|
|
2024-07-14 20:12:57 +00:00
|
|
|
if (status == GIMP_PDB_SUCCESS)
|
2015-12-03 01:02:43 +01:00
|
|
|
{
|
2024-05-06 18:38:12 +00:00
|
|
|
g_object_get (config, "bigtiff", &bigtiff, NULL);
|
2020-05-18 00:13:21 +02:00
|
|
|
|
2024-05-06 18:38:12 +00:00
|
|
|
export = gimp_export_options_get_image (options, &image);
|
2015-12-03 01:02:43 +01:00
|
|
|
}
|
2024-04-30 13:50:24 +00:00
|
|
|
drawables = gimp_image_list_layers (image);
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2020-05-18 00:13:21 +02:00
|
|
|
#if 0
|
|
|
|
/* FIXME */
|
2020-04-14 11:46:17 +02:00
|
|
|
if (n_drawables != 1 && tsvals.save_layers)
|
|
|
|
{
|
|
|
|
g_set_error (&error, G_FILE_ERROR, 0,
|
|
|
|
_("\"Save layers\" option not set while trying to export multiple layers."));
|
|
|
|
|
2020-05-18 00:13:21 +02:00
|
|
|
status = GIMP_PDB_CALLING_ERROR;
|
2020-04-14 11:46:17 +02:00
|
|
|
}
|
2020-05-18 00:13:21 +02:00
|
|
|
#endif
|
2020-04-14 11:46:17 +02:00
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
if (status == GIMP_PDB_SUCCESS)
|
2015-12-03 01:02:43 +01:00
|
|
|
{
|
2024-04-13 15:10:25 +00:00
|
|
|
if (! export_image (file, image, orig_image, G_OBJECT (config),
|
|
|
|
metadata, error))
|
2022-03-11 15:05:06 +01:00
|
|
|
status = GIMP_PDB_EXECUTION_ERROR;
|
2015-12-03 01:02:43 +01:00
|
|
|
}
|
|
|
|
|
2019-08-16 22:55:16 +02:00
|
|
|
if (export == GIMP_EXPORT_EXPORT)
|
2024-04-30 13:50:24 +00:00
|
|
|
gimp_image_delete (image);
|
2019-08-16 22:55:16 +02:00
|
|
|
|
2022-03-11 15:05:06 +01:00
|
|
|
if (status == GIMP_PDB_EXECUTION_ERROR &&
|
|
|
|
run_mode == GIMP_RUN_INTERACTIVE &&
|
|
|
|
! retried && ! bigtiff && tiff_got_file_size_error ())
|
|
|
|
{
|
|
|
|
/* Retrying but just once, when the save failed because we exceeded
|
|
|
|
* TIFF max size, to propose BigTIFF instead. */
|
|
|
|
tiff_reset_file_size_error ();
|
|
|
|
g_clear_error (error);
|
|
|
|
|
2024-05-06 18:38:12 +00:00
|
|
|
return tiff_export_rec (procedure, run_mode, orig_image, file,
|
|
|
|
config, options, metadata, TRUE, error);
|
2022-03-11 15:05:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
2015-12-03 01:02:43 +01:00
|
|
|
}
|
|
|
|
|
2024-11-01 19:13:02 +01:00
|
|
|
static GimpExportCapabilities
|
2024-05-06 18:38:12 +00:00
|
|
|
export_edit_options (GimpProcedure *procedure,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
GimpExportOptions *options,
|
|
|
|
gpointer create_data)
|
|
|
|
{
|
|
|
|
GimpExportCapabilities capabilities;
|
|
|
|
GimpCompression compression;
|
|
|
|
gboolean save_layers;
|
|
|
|
gboolean crop_layers;
|
|
|
|
|
|
|
|
g_object_get (config,
|
|
|
|
"save-layers", &save_layers,
|
|
|
|
"crop-layers", &crop_layers,
|
|
|
|
NULL);
|
|
|
|
compression = gimp_procedure_config_get_choice_id (config, "compression");
|
|
|
|
|
|
|
|
if (compression == GIMP_COMPRESSION_CCITTFAX3 ||
|
|
|
|
compression == GIMP_COMPRESSION_CCITTFAX4)
|
|
|
|
{
|
|
|
|
/* G3/G4 are fax compressions. They only support
|
|
|
|
* monochrome images without alpha support.
|
|
|
|
*/
|
|
|
|
capabilities = GIMP_EXPORT_CAN_HANDLE_INDEXED;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
capabilities = (GIMP_EXPORT_CAN_HANDLE_RGB |
|
|
|
|
GIMP_EXPORT_CAN_HANDLE_GRAY |
|
|
|
|
GIMP_EXPORT_CAN_HANDLE_INDEXED |
|
|
|
|
GIMP_EXPORT_CAN_HANDLE_ALPHA);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (save_layers)
|
|
|
|
{
|
|
|
|
capabilities |= GIMP_EXPORT_CAN_HANDLE_LAYERS;
|
|
|
|
|
|
|
|
if (crop_layers)
|
|
|
|
capabilities |= GIMP_EXPORT_NEEDS_CROP;
|
|
|
|
}
|
|
|
|
|
2024-11-01 19:13:02 +01:00
|
|
|
return capabilities;
|
2024-05-06 18:38:12 +00:00
|
|
|
}
|
|
|
|
|
2015-12-03 01:02:43 +01:00
|
|
|
static gboolean
|
2019-08-17 10:52:05 +02:00
|
|
|
image_is_monochrome (GimpImage *image)
|
2015-12-03 01:02:43 +01:00
|
|
|
{
|
2024-09-22 01:24:25 +02:00
|
|
|
GimpPalette *palette;
|
|
|
|
gboolean monochrome = FALSE;
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2019-08-17 10:52:05 +02:00
|
|
|
g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2024-09-22 01:24:25 +02:00
|
|
|
palette = gimp_image_get_palette (image);
|
2024-09-22 14:34:04 +02:00
|
|
|
if (palette)
|
2015-12-03 01:02:43 +01:00
|
|
|
{
|
2024-09-22 14:34:04 +02:00
|
|
|
gint num_colors;
|
2024-09-22 01:24:25 +02:00
|
|
|
|
2024-09-22 14:34:04 +02:00
|
|
|
num_colors = gimp_palette_get_color_count (palette);
|
2024-09-22 01:24:25 +02:00
|
|
|
|
2024-09-22 14:34:04 +02:00
|
|
|
if (num_colors == 2 || num_colors == 1)
|
2015-12-03 01:02:43 +01:00
|
|
|
{
|
2024-09-22 14:34:04 +02:00
|
|
|
guchar *colors;
|
|
|
|
const guchar bw_map[] = { 0, 0, 0, 255, 255, 255 };
|
|
|
|
const guchar wb_map[] = { 255, 255, 255, 0, 0, 0 };
|
|
|
|
|
|
|
|
colors = gimp_palette_get_colormap (palette, babl_format ("R'G'B' u8"), &num_colors, NULL);
|
2015-12-03 01:02:43 +01:00
|
|
|
|
2024-09-22 14:34:04 +02:00
|
|
|
if (memcmp (colors, bw_map, 3 * num_colors) == 0 ||
|
|
|
|
memcmp (colors, wb_map, 3 * num_colors) == 0)
|
|
|
|
{
|
|
|
|
monochrome = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (colors);
|
|
|
|
}
|
2015-12-03 01:02:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return monochrome;
|
|
|
|
}
|
2019-06-29 14:57:04 +02:00
|
|
|
|
|
|
|
static gboolean
|
2019-08-17 10:52:05 +02:00
|
|
|
image_is_multi_layer (GimpImage *image)
|
2019-06-29 14:57:04 +02:00
|
|
|
{
|
2024-10-22 01:47:45 +02:00
|
|
|
GimpLayer **layers;
|
|
|
|
gint32 n_layers;
|
2019-06-29 14:57:04 +02:00
|
|
|
|
2024-10-22 01:47:45 +02:00
|
|
|
layers = gimp_image_get_layers (image);
|
|
|
|
n_layers = gimp_core_object_array_get_length ((GObject **) layers);
|
|
|
|
g_free (layers);
|
2019-06-29 14:57:04 +02:00
|
|
|
|
|
|
|
return (n_layers > 1);
|
|
|
|
}
|
2020-05-18 00:13:21 +02:00
|
|
|
|
|
|
|
gint
|
|
|
|
gimp_compression_to_tiff_compression (GimpCompression compression)
|
|
|
|
{
|
|
|
|
switch (compression)
|
|
|
|
{
|
|
|
|
case GIMP_COMPRESSION_NONE: return COMPRESSION_NONE;
|
|
|
|
case GIMP_COMPRESSION_LZW: return COMPRESSION_LZW;
|
|
|
|
case GIMP_COMPRESSION_PACKBITS: return COMPRESSION_PACKBITS;
|
|
|
|
case GIMP_COMPRESSION_ADOBE_DEFLATE: return COMPRESSION_ADOBE_DEFLATE;
|
|
|
|
case GIMP_COMPRESSION_JPEG: return COMPRESSION_JPEG;
|
|
|
|
case GIMP_COMPRESSION_CCITTFAX3: return COMPRESSION_CCITTFAX3;
|
|
|
|
case GIMP_COMPRESSION_CCITTFAX4: return COMPRESSION_CCITTFAX4;
|
|
|
|
}
|
|
|
|
|
|
|
|
return COMPRESSION_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
GimpCompression
|
|
|
|
tiff_compression_to_gimp_compression (gint compression)
|
|
|
|
{
|
|
|
|
switch (compression)
|
|
|
|
{
|
|
|
|
case COMPRESSION_NONE: return GIMP_COMPRESSION_NONE;
|
|
|
|
case COMPRESSION_LZW: return GIMP_COMPRESSION_LZW;
|
|
|
|
case COMPRESSION_PACKBITS: return GIMP_COMPRESSION_PACKBITS;
|
|
|
|
case COMPRESSION_DEFLATE: return GIMP_COMPRESSION_ADOBE_DEFLATE;
|
|
|
|
case COMPRESSION_ADOBE_DEFLATE: return GIMP_COMPRESSION_ADOBE_DEFLATE;
|
|
|
|
case COMPRESSION_OJPEG: return GIMP_COMPRESSION_JPEG;
|
|
|
|
case COMPRESSION_JPEG: return GIMP_COMPRESSION_JPEG;
|
|
|
|
case COMPRESSION_CCITTFAX3: return GIMP_COMPRESSION_CCITTFAX3;
|
|
|
|
case COMPRESSION_CCITTFAX4: return GIMP_COMPRESSION_CCITTFAX4;
|
|
|
|
}
|
|
|
|
|
|
|
|
return GIMP_COMPRESSION_NONE;
|
|
|
|
}
|