After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 113033 - Thumbnail PDB API for Plug-Ins
Thumbnail PDB API for Plug-Ins
Status: RESOLVED FIXED
Product: GIMP
Classification: Other
Component: libgimp
1.x
Other All
: Normal normal
: 2.0
Assigned To: GIMP Bugs
GIMP Bugs
Depends on:
Blocks: 25272 127914
 
 
Reported: 2003-05-15 05:41 UTC by hof
Modified: 2003-12-25 21:52 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description hof 2003-05-15 05:41:22 UTC
i want to change gimp-gap plug-ins thumbnail handling
from .xvpics to the new PNG based
Thumbnail Managing Standard. 
(http://triq.net/~pearl/thumbnail-spec/)

therefore i need bugfixes and extensions in
PDB-Procedures dealing with thumbnail handling.


For GAP controlled save and load operations gimp-gap code can
(and already does) use the PDB-procedures:

  gimp_file_save_thumbnail 
      the PDB help needs update, because this procedure 
      works according to the new standard,
      and does not write .xvpics as documented

  gimp_file_load_thumbnail
     this procedure still uses the old .xvpics thumbnail format
     and should be changed to support the new standard.
  
     Maybe this procedure can load thumbnails in the new standard
     and also support the .xvpics too (if there is no thumbnail
     found in ~/.thumbnails/)
     
For GAP controlled delete operations on imagefiles
GAP should be able to delete the thumbnails too.
For GAP controlled rename operations i have to rename
existing thumbnails.

The GAP VCR Navigator dialog is based on thumbnails
and needs a way to check for vaild thumbnail.
(the old implementation did check mtime of the imagefiles
against the mtime of .xvpics thumbnails)

In my preferred solution the GIMP provides 3 new Procedures:
  gboolean  gimp_file_delete_thumbnail(char *filename);
  gboolean  gimp_file_rename_thumbnail(char *filename_old, char 
*filename_new);
  gboolean  gimp_file_has_valid_thumbnail(char *filename);

There should be PDB-wrappers for all those Procedures.
Comment 1 Sven Neumann 2003-05-15 10:26:30 UTC
What do you need gimp_file_delete_thumbnail() for?
Comment 2 Sven Neumann 2003-05-15 12:51:09 UTC
You shouldn't need gimp_file_has_valid_thumbnail() since the core will
check the validity of the thumbnail for you. I will look into API for
deleting and renaming thumbnails. Not sure if we really want a PDB API
for this. Alternatively we could move some functions from
app/core/gimpimagefile.[ch] into libgimp.
Comment 3 Sven Neumann 2003-05-15 13:35:22 UTC
Updated gimp_file_load_thumbnail(). Should work for RGB images, still
needs to be extended for other image types:

2003-05-15  Sven Neumann  <sven@gimp.org>

  * tools/pdbgen/pdb/fileops.pdb (file_load_thumbnail_invoker): use
  GimpImagefile to load a thumbnail. Only works for RGB images yet.
  This adresses bug #113033.

  * app/pdb/fileops_cmds.c: regenerated.

  * app/file/file-utils.[ch]: removed file_utils_readXVThumb(). It
  is not needed any longer since GimpImagefile also handles the
  old-style .xvpics.
Comment 4 Sven Neumann 2003-05-15 20:17:56 UTC
2003-05-15  Sven Neumann  <sven@gimp.org>

  * app/pdb/fileops_cmds.c
  * tools/pdbgen/pdb/fileops.pdb: fixed docs for file_save_thumbnail
  (bug #113033).

Comment 5 Sven Neumann 2003-05-15 22:09:25 UTC
The following change is completely untested:

2003-05-16  Sven Neumann  <sven@gimp.org>

   * app/pdb/fileops_cmds.c
   * tools/pdbgen/pdb/fileops.pdb: this change should fix
   file_load_thumbnail() for images with alpha channel by blending
   the resulting tempbuf on a checkerboard (bug #113033).

Assuming the change is correct, the existing PDB functions are now
completely converted to the new thumbnailing scheme. The remaining
parts are an enhancement request; changing the bug-report accordingly.
Comment 6 hof 2003-05-28 14:46:22 UTC
The GAP VCR Navigator dialog needs a way to check
for vaild thumbnail
for The 'Smart Thumbnail Update' feature.

The full thumbnail update does load all frames of an animation as 
gimp image
and then calls gimp_file_save_thumbnail to create the thumbnail.
the smart update can skip load and thumbnail creation
for imagefiles on disk that have a vaild thumbnail.

Keep in mind that the GAP VCR Navigator (and some other GAP functions)
mainly deals with imagefiles
in a way like a filemanager does,
and usually does not open the images (execpt the current one)
into the GIMP.

I think GAP should at least support the same Thumbnail handling as the
GIMP-core does.

One thing that GAP will do, is introduce a new gimprc Parameter
(video-thumbnails) where the user can select:

 - "none" GAP does NOT create new Thumbnails at all.
    Frames with no thumbnails are presented by an empty standard icon
    in the VCR Navigator dialog.
    Some Users may preferre this, because they dont like too much
    thumbnail files in their home directory  ~/.thumbnails

 - "png" GAP controlled save actions create Thumbnails in 
    the new PNG based standard.
    this should be the default.


>What do you need gimp_file_delete_thumbnail() for?

For all GAP controlled delete image-diskfile ops
GAP should remove Thumbnails for both standards,
regardless of gimprc Thumbnail settings.

(Some Users (like me) dont have a demon
 for thumbnail garbage cleanup)


For all GAP controlled copy and rename image-diskfile operations
GAP should also copy/rename Thumbnails for both standards
(regardless of the gimprc Thumbnail settings)

==> In the the new standard the thumbnailfile 
    must be updated because the PNG-Tag:
    Thumb::URI
    has to change on rename and copy.

    For perfromance reasons it is not a good idea
    to recreate thumbnails by loading (all the) renamed/copied
    originalsized image(s) into the GIMP just to create the same 
thumbnail
    with the new Thumb::URI Tag(s).
    (especially in GAP where copy/rename fileops
    are done on many frames at once.)

Writing these lines i can see that i forgot one more new API
in this feature request.

  gimp_file_copy_thumbnail(old_filename, new_filename)


The new requested procedures
  gimp_file_has_valid_thumbnail
  gimp_file_delete_thumbnail
  gimp_file_copy_thumbnail
  gimp_file_rename_thumbnail
  
can be part of the public GIMP Libraries, linkable
with Plug-Ins (A PDB API is not reqired here)


See gimp-gap-1.3.14a_pre37  gap/gap_thumbnail.c
for more implementation details.
(http://wolfganghofer.tripod.com/gap)

This code already implements what GAP needs
for thumbnail handling,
but i will keep this feature request open
because i think an API to the GIMP
is the better solution.
Comment 7 Sven Neumann 2003-05-28 15:21:49 UTC
A few remarks:

You can check for a valid thumbnail by trying to load the thumbnail.
If there is no valid thumbnail, the function will return FALSE. That
should be sufficient, isn't it?

I would not introduce a new gimprc parameter for gap thumbnails. The
gimprc already allows to enable/disable saving of thumbnails. That
should be good enough. More options will only confuse people.

I don't think we want to add deletion of thumbnails to the core.
It would probably make more sense to move some of the gimpimagefile
functionality into libgimp. The same holds true for copying and renaming.
Comment 8 hof 2003-05-28 16:17:10 UTC
> You can check for a valid thumbnail by trying to load the thumbnail.
> If there is no valid thumbnail, the function will return FALSE. That
> should be sufficient, isn't it?

Good idea, if the thumbnail load procedure returns false on
out of date thumbnails too
(both for PNG and .xvpics) it is best that i
drop the request for gimp_file_has_valid_thumbnail

> I would not introduce a new gimprc parameter for gap thumbnails. The
> gimprc already allows to enable/disable saving of thumbnails.

OK, accepted (i'll change this in the next gimp-gap patch
and check only the GIMP standard gimprc keyword
thumbnail-size "none")

>It would probably make more sense to move some of the gimpimagefile
>functionality into libgimp. The same holds true for copying and 
renaming.

OK
Comment 9 hof 2003-06-11 04:57:46 UTC
The PDB call gimp_file_load_thumbnail always FAILS.
the main reason for this bug seems to be
that  imagefile->state  is 0 (== GIMP_IMAGEFILE_STATE_UNKNOWN)
when 
   gimp_imagefile_get_new_preview is called
To load the thumbnail, the imagefile must have at least
state 3 (GIMP_IMAGEFILE_STATE_EXISTS)
   CALLING TREE:
   file_load_thumbnail_invoker
     gimp_viewable_get_preview
       gimp_imagefile_get_new_preview
         gimp_imagefile_read_png_thumb

Suggested Bugfix (1):

  the file_load_thumbnail_invoker
  Should first check if the passed filename exist

  and set state to
    GIMP_IMAGEFILE_STATE_EXISTS
  according to this test.
  ==> my bugfix adds a call to:
         gimp_imagefile_update (imagefile, size);
      
      before the call of gimp_viewable_get_preview.
      gimp_imagefile_update  makes the check and sets the state.

Suggested Bugfix (2):
  After fixing (1), gimp_file_load_thumbnail
  crashed at temp_buf_free.
  the reason is that temp_buf_free is called twice for
  the same temp_buf and crashes in the 2nd call.
  The first call to temp_buf_free is an implicite one,
  that is hidden somewhere in the call to:
     g_object_unref (imagefile);

  ==> my bugfix assumes that g_object_unref
      is OK and calls temp_buf_free only for
      the other TempBuf pointers used in this procedure.
      My bugfix worked fine at my tests, but may be the wrong way,
      because i am not familiar with the object design of the 
      GIMP core.

     
      The changes to fix (1) and (2) should be applied to 
  tools/pdbgen/pdb/fileops.pdb
  (i just have gimp-1.3.14 sources and
   CVS Blame annotated version of app/pdb/fileops_cmds.c
   with the first bugfix attempt for thubnail loading. (by sven)
   -- forgot to download fileops.pdb --
   therefore i cant send
   a patch for the tools/pdbgen/pdb/fileops.pdb
  )
  but here is how the CODE for the file_load_thumbnail_invoker
  should look after the pdbgen sourcecode generation:

---------------------------- START gimp-
1.3.14/app/pdb/fileops_cmds.c:file_load_thumbnail_invoker ------
static Argument *
file_load_thumbnail_invoker (Gimp     *gimp,
                             Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  gchar *filename;
  gint32 width = 0;
  gint32 height = 0;
  gint32 num_bytes = 0;
  guint8 *thumb_data = NULL;

  gchar *uri;
  GimpImagefile *imagefile = NULL;
  TempBuf *temp_buf = NULL;

  filename = (gchar *) args[0].value.pdb_pointer;
  if (filename == NULL)
    success = FALSE;

  if (success)
    {
      TempBuf *temp_buf_check = NULL;

      uri = g_filename_to_uri (filename, NULL, NULL);

      if (uri)
       imagefile = gimp_imagefile_new (gimp, uri);

      if (imagefile)
       {
         gimp_imagefile_update (imagefile, 
GIMP_THUMBNAIL_SIZE_NORMAL);

 	 temp_buf = gimp_viewable_get_preview (GIMP_VIEWABLE 
(imagefile),
 						   
GIMP_THUMBNAIL_SIZE_NORMAL,
 					       
GIMP_THUMBNAIL_SIZE_NORMAL);
 	 /* dont call g_object_unref (imagefile) too soon, 
          * because it implicite calls temp_buf_free
          */
       }

      if (temp_buf)
       {
 	 width  = temp_buf->width;
 	 height = temp_buf->height;

 	 switch (temp_buf->bytes)
 	   {
 	   case 3:
 	     break;

 	   case 4:
 	     {
    #define INT_MULT(a,b,t)  ((t) = (a) * (b) + 0x80, ((((t) >> 8) + 
(t)) >> 8))
    #define INT_BLEND(a,b,alpha,t)  (INT_MULT((a)-(b), alpha, t) + 
(b))
     
               TempBuf *checks = temp_buf_new_check (width, height,
 						
	GIMP_GRAY_CHECKS,
                                                        
GIMP_SMALL_CHECKS
 						      );
               guchar  *src  = temp_buf_data (temp_buf);
               guchar  *dest = temp_buf_data (checks);
                   
               num_bytes = width * height;
               while (num_bytes--)
                 {
                   register glong t;
    
                   dest[0] = INT_BLEND (src[0] , dest[0] , src[3], t);
                   dest[1] = INT_BLEND (src[1] , dest[1] , src[3], t);
                   dest[2] = INT_BLEND (src[2] , dest[2] , src[3], t);
                   src  += 4;
                   dest += 3;
                 }
    
               if(!imagefile)
                   temp_buf_free (temp_buf);

               temp_buf_check = checks;
               temp_buf = checks;
             }
             break;
                 
           default:
             g_assert_not_reached ();
             break;
         }

         num_bytes  = 3 * width * height;
         thumb_data = g_memdup (temp_buf_data (temp_buf), num_bytes);
    
         if(imagefile)
         {
 	   g_object_unref (imagefile);
           
           /* note: g_object_unref does already call temp_buf_free 
implicte !
            * dont call temp_buf_free again, it would lead to a crash
            */
           if(temp_buf_check)
              temp_buf_free (temp_buf_check);
             
         }
         else
         {
            temp_buf_free (temp_buf);
         }

         success = TRUE;
       }
      else
       {
         success = FALSE;
       }
    
       g_free (uri);

    }

  return_args = procedural_db_return_args (&file_load_thumbnail_proc, 
success);

  if (success)
    {
      return_args[1].value.pdb_int = width;
      return_args[2].value.pdb_int = height;
      return_args[3].value.pdb_int = num_bytes;
      return_args[4].value.pdb_pointer = thumb_data;
    }

  return return_args;
}
---------------------------- END   gimp-
1.3.14/app/pdb/fileops_cmds.c:file_load_thumbnail_invoker -----

