Commit 75849694 authored by Tobias's avatar Tobias

plug-ins: Add layer support to TIFF writing

parent b9458f8a
......@@ -87,7 +87,7 @@ tiff_open (GFile *file,
tiff_io.stream = G_OBJECT (tiff_io.input);
}
else
else if(! strcmp (mode, "w"))
{
tiff_io.output = G_OUTPUT_STREAM (g_file_replace (file,
NULL, FALSE,
......@@ -98,6 +98,21 @@ tiff_open (GFile *file,
tiff_io.stream = G_OBJECT (tiff_io.output);
}
else if(! strcmp (mode, "a"))
{
GIOStream *iostream = G_IO_STREAM (g_file_open_readwrite (file, NULL,
error));
if (! iostream)
return NULL;
tiff_io.input = g_io_stream_get_input_stream (iostream);
tiff_io.output = g_io_stream_get_output_stream (iostream);
tiff_io.stream = G_OBJECT (iostream);
}
else
{
g_assert_not_reached ();
}
#if 0
#warning FIXME !can_seek code is broken
......@@ -383,7 +398,7 @@ tiff_io_close (thandle_t handle)
GError *error = NULL;
gboolean closed = FALSE;
if (io->input)
if (io->input && ! io->output)
{
closed = g_input_stream_close (io->input, NULL, &error);
}
......@@ -401,7 +416,14 @@ tiff_io_close (thandle_t handle)
}
}
closed = g_output_stream_close (io->output, NULL, &error);
if (io->input)
{
closed = g_io_stream_close (G_IO_STREAM (io->stream), NULL, &error);
}
else
{
closed = g_output_stream_close (io->output, NULL, &error);
}
}
if (! closed)
......
......@@ -98,7 +98,11 @@ static void load_separate (TIFF *tif,
gboolean is_bw,
gint extra);
static void load_paths (TIFF *tif,
gint image);
gint image,
gint width,
gint height,
gint offset_x,
gint offset_y);
static void fill_bit2byte (void);
static void convert_bit2byte (const guchar *src,
......@@ -137,6 +141,7 @@ load_dialog (TIFF *tif,
GtkWidget *dialog;
GtkWidget *vbox;
GtkWidget *selector;
GtkWidget *crop_option;
gint i;
gboolean run;
......@@ -160,7 +165,6 @@ load_dialog (TIFF *tif,
gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
vbox, TRUE, TRUE, 0);
gtk_widget_show (vbox);
/* Page Selector */
selector = gimp_page_selector_new ();
......@@ -186,10 +190,17 @@ load_dialog (TIFF *tif,
G_CALLBACK (gtk_window_activate_default),
dialog);
gtk_widget_show (selector);
/* Option to shrink the loaded image to its bounding box
or keep as much empty space as possible.
Note that there seems to be no way to keep the empty
space on the right and bottom. */
crop_option = gtk_check_button_new_with_label (_("Keep empty space around imported layers"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (crop_option),
pages->keep_empty_space);
gtk_box_pack_start (GTK_BOX (vbox), crop_option, TRUE, TRUE, 0);
/* Setup done; display the dialog */
gtk_widget_show (dialog);
gtk_widget_show_all (dialog);
/* run the dialog */
run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
......@@ -203,6 +214,9 @@ load_dialog (TIFF *tif,
gimp_page_selector_get_selected_pages (GIMP_PAGE_SELECTOR (selector),
&pages->n_pages);
pages->keep_empty_space =
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (crop_option));
/* select all if none selected */
if (pages->n_pages == 0)
{
......@@ -900,7 +914,11 @@ load_image (GFile *file,
gimp_image_set_colormap (image, cmap, (1 << bps));
}
load_paths (tif, image);
if (pages->target != GIMP_PAGE_SELECTOR_TARGET_IMAGES)
load_paths (tif, image, cols, rows,
layer_offset_x_pixel, layer_offset_y_pixel);
else
load_paths (tif, image, cols, rows, 0, 0);
/* Allocate ChannelData for all channels, even the background layer */
channel = g_new0 (ChannelData, extra + 1);
......@@ -1031,29 +1049,27 @@ load_image (GFile *file,
g_free (channel);
channel = NULL;
/* TODO: in GIMP 2.6, use a dialog to selectively enable the
* following code, as the save plug-in will then save layer offsets
* as well.
*/
/* compute bounding box of all layers read so far */
if (min_col > layer_offset_x_pixel)
min_col = layer_offset_x_pixel;
if (min_row > layer_offset_y_pixel)
min_row = layer_offset_y_pixel;
if (max_col < layer_offset_x_pixel + cols)
max_col = layer_offset_x_pixel + cols;
if (max_row < layer_offset_y_pixel + rows)
max_row = layer_offset_y_pixel + rows;
/* position the layer */
if (layer_offset_x_pixel > 0 ||
layer_offset_y_pixel > 0)
if (pages->target != GIMP_PAGE_SELECTOR_TARGET_IMAGES)
{
gimp_layer_set_offsets (layer,
layer_offset_x_pixel, layer_offset_y_pixel);
/* compute bounding box of all layers read so far */
if (min_col > layer_offset_x_pixel)
min_col = layer_offset_x_pixel;
if (min_row > layer_offset_y_pixel)
min_row = layer_offset_y_pixel;
if (max_col < layer_offset_x_pixel + cols)
max_col = layer_offset_x_pixel + cols;
if (max_row < layer_offset_y_pixel + rows)
max_row = layer_offset_y_pixel + rows;
/* position the layer */
if (layer_offset_x_pixel > 0 ||
layer_offset_y_pixel > 0)
{
gimp_layer_set_offsets (layer,
layer_offset_x_pixel,
layer_offset_y_pixel);
}
}
gimp_image_insert_layer (image, layer, -1, -1);
......@@ -1067,16 +1083,7 @@ load_image (GFile *file,
gimp_progress_update (1.0);
}
if (pages->target != GIMP_PAGE_SELECTOR_TARGET_IMAGES)
{
/* resize image to bounding box of all layers */
gimp_image_resize (image,
max_col - min_col, max_row - min_row,
-min_col, -min_row);
gimp_image_undo_enable (image);
}
else
if (pages->target == GIMP_PAGE_SELECTOR_TARGET_IMAGES)
{
GList *list = images_list;
......@@ -1094,6 +1101,22 @@ load_image (GFile *file,
g_list_free (images_list);
}
else
{
if (pages->keep_empty_space)
{
/* unfortunately we have no idea about empty space
at the bottom/right of layers */
min_col = 0;
min_row = 0;
}
/* resize image to bounding box of all layers */
gimp_image_resize (image,
max_col - min_col, max_row - min_row,
-min_col, -min_row);
gimp_image_undo_enable (image);
}
return image;
}
......@@ -1170,18 +1193,17 @@ load_rgba (TIFF *tif,
static void
load_paths (TIFF *tif,
gint image)
gint image,
gint width,
gint height,
gint offset_x,
gint offset_y)
{
gint width;
gint height;
gsize n_bytes;
gchar *bytes;
gint path_index;
gsize pos;
width = gimp_image_width (image);
height = gimp_image_height (image);
if (! TIFFGetField (tif, TIFFTAG_PHOTOSHOP, &n_bytes, &bytes))
return;
......@@ -1305,6 +1327,9 @@ load_paths (TIFF *tif,
gdouble f;
guint32 coord;
const gint size = j % 2 ? width : height;
const gint offset = j % 2 ? offset_x : offset_y;
val32 = (guint32 *) (bytes + rec + 2 + j * 4);
coord = GUINT32_FROM_BE (*val32);
......@@ -1316,7 +1341,7 @@ load_paths (TIFF *tif,
* first, gimp expects the horizontal
* component first. Sigh.
*/
points[pointcount * 6 + (j ^ 1)] = f * (j % 2 ? width : height);
points[pointcount * 6 + (j ^ 1)] = f * size + offset;
}
pointcount++;
......
......@@ -29,6 +29,7 @@ typedef struct
gint n_pages;
gint *pages;
GimpPageSelectorTarget target;
gboolean keep_empty_space;
} TiffSelectedPages;
......
This diff is collapsed.
......@@ -33,17 +33,19 @@ typedef struct
gboolean save_iptc;
gboolean save_thumbnail;
gboolean save_profile;
gboolean save_layers;
} TiffSaveVals;
gboolean save_image (GFile *file,
TiffSaveVals *tsvals,
gint32 image,
gint32 drawable,
gint32 orig_image,
const gchar *image_comment,
gint *saved_bpp,
GError **error);
gboolean save_image (GFile *file,
TiffSaveVals *tsvals,
gint32 image,
gint32 orig_image,
const gchar *image_comment,
gint *saved_bpp,
GimpMetadata *metadata,
GimpMetadataSaveFlags metadata_flags,
GError **error);
gboolean save_dialog (TiffSaveVals *tsvals,
const gchar *help_id,
......
......@@ -45,7 +45,6 @@
#include "config.h"
#include <tiffio.h>
#include <gexiv2/gexiv2.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
......@@ -90,7 +89,8 @@ static TiffSaveVals tsvals =
FALSE, /* save xmp */
FALSE, /* save iptc */
TRUE, /* save thumbnail */
TRUE /* save profile */
TRUE, /* save profile */
TRUE /* save layer */
};
static gchar *image_comment = NULL;
......@@ -221,7 +221,12 @@ run (const gchar *name,
pages.target = GIMP_PAGE_SELECTOR_TARGET_LAYERS;
gimp_get_data (LOAD_PROC, &pages.target);
gimp_get_data (LOAD_PROC "-target", &pages.target);
pages.keep_empty_space = TRUE;
gimp_get_data (LOAD_PROC "-keep-empty-space",
&pages.keep_empty_space);
pages.n_pages = pages.o_pages = TIFFNumberOfDirectories (tif);
......@@ -268,9 +273,13 @@ run (const gchar *name,
gint32 image;
gboolean resolution_loaded = FALSE;
gimp_set_data (LOAD_PROC,
gimp_set_data (LOAD_PROC "-target",
&pages.target, sizeof (pages.target));
gimp_set_data (LOAD_PROC "-keep-empty-space",
&pages.keep_empty_space,
sizeof (pages.keep_empty_space));
image = load_image (file, tif, &pages,
&resolution_loaded,
&error);
......@@ -347,7 +356,8 @@ run (const gchar *name,
GIMP_EXPORT_CAN_HANDLE_RGB |
GIMP_EXPORT_CAN_HANDLE_GRAY |
GIMP_EXPORT_CAN_HANDLE_INDEXED |
GIMP_EXPORT_CAN_HANDLE_ALPHA);
GIMP_EXPORT_CAN_HANDLE_ALPHA |
GIMP_EXPORT_CAN_HANDLE_LAYERS);
if (export == GIMP_EXPORT_CANCEL)
{
......@@ -462,55 +472,32 @@ run (const gchar *name,
file = g_file_new_for_uri (param[3].data.d_string);
if (save_image (file, &tsvals,
image, drawable, orig_image, image_comment,
&saved_bpp, &error))
/* saving with layers is not supporting blend modes, so people might
* prefer to save a flat copy. */
if (! tsvals.save_layers)
{
if (metadata)
{
/* See bug 758909: clear TIFFTAG_MIN/MAXSAMPLEVALUE because
* exiv2 saves them with wrong type and the original values
* could be invalid, see also bug 761823
*/
gexiv2_metadata_clear_tag (GEXIV2_METADATA (metadata),
"Exif.Image.0x0118");
gexiv2_metadata_clear_tag (GEXIV2_METADATA (metadata),
"Exif.Image.0x0119");
gexiv2_metadata_clear_tag (GEXIV2_METADATA (metadata),
"Exif.Image.PageNumber");
gimp_metadata_set_bits_per_sample (metadata, saved_bpp);
if (tsvals.save_exif)
metadata_flags |= GIMP_METADATA_SAVE_EXIF;
else
metadata_flags &= ~GIMP_METADATA_SAVE_EXIF;
if (tsvals.save_xmp)
metadata_flags |= GIMP_METADATA_SAVE_XMP;
else
metadata_flags &= ~GIMP_METADATA_SAVE_XMP;
if (tsvals.save_iptc)
metadata_flags |= GIMP_METADATA_SAVE_IPTC;
else
metadata_flags &= ~GIMP_METADATA_SAVE_IPTC;
/* never save metadata thumbnails for TIFF, see bug #729952 */
metadata_flags &= ~GIMP_METADATA_SAVE_THUMBNAIL;
if (tsvals.save_profile)
metadata_flags |= GIMP_METADATA_SAVE_COLOR_PROFILE;
else
metadata_flags &= ~GIMP_METADATA_SAVE_COLOR_PROFILE;
gimp_image_metadata_save_finish (image,
"image/tiff",
metadata, metadata_flags,
file, NULL);
}
gint32 transp;
/* FIXME: Do we have to update drawable, too? */
image = gimp_image_duplicate (image);
/* borrowed from ./libgimp/gimpexport.c:export_merge()
* this makes sure that the exported file size is correct. */
transp = gimp_layer_new (image, "-",
gimp_image_width (image),
gimp_image_height (image),
gimp_drawable_type (drawable) | 1,
100.0, GIMP_LAYER_MODE_NORMAL);
gimp_image_insert_layer (image, transp, -1, 1);
gimp_selection_none (image);
gimp_drawable_edit_clear (transp);
gimp_image_merge_visible_layers (image, GIMP_CLIP_TO_IMAGE);
}
if (save_image (file, &tsvals, image, orig_image, image_comment,
&saved_bpp, metadata, metadata_flags, &error))
{
/* Store mvals data */
gimp_set_data (SAVE_PROC, &tsvals, sizeof (TiffSaveVals));
}
......
......@@ -115,6 +115,20 @@
<property name="position">8</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="save-layers">
<property name="label" translatable="yes">Save layers</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">9</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame2">
<property name="visible">True</property>
......@@ -144,7 +158,7 @@
<property name="expand">True</property>
<property name="fill">True</property>
<property name="padding">3</property>
<property name="position">11</property>
<property name="position">12</property>
</packing>
</child>
</object>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment