[gimp] plug-ins: propose exporting as BigTIFF once if TIFF export fails…
- From: Jehan <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] plug-ins: propose exporting as BigTIFF once if TIFF export fails…
- Date: Fri, 11 Mar 2022 14:18:52 +0000 (UTC)
commit 6e71478cd484c7f86d24b02e3025394cd63c500d
Author: Jehan <jehan girinstud io>
Date: Fri Mar 11 15:05:06 2022 +0100
plug-ins: propose exporting as BigTIFF once if TIFF export fails…
… because we reached max TIFF size.
We detect the specific TIFF error (by string comparison so it's a bit
weak IMO yet it doesn't seem like libtiff provides anything better;
let's trust they don't change their error strings), then we reopen the
export dialog, pre-checking the BigTIFF checkbox newly created (and
making it insensitive). We still fail with error if an error happens the
second time (even for the same error).
plug-ins/file-tiff/file-tiff-io.c | 29 ++++++++
plug-ins/file-tiff/file-tiff-io.h | 8 ++-
plug-ins/file-tiff/file-tiff-save.c | 43 +++++++++---
plug-ins/file-tiff/file-tiff-save.h | 3 +-
plug-ins/file-tiff/file-tiff.c | 133 ++++++++++++++++++++++++------------
5 files changed, 160 insertions(+), 56 deletions(-)
---
diff --git a/plug-ins/file-tiff/file-tiff-io.c b/plug-ins/file-tiff/file-tiff-io.c
index eba1dc22ad..b97cc49959 100644
--- a/plug-ins/file-tiff/file-tiff-io.c
+++ b/plug-ins/file-tiff/file-tiff-io.c
@@ -31,6 +31,7 @@
#include "file-tiff-io.h"
+static gboolean tiff_file_size_error = FALSE;
typedef struct
{
@@ -150,6 +151,18 @@ tiff_open (GFile *file,
NULL, NULL);
}
+gboolean
+tiff_got_file_size_error (void)
+{
+ return tiff_file_size_error;
+}
+
+void
+tiff_reset_file_size_error (void)
+{
+ tiff_file_size_error = FALSE;
+}
+
static void
tiff_io_warning (const gchar *module,
const gchar *fmt,
@@ -247,6 +260,22 @@ tiff_io_error (const gchar *module,
if (! strcmp (fmt, "Compression algorithm does not support random access"))
return;
+ if (g_strcmp0 (fmt, "Maximum TIFF file size exceeded") == 0)
+ {
+ /* @module in my tests were "TIFFAppendToStrip" but I wonder if
+ * this same error could not happen with other "modules".
+ */
+ tiff_file_size_error = TRUE;
+ }
+ else
+ {
+ gchar *msg = g_strdup_vprintf (fmt, ap);
+
+ /* Easier for debugging to at least print messages on stderr. */
+ g_printerr ("LibTiff error: [%s] %s\n", module, msg);
+ g_free (msg);
+ }
+
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, ap);
}
diff --git a/plug-ins/file-tiff/file-tiff-io.h b/plug-ins/file-tiff/file-tiff-io.h
index fc26357758..3c910a7575 100644
--- a/plug-ins/file-tiff/file-tiff-io.h
+++ b/plug-ins/file-tiff/file-tiff-io.h
@@ -41,9 +41,11 @@ static const TIFFFieldInfo geotifftags_fieldinfo[] = {
{ GEOTIFF_ASCIIPARAMS, -1, -1, TIFF_ASCII, FIELD_CUSTOM, TRUE, FALSE, "GeoAsciiParams" }
};
-TIFF * tiff_open (GFile *file,
- const gchar *mode,
- GError **error);
+TIFF * tiff_open (GFile *file,
+ const gchar *mode,
+ GError **error);
+gboolean tiff_got_file_size_error (void);
+void tiff_reset_file_size_error (void);
#endif /* __FILE_TIFF_IO_H__ */
diff --git a/plug-ins/file-tiff/file-tiff-save.c b/plug-ins/file-tiff/file-tiff-save.c
index fb78042866..e88084e785 100644
--- a/plug-ins/file-tiff/file-tiff-save.c
+++ b/plug-ins/file-tiff/file-tiff-save.c
@@ -805,7 +805,8 @@ save_layer (TIFF *tif,
if (!success)
{
- g_message (_("Failed a scanline write on row %d"), row);
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ _("Failed a scanline write on row %d"), row);
goto out;
}
}
@@ -1144,6 +1145,7 @@ out:
gimp_progress_update (1.0);
g_list_free (layers);
+
return status;
}
@@ -1196,7 +1198,8 @@ save_dialog (GimpImage *image,
gboolean has_alpha,
gboolean is_monochrome,
gboolean is_indexed,
- gboolean is_multi_layer)
+ gboolean is_multi_layer,
+ gboolean classic_tiff_failed)
{
GtkWidget *dialog;
GtkListStore *store;
@@ -1222,6 +1225,21 @@ save_dialog (GimpImage *image,
GIMP_PROCEDURE_CONFIG (config),
image);
+ if (classic_tiff_failed)
+ {
+ GtkWidget *bigtiff_checkbox;
+
+ gimp_procedure_dialog_get_label (GIMP_PROCEDURE_DIALOG (dialog),
+ "big-tif-warning",
+ "\xe2\x9a\xa0 Warning: maximum TIFF file size exceeded. "
+ "Retry as BigTIFF or cancel.");
+ g_object_set (config, "bigtiff", TRUE, NULL);
+ bigtiff_checkbox = gimp_procedure_dialog_get_widget (GIMP_PROCEDURE_DIALOG (dialog),
+ "bigtiff",
+ G_TYPE_NONE);
+ gtk_widget_set_sensitive (bigtiff_checkbox, FALSE);
+ }
+
store =
gimp_int_store_new (_("None"), GIMP_COMPRESSION_NONE,
_("LZW"), GIMP_COMPRESSION_LZW,
@@ -1267,12 +1285,21 @@ save_dialog (GimpImage *image,
"save-geotiff",
has_geotiff, NULL, NULL, FALSE);
- gimp_procedure_dialog_fill (GIMP_PROCEDURE_DIALOG (dialog),
- "compression",
- "bigtiff",
- "layers-frame",
- "save-transparent-pixels",
- NULL);
+ if (classic_tiff_failed)
+ gimp_procedure_dialog_fill (GIMP_PROCEDURE_DIALOG (dialog),
+ "compression",
+ "big-tif-warning",
+ "bigtiff",
+ "layers-frame",
+ "save-transparent-pixels",
+ NULL);
+ else
+ gimp_procedure_dialog_fill (GIMP_PROCEDURE_DIALOG (dialog),
+ "compression",
+ "bigtiff",
+ "layers-frame",
+ "save-transparent-pixels",
+ NULL);
g_object_get (config,
"compression", &compression,
diff --git a/plug-ins/file-tiff/file-tiff-save.h b/plug-ins/file-tiff/file-tiff-save.h
index db50ce49cf..7b0dd19841 100644
--- a/plug-ins/file-tiff/file-tiff-save.h
+++ b/plug-ins/file-tiff/file-tiff-save.h
@@ -36,7 +36,8 @@ gboolean save_dialog (GimpImage *image,
gboolean has_alpha,
gboolean is_monochrome,
gboolean is_indexed,
- gboolean is_multi_layer);
+ gboolean is_multi_layer,
+ gboolean classic_tiff_failed);
#endif /* __FILE_TIFF_SAVE_H__ */
diff --git a/plug-ins/file-tiff/file-tiff.c b/plug-ins/file-tiff/file-tiff.c
index d5b2245f49..77577aee66 100644
--- a/plug-ins/file-tiff/file-tiff.c
+++ b/plug-ins/file-tiff/file-tiff.c
@@ -50,6 +50,7 @@
#include <libgimp/gimpui.h>
#include "file-tiff.h"
+#include "file-tiff-io.h"
#include "file-tiff-load.h"
#include "file-tiff-save.h"
@@ -77,28 +78,38 @@ struct _TiffClass
#define TIFF_TYPE (tiff_get_type ())
#define TIFF (obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TIFF_TYPE, Tiff))
-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,
- const GimpValueArray *args,
- gpointer run_data);
-static GimpValueArray * tiff_save (GimpProcedure *procedure,
- GimpRunMode run_mode,
- GimpImage *image,
- gint n_drawables,
- GimpDrawable **drawables,
- GFile *file,
- const GimpValueArray *args,
- gpointer run_data);
-
-static gboolean image_is_monochrome (GimpImage *image);
-static gboolean image_is_multi_layer (GimpImage *image);
+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,
+ const GimpValueArray *args,
+ gpointer run_data);
+static GimpValueArray * tiff_save (GimpProcedure *procedure,
+ GimpRunMode run_mode,
+ GimpImage *image,
+ gint n_drawables,
+ GimpDrawable **drawables,
+ GFile *file,
+ const GimpValueArray *args,
+ gpointer run_data);
+static GimpPDBStatusType tiff_save_rec (GimpProcedure *procedure,
+ GimpRunMode run_mode,
+ GimpImage *orig_image,
+ gint n_orig_drawables,
+ GimpDrawable **orig_drawables,
+ GFile *file,
+ GimpProcedureConfig *config,
+ GimpMetadata *metadata,
+ gboolean retried,
+ GError **error);
+
+static gboolean image_is_monochrome (GimpImage *image);
+static gboolean image_is_multi_layer (GimpImage *image);
G_DEFINE_TYPE (Tiff, tiff, GIMP_TYPE_PLUG_IN)
@@ -316,11 +327,9 @@ tiff_save (GimpProcedure *procedure,
gpointer run_data)
{
GimpProcedureConfig *config;
- GimpPDBStatusType status = GIMP_PDB_SUCCESS;
- GimpExportReturn export = GIMP_EXPORT_CANCEL;
GimpMetadata *metadata;
- GimpImage *orig_image;
GError *error = NULL;
+ GimpPDBStatusType status = GIMP_PDB_SUCCESS;
INIT_I18N ();
gegl_init (NULL, NULL);
@@ -329,8 +338,6 @@ tiff_save (GimpProcedure *procedure,
metadata = gimp_procedure_config_begin_export (config, image, run_mode,
args, "image/tiff");
- orig_image = image;
-
switch (run_mode)
{
case GIMP_RUN_INTERACTIVE:
@@ -341,16 +348,45 @@ tiff_save (GimpProcedure *procedure,
break;
}
+ status = tiff_save_rec (procedure, run_mode, image,
+ n_drawables, drawables,
+ file, config, metadata, FALSE, &error);
+
+ gimp_procedure_config_end_export (config, image, file, status);
+ g_object_unref (config);
+
+ return gimp_procedure_new_return_values (procedure, status, error);
+}
+
+static GimpPDBStatusType
+tiff_save_rec (GimpProcedure *procedure,
+ GimpRunMode run_mode,
+ GimpImage *orig_image,
+ gint n_orig_drawables,
+ GimpDrawable **orig_drawables,
+ GFile *file,
+ GimpProcedureConfig *config,
+ GimpMetadata *metadata,
+ gboolean retried,
+ GError **error)
+{
+ GimpImage *image = orig_image;
+ GimpDrawable **drawables = orig_drawables;
+ gint n_drawables = n_orig_drawables;
+ GimpPDBStatusType status = GIMP_PDB_SUCCESS;
+ GimpExportReturn export = GIMP_EXPORT_CANCEL;
+ gboolean bigtiff = FALSE;
+
if (run_mode == GIMP_RUN_INTERACTIVE)
{
if (! save_dialog (orig_image, procedure, G_OBJECT (config),
n_drawables == 1 ? gimp_drawable_has_alpha (drawables[0]) : TRUE,
- image_is_monochrome (image),
- gimp_image_get_base_type (image) == GIMP_INDEXED,
- image_is_multi_layer (image)))
+ image_is_monochrome (orig_image),
+ gimp_image_get_base_type (orig_image) == GIMP_INDEXED,
+ image_is_multi_layer (orig_image),
+ retried))
{
- return gimp_procedure_new_return_values (procedure, GIMP_PDB_CANCEL,
- NULL);
+ return GIMP_PDB_CANCEL;
}
}
@@ -365,6 +401,7 @@ tiff_save (GimpProcedure *procedure,
gboolean crop_layers;
g_object_get (config,
+ "bigtiff", &bigtiff,
"compression", &compression,
"save-layers", &save_layers,
"crop-layers", &crop_layers,
@@ -386,7 +423,7 @@ tiff_save (GimpProcedure *procedure,
GIMP_EXPORT_CAN_HANDLE_ALPHA);
}
- if (save_layers && image_is_multi_layer (image))
+ if (save_layers && image_is_multi_layer (orig_image))
{
capabilities |= GIMP_EXPORT_CAN_HANDLE_LAYERS;
@@ -398,8 +435,7 @@ tiff_save (GimpProcedure *procedure,
capabilities);
if (export == GIMP_EXPORT_CANCEL)
- return gimp_procedure_new_return_values (procedure, GIMP_PDB_CANCEL,
- NULL);
+ return GIMP_PDB_CANCEL;
}
break;
@@ -420,23 +456,32 @@ tiff_save (GimpProcedure *procedure,
if (status == GIMP_PDB_SUCCESS)
{
- if (! save_image (file, image, orig_image, G_OBJECT (config), metadata,
- &error))
- {
- status = GIMP_PDB_EXECUTION_ERROR;
- }
+ if (! save_image (file, image, orig_image, G_OBJECT (config),
+ metadata, error))
+ status = GIMP_PDB_EXECUTION_ERROR;
}
- gimp_procedure_config_end_export (config, image, file, status);
- g_object_unref (config);
-
if (export == GIMP_EXPORT_EXPORT)
{
gimp_image_delete (image);
g_free (drawables);
}
- return gimp_procedure_new_return_values (procedure, status, error);
+ 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);
+
+ return tiff_save_rec (procedure, run_mode,
+ orig_image, n_orig_drawables, orig_drawables,
+ file, config, metadata, TRUE, error);
+ }
+
+ return status;
}
static gboolean
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]