gimp/app/core/gimpbrush-scale.c

476 lines
12 KiB
C
Raw Normal View History

/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpbrush-scale.c
*
* 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.
*/
app/Makefile.am app/channel_pvt.h app/drawable_pvt.h app/gdisplayF.h 2000-12-29 Michael Natterer <mitch@gimp.org> * app/Makefile.am * app/channel_pvt.h * app/drawable_pvt.h * app/gdisplayF.h * app/gimpdrawableP.h * app/gimpimageP.h * app/layer_pvt.h * app/toolsF.h: removed these files. * app/apptypes.h * tools/pdbgen/enums.pl: added tons of opaque typedefs and enums. * tools/pdbgen/pdb/brush_select.pdb * tools/pdbgen/pdb/brushes.pdb * tools/pdbgen/pdb/channel.pdb * tools/pdbgen/pdb/color.pdb * tools/pdbgen/pdb/convert.pdb * tools/pdbgen/pdb/display.pdb * tools/pdbgen/pdb/drawable.pdb * tools/pdbgen/pdb/fileops.pdb * tools/pdbgen/pdb/gradient_select.pdb * tools/pdbgen/pdb/gradients.pdb * tools/pdbgen/pdb/help.pdb * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/layer.pdb * tools/pdbgen/pdb/pattern_select.pdb * tools/pdbgen/pdb/patterns.pdb * tools/pdbgen/pdb/selection.pdb * tools/pdbgen/pdb/tools.pdb * app/*: chainsaw #include cleanup: - Never (never!!) include stuff in header files except where we need access to structures' contents (like derived objects). - Added prototypes and proper formating in many files. - The #include order in *all* *.c files is as follows: #include "config.h" #include <system stuff> #include <gtk/gtk.h> #include "apptypes.h" #include "gimp stuff" #include "libgimp stuff" #include "libgimp/gimpintl.h" By following this scheme we can easily see a file's dependencies from it's #include's and can grep for the inclusion to find out where a file is used. * tools/pdbgen/app.pl: changed to follow the include scheme above. * libgimp/Makefile.am * libgimp/gimpuitypes.h: new file, included from libgimp/gimpui.h and from app/apptypes.h. * libgimp/gimpcolorbutton.[ch] * libgimp/gimpdialog.[ch] * libgimp/gimphelpui.[ch] * libgimp/gimpparasite.[ch] * libgimp/gimppatheditor.[ch] * libgimp/gimpprotocol.c * libgimp/gimpquerybox.[ch] * libgimp/gimpsizeentry.[ch] * libgimp/gimptypes.h * libgimp/gimpui.h * libgimp/gimpunit.h * libgimp/gimpunitmenu.[ch] * libgimp/gimpwidgets.[ch]: changed accordingly. * plug-ins/FractalExplorer/Dialogs.c * plug-ins/gdyntext/message_window.c * plug-ins/imagemap/imap_default_dialog.c * plug-ins/imagemap/imap_file.c: these files used to include "libgimp/gimpui.h" without including "libgimp/gimp.h". This is no longer possible because the libgimpui headers don't inlcude "libgimp/gimpunit.h" any more.
2000-12-29 23:22:01 +08:00
#include "config.h"
removed from CVS, they are generated. 2001-12-07 Sven Neumann <sven@gimp.org> * app/core/gimpmarshal.[ch]: removed from CVS, they are generated. * app/base/Makefile.am * app/base/base-enums.h: new file defining enums that are to be registered. Used to build app/base/base-enums.c. * app/base/base-types.h: include base-enums.h. * tools/pdbgen/Makefile.am * tools/pdbgen/enumcode.pl * tools/pdbgen/enums.pl: parse the new base-enums.h file and modified the perl voodoo so it doesn't prefix enums with GIMP_ that are already properly namespaced. * app/core/core-types.h: don't need to chop GIMP from enum. * app/pdb/color_cmds.c * app/pdb/tools_cmds.c * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c: regenerated. * app/config/gimpconfig-deserialize.[ch] * app/config/gimpconfig-serialize.[ch] * app/config/gimpconfig.[ch]: made GimpConfig an interface including a reasonable default implementation that works on object properties. * app/config/Makefile.am * app/config/gimpbaseconfig.[ch]: new GimpBaseConfig using the GimpConfig interface. Yet only used for testing from app/main.c. * app/main.c: test the new GimpBaseConfig object. * app/gimprc.c * app/base/base-config.h * app/base/*.c * app/core/gimpdatafiles.c * app/core/gimpdrawable-transform.c * app/core/gimppreviewcache.c * app/gui/preferences-dialog.c * app/paint-funcs/paint-funcs.c * app/xcf/xcf-seek.c: need to include glib-object.h since base-config contains registered enums now. Follow name change of InterpolationType to GimpInterpolationType.
2001-12-08 00:10:53 +08:00
#include <glib-object.h>
app/Makefile.am app/channel_pvt.h app/drawable_pvt.h app/gdisplayF.h 2000-12-29 Michael Natterer <mitch@gimp.org> * app/Makefile.am * app/channel_pvt.h * app/drawable_pvt.h * app/gdisplayF.h * app/gimpdrawableP.h * app/gimpimageP.h * app/layer_pvt.h * app/toolsF.h: removed these files. * app/apptypes.h * tools/pdbgen/enums.pl: added tons of opaque typedefs and enums. * tools/pdbgen/pdb/brush_select.pdb * tools/pdbgen/pdb/brushes.pdb * tools/pdbgen/pdb/channel.pdb * tools/pdbgen/pdb/color.pdb * tools/pdbgen/pdb/convert.pdb * tools/pdbgen/pdb/display.pdb * tools/pdbgen/pdb/drawable.pdb * tools/pdbgen/pdb/fileops.pdb * tools/pdbgen/pdb/gradient_select.pdb * tools/pdbgen/pdb/gradients.pdb * tools/pdbgen/pdb/help.pdb * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/layer.pdb * tools/pdbgen/pdb/pattern_select.pdb * tools/pdbgen/pdb/patterns.pdb * tools/pdbgen/pdb/selection.pdb * tools/pdbgen/pdb/tools.pdb * app/*: chainsaw #include cleanup: - Never (never!!) include stuff in header files except where we need access to structures' contents (like derived objects). - Added prototypes and proper formating in many files. - The #include order in *all* *.c files is as follows: #include "config.h" #include <system stuff> #include <gtk/gtk.h> #include "apptypes.h" #include "gimp stuff" #include "libgimp stuff" #include "libgimp/gimpintl.h" By following this scheme we can easily see a file's dependencies from it's #include's and can grep for the inclusion to find out where a file is used. * tools/pdbgen/app.pl: changed to follow the include scheme above. * libgimp/Makefile.am * libgimp/gimpuitypes.h: new file, included from libgimp/gimpui.h and from app/apptypes.h. * libgimp/gimpcolorbutton.[ch] * libgimp/gimpdialog.[ch] * libgimp/gimphelpui.[ch] * libgimp/gimpparasite.[ch] * libgimp/gimppatheditor.[ch] * libgimp/gimpprotocol.c * libgimp/gimpquerybox.[ch] * libgimp/gimpsizeentry.[ch] * libgimp/gimptypes.h * libgimp/gimpui.h * libgimp/gimpunit.h * libgimp/gimpunitmenu.[ch] * libgimp/gimpwidgets.[ch]: changed accordingly. * plug-ins/FractalExplorer/Dialogs.c * plug-ins/gdyntext/message_window.c * plug-ins/imagemap/imap_default_dialog.c * plug-ins/imagemap/imap_file.c: these files used to include "libgimp/gimpui.h" without including "libgimp/gimp.h". This is no longer possible because the libgimpui headers don't inlcude "libgimp/gimpunit.h" any more.
2000-12-29 23:22:01 +08:00
#include "core-types.h"
#include "gimpbrush.h"
#include "gimpbrush-scale.h"
#include "base/pixel-region.h"
#include "base/temp-buf.h"
#include "paint-funcs/scale-region.h"
/* local function prototypes */
static TempBuf * gimp_brush_scale_buf_up (TempBuf *brush_buf,
gint dest_width,
gint dest_height);
static TempBuf * gimp_brush_scale_mask_down (TempBuf *brush_mask,
gint dest_width,
gint dest_height);
static TempBuf * gimp_brush_scale_pixmap_down (TempBuf *pixmap,
gint dest_width,
gint dest_height);
/* public functions */
void
gimp_brush_real_scale_size (GimpBrush *brush,
gdouble scale,
gint *width,
gint *height)
{
*width = (gint) (brush->mask->width * scale + 0.5);
*height = (gint) (brush->mask->height * scale + 0.5);
}
TempBuf *
gimp_brush_real_scale_mask (GimpBrush *brush,
gdouble scale)
{
gint dest_width;
gint dest_height;
gimp_brush_scale_size (brush, scale, &dest_width, &dest_height);
if (dest_width <= 0 || dest_height <= 0)
return NULL;
if (scale <= 1.0)
{
/* Downscaling with brush_scale_mask is much faster than with
* gimp_brush_scale_buf.
*/
return gimp_brush_scale_mask_down (brush->mask,
dest_width, dest_height);
}
return gimp_brush_scale_buf_up (brush->mask, dest_width, dest_height);
}
TempBuf *
gimp_brush_real_scale_pixmap (GimpBrush *brush,
gdouble scale)
{
gint dest_width;
gint dest_height;
gimp_brush_scale_size (brush, scale, &dest_width, &dest_height);
app/Makefile.am app/channel_pvt.h app/drawable_pvt.h app/gdisplayF.h 2000-12-29 Michael Natterer <mitch@gimp.org> * app/Makefile.am * app/channel_pvt.h * app/drawable_pvt.h * app/gdisplayF.h * app/gimpdrawableP.h * app/gimpimageP.h * app/layer_pvt.h * app/toolsF.h: removed these files. * app/apptypes.h * tools/pdbgen/enums.pl: added tons of opaque typedefs and enums. * tools/pdbgen/pdb/brush_select.pdb * tools/pdbgen/pdb/brushes.pdb * tools/pdbgen/pdb/channel.pdb * tools/pdbgen/pdb/color.pdb * tools/pdbgen/pdb/convert.pdb * tools/pdbgen/pdb/display.pdb * tools/pdbgen/pdb/drawable.pdb * tools/pdbgen/pdb/fileops.pdb * tools/pdbgen/pdb/gradient_select.pdb * tools/pdbgen/pdb/gradients.pdb * tools/pdbgen/pdb/help.pdb * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/layer.pdb * tools/pdbgen/pdb/pattern_select.pdb * tools/pdbgen/pdb/patterns.pdb * tools/pdbgen/pdb/selection.pdb * tools/pdbgen/pdb/tools.pdb * app/*: chainsaw #include cleanup: - Never (never!!) include stuff in header files except where we need access to structures' contents (like derived objects). - Added prototypes and proper formating in many files. - The #include order in *all* *.c files is as follows: #include "config.h" #include <system stuff> #include <gtk/gtk.h> #include "apptypes.h" #include "gimp stuff" #include "libgimp stuff" #include "libgimp/gimpintl.h" By following this scheme we can easily see a file's dependencies from it's #include's and can grep for the inclusion to find out where a file is used. * tools/pdbgen/app.pl: changed to follow the include scheme above. * libgimp/Makefile.am * libgimp/gimpuitypes.h: new file, included from libgimp/gimpui.h and from app/apptypes.h. * libgimp/gimpcolorbutton.[ch] * libgimp/gimpdialog.[ch] * libgimp/gimphelpui.[ch] * libgimp/gimpparasite.[ch] * libgimp/gimppatheditor.[ch] * libgimp/gimpprotocol.c * libgimp/gimpquerybox.[ch] * libgimp/gimpsizeentry.[ch] * libgimp/gimptypes.h * libgimp/gimpui.h * libgimp/gimpunit.h * libgimp/gimpunitmenu.[ch] * libgimp/gimpwidgets.[ch]: changed accordingly. * plug-ins/FractalExplorer/Dialogs.c * plug-ins/gdyntext/message_window.c * plug-ins/imagemap/imap_default_dialog.c * plug-ins/imagemap/imap_file.c: these files used to include "libgimp/gimpui.h" without including "libgimp/gimp.h". This is no longer possible because the libgimpui headers don't inlcude "libgimp/gimpunit.h" any more.
2000-12-29 23:22:01 +08:00
if (dest_width <= 0 || dest_height <= 0)
return NULL;
if (scale <= 1.0)
{
/* Downscaling with brush_scale_pixmap is much faster than with
* gimp_brush_scale_buf.
*/
return gimp_brush_scale_pixmap_down (brush->pixmap,
dest_width, dest_height);
}
return gimp_brush_scale_buf_up (brush->pixmap, dest_width, dest_height);
}
1999-08-22 04:33:13 +08:00
/* private functions */
static TempBuf *
gimp_brush_scale_buf_up (TempBuf *brush_buf,
gint dest_width,
gint dest_height)
{
PixelRegion source_region;
PixelRegion dest_region;
TempBuf *dest_brush_buf;
pixel_region_init_temp_buf (&source_region, brush_buf,
0, 0,
brush_buf->width,
brush_buf->height);
dest_brush_buf = temp_buf_new (dest_width, dest_height, brush_buf->bytes,
0, 0, NULL);
pixel_region_init_temp_buf (&dest_region, dest_brush_buf,
0, 0,
dest_width,
dest_height);
scale_region (&source_region, &dest_region, GIMP_INTERPOLATION_LINEAR,
NULL, NULL);
return dest_brush_buf;
}
static TempBuf *
gimp_brush_scale_mask_down (TempBuf *brush_mask,
gint dest_width,
gint dest_height)
{
TempBuf *scale_brush;
gint src_width;
gint src_height;
gint value;
gint area;
gint i, j;
gint x, x0, y, y0;
gint dx, dx0, dy, dy0;
gint fx, fx0, fy, fy0;
guchar *src, *dest;
g_return_val_if_fail (brush_mask != NULL &&
dest_width != 0 && dest_height != 0, NULL);
src_width = brush_mask->width;
src_height = brush_mask->height;
scale_brush = temp_buf_new (dest_width, dest_height, 1, 0, 0, NULL);
g_return_val_if_fail (scale_brush != NULL, NULL);
/* get the data */
dest = temp_buf_data (scale_brush);
src = temp_buf_data (brush_mask);
fx = fx0 = (src_width << 8) / dest_width;
fy = fy0 = (src_height << 8) / dest_height;
area = (fx0 * fy0) >> 8;
x = x0 = 0;
y = y0 = 0;
dx = dx0 = 0;
dy = dy0 = 0;
for (i=0; i<dest_height; i++)
{
for (j=0; j<dest_width; j++)
{
value = 0;
fy = fy0;
y = y0;
dy = dy0;
if (dy)
{
fx = fx0;
x = x0;
dx = dx0;
if (dx)
{
value += (dx * dy * src[x + src_width * y]) >> 8;
x++;
fx -= dx;
dx = 0;
}
while (fx >= 256)
{
value += dy * src[x + src_width * y];
x++;
fx -= 256;
}
if (fx)
{
value += fx * dy * src[x + src_width * y] >> 8;
dx = 256 - fx;
}
y++;
fy -= dy;
dy = 0;
}
while (fy >= 256)
{
fx = fx0;
x = x0;
dx = dx0;
if (dx)
{
value += dx * src[x + src_width * y];
x++;
fx -= dx;
dx = 0;
}
while (fx >= 256)
{
value += 256 * src[x + src_width * y];
x++;
fx -= 256;
}
if (fx)
{
value += fx * src[x + src_width * y];
dx = 256 - fx;
}
y++;
fy -= 256;
}
if (fy)
{
fx = fx0;
x = x0;
dx = dx0;
if (dx)
{
value += (dx * fy * src[x + src_width * y]) >> 8;
x++;
fx -= dx;
dx = 0;
}
while (fx >= 256)
{
value += fy * src[x + src_width * y];
x++;
fx -= 256;
}
if (fx)
{
value += (fx * fy * src[x + src_width * y]) >> 8;
dx = 256 - fx;
}
dy = 256 - fy;
}
value /= area;
*dest++ = MIN (value, 255);
x0 = x;
dx0 = dx;
}
x0 = 0;
dx0 = 0;
y0 = y;
dy0 = dy;
}
return scale_brush;
}
#define ADD_RGB(dest, factor, src) \
dest[0] += factor * src[0]; \
dest[1] += factor * src[1]; \
dest[2] += factor * src[2];
1999-08-22 04:33:13 +08:00
static TempBuf *
gimp_brush_scale_pixmap_down (TempBuf *pixmap,
gint dest_width,
gint dest_height)
1999-08-22 04:33:13 +08:00
{
TempBuf *scale_brush;
gint src_width;
gint src_height;
gint value[3];
gint factor;
gint area;
gint i, j;
gint x, x0, y, y0;
gint dx, dx0, dy, dy0;
gint fx, fx0, fy, fy0;
guchar *src, *src_ptr, *dest;
g_return_val_if_fail (pixmap != NULL && pixmap->bytes == 3 &&
dest_width != 0 && dest_height != 0, NULL);
src_width = pixmap->width;
src_height = pixmap->height;
scale_brush = temp_buf_new (dest_width, dest_height, 3, 0, 0, NULL);
g_return_val_if_fail (scale_brush != NULL, NULL);
/* get the data */
dest = temp_buf_data (scale_brush);
src = temp_buf_data (pixmap);
1999-08-22 04:33:13 +08:00
fx = fx0 = (src_width << 8) / dest_width;
fy = fy0 = (src_height << 8) / dest_height;
area = (fx0 * fy0) >> 8;
1999-08-22 04:33:13 +08:00
x = x0 = 0;
y = y0 = 0;
dx = dx0 = 0;
dy = dy0 = 0;
1999-08-22 04:33:13 +08:00
for (i=0; i<dest_height; i++)
{
for (j=0; j<dest_width; j++)
{
value[0] = 0;
value[1] = 0;
value[2] = 0;
fy = fy0;
y = y0;
dy = dy0;
if (dy)
{
fx = fx0;
x = x0;
dx = dx0;
if (dx)
{
factor = (dx * dy) >> 8;
src_ptr = src + 3 * (x + y * src_width);
ADD_RGB (value, factor, src_ptr);
x++;
fx -= dx;
dx = 0;
}
while (fx >= 256)
{
factor = dy;
src_ptr = src + 3 * (x + y * src_width);
ADD_RGB (value, factor, src_ptr);
x++;
fx -= 256;
}
if (fx)
{
factor = (fx * dy) >> 8;
src_ptr = src + 3 * (x + y * src_width);
ADD_RGB (value, factor, src_ptr);
dx = 256 - fx;
}
y++;
fy -= dy;
dy = 0;
}
while (fy >= 256)
{
fx = fx0;
x = x0;
dx = dx0;
if (dx)
{
factor = dx;
src_ptr = src + 3 * (x + y * src_width);
ADD_RGB (value, factor, src_ptr);
x++;
fx -= dx;
dx = 0;
}
while (fx >= 256)
{
factor = 256;
src_ptr = src + 3 * (x + y * src_width);
ADD_RGB (value, factor, src_ptr);
x++;
fx -= 256;
}
if (fx)
{
factor = fx;
src_ptr = src + 3 * (x + y * src_width);
ADD_RGB (value, factor, src_ptr);
dx = 256 - fx;
}
y++;
fy -= 256;
}
if (fy)
{
fx = fx0;
x = x0;
dx = dx0;
if (dx)
{
factor = (dx * fy) >> 8;
src_ptr = src + 3 * (x + y * src_width);
ADD_RGB (value, factor, src_ptr);
x++;
fx -= dx;
dx = 0;
}
while (fx >= 256)
{
factor = fy;
src_ptr = src + 3 * (x + y * src_width);
ADD_RGB (value, factor, src_ptr);
x++;
fx -= 256;
}
if (fx)
{
factor = (fx * fy) >> 8;
src_ptr = src + 3 * (x + y * src_width);
ADD_RGB (value, factor, src_ptr);
dx = 256 - fx;
}
dy = 256 - fy;
}
value[0] /= area;
value[1] /= area;
value[2] /= area;
*dest++ = MIN (value[0], 255);
*dest++ = MIN (value[1], 255);
*dest++ = MIN (value[2], 255);
x0 = x;
dx0 = dx;
}
x0 = 0;
dx0 = 0;
y0 = y;
dy0 = dy;
}
return scale_brush;
1999-08-22 04:33:13 +08:00
}
#undef ADD_RGB