[gimp] plug-ins: load the JPEG thumbnail using the new libgimp API



commit 49758867fc6040e9b4ac503bb7866ed53fa4cbb5
Author: Michael Natterer <mitch gimp org>
Date:   Wed Oct 30 00:06:05 2013 +0100

    plug-ins: load the JPEG thumbnail using the new libgimp API

 plug-ins/file-jpeg/jpeg-load.c |  303 ++++------------------------------------
 1 files changed, 30 insertions(+), 273 deletions(-)
---
diff --git a/plug-ins/file-jpeg/jpeg-load.c b/plug-ins/file-jpeg/jpeg-load.c
index 99507cb..91a38d7 100644
--- a/plug-ins/file-jpeg/jpeg-load.c
+++ b/plug-ins/file-jpeg/jpeg-load.c
@@ -459,7 +459,11 @@ jpeg_load_resolution (gint32                         image_ID,
         }
 
       gimp_image_set_resolution (image_ID, xresolution, yresolution);
+
+      return TRUE;
     }
+
+  return FALSE;
 }
 
 /*
@@ -486,53 +490,6 @@ jpeg_load_sanitize_comment (gchar *comment)
     }
 }
 
-typedef struct
-{
-  struct jpeg_source_mgr pub;   /* public fields */
-
-  guchar  *buffer;
-  gint     size;
-  JOCTET   terminal[2];
-} my_source_mgr;
-
-typedef my_source_mgr * my_src_ptr;
-
-static void
-init_source (j_decompress_ptr cinfo)
-{
-}
-
-static boolean
-fill_input_buffer (j_decompress_ptr cinfo)
-{
-  my_src_ptr src = (my_src_ptr) cinfo->src;
-
-  /* Since we have given all we have got already
-   * we simply fake an end of file
-   */
-
-  src->pub.next_input_byte = src->terminal;
-  src->pub.bytes_in_buffer = 2;
-  src->terminal[0]         = (JOCTET) 0xFF;
-  src->terminal[1]         = (JOCTET) JPEG_EOI;
-
-  return TRUE;
-}
-
-static void
-skip_input_data (j_decompress_ptr cinfo,
-                 long             num_bytes)
-{
-  my_src_ptr src = (my_src_ptr) cinfo->src;
-
-  src->pub.next_input_byte = src->pub.next_input_byte + num_bytes;
-}
-
-static void
-term_source (j_decompress_ptr cinfo)
-{
-}
-
 gint32
 load_thumbnail_image (GFile         *file,
                       gint          *width,
@@ -540,44 +497,33 @@ load_thumbnail_image (GFile         *file,
                       GimpImageType *type,
                       GError       **error)
 {
-  gint32 volatile  image_ID         = -1;
-  GimpMetadata    *metadata         = NULL;
-  guint8          *thumbnail_buffer = NULL;
-  gint             thumbnail_size;
-  gint32           layer_ID;
+  gint32 volatile               image_ID = -1;
   struct jpeg_decompress_struct cinfo;
   struct my_error_mgr           jerr;
-  guchar          *buf;
-  guchar         **rowbuf;
-  GimpImageBaseType image_type;
-  GimpImageType    layer_type;
-  GeglBuffer      *buffer = NULL;
-  gint             tile_height;
-  gint             scanlines;
-  gint             i, start, end;
-  gint             orientation;
-  my_src_ptr       src;
-  FILE            *infile;
+  FILE                         *infile   = NULL;
 
-  metadata = gimp_metadata_load_from_file (file, error);
-  if (! metadata)
-    return -1;
-
-  orientation = gexiv2_metadata_get_orientation (metadata);
+  gimp_progress_init_printf (_("Opening thumbnail for '%s'"),
+                             g_file_get_parse_name (file));
 
-  if (! gexiv2_metadata_get_exif_thumbnail (metadata,
-                                            &thumbnail_buffer, &thumbnail_size))
-    {
-      g_object_unref (metadata);
-      return -1;
-    }
+  image_ID = gimp_image_metadata_load_thumbnail (file, error);
+  if (image_ID < 1)
+    return -1;
 
   cinfo.err = jpeg_std_error (&jerr.pub);
   jerr.pub.error_exit     = my_error_exit;
   jerr.pub.output_message = my_output_message;
 
-  gimp_progress_init_printf (_("Opening thumbnail for '%s'"),
-                             g_file_get_parse_name (file));
+  if ((infile = g_fopen (g_file_get_path (file), "rb")) == NULL)
+    {
+      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
+                   _("Could not open '%s' for reading: %s"),
+                   g_file_get_parse_name (file), g_strerror (errno));
+
+      if (image_ID != -1)
+        gimp_image_delete (image_ID);
+
+      return -1;
+    }
 
   /* Establish the setjmp return context for my_error_exit to use. */
   if (setjmp (jerr.setjmp_buffer))
@@ -591,15 +537,6 @@ load_thumbnail_image (GFile         *file,
       if (image_ID != -1)
         gimp_image_delete (image_ID);
 
-      if (metadata)
-        g_object_unref (metadata);
-
-      if (buffer)
-        g_object_unref (buffer);
-
-      if (thumbnail_buffer)
-        g_free (thumbnail_buffer);
-
       return -1;
     }
 
@@ -608,77 +545,31 @@ load_thumbnail_image (GFile         *file,
 
   /* Step 2: specify data source (eg, a file) */
 
-  if (cinfo.src == NULL)
-    cinfo.src = (struct jpeg_source_mgr *)(*cinfo.mem->alloc_small)
-      ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
-       sizeof (my_source_mgr));
-
-  src = (my_src_ptr) cinfo.src;
-
-  src->pub.init_source       = init_source;
-  src->pub.fill_input_buffer = fill_input_buffer;
-  src->pub.skip_input_data   = skip_input_data;
-  src->pub.resync_to_restart = jpeg_resync_to_restart;
-  src->pub.term_source       = term_source;
-
-  src->pub.bytes_in_buffer   = thumbnail_size;
-  src->pub.next_input_byte   = thumbnail_buffer;
-
-  src->buffer = thumbnail_buffer;
-  src->size   = thumbnail_size;
+  jpeg_stdio_src (&cinfo, infile);
 
   /* Step 3: read file parameters with jpeg_read_header() */
 
   jpeg_read_header (&cinfo, TRUE);
 
-  /* Step 4: set parameters for decompression */
-
-  /* In this example, we don't need to change any of the defaults set by
-   * jpeg_read_header(), so we do nothing here.
-   */
-
-  /* Step 5: Start decompressor */
-
   jpeg_start_decompress (&cinfo);
 
-  /* We may need to do some setup of our own at this point before
-   * reading the data.  After jpeg_start_decompress() we have the
-   * correct scaled output image dimensions available, as well as
-   * the output colormap if we asked for color quantization.  In
-   * this example, we need to make an output work buffer of the
-   * right size.
-   */
-
-  /* temporary buffer */
-  tile_height = gimp_tile_height ();
-  buf = g_new (guchar,
-               tile_height * cinfo.output_width * cinfo.output_components);
-
-  rowbuf = g_new (guchar *, tile_height);
-
-  for (i = 0; i < tile_height; i++)
-    rowbuf[i] = buf + cinfo.output_width * cinfo.output_components * i;
+  *width  = cinfo.output_width;
+  *height = cinfo.output_height;
 
-  /* Create a new image of the proper size and associate the
-   * filename with it.
-   */
   switch (cinfo.output_components)
     {
     case 1:
-      image_type = GIMP_GRAY;
-      layer_type = GIMP_GRAY_IMAGE;
+      *type = GIMP_GRAY_IMAGE;
       break;
 
     case 3:
-      image_type = GIMP_RGB;
-      layer_type = GIMP_RGB_IMAGE;
+      *type = GIMP_RGB_IMAGE;
       break;
 
     case 4:
       if (cinfo.out_color_space == JCS_CMYK)
         {
-          image_type = GIMP_RGB;
-          layer_type = GIMP_RGB_IMAGE;
+          *type = GIMP_RGB_IMAGE;
           break;
         }
       /*fallthrough*/
@@ -689,139 +580,11 @@ load_thumbnail_image (GFile         *file,
                  cinfo.output_components, cinfo.out_color_space,
                  cinfo.jpeg_color_space);
 
-      if (metadata)
-        g_object_unref (metadata);
-
-      if (thumbnail_buffer)
-        g_free (thumbnail_buffer);
-
-      return -1;
+      gimp_image_delete (image_ID);
+      image_ID = -1;
       break;
     }
 
-  image_ID = gimp_image_new (cinfo.output_width, cinfo.output_height,
-                             image_type);
-
-  gimp_image_undo_disable (image_ID);
-
-  jpeg_load_resolution (image_ID, &cinfo);
-
-  layer_ID = gimp_layer_new (image_ID, _("Background"),
-                             cinfo.output_width,
-                             cinfo.output_height,
-                             layer_type, 100, GIMP_NORMAL_MODE);
-
-  /* Step 6: while (scan lines remain to be read) */
-  /*           jpeg_read_scanlines(...); */
-
-  /* Here we use the library's state variable cinfo.output_scanline as the
-   * loop counter, so that we don't have to keep track ourselves.
-   */
-  buffer = gimp_drawable_get_buffer (layer_ID);
-
-  while (cinfo.output_scanline < cinfo.output_height)
-    {
-      start = cinfo.output_scanline;
-      end   = cinfo.output_scanline + tile_height;
-      end   = MIN (end, cinfo.output_height);
-      scanlines = end - start;
-
-      for (i = 0; i < scanlines; i++)
-        jpeg_read_scanlines (&cinfo, (JSAMPARRAY) &rowbuf[i], 1);
-
-      if (cinfo.out_color_space == JCS_CMYK)
-        jpeg_load_cmyk_to_rgb (buf, cinfo.output_width * scanlines, NULL);
-
-      gegl_buffer_set (buffer,
-                       GEGL_RECTANGLE (0, start, cinfo.output_width, scanlines),
-                       0,
-                       NULL,
-                       buf,
-                       GEGL_AUTO_ROWSTRIDE);
-
-      gimp_progress_update ((gdouble) cinfo.output_scanline /
-                            (gdouble) cinfo.output_height);
-    }
-
-  /* Step 7: Finish decompression */
-
-  jpeg_finish_decompress (&cinfo);
-  /* We can ignore the return value since suspension is not possible
-   * with the stdio data source.
-   */
-
-  /* Step 8: Release JPEG decompression object */
-
-  /* This is an important step since it will release a good deal
-   * of memory.
-   */
-  jpeg_destroy_decompress (&cinfo);
-
-  g_object_unref (metadata);
-  g_object_unref (buffer);
-  g_free (thumbnail_buffer);
-
-  /* free up the temporary buffers */
-  g_free (rowbuf);
-  g_free (buf);
-
-  /* At this point you may want to check to see whether any
-   * corrupt-data warnings occurred (test whether
-   * jerr.num_warnings is nonzero).
-   */
-  gimp_image_insert_layer (image_ID, layer_ID, -1, 0);
-
-
-  /* NOW to get the dimensions of the actual image to return the
-   * calling app
-   */
-  cinfo.err = jpeg_std_error (&jerr.pub);
-  jerr.pub.error_exit = my_error_exit;
-  jerr.pub.output_message = my_output_message;
-
-  if ((infile = g_fopen (g_file_get_path (file), "rb")) == NULL)
-    {
-      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
-                   _("Could not open '%s' for reading: %s"),
-                   g_file_get_parse_name (file), g_strerror (errno));
-
-      if (image_ID != -1)
-        gimp_image_delete (image_ID);
-
-      return -1;
-    }
-
-  /* Establish the setjmp return context for my_error_exit to use. */
-  if (setjmp (jerr.setjmp_buffer))
-    {
-      /* If we get here, the JPEG code has signaled an error.  We
-       * need to clean up the JPEG object, close the input file,
-       * and return.
-       */
-      jpeg_destroy_decompress (&cinfo);
-
-      if (image_ID != -1)
-        gimp_image_delete (image_ID);
-
-      return -1;
-    }
-
-  /* Now we can initialize the JPEG decompression object. */
-  jpeg_create_decompress (&cinfo);
-
-  /* Step 2: specify data source (eg, a file) */
-
-  jpeg_stdio_src (&cinfo, infile);
-
-  /* Step 3: read file parameters with jpeg_read_header() */
-
-  jpeg_read_header (&cinfo, TRUE);
-
-  jpeg_start_decompress (&cinfo);
-
-  *width  = cinfo.output_width;
-  *height = cinfo.output_height;
-
   /* Step 4: Release JPEG decompression object */
 
   /* This is an important step since it will release a good deal
@@ -831,12 +594,6 @@ load_thumbnail_image (GFile         *file,
 
   fclose (infile);
 
-#if 0
-  jpeg_exif_rotate (image_ID, orientation);
-#endif
-
-  *type = layer_type;
-
   return image_ID;
 }
 


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