Suggested Bugfix (3):

  After fixing (1) and (2) i could see that 
  transparent parts of the thumbnail data contain only
  trash (== unitialized data) instead of the expected chekboard.

  ==> call of temp_buf_new_check  
    mismatch par 3. and 4
    3. param is check_type   (GIMP_GRAY_CHECKS)
    4. param is check_size   (GIMP_SMALL_CHECKS)
    

  ==> the implementation of temp_buf_new_check (gimp-1.3.14)
    does not work at all.

   the patch_temp_buf.c  fixes temp_buf_new_check
   please note that the patch is done against gimp-1.3.14 
   (not against current CVS) because i have no CVS access.

---------------------------- START  patch_temp_buf.c  (gimp-
1.3.14/app/base/temp-buf.c) ----------
--- temp-buf.c.orig.1.3.14	Sat Jun  7 12:11:17 2003
+++ temp-buf.c	Sun Jun  8 11:50:27 2003
@@ -236,23 +236,23 @@
 {
   TempBuf *newbuf;
   guchar  *data;
-  guchar   check_shift = 0;
+  guchar   check_pixels = 0;
   guchar   fg_color = 0;
   guchar   bg_color = 0;
-  gint     i, j;
+  gint     ii, i, j;
 
   g_return_val_if_fail (width > 0 && height > 0, NULL);
 
   switch (check_size)
     {
     case GIMP_SMALL_CHECKS:
-      check_shift = 2;
+      check_pixels = 8;
       break;
     case GIMP_MEDIUM_CHECKS:
-      check_shift = 4;
+      check_pixels = 12;
       break;
     case GIMP_LARGE_CHECKS:
-      check_shift = 6;
+      check_pixels = 16;
       break;
     }
  
@@ -286,13 +286,20 @@
   newbuf = temp_buf_new (width, height, 3, 0, 0, NULL);
   data = temp_buf_data (newbuf);
 
-  for (i = 0, j = 1; i <= height; j++)
+  for (ii=0, j = 0; j < height; j++)
     {
-      for (i = 1; i <= width; i++)
-	{
-	  *(data + i - 1) = ((j & check_shift) && (i & check_shift)) 
-	                    ? fg_color : bg_color;
-	}	  
+      ii = ((j / check_pixels) & 1) ? 0 : check_pixels;
+      
+      for (i = 0+ii ; i < width+ii ; i++)
+	{  
+           register guchar   color = 0;
+
+           color = ((i / check_pixels) &1)  ?  fg_color : bg_color;
+                            
+	  *(data++) = color;
+	  *(data++) = color;
+	  *(data++) = color;
+	}
     } 
 
   return newbuf;
@@ -506,6 +513,8 @@
   if (temp_buf->data)
     g_free (temp_buf->data);
 
+  temp_buf->data = NULL;
+  
   if (temp_buf->swapped)
     temp_buf_swap_free (temp_buf);
 
---------------------------- END  patch_temp_buf.c  (gimp-
1.3.14/app/base/temp-buf.c) ----------

Here is an additional wish:
  
  please add one parameter to gimp_file_load_thumbnail
  where the caller can choose beetween
  
    GIMP_THUMBNAIL_SIZE_NORMAL or GIMP_THUMBNAIL_SIZE_LARGE.
  
  (I think today GAP is the only user of the gimp_file_load_thumbnail
   procedure, so this API change should be no big risk)
 
   this way GAP can display huge thumbnails
   in better quality (PNG 256x256).
   This also would make sense for the planed thumbnail based video
   playback GAP-feature.
   
   For Performance Reasons it wolud be better choice to implement
   gimp_file_load_thumbnail as libgimp procedure.
   The current PDB Implementation might be too slow
   for video playback on slow machines.
Comment 10 hof 2003-06-18 15:41:20 UTC
(temp) set severity to normal
because gimp_file_load_thumbnail does not work in the
current PDB implementation and should be fixed before gimp 1.4
release is out. the other things are just feature requests.

(the GAP Player module is nearly done, and can play
at speed of 16 frames/sec using the fixed PDB implementation
of gimp_file_load_thumbnail on normal sized thumbnail files
and PII 300MHz Machine) 
Comment 11 Dave Neary 2003-07-29 21:19:46 UTC
Adding PATCH keyword to bugs which reference code capable of solving any
outstanding issues in the bug

Dave.
Comment 12 Dave Neary 2003-07-29 21:23:10 UTC
Having discussed this with Sven, I agree (with him) that plug-ins
should be able to load, create, save, update and all the rest plug-ins
without asking the gimp core to do it. The solution is to bunch all
the thumbnail functions from the core into a libgimpthumbnail.so, and
link against it for the plug-ins who want thumbnail functionality.

This would be pretty straightforward, I think, and should be done
before 2.0 if possible.

Dave.
Comment 13 Sven Neumann 2003-08-25 11:34:14 UTC
This change should fix the problems with the existing API:

2003-08-25  Sven Neumann  <sven@gimp.org>

  Fixed some issues with the PDB thumbnail functions spotted by
  Wolfgang Hofer and loosely based on patches he provided:
	
  * tools/pdbgen/pdb/fileops.pdb (file_load_thumbnail): keep a
  reference on the GimpImagefile as long as we need the associated
  preview temp_buf. Call gimp_imagefile_update() before requesting
  the preview.

  * app/pdb/fileops_cmds.c: regenerated.

  * app/base/temp-buf.c (temp_buf_new_check): use a checkerboard
  algorithm similar to the one the displayshell-render code uses.


The library for thumbnail loading is almost done. I hope to get it
into  CVS later this week.
Comment 14 Dave Neary 2003-12-07 21:31:24 UTC
Most of the code for the thumbnail API seems to be in CVS. Is there
anything left to do in this bug report?

Dave.
Comment 15 Sven Neumann 2003-12-08 10:05:19 UTC
Yes, there are one or two things left but these will probably make it
into CVS today.
Comment 16 Sven Neumann 2003-12-16 01:24:22 UTC
I haven't yet closed this bug for a couple of reasons. One was missing
documentation. This has been fixed in the meantime. A couple of things
are still missing though:

(1)  gimp_thumbnail_load_thumb() needs to reviewed. It should use
     gimp_thumbnail_peek_image() and gimp_thumbnail_peek_thumb()
     instead of reimplementing the tests.

(2)  I'd like to add a function to set an image file from a thumbnail.
     This wouldn't be used from GIMP but it would be a trivial
     addition that would allow to implement a thumbnail browser/manager
     on top of libgimpthumb.

(3)  Support for reading .xvpics was dropped when GimpImagefile was 
     ported to GimpThumbnail. I'm in favor of not adding it again but
     I'm undecided. I have the code ready to add it again (in the 
     core, not in libgimpthumb) but I'm not sure if I should add back.
Comment 17 Sven Neumann 2003-12-25 12:32:22 UTC
I'd like to get some feedback on point (3) of my last comment.
Basically I am willing to close this report now and make sure (1) and
(2) are taken care of before 2.0 is released.
Comment 18 Dave Neary 2003-12-25 18:54:38 UTC
I'm in favour of dropping .xvpics support entirely.In any case, all 
we would do (presumably) is read the .xvpics thumbnail, and generate 
a .thumbnails thumb from it. 

So I vote for this to be closed as-is.

Dave.
Comment 19 Sven Neumann 2003-12-25 21:50:52 UTC
What the old implementation was doing was to read the .xvpics thumb
and display it as possibly outdated because it doesn't have a way to
determine if the thumb is uptodate. The bad thing about the .xvpics
thumbs is that limited colors and the fact that transparency is not
supported. Instead the checkerboard is stored the thumbnail :(
Comment 20 Sven Neumann 2003-12-25 21:52:02 UTC
Closing this as FIXED. If there are issues with the new API or its
implementation, please open a new report.