summaryrefslogtreecommitdiff
path: root/gdk-pixbuf/io-jpeg.c
diff options
context:
space:
mode:
authorMatthias Clasen <maclas@gmx.de>2004-01-07 01:57:42 +0000
committerMatthias Clasen <matthiasc@src.gnome.org>2004-01-07 01:57:42 +0000
commit03376d79faf862ada7fca924aed681156398d574 (patch)
tree914249bd1d2864773bec4eadf2f3f533f9523fac /gdk-pixbuf/io-jpeg.c
parent5b26e695a1fc70c99b58f2e9c4c922412fbd1a08 (diff)
downloadgtk+-03376d79faf862ada7fca924aed681156398d574.tar.gz
New public API to save pixbufs to non-file locations. (#82203, Tim Evans)
Wed Jan 7 02:41:14 2004 Matthias Clasen <maclas@gmx.de> * gdk-pixbuf-io.c (gdk_pixbuf_save_to_bufferv): * gdk-pixbuf-io.c (gdk_pixbuf_save_to_buffer): * gdk-pixbuf-io.c (gdk_pixbuf_save_to_callbackv): * gdk-pixbuf-io.c (gdk_pixbuf_save_to_callback): New public API to save pixbufs to non-file locations. (#82203, Tim Evans) * gdk-pixbuf.h: * gdk_pixbuf.def: Declare the new public API. * gdk-pixbuf-io.h: Add save_to_callback to the module interface. * io-jpeg.c: * io-png.c: Implement save_to_callback. * gdk-pixbuf-io.c (gdk_pixbuf_savev): * gdk-pixbuf-io.c (gdk_pixbuf_save): Update documentation. * gdk-pixbuf-io.c (gdk_pixbuf_real_save): Support saving via image_module->save_to_callback. * gdk-pixbuf-io.c (gdk_pixbuf_real_save_to_callback): New generic save_to_callback function which falls back to image_module->save on a temp file.
Diffstat (limited to 'gdk-pixbuf/io-jpeg.c')
-rw-r--r--gdk-pixbuf/io-jpeg.c138
1 files changed, 131 insertions, 7 deletions
diff --git a/gdk-pixbuf/io-jpeg.c b/gdk-pixbuf/io-jpeg.c
index 85d75dfe60..4dd5f8f2a5 100644
--- a/gdk-pixbuf/io-jpeg.c
+++ b/gdk-pixbuf/io-jpeg.c
@@ -780,12 +780,85 @@ gdk_pixbuf__jpeg_image_load_increment (gpointer data,
return TRUE;
}
+/* Save */
+
+#define TO_FUNCTION_BUF_SIZE 4096
+
+typedef struct {
+ struct jpeg_destination_mgr pub;
+ JOCTET *buffer;
+ GdkPixbufSaveFunc save_func;
+ gpointer user_data;
+ GError **error;
+} ToFunctionDestinationManager;
+
+void
+to_callback_init (j_compress_ptr cinfo)
+{
+ ToFunctionDestinationManager *destmgr;
+
+ destmgr = (ToFunctionDestinationManager*) cinfo->dest;
+ destmgr->pub.next_output_byte = destmgr->buffer;
+ destmgr->pub.free_in_buffer = TO_FUNCTION_BUF_SIZE;
+}
+
+static void
+to_callback_do_write (j_compress_ptr cinfo, gsize length)
+{
+ ToFunctionDestinationManager *destmgr;
+
+ destmgr = (ToFunctionDestinationManager*) cinfo->dest;
+ if (!destmgr->save_func (destmgr->buffer,
+ length,
+ destmgr->error,
+ destmgr->user_data)) {
+ struct error_handler_data *errmgr;
+
+ errmgr = (struct error_handler_data *) cinfo->err;
+ /* Use a default error message if the callback didn't set one,
+ * which it should have.
+ */
+ if (errmgr->error && *errmgr->error == NULL) {
+ g_set_error (errmgr->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ "write function failed");
+ }
+ siglongjmp (errmgr->setjmp_buffer, 1);
+ g_assert_not_reached ();
+ }
+}
+
+static guchar
+to_callback_empty_output_buffer (j_compress_ptr cinfo)
+{
+ ToFunctionDestinationManager *destmgr;
+
+ destmgr = (ToFunctionDestinationManager*) cinfo->dest;
+ to_callback_do_write (cinfo, TO_FUNCTION_BUF_SIZE);
+ destmgr->pub.next_output_byte = destmgr->buffer;
+ destmgr->pub.free_in_buffer = TO_FUNCTION_BUF_SIZE;
+ return TRUE;
+}
+
+void
+to_callback_terminate (j_compress_ptr cinfo)
+{
+ ToFunctionDestinationManager *destmgr;
+
+ destmgr = (ToFunctionDestinationManager*) cinfo->dest;
+ to_callback_do_write (cinfo, TO_FUNCTION_BUF_SIZE - destmgr->pub.free_in_buffer);
+}
+
static gboolean
-gdk_pixbuf__jpeg_image_save (FILE *f,
- GdkPixbuf *pixbuf,
- gchar **keys,
- gchar **values,
- GError **error)
+real_save_jpeg (GdkPixbuf *pixbuf,
+ gchar **keys,
+ gchar **values,
+ GError **error,
+ gboolean to_callback,
+ FILE *f,
+ GdkPixbufSaveFunc save_func,
+ gpointer user_data)
{
/* FIXME error handling is broken */
@@ -800,6 +873,9 @@ gdk_pixbuf__jpeg_image_save (FILE *f,
int w, h = 0;
int rowstride = 0;
struct error_handler_data jerr;
+ ToFunctionDestinationManager to_callback_destmgr;
+
+ to_callback_destmgr.buffer = NULL;
if (keys && *keys) {
gchar **kiter = keys;
@@ -854,7 +930,9 @@ gdk_pixbuf__jpeg_image_save (FILE *f,
pixels = gdk_pixbuf_get_pixels (pixbuf);
g_return_val_if_fail (pixels != NULL, FALSE);
- /* allocate a small buffer to convert image data */
+ /* Allocate a small buffer to convert image data,
+ * and a larger buffer if doing to_callback save.
+ */
buf = g_try_malloc (w * 3 * sizeof (guchar));
if (!buf) {
g_set_error (error,
@@ -863,6 +941,16 @@ gdk_pixbuf__jpeg_image_save (FILE *f,
_("Couldn't allocate memory for loading JPEG file"));
return FALSE;
}
+ if (to_callback) {
+ to_callback_destmgr.buffer = g_try_malloc (TO_FUNCTION_BUF_SIZE);
+ if (!to_callback_destmgr.buffer) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+ _("Couldn't allocate memory for loading JPEG file"));
+ return FALSE;
+ }
+ }
/* set up error handling */
jerr.pub.error_exit = fatal_error_handler;
@@ -873,12 +961,23 @@ gdk_pixbuf__jpeg_image_save (FILE *f,
if (sigsetjmp (jerr.setjmp_buffer, 1)) {
jpeg_destroy_compress (&cinfo);
g_free (buf);
+ g_free (to_callback_destmgr.buffer);
return FALSE;
}
/* setup compress params */
jpeg_create_compress (&cinfo);
- jpeg_stdio_dest (&cinfo, f);
+ if (to_callback) {
+ to_callback_destmgr.pub.init_destination = to_callback_init;
+ to_callback_destmgr.pub.empty_output_buffer = to_callback_empty_output_buffer;
+ to_callback_destmgr.pub.term_destination = to_callback_terminate;
+ to_callback_destmgr.error = error;
+ to_callback_destmgr.save_func = save_func;
+ to_callback_destmgr.user_data = user_data;
+ cinfo.dest = (struct jpeg_destination_mgr*) &to_callback_destmgr;
+ } else {
+ jpeg_stdio_dest (&cinfo, f);
+ }
cinfo.image_width = w;
cinfo.image_height = h;
cinfo.input_components = 3;
@@ -909,9 +1008,33 @@ gdk_pixbuf__jpeg_image_save (FILE *f,
jpeg_finish_compress (&cinfo);
jpeg_destroy_compress(&cinfo);
g_free (buf);
+ g_free (to_callback_destmgr.buffer);
return TRUE;
}
+static gboolean
+gdk_pixbuf__jpeg_image_save (FILE *f,
+ GdkPixbuf *pixbuf,
+ gchar **keys,
+ gchar **values,
+ GError **error)
+{
+ return real_save_jpeg (pixbuf, keys, values, error,
+ FALSE, f, NULL, NULL);
+}
+
+static gboolean
+gdk_pixbuf__jpeg_image_save_to_callback (GdkPixbufSaveFunc save_func,
+ gpointer user_data,
+ GdkPixbuf *pixbuf,
+ gchar **keys,
+ gchar **values,
+ GError **error)
+{
+ return real_save_jpeg (pixbuf, keys, values, error,
+ TRUE, NULL, save_func, user_data);
+}
+
void
MODULE_ENTRY (jpeg, fill_vtable) (GdkPixbufModule *module)
{
@@ -920,6 +1043,7 @@ MODULE_ENTRY (jpeg, fill_vtable) (GdkPixbufModule *module)
module->stop_load = gdk_pixbuf__jpeg_image_stop_load;
module->load_increment = gdk_pixbuf__jpeg_image_load_increment;
module->save = gdk_pixbuf__jpeg_image_save;
+ module->save_to_callback = gdk_pixbuf__jpeg_image_save_to_callback;
}
void