[gtk/image-loading] Add code to save jpegs



commit a284a964fb52327fff43a1e1970e30fa9e3d1cef
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Sep 14 17:40:29 2021 -0400

    Add code to save jpegs

 gdk/loaders/gdkjpeg.c        | 98 +++++++++++++++++++++++++++++++++++++++++++-
 gdk/loaders/gdkjpegprivate.h |  2 +
 2 files changed, 99 insertions(+), 1 deletion(-)
---
diff --git a/gdk/loaders/gdkjpeg.c b/gdk/loaders/gdkjpeg.c
index 74a1c9623a..8966514948 100644
--- a/gdk/loaders/gdkjpeg.c
+++ b/gdk/loaders/gdkjpeg.c
@@ -70,7 +70,42 @@ output_message_handler (j_common_ptr cinfo)
 }
 
 /* }}} */
- /* {{{ Public API */
+/* {{{ Format conversion */
+
+static void
+convert_to_rgb (guchar *data,
+                int     width,
+                int     height,
+                int     stride)
+{
+  gsize x, y;
+  guchar *src, *dest;
+
+  for (y = 0; y < height; y++)
+    {
+      src = data;
+      dest = data;
+
+      for (x = 0; x < width; x++)
+        {
+          guint32 pixel;
+
+          memcpy (&pixel, src, sizeof (guint32));
+
+          dest[0] = (pixel & 0x00ff0000) >> 16;
+          dest[1] = (pixel & 0x0000ff00) >>  8;
+          dest[2] = (pixel & 0x000000ff) >>  0;
+
+          dest += 3;
+          src += 4;
+        }
+
+      data += stride;
+    }
+}
+
+/* }}} */
+/* {{{ Public API */
 
 GdkTexture *
 gdk_load_jpeg (GBytes  *input_bytes,
@@ -141,6 +176,67 @@ gdk_load_jpeg (GBytes  *input_bytes,
   return texture;
 }
 
+GBytes *
+gdk_save_jpeg (GdkTexture *texture)
+{
+  struct jpeg_compress_struct info;
+  struct error_handler_data jerr;
+  struct jpeg_error_mgr err;
+  guchar *data = NULL;
+  gulong size = 0;
+  guchar *input = NULL;
+  guchar *row;
+  int width, height, stride;
+
+  width = gdk_texture_get_width (texture);
+  height = gdk_texture_get_height (texture);
+
+  info.err = jpeg_std_error (&jerr.pub);
+  jerr.pub.error_exit = fatal_error_handler;
+  jerr.pub.output_message = output_message_handler;
+  jerr.error = NULL;
+
+  if (sigsetjmp (jerr.setjmp_buffer, 1))
+    {
+      free (data);
+      g_free (input);
+      jpeg_destroy_compress (&info);
+      return NULL;
+    }
+
+  info.err = jpeg_std_error (&err);
+  jpeg_create_compress (&info);
+  info.image_width = width;
+  info.image_height = height;
+  info.input_components = 3;
+  info.in_color_space = JCS_RGB;
+
+  jpeg_set_defaults (&info);
+  jpeg_set_quality (&info, 75, TRUE);
+
+  jpeg_mem_dest (&info, &data, &size);
+
+  stride = width * 4;
+  input = g_malloc (stride * height);
+  gdk_texture_download (texture, input, stride);
+  convert_to_rgb (data, width, height, stride);
+
+  jpeg_start_compress (&info, TRUE);
+
+  while (info.next_scanline < info.image_height)
+    {
+      row = &input[info.next_scanline * stride];
+      jpeg_write_scanlines (&info, &row, 1);
+    }
+
+  jpeg_finish_compress (&info);
+
+  g_free (input);
+  jpeg_destroy_compress (&info);
+
+  return g_bytes_new_with_free_func (data, size, (GDestroyNotify) free, NULL);
+}
+
 /* }}} */
 
 /* vim:set foldmethod=marker expandtab: */
diff --git a/gdk/loaders/gdkjpegprivate.h b/gdk/loaders/gdkjpegprivate.h
index 4dcccbaf8d..28e7b90f28 100644
--- a/gdk/loaders/gdkjpegprivate.h
+++ b/gdk/loaders/gdkjpegprivate.h
@@ -26,6 +26,8 @@
 GdkTexture *gdk_load_jpeg         (GBytes           *bytes,
                                    GError          **error);
 
+GBytes     *gdk_save_jpeg         (GdkTexture     *texture);
+
 static inline gboolean
 gdk_is_jpeg (GBytes *bytes)
 {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]