[gegl] jpg: Port jpg-save operation to GIO
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] jpg: Port jpg-save operation to GIO
- Date: Fri, 28 Apr 2017 23:23:21 +0000 (UTC)
commit 8d784c475fa68a0de805503dcf9b3b814aa157c3
Author: Martin Blanchard <tchaik gmx com>
Date: Sun Jul 3 22:43:54 2016 +0200
jpg: Port jpg-save operation to GIO
Make use of gegl_gio_open_output_stream() service. No more direct
fopen() call for output.
https://bugzilla.gnome.org/show_bug.cgi?id=768351
operations/external/jpg-save.c | 224 +++++++++++++++++++++++++++++-----------
1 files changed, 165 insertions(+), 59 deletions(-)
---
diff --git a/operations/external/jpg-save.c b/operations/external/jpg-save.c
index 674c1d8..b7b281e 100644
--- a/operations/external/jpg-save.c
+++ b/operations/external/jpg-save.c
@@ -23,22 +23,22 @@
#ifdef GEGL_PROPERTIES
property_file_path (path, _("File"), "")
- description (_("Target path and filename, use '-' for stdout"))
+ description (_("Target path and filename, use '-' for stdout"))
-property_int (quality, _("Quality"), 90)
- description (_("JPEG compression quality (between 1 and 100)"))
- value_range (1, 100)
+property_int (quality, _("Quality"), 90)
+ description (_("JPEG compression quality (between 1 and 100)"))
+ value_range (1, 100)
-property_int (smoothing, _("Smoothing"), 0)
- description(_("Smoothing factor from 1 to 100; 0 disables smoothing"))
- value_range (0, 100)
+property_int (smoothing, _("Smoothing"), 0)
+ description(_("Smoothing factor from 1 to 100; 0 disables smoothing"))
+ value_range (0, 100)
property_boolean (optimize, _("Optimize"), TRUE)
- description (_("Use optimized huffman tables"))
+ description (_("Use optimized huffman tables"))
property_boolean (progressive, _("Progressive"), TRUE)
- description (_("Create progressive JPEG images"))
+ description (_("Create progressive JPEG images"))
property_boolean (grayscale, _("Grayscale"), FALSE)
- description (_("Create a grayscale (monochrome) image"))
+ description (_("Create a grayscale (monochrome) image"))
#else
@@ -46,46 +46,119 @@ property_boolean (grayscale, _("Grayscale"), FALSE)
#define GEGL_OP_NAME jpg_save
#define GEGL_OP_C_SOURCE jpg-save.c
-#include "gegl-op.h"
-#include <stdio.h>
+#include <gegl-op.h>
+#include <gegl-gio-private.h>
+#include <stdio.h> /* jpeglib.h needs FILE... */
#include <jpeglib.h>
-static gint
-gegl_buffer_export_jpg (GeglBuffer *gegl_buffer,
- const gchar *path,
- gint quality,
- gint smoothing,
- gboolean optimize,
- gboolean progressive,
- gboolean grayscale,
- gint src_x,
- gint src_y,
- gint width,
- gint height)
+static const gsize buffer_size = 4096;
+
+static void
+init_buffer (j_compress_ptr cinfo)
{
- FILE *fp;
- struct jpeg_compress_struct cinfo;
- struct jpeg_error_mgr jerr;
- JSAMPROW row_pointer[1];
- const Babl *format;
+ struct jpeg_destination_mgr *dest = cinfo->dest;
+ guchar *buffer;
- if (!strcmp (path, "-"))
+ buffer = g_try_new (guchar, buffer_size);
+
+ g_assert (buffer != NULL);
+
+ dest->next_output_byte = buffer;
+ dest->free_in_buffer = buffer_size;
+}
+
+static boolean
+write_to_stream (j_compress_ptr cinfo)
+{
+ struct jpeg_destination_mgr *dest = cinfo->dest;
+ GOutputStream *stream = (GOutputStream *) cinfo->client_data;
+ GError *error = NULL;
+ guchar *buffer;
+ gsize size;
+ gboolean success;
+ gsize written;
+
+ g_assert (stream);
+
+ size = buffer_size - dest->free_in_buffer;
+ buffer = (guchar *) dest->next_output_byte - size;
+
+ success = g_output_stream_write_all (G_OUTPUT_STREAM (stream),
+ (const void *) buffer, buffer_size, &written,
+ NULL, &error);
+ if (!success || error != NULL)
{
- fp = stdout;
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ return FALSE;
}
- else
+
+ dest->next_output_byte = buffer;
+ dest->free_in_buffer = buffer_size;
+
+ return TRUE;
+}
+
+static void
+close_stream (j_compress_ptr cinfo)
+{
+ struct jpeg_destination_mgr *dest = cinfo->dest;
+ GOutputStream *stream = (GOutputStream *) cinfo->client_data;
+ GError *error = NULL;
+ guchar *buffer;
+ gsize size;
+ gboolean success;
+ gsize written;
+ gboolean closed;
+
+ g_assert (stream);
+
+ size = buffer_size - dest->free_in_buffer;
+ buffer = (guchar *) dest->next_output_byte - size;
+
+ success = g_output_stream_write_all (G_OUTPUT_STREAM (stream),
+ (const void *) buffer, size, &written,
+ NULL, &error);
+ if (!success || error != NULL)
{
- fp = fopen (path, "wb");
+ g_warning ("%s", error->message);
+ g_error_free (error);
}
- if (!fp)
+
+ closed = g_output_stream_close (G_OUTPUT_STREAM (stream),
+ NULL, &error);
+ if (!closed)
{
- return -1;
+ g_warning ("%s", error->message);
+ g_error_free (error);
}
- cinfo.err = jpeg_std_error (&jerr);
- jpeg_create_compress (&cinfo);
+ g_free (buffer);
+
+ dest->next_output_byte = NULL;
+ dest->free_in_buffer = 0;
+}
+
+static gint
+export_jpg (GeglOperation *operation,
+ GeglBuffer *input,
+ const GeglRectangle *result,
+ struct jpeg_compress_struct cinfo,
+ gint quality,
+ gint smoothing,
+ gboolean optimize,
+ gboolean progressive,
+ gboolean grayscale)
+{
+ gint src_x, src_y;
+ gint width, height;
+ JSAMPROW row_pointer[1];
+ const Babl *format;
- jpeg_stdio_dest (&cinfo, fp);
+ src_x = result->x;
+ src_y = result->y;
+ width = result->width - result->x;
+ height = result->height - result->y;
cinfo.image_width = width;
cinfo.image_height = height;
@@ -145,7 +218,7 @@ gegl_buffer_export_jpg (GeglBuffer *gegl_buffer,
rect.width = width;
rect.height = 1;
- gegl_buffer_get (gegl_buffer, &rect, 1.0, format,
+ gegl_buffer_get (input, &rect, 1.0, format,
row_pointer[0], GEGL_AUTO_ROWSTRIDE,
GEGL_ABYSS_NONE);
@@ -153,31 +226,65 @@ gegl_buffer_export_jpg (GeglBuffer *gegl_buffer,
}
jpeg_finish_compress (&cinfo);
- jpeg_destroy_compress (&cinfo);
g_free (row_pointer[0]);
- if (stdout != fp)
- fclose (fp);
-
return 0;
}
static gboolean
-gegl_jpg_save_process (GeglOperation *operation,
- GeglBuffer *input,
- const GeglRectangle *result,
- int level)
+process (GeglOperation *operation,
+ GeglBuffer *input,
+ const GeglRectangle *result,
+ int level)
{
GeglProperties *o = GEGL_PROPERTIES (operation);
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ struct jpeg_destination_mgr dest;
+ GOutputStream *stream;
+ GFile *file = NULL;
+ gboolean status = TRUE;
+ GError *error = NULL;
- gegl_buffer_export_jpg (input, o->path, o->quality, o->smoothing,
- o->optimize, o->progressive, o->grayscale,
- result->x, result->y,
- result->width, result->height);
- return TRUE;
-}
+ cinfo.err = jpeg_std_error (&jerr);
+ jpeg_create_compress (&cinfo);
+
+ stream = gegl_gio_open_output_stream (NULL, o->path, &file, &error);
+ if (stream == NULL)
+ {
+ status = FALSE;
+ g_warning ("%s", error->message);
+ goto cleanup;
+ }
+
+ dest.init_destination = init_buffer;
+ dest.empty_output_buffer = write_to_stream;
+ dest.term_destination = close_stream;
+
+ cinfo.client_data = stream;
+ cinfo.dest = &dest;
+
+ if (export_jpg (operation, input, result, cinfo,
+ o->quality, o->smoothing, o->optimize, o->progressive, o->grayscale))
+ {
+ status = FALSE;
+ g_warning("could not export JPEG file");
+ goto cleanup;
+ }
+
+cleanup:
+ jpeg_destroy_compress (&cinfo);
+
+ if (stream != NULL)
+ g_clear_object (&stream);
+
+ if (file != NULL)
+ g_clear_object (&file);
+
+ return status;
+}
static void
gegl_op_class_init (GeglOpClass *klass)
@@ -188,15 +295,14 @@ gegl_op_class_init (GeglOpClass *klass)
operation_class = GEGL_OPERATION_CLASS (klass);
sink_class = GEGL_OPERATION_SINK_CLASS (klass);
- sink_class->process = gegl_jpg_save_process;
+ sink_class->process = process;
sink_class->needs_full = TRUE;
gegl_operation_class_set_keys (operation_class,
- "name", "gegl:jpg-save",
- "title", _("JPEG File Saver"),
- "categories", "output",
- "description",
- _("JPEG image saver, using libjpeg"),
+ "name", "gegl:jpg-save",
+ "title", _("JPEG File Saver"),
+ "categories", "output",
+ "description", _("JPEG image saver, using libjpeg"),
NULL);
gegl_operation_handlers_register_saver (
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]