Commit 9b7d21da authored by BST 1999 Andy Thomas's avatar BST 1999 Andy Thomas Committed by Andy Thomas

gimp/app/gimppreviewcache.c gimp/app/gimppreviewcache.h


Wed Jun 23 23:52:54 BST 1999 Andy Thomas <alt@gimp.org>

	* gimp/app/gimppreviewcache.c
	* gimp/app/gimppreviewcache.h
	* gimp/app/drawable_cmds.c
	* gimp/app/gdisplay.c
	* gimp/app/gimpdrawableP.h
	* gimp/app/gimage_cmds.c
	* gimp/app/Makefile.am
	* gimp/app/layers_dialog.c
	* gimp/app/channel.c
	* gimp/app/lc_dialog.c
	* gimp/app/lc_dialog.h
	* gimp/app/lc_dialogP.h
	* gimp/app/layer.c
	* gimp/app/gimpdrawable.c
	* gimp/app/internal_procs.c
	* gimp/libgimp/gimp.h
	* gimp/libgimp/gimpimage.c
	* gimp/libgimp/gimpdrawable.c
	* gimp/libgimp/gimpmenu.c
	* gimp/tools/pdbgen/pdb/drawable.pdb
	* gimp/tools/pdbgen/pdb/gimage.pdb

	Added thumbnail image preview functions.
	Previews are visible on the L&C&P dialogs as well as in the
	drawables/channels/ menus generated for plugins
	(see the bumpmap & Mapobject plugins).

	PDB interface exists to simply extract a thumbnail preview
	of a given size. This is much quicker & more efficient
	than getting the image data tile-by-tile if you only need a small
	image since a "preview cache" has been implemented. This cache also
	reduces the number of times the tiles cached is scanned since smaller
	previews are always generated from large ones if they exists and
	are valid.

	Some possible usages (I don't intend to implement these ideas. Just
	suggestions). More plugins using the thumbnail preview (ie any that
	use multiple images). Indication of "active image" somewhere.....
	Actually almost anywhere a drawable/image name appears.
