plug-ins: port file-tiff to GIO
Using code from gegl:tiff-load and gegl:tiff-save which has a mode for local buffering if the input/output streams don't support seeking. Unfortunately this code is broken and is disabled for now.
This commit is contained in:
@ -32,12 +32,41 @@
|
||||
#include "file-tiff-io.h"
|
||||
|
||||
|
||||
static void tiff_warning (const gchar *module,
|
||||
const gchar *fmt,
|
||||
va_list ap) G_GNUC_PRINTF (2, 0);
|
||||
static void tiff_error (const gchar *module,
|
||||
const gchar *fmt,
|
||||
va_list ap) G_GNUC_PRINTF (2, 0);
|
||||
typedef struct
|
||||
{
|
||||
GFile *file;
|
||||
GObject *stream;
|
||||
GInputStream *input;
|
||||
GOutputStream *output;
|
||||
gboolean can_seek;
|
||||
|
||||
gchar *buffer;
|
||||
gsize allocated;
|
||||
gsize used;
|
||||
gsize position;
|
||||
} TiffIO;
|
||||
|
||||
|
||||
static void tiff_io_warning (const gchar *module,
|
||||
const gchar *fmt,
|
||||
va_list ap) G_GNUC_PRINTF (2, 0);
|
||||
static void tiff_io_error (const gchar *module,
|
||||
const gchar *fmt,
|
||||
va_list ap) G_GNUC_PRINTF (2, 0);
|
||||
static tsize_t tiff_io_read (thandle_t handle,
|
||||
tdata_t buffer,
|
||||
tsize_t size);
|
||||
static tsize_t tiff_io_write (thandle_t handle,
|
||||
tdata_t buffer,
|
||||
tsize_t size);
|
||||
static toff_t tiff_io_seek (thandle_t handle,
|
||||
toff_t offset,
|
||||
gint whence);
|
||||
static gint tiff_io_close (thandle_t handle);
|
||||
static toff_t tiff_io_get_file_size (thandle_t handle);
|
||||
|
||||
|
||||
static TiffIO tiff_io = { 0, };
|
||||
|
||||
|
||||
TIFF *
|
||||
@ -45,33 +74,51 @@ tiff_open (GFile *file,
|
||||
const gchar *mode,
|
||||
GError **error)
|
||||
{
|
||||
gchar *filename = g_file_get_path (file);
|
||||
TIFFSetWarningHandler (tiff_io_warning);
|
||||
TIFFSetErrorHandler (tiff_io_error);
|
||||
|
||||
TIFFSetWarningHandler (tiff_warning);
|
||||
TIFFSetErrorHandler (tiff_error);
|
||||
tiff_io.file = file;
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
gunichar2 *utf16_filename = g_utf8_to_utf16 (filename, -1, NULL, NULL, error);
|
||||
|
||||
if (utf16_filename)
|
||||
if (! strcmp (mode, "r"))
|
||||
{
|
||||
TIFF *tif = TIFFOpenW (utf16_filename, mode);
|
||||
tiff_io.input = G_INPUT_STREAM (g_file_read (file, NULL, error));
|
||||
if (! tiff_io.input)
|
||||
return NULL;
|
||||
|
||||
g_free (utf16_filename);
|
||||
tiff_io.stream = G_OBJECT (tiff_io.input);
|
||||
}
|
||||
else
|
||||
{
|
||||
tiff_io.output = G_OUTPUT_STREAM (g_file_replace (file,
|
||||
NULL, FALSE,
|
||||
G_FILE_CREATE_NONE,
|
||||
NULL, error));
|
||||
if (! tiff_io.output)
|
||||
return FALSE;
|
||||
|
||||
return tif;
|
||||
tiff_io.stream = G_OBJECT (tiff_io.output);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
return TIFFOpen (filename, mode);
|
||||
#if 0
|
||||
#warning FIXME !can_seek code is broken
|
||||
tiff_io.can_seek = g_seekable_can_seek (G_SEEKABLE (tiff_io.stream));
|
||||
#endif
|
||||
tiff_io.can_seek = TRUE;
|
||||
|
||||
return TIFFClientOpen ("file-tiff", mode,
|
||||
(thandle_t) &tiff_io,
|
||||
tiff_io_read,
|
||||
tiff_io_write,
|
||||
tiff_io_seek,
|
||||
tiff_io_close,
|
||||
tiff_io_get_file_size,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
tiff_warning (const gchar *module,
|
||||
const gchar *fmt,
|
||||
va_list ap)
|
||||
tiff_io_warning (const gchar *module,
|
||||
const gchar *fmt,
|
||||
va_list ap)
|
||||
{
|
||||
gint tag = 0;
|
||||
|
||||
@ -116,9 +163,9 @@ tiff_warning (const gchar *module,
|
||||
}
|
||||
|
||||
static void
|
||||
tiff_error (const gchar *module,
|
||||
const gchar *fmt,
|
||||
va_list ap)
|
||||
tiff_io_error (const gchar *module,
|
||||
const gchar *fmt,
|
||||
va_list ap)
|
||||
{
|
||||
/* Workaround for: http://bugzilla.gnome.org/show_bug.cgi?id=132297
|
||||
* Ignore the errors related to random access and JPEG compression
|
||||
@ -128,3 +175,273 @@ tiff_error (const gchar *module,
|
||||
|
||||
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, ap);
|
||||
}
|
||||
|
||||
static tsize_t
|
||||
tiff_io_read (thandle_t handle,
|
||||
tdata_t buffer,
|
||||
tsize_t size)
|
||||
{
|
||||
TiffIO *io = (TiffIO *) handle;
|
||||
GError *error = NULL;
|
||||
gssize read = -1;
|
||||
|
||||
if (io->can_seek)
|
||||
{
|
||||
gsize bytes_read = 0;
|
||||
|
||||
if (! g_input_stream_read_all (io->input,
|
||||
(void *) buffer, (gsize) size,
|
||||
&bytes_read,
|
||||
NULL, &error))
|
||||
{
|
||||
g_printerr ("%s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
read = bytes_read;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (io->position + size > io->used)
|
||||
{
|
||||
gsize missing;
|
||||
gsize bytes_read;
|
||||
|
||||
missing = io->position + size - io->used;
|
||||
|
||||
if (io->used + missing > io->allocated)
|
||||
{
|
||||
gchar *new_buffer;
|
||||
gsize new_size = 1;
|
||||
gsize needed;
|
||||
|
||||
needed = io->used + missing - io->allocated;
|
||||
while (new_size < io->allocated + needed)
|
||||
new_size *= 2;
|
||||
|
||||
new_buffer = g_try_realloc (io->buffer, new_size);
|
||||
if (! new_buffer)
|
||||
return -1;
|
||||
|
||||
io->buffer = new_buffer;
|
||||
io->allocated = new_size;
|
||||
}
|
||||
|
||||
if (! g_input_stream_read_all (io->input,
|
||||
(void *) (io->buffer + io->used),
|
||||
missing,
|
||||
&bytes_read, NULL, &error))
|
||||
{
|
||||
g_printerr ("%s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
io->used += bytes_read;
|
||||
}
|
||||
|
||||
g_assert (io->position + size <= io->used);
|
||||
|
||||
memcpy (buffer, io->buffer + io->position, size);
|
||||
io->position += size;
|
||||
|
||||
read = size;
|
||||
}
|
||||
|
||||
return (tsize_t) read;
|
||||
}
|
||||
|
||||
static tsize_t
|
||||
tiff_io_write (thandle_t handle,
|
||||
tdata_t buffer,
|
||||
tsize_t size)
|
||||
{
|
||||
TiffIO *io = (TiffIO *) handle;
|
||||
GError *error = NULL;
|
||||
gssize written = -1;
|
||||
|
||||
if (io->can_seek)
|
||||
{
|
||||
gsize bytes_written = 0;
|
||||
|
||||
if (! g_output_stream_write_all (io->output,
|
||||
(void *) buffer, (gsize) size,
|
||||
&bytes_written,
|
||||
NULL, &error))
|
||||
{
|
||||
g_printerr ("%s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
written = bytes_written;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (io->position + size > io->allocated)
|
||||
{
|
||||
gchar *new_buffer;
|
||||
gsize new_size;
|
||||
|
||||
new_size = io->position + size;
|
||||
|
||||
new_buffer = g_try_realloc (io->buffer, new_size);
|
||||
if (! new_buffer)
|
||||
return -1;
|
||||
|
||||
io->buffer = new_buffer;
|
||||
io->allocated = new_size;
|
||||
}
|
||||
|
||||
g_assert (io->position + size <= io->allocated);
|
||||
|
||||
memcpy (io->buffer + io->position, buffer, size);
|
||||
io->position += size;
|
||||
|
||||
io->used = MAX (io->used, io->position);
|
||||
|
||||
written = size;
|
||||
}
|
||||
|
||||
return (tsize_t) written;
|
||||
}
|
||||
|
||||
static GSeekType
|
||||
lseek_to_seek_type (gint whence)
|
||||
{
|
||||
switch (whence)
|
||||
{
|
||||
default:
|
||||
case SEEK_SET:
|
||||
return G_SEEK_SET;
|
||||
|
||||
case SEEK_CUR:
|
||||
return G_SEEK_CUR;
|
||||
|
||||
case SEEK_END:
|
||||
return G_SEEK_END;
|
||||
}
|
||||
}
|
||||
|
||||
static toff_t
|
||||
tiff_io_seek (thandle_t handle,
|
||||
toff_t offset,
|
||||
gint whence)
|
||||
{
|
||||
TiffIO *io = (TiffIO *) handle;
|
||||
GError *error = NULL;
|
||||
gboolean sought = FALSE;
|
||||
goffset position = -1;
|
||||
|
||||
if (io->can_seek)
|
||||
{
|
||||
sought = g_seekable_seek (G_SEEKABLE (io->stream),
|
||||
(goffset) offset, lseek_to_seek_type (whence),
|
||||
NULL, &error);
|
||||
if (sought)
|
||||
{
|
||||
position = g_seekable_tell (G_SEEKABLE (io->stream));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_printerr ("%s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (whence)
|
||||
{
|
||||
default:
|
||||
case SEEK_SET:
|
||||
if (offset <= io->used)
|
||||
position = io->position = offset;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
if (io->position + offset <= io->used)
|
||||
position = io->position += offset;
|
||||
break;
|
||||
|
||||
case G_SEEK_END:
|
||||
if (io->used + offset <= io->used)
|
||||
position = io->position = io->used + offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (toff_t) position;
|
||||
}
|
||||
|
||||
static gint
|
||||
tiff_io_close (thandle_t handle)
|
||||
{
|
||||
TiffIO *io = (TiffIO *) handle;
|
||||
GError *error = NULL;
|
||||
gboolean closed = FALSE;
|
||||
|
||||
if (io->input)
|
||||
{
|
||||
closed = g_input_stream_close (io->input, NULL, &error);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! io->can_seek && io->buffer && io->allocated)
|
||||
{
|
||||
if (! g_output_stream_write_all (io->output,
|
||||
(void *) io->buffer,
|
||||
io->allocated,
|
||||
NULL, NULL, &error))
|
||||
{
|
||||
g_printerr ("%s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
|
||||
closed = g_output_stream_close (io->output, NULL, &error);
|
||||
}
|
||||
|
||||
if (! closed)
|
||||
{
|
||||
g_printerr ("%s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
g_object_unref (io->stream);
|
||||
io->stream = NULL;
|
||||
io->input = NULL;
|
||||
io->output = NULL;
|
||||
|
||||
g_free (io->buffer);
|
||||
io->buffer = NULL;
|
||||
|
||||
io->allocated = 0;
|
||||
io->used = 0;
|
||||
io->position = 0;
|
||||
|
||||
return closed ? 0 : -1;
|
||||
}
|
||||
|
||||
static toff_t
|
||||
tiff_io_get_file_size (thandle_t handle)
|
||||
{
|
||||
TiffIO *io = (TiffIO *) handle;
|
||||
GError *error = NULL;
|
||||
GFileInfo *info;
|
||||
goffset size = 0;
|
||||
|
||||
info = g_file_query_info (io->file,
|
||||
G_FILE_ATTRIBUTE_STANDARD_SIZE,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
NULL, &error);
|
||||
if (! info)
|
||||
{
|
||||
g_printerr ("%s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
else
|
||||
{
|
||||
size = g_file_info_get_size (info);
|
||||
g_object_unref (info);
|
||||
}
|
||||
|
||||
return (toff_t) size;
|
||||
}
|
||||
|
||||
@ -145,6 +145,7 @@ query (void)
|
||||
load_args, load_return_vals);
|
||||
|
||||
gimp_register_file_handler_mime (LOAD_PROC, "image/tiff");
|
||||
gimp_register_file_handler_uri (LOAD_PROC);
|
||||
gimp_register_magic_load_handler (LOAD_PROC,
|
||||
"tif,tiff",
|
||||
"",
|
||||
@ -165,6 +166,7 @@ query (void)
|
||||
save_args_old, NULL);
|
||||
|
||||
gimp_register_file_handler_mime (SAVE_PROC, "image/tiff");
|
||||
gimp_register_file_handler_uri (SAVE_PROC);
|
||||
gimp_register_save_handler (SAVE_PROC, "tif,tiff", "");
|
||||
|
||||
gimp_install_procedure (SAVE2_PROC,
|
||||
@ -207,7 +209,7 @@ run (const gchar *name,
|
||||
|
||||
if (strcmp (name, LOAD_PROC) == 0)
|
||||
{
|
||||
GFile *file = g_file_new_for_path (param[1].data.d_string);
|
||||
GFile *file = g_file_new_for_uri (param[1].data.d_string);
|
||||
TIFF *tif;
|
||||
|
||||
tif = tiff_open (file, "r", &error);
|
||||
@ -456,7 +458,7 @@ run (const gchar *name,
|
||||
GFile *file;
|
||||
gint saved_bpp;
|
||||
|
||||
file = g_file_new_for_path (param[3].data.d_string);
|
||||
file = g_file_new_for_uri (param[3].data.d_string);
|
||||
|
||||
if (save_image (file, &tsvals,
|
||||
image, drawable, orig_image, image_comment,
|
||||
|
||||
Reference in New Issue
Block a user