mirror of https://github.com/GNOME/gimp.git
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.
This commit is contained in:
parent
6bd258c588
commit
9b7d21dab5
42
ChangeLog
42
ChangeLog
|
@ -1,3 +1,45 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,271 @@
|
|||
/* 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;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/* 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;
|
||||
return_args[3].value.pdb_int = bpp;
|
||||
return_args[4].value.pdb_int = num_pixels;
|
||||
return_args[5].value.pdb_pointer = thumbnail_data;
|
||||
}
|
||||
|
||||
return return_args;
|
||||
}
|
||||
|
||||
static ProcArg drawable_thumbnail_inargs[] =
|
||||
{
|
||||
{
|
||||
PDB_DRAWABLE,
|
||||
"drawable",
|
||||
"The drawable"
|
||||
},
|
||||
{
|
||||
PDB_INT32,
|
||||
"width",
|
||||
"The thumbnail width"
|
||||
},
|
||||
{
|
||||
PDB_INT32,
|
||||
"height",
|
||||
"The thumbnail height"
|
||||
}
|
||||
};
|
||||
|
||||
static ProcArg drawable_thumbnail_outargs[] =
|
||||
{
|
||||
{
|
||||
PDB_INT32,
|
||||
"width",
|
||||
"The previews width"
|
||||
},
|
||||
{
|
||||
PDB_INT32,
|
||||
"height",
|
||||
"The previews height"
|
||||
},
|
||||
{
|
||||
PDB_INT32,
|
||||
"bpp",
|
||||
"The previews bpp"
|
||||
},
|
||||
{
|
||||
PDB_INT32,
|
||||
"thumbnail_data_count",
|
||||
"The number of pixels in thumbnail data"
|
||||
},
|
||||
{
|
||||
PDB_INT8ARRAY,
|
||||
"thumbnail_data",
|
||||
"The thumbnail data"
|
||||
}
|
||||
};
|
||||
|
||||
static ProcRecord drawable_thumbnail_proc =
|
||||
{
|
||||
"gimp_drawable_thumbnail",
|
||||
"Get a thumbnail of a drawable.",
|
||||
"This function gets data from which a thumbnail of a drawable preview can be created. Maximum x or y dimension is 128 pixels. The pixles are returned in the RGB[A] format. The bpp return value gives the number of bytes in the image. The alpha channel also returned if the drawable has one.",
|
||||
"Andy Thomas",
|
||||
"Andy Thomas",
|
||||
"1999",
|
||||
PDB_INTERNAL,
|
||||
3,
|
||||
drawable_thumbnail_inargs,
|
||||
5,
|
||||
drawable_thumbnail_outargs,
|
||||
{ { drawable_thumbnail_invoker } }
|
||||
};
|
||||
|
|
|
@ -151,6 +151,8 @@ gdisplay_new (GimpImage *gimage,
|
|||
gimage->instance_count++;
|
||||
gimage->ref_count++;
|
||||
|
||||
lc_dialog_preview_update(gimage);
|
||||
|
||||
return gdisp;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "procedural_db.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "channel.h"
|
||||
|
@ -65,6 +66,7 @@ static ProcRecord image_disable_undo_proc;
|
|||
static ProcRecord image_clean_all_proc;
|
||||
static ProcRecord image_floating_selection_proc;
|
||||
static ProcRecord image_floating_sel_attached_to_proc;
|
||||
static ProcRecord image_thumbnail_proc;
|
||||
static ProcRecord image_width_proc;
|
||||
static ProcRecord image_height_proc;
|
||||
static ProcRecord image_get_active_layer_proc;
|
||||
|
@ -122,6 +124,7 @@ register_gimage_procs (void)
|
|||
procedural_db_register (&image_clean_all_proc);
|
||||
procedural_db_register (&image_floating_selection_proc);
|
||||
procedural_db_register (&image_floating_sel_attached_to_proc);
|
||||
procedural_db_register (&image_thumbnail_proc);
|
||||
procedural_db_register (&image_width_proc);
|
||||
procedural_db_register (&image_height_proc);
|
||||
procedural_db_register (&image_get_active_layer_proc);
|
||||
|
@ -2178,6 +2181,142 @@ static ProcRecord image_floating_sel_attached_to_proc =
|
|||
{ { image_floating_sel_attached_to_invoker } }
|
||||
};
|
||||
|
||||
static Argument *
|
||||
image_thumbnail_invoker (Argument *args)
|
||||
{
|
||||
gboolean success = TRUE;
|
||||
Argument *return_args;
|
||||
GimpImage *gimage;
|
||||
gint32 req_width;
|
||||
gint32 req_height;
|
||||
gint32 width = 0;
|
||||
gint32 height = 0;
|
||||
gint32 bpp = 0;
|
||||
gint32 num_pixels = 0;
|
||||
gint8 *thumbnail_data = NULL;
|
||||
|
||||
gimage = pdb_id_to_image (args[0].value.pdb_int);
|
||||
if (gimage == 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 = gimage->width;
|
||||
dheight = gimage->height;
|
||||
|
||||
if(dwidth > dheight)
|
||||
{
|
||||
req_height = (req_width*dheight)/dwidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
req_width = (req_height*dwidth)/dheight;
|
||||
}
|
||||
|
||||
buf = gimp_image_construct_composite_preview(gimage,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 (&image_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 = bpp;
|
||||
return_args[4].value.pdb_int = num_pixels;
|
||||
return_args[5].value.pdb_pointer = thumbnail_data;
|
||||
}
|
||||
|
||||
return return_args;
|
||||
}
|
||||
|
||||
static ProcArg image_thumbnail_inargs[] =
|
||||
{
|
||||
{
|
||||
PDB_IMAGE,
|
||||
"image",
|
||||
"The image"
|
||||
},
|
||||
{
|
||||
PDB_INT32,
|
||||
"width",
|
||||
"The thumbnail width"
|
||||
},
|
||||
{
|
||||
PDB_INT32,
|
||||
"height",
|
||||
"The thumbnail height"
|
||||
}
|
||||
};
|
||||
|
||||
static ProcArg image_thumbnail_outargs[] =
|
||||
{
|
||||
{
|
||||
PDB_INT32,
|
||||
"width",
|
||||
"The previews width"
|
||||
},
|
||||
{
|
||||
PDB_INT32,
|
||||
"height",
|
||||
"The previews height"
|
||||
},
|
||||
{
|
||||
PDB_INT32,
|
||||
"bpp",
|
||||
"The previews bpp"
|
||||
},
|
||||
{
|
||||
PDB_INT32,
|
||||
"thumbnail_data_count",
|
||||
"The number of pixels in thumbnail data"
|
||||
},
|
||||
{
|
||||
PDB_INT8ARRAY,
|
||||
"thumbnail_data",
|
||||
"The thumbnail data"
|
||||
}
|
||||
};
|
||||
|
||||
static ProcRecord image_thumbnail_proc =
|
||||
{
|
||||
"gimp_image_thumbnail",
|
||||
"Get a thumbnail of an image.",
|
||||
"This function gets data from which a thumbnail of an image preview can be created. Maximum x or y dimension is 128 pixels. The pixles are returned in the RGB[A] format. The bpp return value gives the number of bytes in the image. The alpha channel also returned if the image has one.",
|
||||
"Andy Thomas",
|
||||
"Andy Thomas",
|
||||
"1999",
|
||||
PDB_INTERNAL,
|
||||
3,
|
||||
image_thumbnail_inargs,
|
||||
5,
|
||||
image_thumbnail_outargs,
|
||||
{ { image_thumbnail_invoker } }
|
||||
};
|
||||
|
||||
static Argument *
|
||||
image_width_invoker (Argument *args)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "gimpobjectP.h"
|
||||
#include "gimpdrawable.h"
|
||||
#include "parasitelistF.h"
|
||||
#include "gimppreviewcache.h"
|
||||
|
||||
struct _GimpDrawable
|
||||
{
|
||||
|
@ -43,7 +44,7 @@ struct _GimpDrawable
|
|||
ParasiteList *parasites; /* Plug-in parasite data */
|
||||
|
||||
/* Preview variables */
|
||||
TempBuf *preview; /* preview of the channel */
|
||||
GSList *preview_cache; /* preview caches of the channel */
|
||||
int preview_valid; /* is the preview valid? */
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,271 @@
|
|||
/* 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;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/* 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__ */
|
|
@ -78,6 +78,8 @@
|
|||
#define SELECTED 1
|
||||
#define INSENSITIVE 2
|
||||
|
||||
|
||||
|
||||
typedef struct _LayersDialog LayersDialog;
|
||||
|
||||
struct _LayersDialog
|
||||
|
@ -257,7 +259,6 @@ static OpsButton layers_ops_buttons[] =
|
|||
{ NULL, NULL, NULL, NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
|
||||
/************************************/
|
||||
/* Public layers dialog functions */
|
||||
/************************************/
|
||||
|
@ -424,6 +425,22 @@ layers_dialog_free ()
|
|||
layersD = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
layers_dialog_invalidate_previews(GimpImage *gimage)
|
||||
{
|
||||
GSList *list = gimage->layers;
|
||||
Layer * layer;
|
||||
/* Invalidate all previews ... */
|
||||
/* This is called during loading the image */
|
||||
|
||||
while (list)
|
||||
{
|
||||
layer = (Layer *) list->data;
|
||||
GIMP_DRAWABLE(layer)->preview_valid = FALSE;
|
||||
list = g_slist_next (list);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
layers_dialog_update (GimpImage* gimage)
|
||||
{
|
||||
|
@ -582,6 +599,7 @@ layers_dialog_flush ()
|
|||
|
||||
gtk_container_foreach (GTK_CONTAINER (layersD->layer_list),
|
||||
layer_widget_layer_flush, NULL);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1222,7 +1240,6 @@ opacity_scale_update (GtkAdjustment *adjustment,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
preserve_trans_update (GtkWidget *w,
|
||||
gpointer data)
|
||||
|
|
|
@ -59,7 +59,7 @@ void register_tools_procs (void);
|
|||
void register_undo_procs (void);
|
||||
void register_unit_procs (void);
|
||||
|
||||
/* 295 procedures registered total */
|
||||
/* 297 procedures registered total */
|
||||
|
||||
void
|
||||
internal_procs_init (void)
|
||||
|
@ -73,82 +73,82 @@ internal_procs_init (void)
|
|||
app_init_update_status (NULL, _("Channel"), 0.047);
|
||||
register_channel_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Channel Ops"), 0.095);
|
||||
app_init_update_status (NULL, _("Channel Ops"), 0.094);
|
||||
register_channel_ops_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Color"), 0.102);
|
||||
app_init_update_status (NULL, _("Color"), 0.101);
|
||||
register_color_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Convert"), 0.142);
|
||||
app_init_update_status (NULL, _("Convert"), 0.141);
|
||||
register_convert_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Drawable procedures"), 0.156);
|
||||
app_init_update_status (NULL, _("Drawable procedures"), 0.155);
|
||||
register_drawable_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Edit procedures"), 0.227);
|
||||
app_init_update_status (NULL, _("Edit procedures"), 0.229);
|
||||
register_edit_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("File Operations"), 0.247);
|
||||
app_init_update_status (NULL, _("File Operations"), 0.249);
|
||||
register_fileops_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Floating selections"), 0.268);
|
||||
app_init_update_status (NULL, _("Floating selections"), 0.269);
|
||||
register_floating_sel_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("GDisplay procedures"), 0.288);
|
||||
app_init_update_status (NULL, _("GDisplay procedures"), 0.29);
|
||||
register_gdisplay_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Image"), 0.298);
|
||||
app_init_update_status (NULL, _("Image"), 0.3);
|
||||
register_gimage_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Image mask"), 0.478);
|
||||
app_init_update_status (NULL, _("Image mask"), 0.481);
|
||||
register_gimage_mask_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Gimprc procedures"), 0.536);
|
||||
app_init_update_status (NULL, _("Gimprc procedures"), 0.539);
|
||||
register_gimprc_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Gradients"), 0.542);
|
||||
app_init_update_status (NULL, _("Gradients"), 0.545);
|
||||
register_gradient_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Gradient UI"), 0.559);
|
||||
app_init_update_status (NULL, _("Gradient UI"), 0.562);
|
||||
register_gradient_select_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Guide procedures"), 0.573);
|
||||
app_init_update_status (NULL, _("Guide procedures"), 0.576);
|
||||
register_guides_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Interface"), 0.593);
|
||||
app_init_update_status (NULL, _("Interface"), 0.596);
|
||||
register_interface_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Layer"), 0.603);
|
||||
app_init_update_status (NULL, _("Layer"), 0.606);
|
||||
register_layer_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Miscellaneous"), 0.705);
|
||||
app_init_update_status (NULL, _("Miscellaneous"), 0.707);
|
||||
register_misc_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Palette"), 0.712);
|
||||
app_init_update_status (NULL, _("Palette"), 0.714);
|
||||
register_palette_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Parasite procedures"), 0.736);
|
||||
app_init_update_status (NULL, _("Parasite procedures"), 0.737);
|
||||
register_parasite_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Paths"), 0.78);
|
||||
app_init_update_status (NULL, _("Paths"), 0.781);
|
||||
register_paths_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Pattern UI"), 0.81);
|
||||
app_init_update_status (NULL, _("Pattern UI"), 0.811);
|
||||
register_pattern_select_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Patterns"), 0.82);
|
||||
app_init_update_status (NULL, _("Patterns"), 0.822);
|
||||
register_patterns_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Plug-in"), 0.834);
|
||||
app_init_update_status (NULL, _("Plug-in"), 0.835);
|
||||
register_plug_in_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Procedural database"), 0.847);
|
||||
app_init_update_status (NULL, _("Procedural database"), 0.848);
|
||||
register_procedural_db_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Text procedures"), 0.875);
|
||||
register_text_tool_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Tool procedures"), 0.888);
|
||||
app_init_update_status (NULL, _("Tool procedures"), 0.889);
|
||||
register_tools_procs ();
|
||||
|
||||
app_init_update_status (NULL, _("Undo"), 0.956);
|
||||
|
|
32
app/layer.c
32
app/layer.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -78,6 +78,8 @@
|
|||
#define SELECTED 1
|
||||
#define INSENSITIVE 2
|
||||
|
||||
|
||||
|
||||
typedef struct _LayersDialog LayersDialog;
|
||||
|
||||
struct _LayersDialog
|
||||
|
@ -257,7 +259,6 @@ static OpsButton layers_ops_buttons[] =
|
|||
{ NULL, NULL, NULL, NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
|
||||
/************************************/
|
||||
/* Public layers dialog functions */
|
||||
/************************************/
|
||||
|
@ -424,6 +425,22 @@ layers_dialog_free ()
|
|||
layersD = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
layers_dialog_invalidate_previews(GimpImage *gimage)
|
||||
{
|
||||
GSList *list = gimage->layers;
|
||||
Layer * layer;
|
||||
/* Invalidate all previews ... */
|
||||
/* This is called during loading the image */
|
||||
|
||||
while (list)
|
||||
{
|
||||
layer = (Layer *) list->data;
|
||||
GIMP_DRAWABLE(layer)->preview_valid = FALSE;
|
||||
list = g_slist_next (list);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
layers_dialog_update (GimpImage* gimage)
|
||||
{
|
||||
|
@ -582,6 +599,7 @@ layers_dialog_flush ()
|
|||
|
||||
gtk_container_foreach (GTK_CONTAINER (layersD->layer_list),
|
||||
layer_widget_layer_flush, NULL);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1222,7 +1240,6 @@ opacity_scale_update (GtkAdjustment *adjustment,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
preserve_trans_update (GtkWidget *w,
|
||||
gpointer data)
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
#ifndef __LAYERS_DIALOG_P_H__
|
||||
#define __LAYERS_DIALOG_P_H__
|
||||
|
||||
void render_fs_preview (GtkWidget *, GdkPixmap *);
|
||||
void render_preview (TempBuf *, GtkWidget *, int, int, int);
|
||||
void render_fs_preview (GtkWidget *, GdkPixmap *);
|
||||
void render_preview (TempBuf *, GtkWidget *, int, int, int);
|
||||
void layers_dialog_invalidate_previews (GimpImage *gimage);
|
||||
|
||||
#endif /* __LAYERS_DIALOG_P_H__ */
|
||||
|
|
236
app/lc_dialog.c
236
app/lc_dialog.c
|
@ -28,10 +28,19 @@
|
|||
#include "image_render.h"
|
||||
#include "lc_dialog.h"
|
||||
#include "lc_dialogP.h"
|
||||
#include "layers_dialogP.h"
|
||||
#include "session.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
#define GRAD_CHECK_SIZE_SM 4
|
||||
|
||||
#define GRAD_CHECK_DARK (1.0 / 3.0)
|
||||
#define GRAD_CHECK_LIGHT (2.0 / 3.0)
|
||||
|
||||
#define MENU_THUMBNAIL_WIDTH 24
|
||||
#define MENU_THUMBNAIL_HEIGHT 24
|
||||
|
||||
/* local function prototypes */
|
||||
static void lc_dialog_update (GimpImage *);
|
||||
static void lc_dialog_image_menu_callback (GtkWidget *, gpointer);
|
||||
|
@ -42,6 +51,12 @@ static void lc_dialog_remove_cb (GimpSet *, GimpImage *, gpointer);
|
|||
static void lc_dialog_destroy_cb (GimpImage *, gpointer);
|
||||
static void lc_dialog_change_image (GimpContext *, GimpImage *,
|
||||
gpointer);
|
||||
static void lc_dialog_image_menu_preview_update_cb (GtkWidget *,gpointer);
|
||||
static void lc_dialog_fill_preview_with_thumb(GtkWidget *,
|
||||
GimpImage *,
|
||||
gint ,
|
||||
gint );
|
||||
|
||||
|
||||
/* FIXME: move these to a better place */
|
||||
static GtkWidget * lc_dialog_create_image_menu (GimpImage **, int *,
|
||||
|
@ -262,6 +277,56 @@ lc_dialog_flush ()
|
|||
paths_dialog_flush ();
|
||||
}
|
||||
|
||||
static gint
|
||||
image_menu_preview_update_do(GimpImage *gimage)
|
||||
{
|
||||
if(lc_dialog)
|
||||
{
|
||||
gtk_container_foreach (GTK_CONTAINER (lc_dialog->image_menu),
|
||||
lc_dialog_image_menu_preview_update_cb, (gpointer)gimage);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
menu_preview_dirty (GtkObject *obj,
|
||||
gpointer client_data)
|
||||
{
|
||||
/* Update preview at a less busy time */
|
||||
/* printf("menu_preview_dirty:: adding %p to obj %p\n",client_data,obj); */
|
||||
gtk_idle_add((GtkFunction)image_menu_preview_update_do,(gpointer)obj);
|
||||
}
|
||||
|
||||
void
|
||||
lc_dialog_preview_update(GimpImage *gimage)
|
||||
{
|
||||
layers_dialog_invalidate_previews(gimage);
|
||||
gtk_idle_add((GtkFunction)image_menu_preview_update_do,gimage);
|
||||
}
|
||||
|
||||
static void
|
||||
lc_dialog_image_menu_preview_update_cb (GtkWidget *widget,
|
||||
gpointer client_data)
|
||||
{
|
||||
GtkWidget *menu_preview;
|
||||
GimpImage *gimage;
|
||||
GimpImage *gimage_to_update = GIMP_IMAGE((GimpImage *)client_data);
|
||||
|
||||
menu_preview = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(widget),"menu_preview");
|
||||
gimage = GIMP_IMAGE((GimpImage *)gtk_object_get_data(GTK_OBJECT(widget),"menu_preview_gimage"));
|
||||
/* printf("image_menu_preview_update::menu_preview = %p gimage %p gimage_to_update %d\n",menu_preview,gimage,gimage_to_update); */
|
||||
|
||||
if(menu_preview && gimage && gimage_to_update == gimage)
|
||||
{
|
||||
/* Must update the preview? */
|
||||
lc_dialog_fill_preview_with_thumb(menu_preview,
|
||||
gimage,
|
||||
MENU_THUMBNAIL_WIDTH,
|
||||
MENU_THUMBNAIL_HEIGHT);
|
||||
gtk_widget_draw(GTK_WIDGET(menu_preview),NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lc_dialog_update_image_list ()
|
||||
{
|
||||
|
@ -334,6 +399,131 @@ typedef struct
|
|||
GImage *id;
|
||||
} IMCBData;
|
||||
|
||||
static void
|
||||
lc_dialog_fill_preview_with_thumb(GtkWidget *w,
|
||||
GimpImage *gimage,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
guchar *drawable_data;
|
||||
TempBuf *buf;
|
||||
gint bpp;
|
||||
gint dwidth;
|
||||
gint dheight;
|
||||
|
||||
bpp = 0; /* Only returned */
|
||||
|
||||
dwidth = gimage->width;
|
||||
dheight = gimage->height;
|
||||
|
||||
/* Get right aspect ratio */
|
||||
if(dwidth > dheight)
|
||||
{
|
||||
height = (width*dheight)/dwidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = (height*dwidth)/dheight;
|
||||
}
|
||||
|
||||
buf = gimp_image_construct_composite_preview(gimage,
|
||||
width,
|
||||
height);
|
||||
|
||||
drawable_data = temp_buf_data(buf);
|
||||
bpp = buf->bytes;
|
||||
|
||||
gtk_preview_size(GTK_PREVIEW(w),width,height);
|
||||
|
||||
/* First greyscale and non-alpha */
|
||||
if(bpp < 4)
|
||||
{
|
||||
guchar *buf;
|
||||
guchar *src;
|
||||
gint x,y;
|
||||
|
||||
/* Draw the image */
|
||||
buf = g_new (gchar, width * 3);
|
||||
src = drawable_data;
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
if (bpp == 1)
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
buf[x*3+0] = src[x];
|
||||
buf[x*3+1] = src[x];
|
||||
buf[x*3+2] = src[x];
|
||||
}
|
||||
else
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
buf[x*3+0] = src[x*3+0];
|
||||
buf[x*3+1] = src[x*3+1];
|
||||
buf[x*3+2] = src[x*3+2];
|
||||
}
|
||||
gtk_preview_draw_row (GTK_PREVIEW (w), (guchar *)buf, 0, y, width);
|
||||
src += width * bpp;
|
||||
}
|
||||
g_free(buf);
|
||||
}
|
||||
else /* Has alpha channel */
|
||||
{
|
||||
gint x,y;
|
||||
guchar *src;
|
||||
gdouble r, g, b, a;
|
||||
gdouble c0, c1;
|
||||
guchar *p0, *p1,*even,*odd;
|
||||
|
||||
/* Draw the thumbnail with checks */
|
||||
src = drawable_data;
|
||||
|
||||
even = g_malloc(width*3);
|
||||
odd = g_malloc(width*3);
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
p0 = even;
|
||||
p1 = odd;
|
||||
|
||||
for (x = 0; x < width; x++) {
|
||||
r = ((gdouble)src[x*4+0])/255.0;
|
||||
g = ((gdouble)src[x*4+1])/255.0;
|
||||
b = ((gdouble)src[x*4+2])/255.0;
|
||||
a = ((gdouble)src[x*4+3])/255.0;
|
||||
|
||||
if ((x / GRAD_CHECK_SIZE_SM) & 1) {
|
||||
c0 = GRAD_CHECK_LIGHT;
|
||||
c1 = GRAD_CHECK_DARK;
|
||||
} else {
|
||||
c0 = GRAD_CHECK_DARK;
|
||||
c1 = GRAD_CHECK_LIGHT;
|
||||
} /* else */
|
||||
|
||||
*p0++ = (c0 + (r - c0) * a) * 255.0;
|
||||
*p0++ = (c0 + (g - c0) * a) * 255.0;
|
||||
*p0++ = (c0 + (b - c0) * a) * 255.0;
|
||||
|
||||
*p1++ = (c1 + (r - c1) * a) * 255.0;
|
||||
*p1++ = (c1 + (g - c1) * a) * 255.0;
|
||||
*p1++ = (c1 + (b - c1) * a) * 255.0;
|
||||
|
||||
} /* for */
|
||||
|
||||
if ((y / GRAD_CHECK_SIZE_SM) & 1)
|
||||
{
|
||||
gtk_preview_draw_row (GTK_PREVIEW (w), (guchar *)odd, 0, y, width);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_preview_draw_row (GTK_PREVIEW (w), (guchar *)even, 0, y, width);
|
||||
}
|
||||
src += width * bpp;
|
||||
}
|
||||
g_free(even);
|
||||
g_free(odd);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lc_dialog_create_image_menu_cb (gpointer im,
|
||||
gpointer d)
|
||||
|
@ -343,6 +533,10 @@ lc_dialog_create_image_menu_cb (gpointer im,
|
|||
char *image_name;
|
||||
char *menu_item_label;
|
||||
GtkWidget *menu_item;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *wcolor_box;
|
||||
GtkWidget *wlabel;
|
||||
|
||||
/* make sure the default index gets set to _something_, if possible */
|
||||
if (*data->default_index == -1)
|
||||
|
@ -360,12 +554,50 @@ lc_dialog_create_image_menu_cb (gpointer im,
|
|||
image_name = g_basename (gimage_filename (gimage));
|
||||
menu_item_label =
|
||||
g_strdup_printf ("%s-%d", image_name, pdb_image_to_id (gimage));
|
||||
menu_item = gtk_menu_item_new_with_label (menu_item_label);
|
||||
menu_item = gtk_menu_item_new();
|
||||
gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
|
||||
(GtkSignalFunc) data->callback, gimage);
|
||||
hbox = gtk_hbox_new(FALSE, 0);
|
||||
gtk_container_add (GTK_CONTAINER (menu_item), hbox);
|
||||
gtk_widget_show(hbox);
|
||||
|
||||
vbox = gtk_vbox_new(FALSE, 0);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show(vbox);
|
||||
|
||||
wcolor_box = gtk_preview_new(GTK_PREVIEW_COLOR);
|
||||
gtk_preview_set_dither (GTK_PREVIEW (wcolor_box), GDK_RGB_DITHER_MAX);
|
||||
|
||||
lc_dialog_fill_preview_with_thumb(wcolor_box,
|
||||
gimage,
|
||||
MENU_THUMBNAIL_WIDTH,
|
||||
MENU_THUMBNAIL_HEIGHT);
|
||||
|
||||
gtk_widget_set_usize( GTK_WIDGET (wcolor_box) ,
|
||||
MENU_THUMBNAIL_WIDTH ,
|
||||
MENU_THUMBNAIL_HEIGHT);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(vbox), wcolor_box);
|
||||
gtk_widget_show(wcolor_box);
|
||||
|
||||
wlabel = gtk_label_new(menu_item_label);
|
||||
gtk_misc_set_alignment(GTK_MISC(wlabel), 0.0, 0.5);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), wlabel, TRUE, TRUE, 4);
|
||||
gtk_widget_show(wlabel);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (data->menu), menu_item);
|
||||
if(gtk_object_get_data(GTK_OBJECT (gimage),"menu_preview_dirty") == NULL)
|
||||
{
|
||||
/* Only add this signal once */
|
||||
gtk_object_set_data(GTK_OBJECT (gimage),"menu_preview_dirty",(gpointer)1);
|
||||
gtk_signal_connect_after (GTK_OBJECT (gimage), "dirty",
|
||||
GTK_SIGNAL_FUNC(menu_preview_dirty),NULL);
|
||||
}
|
||||
gtk_object_set_data(GTK_OBJECT(menu_item),"menu_preview",wcolor_box);
|
||||
gtk_object_set_data(GTK_OBJECT(menu_item),"menu_preview_gimage",gimage);
|
||||
|
||||
gtk_widget_show (menu_item);
|
||||
|
||||
|
||||
g_free (menu_item_label);
|
||||
data->num_items ++;
|
||||
}
|
||||
|
|
|
@ -28,5 +28,7 @@ void lc_dialog_rebuild (int); /* implies free & create */
|
|||
void lc_dialog_flush (void);
|
||||
|
||||
void lc_dialog_update_image_list (void);
|
||||
void lc_dialog_preview_update (GimpImage *gimage);
|
||||
|
||||
|
||||
#endif /* __LC_DIALOG_H__ */
|
||||
|
|
|
@ -527,6 +527,10 @@ gint32 gimp_image_get_layer_by_tattoo (gint32 image_ID,
|
|||
gint32 gimp_image_get_channel_by_tattoo (gint32 image_ID,
|
||||
gint32 tattoo);
|
||||
|
||||
guchar * gimp_image_get_thumbnail_data (gint32 image_ID,
|
||||
gint *width,
|
||||
gint *height,
|
||||
gint *bytes);
|
||||
|
||||
/****************************************
|
||||
* Guides *
|
||||
|
@ -719,7 +723,10 @@ void gimp_layer_attach_new_parasite(gint32 drawable,
|
|||
int size, const void *data);
|
||||
void gimp_drawable_detach_parasite (gint32 drawable,
|
||||
const char *name);
|
||||
|
||||
guchar * gimp_drawable_get_thumbnail_data (gint32 drawable_ID,
|
||||
gint *width,
|
||||
gint *height,
|
||||
gint *bytes);
|
||||
|
||||
/****************************************
|
||||
* GTiles *
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "gimp.h"
|
||||
|
||||
|
||||
|
@ -654,3 +656,36 @@ gimp_drawable_detach_parasite (gint32 drawable_ID,
|
|||
gimp_destroy_params (return_vals, nreturn_vals);
|
||||
}
|
||||
|
||||
guchar *
|
||||
gimp_drawable_get_thumbnail_data (gint32 drawable_ID,
|
||||
gint *width,
|
||||
gint *height,
|
||||
gint *bytes)
|
||||
{
|
||||
GParam *return_vals;
|
||||
int nreturn_vals;
|
||||
gchar *drawable_data = NULL;
|
||||
|
||||
return_vals = gimp_run_procedure ("gimp_drawable_thumbnail",
|
||||
&nreturn_vals,
|
||||
PARAM_DRAWABLE, drawable_ID,
|
||||
PARAM_INT32, *width,
|
||||
PARAM_INT32, *height,
|
||||
PARAM_END);
|
||||
|
||||
if (return_vals[0].data.d_status == STATUS_SUCCESS)
|
||||
{
|
||||
*width = return_vals[1].data.d_int32;
|
||||
*height = return_vals[2].data.d_int32;
|
||||
*bytes = return_vals[3].data.d_int32;
|
||||
drawable_data = g_new (gchar,return_vals[4].data.d_int32);
|
||||
g_memmove (drawable_data, return_vals[5].data.d_int32array,return_vals[4].data.d_int32);
|
||||
}
|
||||
|
||||
gimp_destroy_params (return_vals, nreturn_vals);
|
||||
|
||||
return drawable_data;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "gimp.h"
|
||||
|
||||
|
||||
|
@ -654,3 +656,36 @@ gimp_drawable_detach_parasite (gint32 drawable_ID,
|
|||
gimp_destroy_params (return_vals, nreturn_vals);
|
||||
}
|
||||
|
||||
guchar *
|
||||
gimp_drawable_get_thumbnail_data (gint32 drawable_ID,
|
||||
gint *width,
|
||||
gint *height,
|
||||
gint *bytes)
|
||||
{
|
||||
GParam *return_vals;
|
||||
int nreturn_vals;
|
||||
gchar *drawable_data = NULL;
|
||||
|
||||
return_vals = gimp_run_procedure ("gimp_drawable_thumbnail",
|
||||
&nreturn_vals,
|
||||
PARAM_DRAWABLE, drawable_ID,
|
||||
PARAM_INT32, *width,
|
||||
PARAM_INT32, *height,
|
||||
PARAM_END);
|
||||
|
||||
if (return_vals[0].data.d_status == STATUS_SUCCESS)
|
||||
{
|
||||
*width = return_vals[1].data.d_int32;
|
||||
*height = return_vals[2].data.d_int32;
|
||||
*bytes = return_vals[3].data.d_int32;
|
||||
drawable_data = g_new (gchar,return_vals[4].data.d_int32);
|
||||
g_memmove (drawable_data, return_vals[5].data.d_int32array,return_vals[4].data.d_int32);
|
||||
}
|
||||
|
||||
gimp_destroy_params (return_vals, nreturn_vals);
|
||||
|
||||
return drawable_data;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1132,3 +1132,35 @@ gimp_image_get_channel_by_tattoo (gint32 image_ID, gint32 tattoo)
|
|||
return channel;
|
||||
}
|
||||
|
||||
guchar *
|
||||
gimp_image_get_thumbnail_data (gint32 image_ID,
|
||||
gint *width,
|
||||
gint *height,
|
||||
gint *bytes)
|
||||
{
|
||||
GParam *return_vals;
|
||||
int nreturn_vals;
|
||||
gchar *image_data = NULL;
|
||||
|
||||
return_vals = gimp_run_procedure ("gimp_image_thumbnail",
|
||||
&nreturn_vals,
|
||||
PARAM_DRAWABLE, image_ID,
|
||||
PARAM_INT32, *width,
|
||||
PARAM_INT32, *height,
|
||||
PARAM_END);
|
||||
|
||||
if (return_vals[0].data.d_status == STATUS_SUCCESS)
|
||||
{
|
||||
*width = return_vals[1].data.d_int32;
|
||||
*height = return_vals[2].data.d_int32;
|
||||
*bytes = return_vals[3].data.d_int32;
|
||||
image_data = g_new (gchar,return_vals[4].data.d_int32);
|
||||
g_memmove (image_data, return_vals[5].data.d_int32array,return_vals[4].data.d_int32);
|
||||
}
|
||||
|
||||
gimp_destroy_params (return_vals, nreturn_vals);
|
||||
|
||||
return image_data;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1132,3 +1132,35 @@ gimp_image_get_channel_by_tattoo (gint32 image_ID, gint32 tattoo)
|
|||
return channel;
|
||||
}
|
||||
|
||||
guchar *
|
||||
gimp_image_get_thumbnail_data (gint32 image_ID,
|
||||
gint *width,
|
||||
gint *height,
|
||||
gint *bytes)
|
||||
{
|
||||
GParam *return_vals;
|
||||
int nreturn_vals;
|
||||
gchar *image_data = NULL;
|
||||
|
||||
return_vals = gimp_run_procedure ("gimp_image_thumbnail",
|
||||
&nreturn_vals,
|
||||
PARAM_DRAWABLE, image_ID,
|
||||
PARAM_INT32, *width,
|
||||
PARAM_INT32, *height,
|
||||
PARAM_END);
|
||||
|
||||
if (return_vals[0].data.d_status == STATUS_SUCCESS)
|
||||
{
|
||||
*width = return_vals[1].data.d_int32;
|
||||
*height = return_vals[2].data.d_int32;
|
||||
*bytes = return_vals[3].data.d_int32;
|
||||
image_data = g_new (gchar,return_vals[4].data.d_int32);
|
||||
g_memmove (image_data, return_vals[5].data.d_int32array,return_vals[4].data.d_int32);
|
||||
}
|
||||
|
||||
gimp_destroy_params (return_vals, nreturn_vals);
|
||||
|
||||
return image_data;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,13 @@
|
|||
#include "gimp.h"
|
||||
#include "gimpui.h"
|
||||
|
||||
#define GRAD_CHECK_SIZE_SM 4
|
||||
|
||||
#define GRAD_CHECK_DARK (1.0 / 3.0)
|
||||
#define GRAD_CHECK_LIGHT (2.0 / 3.0)
|
||||
|
||||
#define MENU_THUMBNAIL_WIDTH 24
|
||||
#define MENU_THUMBNAIL_HEIGHT 24
|
||||
|
||||
/* Copy data from temp_PDB call */
|
||||
struct _GBrushData {
|
||||
|
@ -84,7 +91,10 @@ static gboolean input_callback (GIOChannel *channel,
|
|||
gpointer data);
|
||||
static void gimp_setup_callbacks (void);
|
||||
static gchar* gen_temp_plugin_name (void);
|
||||
|
||||
static void fill_preview_with_thumb(GtkWidget *,
|
||||
gint32,
|
||||
gint,
|
||||
gint);
|
||||
/* From gimp.c */
|
||||
void gimp_run_temp (void);
|
||||
|
||||
|
@ -95,7 +105,6 @@ static GBrushData *active_brush_pdb = NULL;
|
|||
static GPatternData *active_pattern_pdb = NULL;
|
||||
static GGradientData *active_gradient_pdb = NULL;
|
||||
|
||||
|
||||
GtkWidget*
|
||||
gimp_image_menu_new (GimpConstraintFunc constraint,
|
||||
GimpMenuCallback callback,
|
||||
|
@ -156,6 +165,8 @@ gimp_image_menu_new (GimpConstraintFunc constraint,
|
|||
return menu;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GtkWidget*
|
||||
gimp_layer_menu_new (GimpConstraintFunc constraint,
|
||||
GimpMenuCallback callback,
|
||||
|
@ -193,15 +204,49 @@ gimp_layer_menu_new (GimpConstraintFunc constraint,
|
|||
for (j = 0; j < nlayers; j++)
|
||||
if (!constraint || (* constraint) (images[i], layers[j], data))
|
||||
{
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *wcolor_box;
|
||||
GtkWidget *wlabel;
|
||||
|
||||
name = gimp_layer_get_name (layers[j]);
|
||||
label = g_new (char, strlen (image_label) + strlen (name) + 2);
|
||||
sprintf (label, "%s/%s", image_label, name);
|
||||
g_free (name);
|
||||
|
||||
menuitem = gtk_menu_item_new_with_label (label);
|
||||
menuitem = gtk_menu_item_new();
|
||||
gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
|
||||
(GtkSignalFunc) gimp_menu_callback,
|
||||
&layers[j]);
|
||||
|
||||
hbox = gtk_hbox_new(FALSE, 0);
|
||||
gtk_container_add(GTK_CONTAINER(menuitem), hbox);
|
||||
gtk_widget_show(hbox);
|
||||
|
||||
vbox = gtk_vbox_new(FALSE, 0);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show(vbox);
|
||||
|
||||
wcolor_box = gtk_preview_new(GTK_PREVIEW_COLOR);
|
||||
gtk_preview_set_dither (GTK_PREVIEW (wcolor_box), GDK_RGB_DITHER_MAX);
|
||||
|
||||
fill_preview_with_thumb(wcolor_box,
|
||||
layers[j],
|
||||
MENU_THUMBNAIL_WIDTH,
|
||||
MENU_THUMBNAIL_HEIGHT);
|
||||
|
||||
gtk_widget_set_usize( GTK_WIDGET (wcolor_box) ,
|
||||
MENU_THUMBNAIL_WIDTH ,
|
||||
MENU_THUMBNAIL_HEIGHT);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(vbox), wcolor_box);
|
||||
gtk_widget_show(wcolor_box);
|
||||
|
||||
wlabel = gtk_label_new(label);
|
||||
gtk_misc_set_alignment(GTK_MISC(wlabel), 0.0, 0.5);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), wlabel, TRUE, TRUE, 4);
|
||||
gtk_widget_show(wlabel);
|
||||
|
||||
gtk_menu_append (GTK_MENU (menu), menuitem);
|
||||
gtk_widget_show (menuitem);
|
||||
|
||||
|
@ -273,15 +318,49 @@ gimp_channel_menu_new (GimpConstraintFunc constraint,
|
|||
for (j = 0; j < nchannels; j++)
|
||||
if (!constraint || (* constraint) (images[i], channels[j], data))
|
||||
{
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *wcolor_box;
|
||||
GtkWidget *wlabel;
|
||||
|
||||
name = gimp_channel_get_name (channels[j]);
|
||||
label = g_new (char, strlen (image_label) + strlen (name) + 2);
|
||||
sprintf (label, "%s/%s", image_label, name);
|
||||
g_free (name);
|
||||
|
||||
menuitem = gtk_menu_item_new_with_label (label);
|
||||
menuitem = gtk_menu_item_new();
|
||||
gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
|
||||
(GtkSignalFunc) gimp_menu_callback,
|
||||
&channels[j]);
|
||||
|
||||
hbox = gtk_hbox_new(FALSE, 0);
|
||||
gtk_container_add(GTK_CONTAINER(menuitem), hbox);
|
||||
gtk_widget_show(hbox);
|
||||
|
||||
vbox = gtk_vbox_new(FALSE, 0);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show(vbox);
|
||||
|
||||
wcolor_box = gtk_preview_new(GTK_PREVIEW_COLOR);
|
||||
gtk_preview_set_dither (GTK_PREVIEW (wcolor_box), GDK_RGB_DITHER_MAX);
|
||||
|
||||
fill_preview_with_thumb(wcolor_box,
|
||||
channels[j],
|
||||
MENU_THUMBNAIL_WIDTH,
|
||||
MENU_THUMBNAIL_HEIGHT);
|
||||
|
||||
gtk_widget_set_usize( GTK_WIDGET (wcolor_box) ,
|
||||
MENU_THUMBNAIL_WIDTH ,
|
||||
MENU_THUMBNAIL_HEIGHT);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(vbox), wcolor_box);
|
||||
gtk_widget_show(wcolor_box);
|
||||
|
||||
wlabel = gtk_label_new(label);
|
||||
gtk_misc_set_alignment(GTK_MISC(wlabel), 0.0, 0.5);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), wlabel, TRUE, TRUE, 4);
|
||||
gtk_widget_show(wlabel);
|
||||
|
||||
gtk_menu_append (GTK_MENU (menu), menuitem);
|
||||
gtk_widget_show (menuitem);
|
||||
|
||||
|
@ -355,15 +434,49 @@ gimp_drawable_menu_new (GimpConstraintFunc constraint,
|
|||
for (j = 0; j < nlayers; j++)
|
||||
if (!constraint || (* constraint) (images[i], layers[j], data))
|
||||
{
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *wcolor_box;
|
||||
GtkWidget *wlabel;
|
||||
|
||||
name = gimp_layer_get_name (layers[j]);
|
||||
label = g_new (char, strlen (image_label) + strlen (name) + 2);
|
||||
sprintf (label, "%s/%s", image_label, name);
|
||||
g_free (name);
|
||||
|
||||
menuitem = gtk_menu_item_new_with_label (label);
|
||||
menuitem = gtk_menu_item_new();
|
||||
gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
|
||||
(GtkSignalFunc) gimp_menu_callback,
|
||||
&layers[j]);
|
||||
|
||||
hbox = gtk_hbox_new(FALSE, 0);
|
||||
gtk_container_add(GTK_CONTAINER(menuitem), hbox);
|
||||
gtk_widget_show(hbox);
|
||||
|
||||
vbox = gtk_vbox_new(FALSE, 0);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show(vbox);
|
||||
|
||||
wcolor_box = gtk_preview_new(GTK_PREVIEW_COLOR);
|
||||
gtk_preview_set_dither (GTK_PREVIEW (wcolor_box), GDK_RGB_DITHER_MAX);
|
||||
|
||||
fill_preview_with_thumb(wcolor_box,
|
||||
layers[j],
|
||||
MENU_THUMBNAIL_WIDTH,
|
||||
MENU_THUMBNAIL_HEIGHT);
|
||||
|
||||
gtk_widget_set_usize( GTK_WIDGET (wcolor_box) ,
|
||||
MENU_THUMBNAIL_WIDTH ,
|
||||
MENU_THUMBNAIL_HEIGHT);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(vbox), wcolor_box);
|
||||
gtk_widget_show(wcolor_box);
|
||||
|
||||
wlabel = gtk_label_new(label);
|
||||
gtk_misc_set_alignment(GTK_MISC(wlabel), 0.0, 0.5);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), wlabel, TRUE, TRUE, 4);
|
||||
gtk_widget_show(wlabel);
|
||||
|
||||
gtk_menu_append (GTK_MENU (menu), menuitem);
|
||||
gtk_widget_show (menuitem);
|
||||
|
||||
|
@ -384,15 +497,49 @@ gimp_drawable_menu_new (GimpConstraintFunc constraint,
|
|||
for (j = 0; j < nchannels; j++)
|
||||
if (!constraint || (* constraint) (images[i], channels[j], data))
|
||||
{
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *wcolor_box;
|
||||
GtkWidget *wlabel;
|
||||
|
||||
name = gimp_channel_get_name (channels[j]);
|
||||
label = g_new (char, strlen (image_label) + strlen (name) + 2);
|
||||
sprintf (label, "%s/%s", image_label, name);
|
||||
g_free (name);
|
||||
|
||||
menuitem = gtk_menu_item_new_with_label (label);
|
||||
menuitem = gtk_menu_item_new();
|
||||
gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
|
||||
(GtkSignalFunc) gimp_menu_callback,
|
||||
&channels[j]);
|
||||
|
||||
hbox = gtk_hbox_new(FALSE, 0);
|
||||
gtk_container_add(GTK_CONTAINER(menuitem), hbox);
|
||||
gtk_widget_show(hbox);
|
||||
|
||||
vbox = gtk_vbox_new(FALSE, 0);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show(vbox);
|
||||
|
||||
wcolor_box = gtk_preview_new(GTK_PREVIEW_COLOR);
|
||||
gtk_preview_set_dither (GTK_PREVIEW (wcolor_box), GDK_RGB_DITHER_MAX);
|
||||
|
||||
fill_preview_with_thumb(wcolor_box,
|
||||
channels[j],
|
||||
MENU_THUMBNAIL_WIDTH,
|
||||
MENU_THUMBNAIL_HEIGHT);
|
||||
|
||||
gtk_widget_set_usize( GTK_WIDGET (wcolor_box) ,
|
||||
MENU_THUMBNAIL_WIDTH ,
|
||||
MENU_THUMBNAIL_HEIGHT);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(vbox), wcolor_box);
|
||||
gtk_widget_show(wcolor_box);
|
||||
|
||||
wlabel = gtk_label_new(label);
|
||||
gtk_misc_set_alignment(GTK_MISC(wlabel), 0.0, 0.5);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), wlabel, TRUE, TRUE, 4);
|
||||
gtk_widget_show(wlabel);
|
||||
|
||||
gtk_menu_append (GTK_MENU (menu), menuitem);
|
||||
gtk_widget_show (menuitem);
|
||||
|
||||
|
@ -441,6 +588,107 @@ gimp_menu_callback (GtkWidget *w,
|
|||
(* callback) (*id, callback_data);
|
||||
}
|
||||
|
||||
static void
|
||||
fill_preview_with_thumb(GtkWidget *w,gint32 drawableId,gint width,gint height)
|
||||
{
|
||||
guchar *drawable_data;
|
||||
gint bpp;
|
||||
|
||||
bpp = 0; /* Only returned */
|
||||
|
||||
drawable_data = gimp_drawable_get_thumbnail_data(drawableId,&width,&height,&bpp);
|
||||
|
||||
gtk_preview_size(GTK_PREVIEW(w),width,height);
|
||||
|
||||
/* First greyscale and non-alpha */
|
||||
if(bpp < 4)
|
||||
{
|
||||
guchar *buf;
|
||||
guchar *src;
|
||||
gint x,y;
|
||||
|
||||
/* Draw the image */
|
||||
buf = g_new (gchar, width * 3);
|
||||
src = drawable_data;
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
if (bpp == 1)
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
buf[x*3+0] = src[x];
|
||||
buf[x*3+1] = src[x];
|
||||
buf[x*3+2] = src[x];
|
||||
}
|
||||
else
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
buf[x*3+0] = src[x*3+0];
|
||||
buf[x*3+1] = src[x*3+1];
|
||||
buf[x*3+2] = src[x*3+2];
|
||||
}
|
||||
gtk_preview_draw_row (GTK_PREVIEW (w), (guchar *)buf, 0, y, width);
|
||||
src += width * bpp;
|
||||
}
|
||||
g_free(buf);
|
||||
}
|
||||
else /* Has alpha channel */
|
||||
{
|
||||
gint x,y;
|
||||
guchar *src;
|
||||
gdouble r, g, b, a;
|
||||
gdouble c0, c1;
|
||||
guchar *p0, *p1,*even,*odd;
|
||||
|
||||
/* Draw the thumbnail with checks */
|
||||
src = drawable_data;
|
||||
|
||||
even = g_malloc(width*3);
|
||||
odd = g_malloc(width*3);
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
p0 = even;
|
||||
p1 = odd;
|
||||
|
||||
for (x = 0; x < width; x++) {
|
||||
r = ((gdouble)src[x*4+0])/255.0;
|
||||
g = ((gdouble)src[x*4+1])/255.0;
|
||||
b = ((gdouble)src[x*4+2])/255.0;
|
||||
a = ((gdouble)src[x*4+3])/255.0;
|
||||
|
||||
if ((x / GRAD_CHECK_SIZE_SM) & 1) {
|
||||
c0 = GRAD_CHECK_LIGHT;
|
||||
c1 = GRAD_CHECK_DARK;
|
||||
} else {
|
||||
c0 = GRAD_CHECK_DARK;
|
||||
c1 = GRAD_CHECK_LIGHT;
|
||||
} /* else */
|
||||
|
||||
*p0++ = (c0 + (r - c0) * a) * 255.0;
|
||||
*p0++ = (c0 + (g - c0) * a) * 255.0;
|
||||
*p0++ = (c0 + (b - c0) * a) * 255.0;
|
||||
|
||||
*p1++ = (c1 + (r - c1) * a) * 255.0;
|
||||
*p1++ = (c1 + (g - c1) * a) * 255.0;
|
||||
*p1++ = (c1 + (b - c1) * a) * 255.0;
|
||||
|
||||
} /* for */
|
||||
|
||||
if ((y / GRAD_CHECK_SIZE_SM) & 1)
|
||||
{
|
||||
gtk_preview_draw_row (GTK_PREVIEW (w), (guchar *)odd, 0, y, width);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_preview_draw_row (GTK_PREVIEW (w), (guchar *)even, 0, y, width);
|
||||
}
|
||||
src += width * bpp;
|
||||
}
|
||||
g_free(even);
|
||||
g_free(odd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* These functions allow the callback PDB work with gtk
|
||||
* ALT.
|
||||
|
@ -734,7 +982,6 @@ gen_temp_plugin_name (void)
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Can only be used in conjuction with gdk since we need to tie into the input
|
||||
* selection mech.
|
||||
*/
|
||||
|
|
|
@ -426,6 +426,91 @@ HELP
|
|||
%invoke = ( code => 'gimp_drawable_set_gimage (drawable, gimage);' );
|
||||
}
|
||||
|
||||
|
||||
sub dim_args () {
|
||||
my @args;
|
||||
foreach (qw(width height bpp)) {
|
||||
push @args, { name => $_, type => 'int32', desc => "The previews $_", init => 1 };
|
||||
}
|
||||
@args;
|
||||
}
|
||||
|
||||
sub drawable_thumbnail {
|
||||
$blurb = 'Get a thumbnail of a drawable.';
|
||||
|
||||
$help = <<'HELP';
|
||||
This function gets data from which a thumbnail of a drawable preview can be
|
||||
created. Maximum x or y dimension is 128 pixels. The pixles are returned
|
||||
in the RGB[A] format. The bpp return value gives the number of bytes in
|
||||
the image. The alpha channel also returned if the drawable has one.
|
||||
HELP
|
||||
|
||||
$author = $copyright = 'Andy Thomas';
|
||||
$date = '1999';
|
||||
|
||||
@inargs = (
|
||||
{ name => 'drawable',
|
||||
type => 'drawable',
|
||||
desc => 'The drawable' },
|
||||
{ name => 'width', type => '0 < int32',
|
||||
desc => 'The thumbnail width',
|
||||
alias => 'req_width' },
|
||||
{ name => 'height', type => '0 < int32',
|
||||
desc => 'The thumbnail height',
|
||||
alias => 'req_height' }
|
||||
);
|
||||
|
||||
@outargs = (
|
||||
&dim_args,
|
||||
{ name => 'thumbnail_data', type => 'int8array',
|
||||
desc => 'The thumbnail data', init => 1,
|
||||
array => { name => 'thumbnail_data_count',
|
||||
desc => 'The number of pixels in thumbnail data',
|
||||
alias => 'num_pixels', init => 1 } }
|
||||
);
|
||||
|
||||
%invoke = (
|
||||
headers => [ qw(<glib.h> <string.h>) ],
|
||||
code => <<'CODE'
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
CODE
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@headers = qw("drawable.h");
|
||||
|
||||
@procs = qw(drawable_merge_shadow drawable_fill drawable_update
|
||||
|
@ -434,7 +519,7 @@ HELP
|
|||
drawable_gray drawable_indexed drawable_bytes drawable_width
|
||||
drawable_height drawable_offsets drawable_layer
|
||||
drawable_layer_mask drawable_channel drawable_get_pixel
|
||||
drawable_set_pixel drawable_set_image);
|
||||
drawable_set_pixel drawable_set_image drawable_thumbnail);
|
||||
%exports = (app => [@procs], lib => [@procs]);
|
||||
|
||||
$desc = 'Drawable procedures';
|
||||
|
|
|
@ -1184,6 +1184,84 @@ CODE
|
|||
SUB
|
||||
}
|
||||
|
||||
sub preview_dim_args () {
|
||||
my @args;
|
||||
foreach (qw(width height bpp)) {
|
||||
push @args, { name => $_, type => 'int32', desc => "The previews $_", init => 1 };
|
||||
}
|
||||
@args;
|
||||
}
|
||||
|
||||
sub image_thumbnail {
|
||||
$blurb = 'Get a thumbnail of an image.';
|
||||
|
||||
$help = <<'HELP';
|
||||
This function gets data from which a thumbnail of an image preview can be
|
||||
created. Maximum x or y dimension is 128 pixels. The pixles are returned
|
||||
in the RGB[A] format. The bpp return value gives the number of bytes in
|
||||
the image. The alpha channel also returned if the image has one.
|
||||
HELP
|
||||
|
||||
$author = $copyright = 'Andy Thomas';
|
||||
$date = '1999';
|
||||
|
||||
@inargs = (
|
||||
&std_image_arg,
|
||||
{ name => 'width', type => '0 < int32',
|
||||
desc => 'The thumbnail width',
|
||||
alias => 'req_width' },
|
||||
{ name => 'height', type => '0 < int32',
|
||||
desc => 'The thumbnail height',
|
||||
alias => 'req_height' }
|
||||
);
|
||||
|
||||
@outargs = (
|
||||
&preview_dim_args,
|
||||
{ name => 'thumbnail_data', type => 'int8array',
|
||||
desc => 'The thumbnail data', init => 1,
|
||||
array => { name => 'thumbnail_data_count',
|
||||
desc => 'The number of pixels in thumbnail data',
|
||||
alias => 'num_pixels', init => 1 } }
|
||||
);
|
||||
|
||||
%invoke = (
|
||||
headers => [ qw(<glib.h> <string.h>) ],
|
||||
code => <<'CODE'
|
||||
{
|
||||
TempBuf * buf;
|
||||
gint dwidth,dheight;
|
||||
|
||||
if(req_width <= 128 && req_height <= 128)
|
||||
{
|
||||
|
||||
/* Adjust the width/height ratio */
|
||||
|
||||
dwidth = gimage->width;
|
||||
dheight = gimage->height;
|
||||
|
||||
if(dwidth > dheight)
|
||||
{
|
||||
req_height = (req_width*dheight)/dwidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
req_width = (req_height*dwidth)/dheight;
|
||||
}
|
||||
|
||||
buf = gimp_image_construct_composite_preview(gimage,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;
|
||||
}
|
||||
}
|
||||
CODE
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@headers = qw(<string.h> "gimage.h");
|
||||
|
||||
$extra{app}->{code} = <<'CODE';
|
||||
|
@ -1210,7 +1288,7 @@ unshift @procs, qw(list_images image_new image_resize image_scale image_delete
|
|||
image_active_drawable image_base_type image_get_cmap
|
||||
image_set_cmap image_enable_undo image_disable_undo
|
||||
image_clean_all image_floating_selection
|
||||
image_floating_sel_attached_to);
|
||||
image_floating_sel_attached_to image_thumbnail);
|
||||
%exports = (app => [@procs]);
|
||||
|
||||
$desc = 'Image';
|
||||
|
|
|
@ -1184,6 +1184,84 @@ CODE
|
|||
SUB
|
||||
}
|
||||
|
||||
sub preview_dim_args () {
|
||||
my @args;
|
||||
foreach (qw(width height bpp)) {
|
||||
push @args, { name => $_, type => 'int32', desc => "The previews $_", init => 1 };
|
||||
}
|
||||
@args;
|
||||
}
|
||||
|
||||
sub image_thumbnail {
|
||||
$blurb = 'Get a thumbnail of an image.';
|
||||
|
||||
$help = <<'HELP';
|
||||
This function gets data from which a thumbnail of an image preview can be
|
||||
created. Maximum x or y dimension is 128 pixels. The pixles are returned
|
||||
in the RGB[A] format. The bpp return value gives the number of bytes in
|
||||
the image. The alpha channel also returned if the image has one.
|
||||
HELP
|
||||
|
||||
$author = $copyright = 'Andy Thomas';
|
||||
$date = '1999';
|
||||
|
||||
@inargs = (
|
||||
&std_image_arg,
|
||||
{ name => 'width', type => '0 < int32',
|
||||
desc => 'The thumbnail width',
|
||||
alias => 'req_width' },
|
||||
{ name => 'height', type => '0 < int32',
|
||||
desc => 'The thumbnail height',
|
||||
alias => 'req_height' }
|
||||
);
|
||||
|
||||
@outargs = (
|
||||
&preview_dim_args,
|
||||
{ name => 'thumbnail_data', type => 'int8array',
|
||||
desc => 'The thumbnail data', init => 1,
|
||||
array => { name => 'thumbnail_data_count',
|
||||
desc => 'The number of pixels in thumbnail data',
|
||||
alias => 'num_pixels', init => 1 } }
|
||||
);
|
||||
|
||||
%invoke = (
|
||||
headers => [ qw(<glib.h> <string.h>) ],
|
||||
code => <<'CODE'
|
||||
{
|
||||
TempBuf * buf;
|
||||
gint dwidth,dheight;
|
||||
|
||||
if(req_width <= 128 && req_height <= 128)
|
||||
{
|
||||
|
||||
/* Adjust the width/height ratio */
|
||||
|
||||
dwidth = gimage->width;
|
||||
dheight = gimage->height;
|
||||
|
||||
if(dwidth > dheight)
|
||||
{
|
||||
req_height = (req_width*dheight)/dwidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
req_width = (req_height*dwidth)/dheight;
|
||||
}
|
||||
|
||||
buf = gimp_image_construct_composite_preview(gimage,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;
|
||||
}
|
||||
}
|
||||
CODE
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@headers = qw(<string.h> "gimage.h");
|
||||
|
||||
$extra{app}->{code} = <<'CODE';
|
||||
|
@ -1210,7 +1288,7 @@ unshift @procs, qw(list_images image_new image_resize image_scale image_delete
|
|||
image_active_drawable image_base_type image_get_cmap
|
||||
image_set_cmap image_enable_undo image_disable_undo
|
||||
image_clean_all image_floating_selection
|
||||
image_floating_sel_attached_to);
|
||||
image_floating_sel_attached_to image_thumbnail);
|
||||
%exports = (app => [@procs]);
|
||||
|
||||
$desc = 'Image';
|
||||
|
|
Loading…
Reference in New Issue