parent 6bd258c5
Wed Jun 23 23:52:54 BST 1999 Andy Thomas <alt@gimp.org>
* gimp/app/gimppreviewcache.c
* gimp/app/gimppreviewcache.h
* gimp/app/drawable_cmds.c
* gimp/app/gdisplay.c
* gimp/app/gimpdrawableP.h
* gimp/app/gimage_cmds.c
* gimp/app/Makefile.am
* gimp/app/layers_dialog.c
* gimp/app/channel.c
* gimp/app/lc_dialog.c
* gimp/app/lc_dialog.h
* gimp/app/lc_dialogP.h
* gimp/app/layer.c
* gimp/app/gimpdrawable.c
* gimp/app/internal_procs.c
* gimp/libgimp/gimp.h
* gimp/libgimp/gimpimage.c
* gimp/libgimp/gimpdrawable.c
* gimp/libgimp/gimpmenu.c
* gimp/tools/pdbgen/pdb/drawable.pdb
* gimp/tools/pdbgen/pdb/gimage.pdb
Added thumbnail image preview functions.
Previews are visible on the L&C&P dialogs as well as in the
drawables/channels/ menus generated for plugins
(see the bumpmap & Mapobject plugins).
PDB interface exists to simply extract a thumbnail preview
of a given size. This is much quicker & more efficient
than getting the image data tile-by-tile if you only need a small
image since a "preview cache" has been implemented. This cache also
reduces the number of times the tiles cached is scanned since smaller
previews are always generated from large ones if they exists and
are valid.
Some possible usages (I don't intend to implement these ideas. Just
suggestions). More plugins using the thumbnail preview (ie any that
use multiple images). Indication of "active image" somewhere.....
Actually almost anywhere a drawable/image name appears.
1999-06-23 Michael Natterer <mitschel@cs.tu-berlin.de>
* app/brightness_contrast.c
......
......@@ -18,6 +18,8 @@ libgimpim_a_SOURCES = \
gimpobject.h \
gimpobjectF.h \
gimpobjectP.h \
gimppreviewcache.h \
gimppreviewcache.c \
gimpset.c \
gimpset.h \
gimpsetF.h \
......
......@@ -30,6 +30,7 @@
#include "parasitelist.h"
#include "temp_buf.h"
#include "undo.h"
#include "gimppreviewcache.h"
#include "libgimp/gimpintl.h"
......@@ -425,12 +426,13 @@ channel_preview (Channel *channel, int width, int height)
MaskBuf * preview_buf;
PixelRegion srcPR, destPR;
int subsample;
TempBuf *ret_buf;
/* The easy way */
if (GIMP_DRAWABLE(channel)->preview_valid &&
GIMP_DRAWABLE(channel)->preview->width == width &&
GIMP_DRAWABLE(channel)->preview->height == height)
return GIMP_DRAWABLE(channel)->preview;
(ret_buf = gimp_preview_cache_get(&(GIMP_DRAWABLE(channel)->preview_cache),
width,height)))
return ret_buf;
/* The hard way */
else
{
......@@ -455,13 +457,11 @@ channel_preview (Channel *channel, int width, int height)
subsample_region (&srcPR, &destPR, subsample);
if (GIMP_DRAWABLE(channel)->preview_valid)
mask_buf_free (GIMP_DRAWABLE(channel)->preview);
GIMP_DRAWABLE(channel)->preview = preview_buf;
if(!GIMP_DRAWABLE(channel)->preview_valid)
gimp_preview_cache_invalidate(&(GIMP_DRAWABLE(channel)->preview_cache));
GIMP_DRAWABLE(channel)->preview_valid = 1;
return GIMP_DRAWABLE(channel)->preview;
gimp_preview_cache_add(&(GIMP_DRAWABLE(channel)->preview_cache),preview_buf);
return preview_buf;
}
}
......
......@@ -30,6 +30,7 @@
#include "parasitelist.h"
#include "temp_buf.h"
#include "undo.h"
#include "gimppreviewcache.h"
#include "libgimp/gimpintl.h"
......@@ -425,12 +426,13 @@ channel_preview (Channel *channel, int width, int height)
MaskBuf * preview_buf;
PixelRegion srcPR, destPR;
int subsample;
TempBuf *ret_buf;
/* The easy way */
if (GIMP_DRAWABLE(channel)->preview_valid &&
GIMP_DRAWABLE(channel)->preview->width == width &&
GIMP_DRAWABLE(channel)->preview->height == height)
return GIMP_DRAWABLE(channel)->preview;
(ret_buf = gimp_preview_cache_get(&(GIMP_DRAWABLE(channel)->preview_cache),
width,height)))
return ret_buf;
/* The hard way */
else
{
......@@ -455,13 +457,11 @@ channel_preview (Channel *channel, int width, int height)
subsample_region (&srcPR, &destPR, subsample);
if (GIMP_DRAWABLE(channel)->preview_valid)
mask_buf_free (GIMP_DRAWABLE(channel)->preview);
GIMP_DRAWABLE(channel)->preview = preview_buf;
if(!GIMP_DRAWABLE(channel)->preview_valid)
gimp_preview_cache_invalidate(&(GIMP_DRAWABLE(channel)->preview_cache));
GIMP_DRAWABLE(channel)->preview_valid = 1;
return GIMP_DRAWABLE(channel)->preview;
gimp_preview_cache_add(&(GIMP_DRAWABLE(channel)->preview_cache),preview_buf);
return preview_buf;
}
}
......
......@@ -30,6 +30,7 @@
#include "parasitelist.h"
#include "temp_buf.h"
#include "undo.h"
#include "gimppreviewcache.h"
#include "libgimp/gimpintl.h"
......@@ -425,12 +426,13 @@ channel_preview (Channel *channel, int width, int height)
MaskBuf * preview_buf;
PixelRegion srcPR, destPR;
int subsample;
TempBuf *ret_buf;
/* The easy way */
if (GIMP_DRAWABLE(channel)->preview_valid &&
GIMP_DRAWABLE(channel)->preview->width == width &&
GIMP_DRAWABLE(channel)->preview->height == height)
return GIMP_DRAWABLE(channel)->preview;
(ret_buf = gimp_preview_cache_get(&(GIMP_DRAWABLE(channel)->preview_cache),
width,height)))
return ret_buf;
/* The hard way */
else
{
......@@ -455,13 +457,11 @@ channel_preview (Channel *channel, int width, int height)
subsample_region (&srcPR, &destPR, subsample);
if (GIMP_DRAWABLE(channel)->preview_valid)
mask_buf_free (GIMP_DRAWABLE(channel)->preview);
GIMP_DRAWABLE(channel)->preview = preview_buf;
if(!GIMP_DRAWABLE(channel)->preview_valid)
gimp_preview_cache_invalidate(&(GIMP_DRAWABLE(channel)->preview_cache));
GIMP_DRAWABLE(channel)->preview_valid = 1;
return GIMP_DRAWABLE(channel)->preview;
gimp_preview_cache_add(&(GIMP_DRAWABLE(channel)->preview_cache),preview_buf);
return preview_buf;
}
}
......
......@@ -650,7 +650,7 @@ gimp_drawable_init (GimpDrawable *drawable)
drawable->gimage = NULL;
drawable->type = -1;
drawable->has_alpha = FALSE;
drawable->preview = NULL;
drawable->preview_cache = NULL;
drawable->preview_valid = FALSE;
drawable->parasites = parasite_list_new();
drawable->tattoo = 0;
......@@ -679,8 +679,8 @@ gimp_drawable_destroy (GtkObject *object)
if (drawable->tiles)
tile_manager_destroy (drawable->tiles);
if (drawable->preview)
temp_buf_free (drawable->preview);
if (drawable->preview_cache)
gimp_preview_cache_invalidate(&drawable->preview_cache);
if (drawable->parasites)
gtk_object_unref(GTK_OBJECT(drawable->parasites));
......@@ -740,7 +740,7 @@ gimp_drawable_configure (GimpDrawable *drawable,
gimp_drawable_set_name(drawable, name);
/* preview variables */
drawable->preview = NULL;
drawable->preview_cache = NULL;
drawable->preview_valid = FALSE;
}
......@@ -33,6 +33,8 @@
#include "parasitelist.h"
#include "undo.h"
#include "gimpsignal.h"
#include "gimppreviewcache.h"
#include "libgimp/gimpintl.h"
#include "libgimp/parasite.h"
......@@ -1114,15 +1116,16 @@ layer_preview (layer, w, h)
int type;
int bytes;
int subsample;
TempBuf *ret_buf;
type = 0;
bytes = 0;
/* The easy way */
if (GIMP_DRAWABLE(layer)->preview_valid &&
GIMP_DRAWABLE(layer)->preview->width == w &&
GIMP_DRAWABLE(layer)->preview->height == h)
return GIMP_DRAWABLE(layer)->preview;
(ret_buf = gimp_preview_cache_get(&(GIMP_DRAWABLE(layer)->preview_cache),
w,h)))
return ret_buf;
/* The hard way */
else
{
......@@ -1163,13 +1166,13 @@ layer_preview (layer, w, h)
layer_preview_scale (type, gimage->cmap, &srcPR, &destPR, subsample);
if (GIMP_DRAWABLE(layer)->preview)
temp_buf_free (GIMP_DRAWABLE(layer)->preview);
if (!GIMP_DRAWABLE(layer)->preview_valid)
gimp_preview_cache_invalidate(&(GIMP_DRAWABLE(layer)->preview_cache));
GIMP_DRAWABLE(layer)->preview = preview_buf;
GIMP_DRAWABLE(layer)->preview_valid = TRUE;
return GIMP_DRAWABLE(layer)->preview;
gimp_preview_cache_add(&(GIMP_DRAWABLE(layer)->preview_cache),preview_buf);
return preview_buf;
}
}
......@@ -1183,6 +1186,7 @@ layer_mask_preview (layer, w, h)
LayerMask *mask;
PixelRegion srcPR, destPR;
int subsample;
TempBuf *ret_buf;
mask = layer->mask;
if (!mask)
......@@ -1190,9 +1194,9 @@ layer_mask_preview (layer, w, h)
/* The easy way */
if (GIMP_DRAWABLE(mask)->preview_valid &&
GIMP_DRAWABLE(mask)->preview->width == w &&
GIMP_DRAWABLE(mask)->preview->height == h)
return GIMP_DRAWABLE(mask)->preview;
(ret_buf = gimp_preview_cache_get(&(GIMP_DRAWABLE(mask)->preview_cache),
w,h)))
return ret_buf;
/* The hard way */
else
{
......@@ -1215,13 +1219,13 @@ layer_mask_preview (layer, w, h)
layer_preview_scale (1 /* GRAY */, NULL, &srcPR, &destPR, subsample);
if (GIMP_DRAWABLE(mask)->preview)
temp_buf_free (GIMP_DRAWABLE(mask)->preview);
if(!GIMP_DRAWABLE(mask)->preview_valid)
gimp_preview_cache_invalidate(&(GIMP_DRAWABLE(mask)->preview_cache));
GIMP_DRAWABLE(mask)->preview = preview_buf;
GIMP_DRAWABLE(mask)->preview_valid = TRUE;
gimp_preview_cache_add(&(GIMP_DRAWABLE(mask)->preview_cache),preview_buf);
return GIMP_DRAWABLE(mask)->preview;
return preview_buf;
}
}
......
/* The GIMP -- an image manipulation program
* Copyright (C) 1999 Andy Thomas alt@gimp.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "gimpdrawableP.h"
#include "gimage.h"
#include "temp_buf.h"
#include "gimppreviewcache.h"
static gint
preview_cache_compare(gconstpointer a,
gconstpointer b)
{
PreviewCache *pc1 = (PreviewCache *)a;
PreviewCache *pc2 = (PreviewCache *)b;
if(pc1->width > pc2->width && pc1->height > pc2->height)
return -1;
return 1;
}
static void
preview_cache_find_exact(gpointer data, gpointer udata)
{
PreviewCache *pc = (PreviewCache *)data;
PreviewNearest *pNearest = (PreviewNearest *)udata;
/* printf("this value w,h [%d,%d]\n",pc->width,pc->height); */
/* if(pNearest->pc) */
/* printf("current nearest value w,h [%d,%d]\n",pNearest->pc->width,pNearest->pc->height); */
if(pNearest->pc)
return;
if(pc->width == pNearest->width &&
pc->height == pNearest->height)
{
/* Ok we could make the preview out of this one...
* If we already have it are these bigger dimensions?
*/
pNearest->pc = pc;
return;
}
}
static void
preview_cache_find_biggest(gpointer data, gpointer udata)
{
PreviewCache *pc = (PreviewCache *)data;
PreviewNearest *pNearest = (PreviewNearest *)udata;
/* printf("this value w,h [%d,%d]\n",pc->width,pc->height); */
/* if(pNearest->pc) */
/* printf("current nearest value w,h [%d,%d]\n",pNearest->pc->width,pNearest->pc->height); */
if(pc->width >= pNearest->width &&
pc->height >= pNearest->height)
{
/* Ok we could make the preview out of this one...
* If we already have it are these bigger dimensions?
*/
if(pNearest->pc)
{
if(pNearest->pc->width > pc->width &&
pNearest->pc->height > pc->height)
return;
}
pNearest->pc = pc;
}
}
static void
preview_cache_remove_smallest(GSList **plist)
{
GSList *cur = *plist;
PreviewCache *smallest = NULL;
/* printf("Removing smallest\n"); */
if(!cur)
return;
do
{
if(!smallest)
{
smallest = cur->data;
/* printf("init smallest %d,%d\n",smallest->width,smallest->height); */
}
else
{
PreviewCache *pcthis = cur->data;
/* printf("Checking %d,%d\n",pcthis->width,pcthis->height); */
if((smallest->height*smallest->width) >=
(pcthis->height*pcthis->width))
{
smallest = pcthis;
/* printf("smallest now %d,%d\n",smallest->width,smallest->height); */
}
}
} while((cur = g_slist_next(cur)));
*plist = g_slist_remove(*plist,smallest);
/* printf("removed %d,%d\n",smallest->width,smallest->height); */
/* printf("removed smallest\n"); */
}
static void
preview_cache_invalidate(gpointer data, gpointer udata)
{
PreviewCache *pc = (PreviewCache *)data;
temp_buf_free (pc->preview);
g_free(pc);
}
static void
preview_cache_print(gpointer data, gpointer udata)
{
/* PreviewCache *pc = (PreviewCache *)data; */
if(!data)
{
/* printf("\tNo Cache\n"); */
return;
}
/* printf("\tvalue w,h [%d,%d] => %p\n",pc->width,pc->height,pc->preview); */
}
void
gimp_preview_cache_invalidate(GSList **plist)
{
/* printf("gimp_preview_cache_invalidate\n"); */
g_slist_foreach(*plist,preview_cache_print,NULL);
g_slist_foreach(*plist,preview_cache_invalidate,NULL);
*plist = NULL;
}
void
gimp_preview_cache_add(GSList **plist,
TempBuf *buf)
{
PreviewCache *pc;
/* printf("gimp_preview_cache_add %d %d\n",buf->width,buf->height); */
g_slist_foreach(*plist,preview_cache_print,NULL);
if(g_slist_length(*plist) > MAX_CACHE_PREVIEWS)
{
/* Remove the smallest */
preview_cache_remove_smallest(plist);
}
pc = g_new0(PreviewCache,1);
pc->preview = buf;
pc->width = buf->width;
pc->height = buf->height;
*plist = g_slist_insert_sorted(*plist,pc,preview_cache_compare);
}
TempBuf *
gimp_preview_cache_get(GSList **plist,
gint width,
gint height)
{
PreviewNearest pn;
PreviewCache *pc;
/* printf("gimp_preview_cache_get %d %d\n",width,height); */
g_slist_foreach(*plist,preview_cache_print,NULL);
pn.pc = NULL;
pn.width = width;
pn.height = height;
g_slist_foreach(*plist,preview_cache_find_exact,&pn);
if(pn.pc && pn.pc->preview)
{
/* printf("extact value w,h [%d,%d] => %p\n",pn.pc->width,pn.pc->height,pn.pc->preview); */
return pn.pc->preview;
}
g_slist_foreach(*plist,preview_cache_find_biggest,&pn);
if(pn.pc)
{
gint pwidth;
gint pheight;
gdouble x_ratio;
gdouble y_ratio;
guchar *src_data;
guchar *dest_data;
gint loop1,loop2;
/* printf("nearest value w,h [%d,%d] => %p\n",pn.pc->width,pn.pc->height,pn.pc->preview); */
/* if(pn.pc->width == width && */
/* pn.pc->height == height) */
/* return pn.pc->preview; */
if(!pn.pc->preview)
{
g_error("gimp_preview_cache_get:: Invalid cache item");
return NULL;
}
/* Make up new preview from the large one... */
pwidth = pn.pc->preview->width;
pheight = pn.pc->preview->height;
/* Now get the real one and add to cache */
/* printf("Must create from large preview\n"); */
pc = g_new0(PreviewCache,1);
pc->preview = temp_buf_new(width,height,pn.pc->preview->bytes,0,0,NULL);
/* preview from nearest bigger one */
x_ratio = (gdouble)pwidth/(gdouble)width;
y_ratio = (gdouble)pheight/(gdouble)height;
src_data = temp_buf_data(pn.pc->preview);
dest_data = temp_buf_data(pc->preview);
/* printf("x_ratio , y_ratio [%f,%f]\n",x_ratio,y_ratio); */
for(loop1 = 0 ; loop1 < height ; loop1++)
for(loop2 = 0 ; loop2 < width ; loop2++)
{
int i;
guchar *src_pixel = src_data +
((gint)(loop2*x_ratio))*pn.pc->preview->bytes +
((gint)(loop1*y_ratio))*pwidth*pn.pc->preview->bytes;
guchar *dest_pixel = dest_data +
(loop2+loop1*width)*pn.pc->preview->bytes;
for(i = 0 ; i < pn.pc->preview->bytes; i++)
*dest_pixel++ = *src_pixel++;
}
pc->width = width;
pc->height = height;
*plist = g_slist_insert_sorted(*plist,pc,preview_cache_compare);
/* printf("New preview created [%d,%d] => %p\n",pc->width,pc->height,pc->preview); */
return pc->preview;
}
/* printf("gimp_preview_cache_get returning NULL\n"); */
return NULL;
}
/* The GIMP -- an image manipulation program
* Copyright (C) 1999 Andy Thomas alt@gimp.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GIMPPREVIEWCACHE_H__
#define __GIMPPREVIEWCACHE_H__
#include "temp_buf.h"
typedef struct _PreviewCache {
TempBuf* preview;
gint width;
gint height;
} PreviewCache;
typedef struct _PreviewNearest {
PreviewCache *pc;
gint width;
gint height;
} PreviewNearest;
#define MAX_CACHE_PREVIEWS 5
TempBuf * gimp_preview_cache_get(GSList **,gint,gint);
void gimp_preview_cache_add(GSList **,TempBuf *);
void gimp_preview_cache_invalidate(GSList **);
#endif /* __GIMPPREVIEWCACHE_H__ */
......@@ -151,6 +151,8 @@ gdisplay_new (GimpImage *gimage,
gimage->instance_count++;
gimage->ref_count++;
lc_dialog_preview_update(gimage);
return gdisp;
}
......
......@@ -151,6 +151,8 @@ gdisplay_new (GimpImage *gimage,
gimage->instance_count++;
gimage->ref_count++;
lc_dialog_preview_update(gimage);
return gdisp;
}
......
......@@ -20,6 +20,9 @@
#include "procedural_db.h"
#include <glib.h>
#include <string.h>
#include "drawable.h"
#include "gimpdrawable.h"
#include "gimpimage.h"
......@@ -45,6 +48,7 @@ static ProcRecord drawable_channel_proc;
static ProcRecord drawable_get_pixel_proc;
static ProcRecord drawable_set_pixel_proc;
static ProcRecord drawable_set_image_proc;
static ProcRecord drawable_thumbnail_proc;
void
register_drawable_procs (void)
......@@ -70,6 +74,7 @@ register_drawable_procs (void)
procedural_db_register (&drawable_get_pixel_proc);
procedural_db_register (&drawable_set_pixel_proc);
procedural_db_register (&drawable_set_image_proc);
procedural_db_register (&drawable_thumbnail_proc);
}
static Argument *
......@@ -1270,3 +1275,143 @@ static ProcRecord drawable_set_image_proc =
NULL,
{ { drawable_set_image_invoker } }
};
static Argument *
drawable_thumbnail_invoker (Argument *args)
{
gboolean success = TRUE;
Argument *return_args;
GimpDrawable *drawable;
gint32 req_width;
gint32 req_height;
gint32 width = 0;
gint32 height = 0;
gint32 bpp = 0;
gint32 num_pixels = 0;
gint8 *thumbnail_data = NULL;
drawable = gimp_drawable_get_ID (args[0].value.pdb_int);
if (drawable == NULL)
success = FALSE;
req_width = args[1].value.pdb_int;
if (req_width <= 0)
success = FALSE;
req_height = args[2].value.pdb_int;
if (req_height <= 0)
success = FALSE;
if (success)
{
TempBuf * buf;
gint dwidth,dheight;
if(req_width <= 128 && req_height <= 128)
{
/* Adjust the width/height ratio */
dwidth = drawable_width(GIMP_DRAWABLE(drawable));
dheight = drawable_height(GIMP_DRAWABLE(drawable));
if(dwidth > dheight)
{
req_height = (req_width*dheight)/dwidth;
}
else
{
req_width = (req_height*dwidth)/dheight;
}
if(GIMP_IS_LAYER(drawable))
buf = layer_preview(GIMP_LAYER(drawable),req_width,req_height);
else
buf = channel_preview(GIMP_CHANNEL(drawable),req_width,req_height);
num_pixels = buf->height * buf->width * buf->bytes;
thumbnail_data = (gint8 *)g_new (gint8, num_pixels);
g_memmove (thumbnail_data, temp_buf_data (buf), num_pixels);
width = buf->width;
height = buf->height;
bpp = buf->bytes;
}
}
return_args = procedural_db_return_args (&drawable_thumbnail_proc, success);
if (success)
{
return_args[1].value.pdb_int = width;
return_args[2].value.pdb_int = height;