gimp/app/image_render.c

849 lines
18 KiB
C
Raw Normal View History

1997-11-25 06:05:25 +08:00
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* 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.
1997-11-25 06:05:25 +08:00
*/
#include <stdlib.h>
#include <string.h>
1997-11-25 06:05:25 +08:00
#include "appenv.h"
#include "gimprc.h"
#include "gximage.h"
#include "image_render.h"
#include "pixel_region.h"
#include "scale.h"
1998-08-12 01:35:34 +08:00
#include "tile.h" /* ick. */
1997-11-25 06:05:25 +08:00
typedef struct _RenderInfo RenderInfo;
typedef void (*RenderFunc) (RenderInfo *info);
struct _RenderInfo
{
GDisplay *gdisp;
TileManager *src_tiles;
guint *alpha;
guchar *scale;
guchar *src;
guchar *dest;
int x, y;
int w, h;
float scalex;
float scaley;
1997-11-25 06:05:25 +08:00
int src_x, src_y;
int src_bpp;
int dest_bpp;
int dest_bpl;
int dest_width;
int byte_order;
};
/* accelerate transparency of image scaling */
guchar *blend_dark_check = NULL;
guchar *blend_light_check = NULL;
guchar *tile_buf = NULL;
guchar *check_buf = NULL;
guchar *empty_buf = NULL;
guchar *temp_buf = NULL;
static guint check_mod;
static guint check_shift;
static guchar check_combos[6][2] =
{
{ 204, 255 },
{ 102, 153 },
{ 0, 51 },
{ 255, 255 },
{ 127, 127 },
{ 0, 0 }
};
void
render_setup (int check_type,
int check_size)
{
int i, j;
/* based on the tile size, determine the tile shift amount
* (assume here that tile_height and tile_width are equal)
*/
/* allocate a buffer for arranging information from a row of tiles */
if (!tile_buf)
tile_buf = g_new (guchar, GXIMAGE_WIDTH * MAX_CHANNELS);
if (check_type < 0 || check_type > 5)
g_error ("invalid check_type argument to render_setup: %d", check_type);
if (check_size < 0 || check_size > 2)
g_error ("invalid check_size argument to render_setup: %d", check_size);
if (!blend_dark_check)
blend_dark_check = g_new (guchar, 65536);
if (!blend_light_check)
blend_light_check = g_new (guchar, 65536);
for (i = 0; i < 256; i++)
for (j = 0; j < 256; j++)
{
blend_dark_check [(i << 8) + j] = (guchar)
((j * i + check_combos[check_type][0] * (255 - i)) / 255);
blend_light_check [(i << 8) + j] = (guchar)
((j * i + check_combos[check_type][1] * (255 - i)) / 255);
}
switch (check_size)
{
case SMALL_CHECKS:
check_mod = 0x3;
check_shift = 2;
break;
case MEDIUM_CHECKS:
check_mod = 0x7;
check_shift = 3;
break;
case LARGE_CHECKS:
check_mod = 0xf;
check_shift = 4;
break;
}
/* calculate check buffer for previews */
if (preview_size)
{
if (check_buf)
g_free (check_buf);
if (empty_buf)
g_free (empty_buf);
if (temp_buf)
g_free (temp_buf);
check_buf = (unsigned char *) g_malloc ((preview_size + 4) * 3);
for (i = 0; i < (preview_size + 4); i++)
{
if (i & 0x4)
{
check_buf[i * 3 + 0] = blend_dark_check[0];
check_buf[i * 3 + 1] = blend_dark_check[0];
check_buf[i * 3 + 2] = blend_dark_check[0];
}
else
{
check_buf[i * 3 + 0] = blend_light_check[0];
check_buf[i * 3 + 1] = blend_light_check[0];
check_buf[i * 3 + 2] = blend_light_check[0];
}
}
empty_buf = (unsigned char *) g_malloc ((preview_size + 4) * 3);
memset (empty_buf, 0, (preview_size + 4) * 3);
temp_buf = (unsigned char *) g_malloc ((preview_size + 4) * 3);
}
else
{
check_buf = NULL;
empty_buf = NULL;
temp_buf = NULL;
}
}
void
render_free (void)
{
g_free (tile_buf);
g_free (check_buf);
}
/* Render Image functions */
static void render_image_rgb (RenderInfo *info);
static void render_image_rgb_a (RenderInfo *info);
static void render_image_gray (RenderInfo *info);
static void render_image_gray_a (RenderInfo *info);
static void render_image_indexed (RenderInfo *info);
static void render_image_indexed_a (RenderInfo *info);
1997-11-25 06:05:25 +08:00
static void render_image_init_info (RenderInfo *info,
GDisplay *gdisp,
int x,
int y,
int w,
int h);
static guint* render_image_init_alpha (int mult);
static guchar* render_image_accelerate_scaling (int width,
int start,
float scalex);
1997-11-25 06:05:25 +08:00
static guchar* render_image_tile_fault (RenderInfo *info);
static RenderFunc render_funcs[6] =
1997-11-25 06:05:25 +08:00
{
render_image_rgb,
render_image_rgb_a,
render_image_gray,
render_image_gray_a,
render_image_indexed,
render_image_indexed_a,
1997-11-25 06:05:25 +08:00
};
/*****************************************************************/
/* This function is the core of the display--it offsets and */
/* scales the image according to the current parameters in the */
/* gdisp object. It handles color, grayscale, 8, 15, 16, 24, */
/* & 32 bit output depths. */
/*****************************************************************/
void
render_image (GDisplay *gdisp,
int x,
int y,
int w,
int h)
{
RenderInfo info;
int image_type;
render_image_init_info (&info, gdisp, x, y, w, h);
image_type = gimage_projection_type (gdisp->gimage);
if ((image_type < 0) || (image_type > 5))
{
g_message ("unknown gimage projection type: %d",
1997-11-25 06:05:25 +08:00
gimage_projection_type (gdisp->gimage));
return;
}
if ((info.dest_bpp < 1) || (info.dest_bpp > 4))
{
g_message ("unsupported destination bytes per pixel: %d", info.dest_bpp);
1997-11-25 06:05:25 +08:00
return;
}
/* Currently, only RGBA and GRAYA projection types are used - the rest
* are in case of future need. -- austin, 28th Nov 1998. */
if (image_type != RGBA_GIMAGE && image_type != GRAYA_GIMAGE)
g_warning ("using untested projection type %d", image_type);
(* render_funcs[image_type]) (&info);
1997-11-25 06:05:25 +08:00
}
/*************************/
/* 8 Bit functions */
/*************************/
static void
render_image_indexed (RenderInfo *info)
1997-11-25 06:05:25 +08:00
{
guchar *src;
guchar *dest;
guchar *cmap;
1997-11-25 06:05:25 +08:00
gulong val;
int byte_order;
int y, ye;
int x, xe;
int initial;
float error;
float step;
1997-11-25 06:05:25 +08:00
cmap = gimage_cmap (info->gdisp->gimage);
1997-11-25 06:05:25 +08:00
y = info->y;
ye = info->y + info->h;
xe = info->x + info->w;
step = 1.0 / info->scaley;
error = y * step;
error -= ((int)error) - step;
1997-11-25 06:05:25 +08:00
initial = TRUE;
byte_order = info->byte_order;
info->src = render_image_tile_fault (info);
for (; y < ye; y++)
{
if (!initial && (error < 1.0))
1997-11-25 06:05:25 +08:00
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
else
{
src = info->src;
dest = info->dest;
g_return_if_fail (src != NULL);
for (x = info->x; x < xe; x++)
{
val = src[INDEXED_PIX] * 3;
src += 1;
dest[0] = cmap[val+0];
dest[1] = cmap[val+1];
dest[2] = cmap[val+2];
dest += 3;
}
1997-11-25 06:05:25 +08:00
}
info->dest += info->dest_bpl;
initial = FALSE;
if (error >= 1.0)
1997-11-25 06:05:25 +08:00
{
info->src_y += (int)error;
error -= (int)error;
1997-11-25 06:05:25 +08:00
info->src = render_image_tile_fault (info);
initial = TRUE;
1997-11-25 06:05:25 +08:00
}
error += step;
1997-11-25 06:05:25 +08:00
}
}
static void
render_image_indexed_a (RenderInfo *info)
1997-11-25 06:05:25 +08:00
{
guchar *src;
guchar *dest;
guint *alpha;
guchar *cmap;
gulong r, g, b;
1997-11-25 06:05:25 +08:00
gulong val;
guint a;
int dark_light;
1997-11-25 06:05:25 +08:00
int byte_order;
int y, ye;
int x, xe;
int initial;
float error;
float step;
1997-11-25 06:05:25 +08:00
cmap = gimage_cmap (info->gdisp->gimage);
alpha = info->alpha;
1997-11-25 06:05:25 +08:00
y = info->y;
ye = info->y + info->h;
xe = info->x + info->w;
step = 1.0 / info->scaley;
error = y * step;
error -= ((int)error) - step;
1997-11-25 06:05:25 +08:00
initial = TRUE;
byte_order = info->byte_order;
info->src = render_image_tile_fault (info);
for (; y < ye; y++)
{
if (!initial && (error < 1.0) && (y & check_mod))
1997-11-25 06:05:25 +08:00
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
else
{
src = info->src;
dest = info->dest;
dark_light = (y >> check_shift) + (info->x >> check_shift);
g_return_if_fail (src != NULL);
1997-11-25 06:05:25 +08:00
for (x = info->x; x < xe; x++)
{
a = alpha[src[ALPHA_I_PIX]];
val = src[INDEXED_PIX] * 3;
src += 2;
if (dark_light & 0x1)
{
r = blend_dark_check[(a | cmap[val+0])];
g = blend_dark_check[(a | cmap[val+1])];
b = blend_dark_check[(a | cmap[val+2])];
}
else
{
r = blend_light_check[(a | cmap[val+0])];
g = blend_light_check[(a | cmap[val+1])];
b = blend_light_check[(a | cmap[val+2])];
}
dest[0] = r;
dest[1] = g;
dest[2] = b;
1997-11-25 06:05:25 +08:00
dest += 3;
if (((x + 1) & check_mod) == 0)
dark_light += 1;
1997-11-25 06:05:25 +08:00
}
}
info->dest += info->dest_bpl;
initial = FALSE;
if (error >= 1.0)
1997-11-25 06:05:25 +08:00
{
info->src_y += (int)error;
error -= (int)error;
1997-11-25 06:05:25 +08:00
info->src = render_image_tile_fault (info);
initial = TRUE;
1997-11-25 06:05:25 +08:00
}
error += step;
1997-11-25 06:05:25 +08:00
}
}
static void
render_image_gray (RenderInfo *info)
1997-11-25 06:05:25 +08:00
{
guchar *src;
guchar *dest;
gulong val;
int byte_order;
int y, ye;
int x, xe;
int initial;
float error;
float step;
1997-11-25 06:05:25 +08:00
y = info->y;
ye = info->y + info->h;
xe = info->x + info->w;
step = 1.0 / info->scaley;
error = y * step;
error -= ((int)error) - step;
1997-11-25 06:05:25 +08:00
initial = TRUE;
byte_order = info->byte_order;
info->src = render_image_tile_fault (info);
for (; y < ye; y++)
{
if (!initial && (error < 1.0))
1997-11-25 06:05:25 +08:00
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
else
{
src = info->src;
dest = info->dest;
g_return_if_fail (src != NULL);
for (x = info->x; x < xe; x++)
{
val = src[GRAY_PIX];
src += 1;
1997-11-25 06:05:25 +08:00
dest[0] = val;
dest[1] = val;
dest[2] = val;
dest += 3;
}
1997-11-25 06:05:25 +08:00
}
info->dest += info->dest_bpl;
initial = FALSE;
if (error >= 1.0)
1997-11-25 06:05:25 +08:00
{
info->src_y += (int)error;
error -= (int)error;
1997-11-25 06:05:25 +08:00
info->src = render_image_tile_fault (info);
initial = TRUE;
1997-11-25 06:05:25 +08:00
}
error += step;
1997-11-25 06:05:25 +08:00
}
}
static void
render_image_gray_a (RenderInfo *info)
1997-11-25 06:05:25 +08:00
{
guchar *src;
guchar *dest;
guint *alpha;
gulong val;
guint a;
int dark_light;
int byte_order;
int y, ye;
int x, xe;
int initial;
float error;
float step;
1997-11-25 06:05:25 +08:00
alpha = info->alpha;
y = info->y;
ye = info->y + info->h;
xe = info->x + info->w;
step = 1.0 / info->scaley;
error = y * step;
error -= ((int)error) - step;
1997-11-25 06:05:25 +08:00
initial = TRUE;
byte_order = info->byte_order;
info->src = render_image_tile_fault (info);
for (; y < ye; y++)
{
if (!initial && (error < 1.0) && (y & check_mod))
1997-11-25 06:05:25 +08:00
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
else
{
src = info->src;
dest = info->dest;
dark_light = (y >> check_shift) + (info->x >> check_shift);
g_return_if_fail (src != NULL);
for (x = info->x; x < xe; x++)
{
a = alpha[src[ALPHA_G_PIX]];
if (dark_light & 0x1)
val = blend_dark_check[(a | src[GRAY_PIX])];
else
val = blend_light_check[(a | src[GRAY_PIX])];
src += 2;
dest[0] = val;
dest[1] = val;
dest[2] = val;
dest += 3;
if (((x + 1) & check_mod) == 0)
dark_light += 1;
}
1997-11-25 06:05:25 +08:00
}
info->dest += info->dest_bpl;
initial = FALSE;
if (error >= 1.0)
1997-11-25 06:05:25 +08:00
{
info->src_y += (int)error;
error -= (int)error;
1997-11-25 06:05:25 +08:00
info->src = render_image_tile_fault (info);
initial = TRUE;
1997-11-25 06:05:25 +08:00
}
error += step;
1997-11-25 06:05:25 +08:00
}
}
static void
render_image_rgb (RenderInfo *info)
1997-11-25 06:05:25 +08:00
{
guchar *src;
guchar *dest;
int y, x;
gboolean initial;
float error;
const int ye = info->y + info->h;
const int xe = info->x + info->w;
const float step = 1.0 / info->scaley;
1997-11-25 06:05:25 +08:00
y = info->y;
error = y * step;
error -= (int)error - step;
1997-11-25 06:05:25 +08:00
initial = TRUE;
info->src = render_image_tile_fault (info);
for (; y < ye; y++)
{
if (!initial && (error < 1.0))
1997-11-25 06:05:25 +08:00
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
else
{
src = info->src;
dest = info->dest;
g_return_if_fail (src != NULL);
/* replace this with memcpy, or better yet, avoid it altogether? */
for (x = info->x; x < xe; x++)
{
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
src += 3;
dest += 3;
}
1997-11-25 06:05:25 +08:00
}
info->dest += info->dest_bpl;
initial = FALSE;
if (error >= 1.0)
1997-11-25 06:05:25 +08:00
{
info->src_y += (int)error;
error -= (int)error;
1997-11-25 06:05:25 +08:00
info->src = render_image_tile_fault (info);
initial = TRUE;
1997-11-25 06:05:25 +08:00
}
error += step;
1997-11-25 06:05:25 +08:00
}
}
1997-11-25 06:05:25 +08:00
static void
render_image_rgb_a (RenderInfo *info)
1997-11-25 06:05:25 +08:00
{
guchar *src;
guchar *dest;
guint *alpha;
gulong r, g, b;
guint a;
int dark_light;
gboolean byte_order;
int y, x;
1997-11-25 06:05:25 +08:00
int initial;
float error;
const int ye = info->y + info->h;
const int xe = info->x + info->w;
const float step = 1.0 / info->scaley;
1997-11-25 06:05:25 +08:00
alpha = info->alpha;
y = info->y;
error = y * step;
error -= ((int)error) - step;
1997-11-25 06:05:25 +08:00
initial = TRUE;
byte_order = info->byte_order;
info->src = render_image_tile_fault (info);
for (; y < ye; y++)
{
if (!initial && (error < 1.0) && (y & check_mod))
1997-11-25 06:05:25 +08:00
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
else
{
src = info->src;
dest = info->dest;
dark_light = (y >> check_shift) + (info->x >> check_shift);
g_return_if_fail (src != NULL);
add sample_colorize and curve_bend defs * plug-ins/common/plugin-defs.pl: add sample_colorize and curve_bend defs * libgimp/color_selector.h: minor consistency cleanup * libgimp/gimpchainbutton.[ch]: use new style gtk object helper macros * libgimp/gimpfileselection.c * libgimp/gimpmatrix.h: minor cleanup * libgimp/gimpintl.h: resync with gnome-i18n.h * libgimp/color_display.h * app/gimp.sym * app/gdisplay_color.[ch] * app/app_procs.c * app/gdisplay.h * app/image_render.c: color display transformation code. Still unfinished, so it's not activated yet. * app/buildmenu.h: remove unused defines (PULLDOWN, POPUP, OPTION) * app/colormaps.[ch] * app/image_render.c: remove vestigal dithering stuff * app/convolve.h * app/gimpdrawable.h * app/gimpimage.h * app/lut_funcs.h * app/paint_funcs.h * app/plug_in.h: enum nick changes from Marc * app/channel_ops.c * app/crop.c * app/gdisplay.c * app/gimpimage.[ch] * app/move.c: s/([A-Z]+)_GUIDE/ORIENTATION_$1/ * app/flip_tool.[ch] * app/shear_tool.[ch]: use ORIENTATION_* constants instead of our own * app/disp_callbacks.c: remove HORIZONTAL and VERTICAL #defines * app/general.h: enumified TOKEN_* symbols * app/lc_dialog.c * app/paint_funcs.c: remove unused variables * tools/pdbgen/lib.pl: autogen gimpenums.h (unfinished) * tools/pdbgen/stddefs.pdb: new std_orientation_enum, remove layer_mode shortcut since we've skipped it in app/ * tools/pdbgen/pdb/brush_select.pdb * tools/pdbgen/pdb/brushes.pdb * tools/pdbgen/pdb/drawable.pdb * tools/pdbgen/pdb/gimage.pdb * tools/pdbgen/pdb/guides.pdb * tools/pdbgen/pdb/layer.pdb * tools/pdbgen/pdb/tools.pdb: reflect above enum changes, whitespace cleanups * tools/pdbgen/enums.pl * app/brush_select_cmds.c * app/brushes_cmds.c * app/color_cmds.c * app/drawable_cmds.c * app/gimage_cmds.c * app/layer_cmds.c * app/procedural_db_cmds.c * app/tools_cmds.c: reflect pdb and enum nick changes above -Yosh
1999-07-29 07:00:08 +08:00
for (x = info->x; x < xe; x++)
{
a = alpha[src[ALPHA_PIX]];
if (dark_light & 0x1)
{
r = blend_dark_check[(a | src[RED_PIX])];
g = blend_dark_check[(a | src[GREEN_PIX])];
b = blend_dark_check[(a | src[BLUE_PIX])];
}
else
{
r = blend_light_check[(a | src[RED_PIX])];
g = blend_light_check[(a | src[GREEN_PIX])];
b = blend_light_check[(a | src[BLUE_PIX])];
}
1997-11-25 06:05:25 +08:00
add sample_colorize and curve_bend defs * plug-ins/common/plugin-defs.pl: add sample_colorize and curve_bend defs * libgimp/color_selector.h: minor consistency cleanup * libgimp/gimpchainbutton.[ch]: use new style gtk object helper macros * libgimp/gimpfileselection.c * libgimp/gimpmatrix.h: minor cleanup * libgimp/gimpintl.h: resync with gnome-i18n.h * libgimp/color_display.h * app/gimp.sym * app/gdisplay_color.[ch] * app/app_procs.c * app/gdisplay.h * app/image_render.c: color display transformation code. Still unfinished, so it's not activated yet. * app/buildmenu.h: remove unused defines (PULLDOWN, POPUP, OPTION) * app/colormaps.[ch] * app/image_render.c: remove vestigal dithering stuff * app/convolve.h * app/gimpdrawable.h * app/gimpimage.h * app/lut_funcs.h * app/paint_funcs.h * app/plug_in.h: enum nick changes from Marc * app/channel_ops.c * app/crop.c * app/gdisplay.c * app/gimpimage.[ch] * app/move.c: s/([A-Z]+)_GUIDE/ORIENTATION_$1/ * app/flip_tool.[ch] * app/shear_tool.[ch]: use ORIENTATION_* constants instead of our own * app/disp_callbacks.c: remove HORIZONTAL and VERTICAL #defines * app/general.h: enumified TOKEN_* symbols * app/lc_dialog.c * app/paint_funcs.c: remove unused variables * tools/pdbgen/lib.pl: autogen gimpenums.h (unfinished) * tools/pdbgen/stddefs.pdb: new std_orientation_enum, remove layer_mode shortcut since we've skipped it in app/ * tools/pdbgen/pdb/brush_select.pdb * tools/pdbgen/pdb/brushes.pdb * tools/pdbgen/pdb/drawable.pdb * tools/pdbgen/pdb/gimage.pdb * tools/pdbgen/pdb/guides.pdb * tools/pdbgen/pdb/layer.pdb * tools/pdbgen/pdb/tools.pdb: reflect above enum changes, whitespace cleanups * tools/pdbgen/enums.pl * app/brush_select_cmds.c * app/brushes_cmds.c * app/color_cmds.c * app/drawable_cmds.c * app/gimage_cmds.c * app/layer_cmds.c * app/procedural_db_cmds.c * app/tools_cmds.c: reflect pdb and enum nick changes above -Yosh
1999-07-29 07:00:08 +08:00
src += 4;
1997-11-25 06:05:25 +08:00
add sample_colorize and curve_bend defs * plug-ins/common/plugin-defs.pl: add sample_colorize and curve_bend defs * libgimp/color_selector.h: minor consistency cleanup * libgimp/gimpchainbutton.[ch]: use new style gtk object helper macros * libgimp/gimpfileselection.c * libgimp/gimpmatrix.h: minor cleanup * libgimp/gimpintl.h: resync with gnome-i18n.h * libgimp/color_display.h * app/gimp.sym * app/gdisplay_color.[ch] * app/app_procs.c * app/gdisplay.h * app/image_render.c: color display transformation code. Still unfinished, so it's not activated yet. * app/buildmenu.h: remove unused defines (PULLDOWN, POPUP, OPTION) * app/colormaps.[ch] * app/image_render.c: remove vestigal dithering stuff * app/convolve.h * app/gimpdrawable.h * app/gimpimage.h * app/lut_funcs.h * app/paint_funcs.h * app/plug_in.h: enum nick changes from Marc * app/channel_ops.c * app/crop.c * app/gdisplay.c * app/gimpimage.[ch] * app/move.c: s/([A-Z]+)_GUIDE/ORIENTATION_$1/ * app/flip_tool.[ch] * app/shear_tool.[ch]: use ORIENTATION_* constants instead of our own * app/disp_callbacks.c: remove HORIZONTAL and VERTICAL #defines * app/general.h: enumified TOKEN_* symbols * app/lc_dialog.c * app/paint_funcs.c: remove unused variables * tools/pdbgen/lib.pl: autogen gimpenums.h (unfinished) * tools/pdbgen/stddefs.pdb: new std_orientation_enum, remove layer_mode shortcut since we've skipped it in app/ * tools/pdbgen/pdb/brush_select.pdb * tools/pdbgen/pdb/brushes.pdb * tools/pdbgen/pdb/drawable.pdb * tools/pdbgen/pdb/gimage.pdb * tools/pdbgen/pdb/guides.pdb * tools/pdbgen/pdb/layer.pdb * tools/pdbgen/pdb/tools.pdb: reflect above enum changes, whitespace cleanups * tools/pdbgen/enums.pl * app/brush_select_cmds.c * app/brushes_cmds.c * app/color_cmds.c * app/drawable_cmds.c * app/gimage_cmds.c * app/layer_cmds.c * app/procedural_db_cmds.c * app/tools_cmds.c: reflect pdb and enum nick changes above -Yosh
1999-07-29 07:00:08 +08:00
dest[0] = r;
dest[1] = g;
dest[2] = b;
dest += 3;
1997-11-25 06:05:25 +08:00
add sample_colorize and curve_bend defs * plug-ins/common/plugin-defs.pl: add sample_colorize and curve_bend defs * libgimp/color_selector.h: minor consistency cleanup * libgimp/gimpchainbutton.[ch]: use new style gtk object helper macros * libgimp/gimpfileselection.c * libgimp/gimpmatrix.h: minor cleanup * libgimp/gimpintl.h: resync with gnome-i18n.h * libgimp/color_display.h * app/gimp.sym * app/gdisplay_color.[ch] * app/app_procs.c * app/gdisplay.h * app/image_render.c: color display transformation code. Still unfinished, so it's not activated yet. * app/buildmenu.h: remove unused defines (PULLDOWN, POPUP, OPTION) * app/colormaps.[ch] * app/image_render.c: remove vestigal dithering stuff * app/convolve.h * app/gimpdrawable.h * app/gimpimage.h * app/lut_funcs.h * app/paint_funcs.h * app/plug_in.h: enum nick changes from Marc * app/channel_ops.c * app/crop.c * app/gdisplay.c * app/gimpimage.[ch] * app/move.c: s/([A-Z]+)_GUIDE/ORIENTATION_$1/ * app/flip_tool.[ch] * app/shear_tool.[ch]: use ORIENTATION_* constants instead of our own * app/disp_callbacks.c: remove HORIZONTAL and VERTICAL #defines * app/general.h: enumified TOKEN_* symbols * app/lc_dialog.c * app/paint_funcs.c: remove unused variables * tools/pdbgen/lib.pl: autogen gimpenums.h (unfinished) * tools/pdbgen/stddefs.pdb: new std_orientation_enum, remove layer_mode shortcut since we've skipped it in app/ * tools/pdbgen/pdb/brush_select.pdb * tools/pdbgen/pdb/brushes.pdb * tools/pdbgen/pdb/drawable.pdb * tools/pdbgen/pdb/gimage.pdb * tools/pdbgen/pdb/guides.pdb * tools/pdbgen/pdb/layer.pdb * tools/pdbgen/pdb/tools.pdb: reflect above enum changes, whitespace cleanups * tools/pdbgen/enums.pl * app/brush_select_cmds.c * app/brushes_cmds.c * app/color_cmds.c * app/drawable_cmds.c * app/gimage_cmds.c * app/layer_cmds.c * app/procedural_db_cmds.c * app/tools_cmds.c: reflect pdb and enum nick changes above -Yosh
1999-07-29 07:00:08 +08:00
if (((x + 1) & check_mod) == 0)
dark_light += 1;
}
1997-11-25 06:05:25 +08:00
}
info->dest += info->dest_bpl;
initial = FALSE;
if (error >= 1.0)
1997-11-25 06:05:25 +08:00
{
info->src_y += (int)error;
error -= (int)error;
1997-11-25 06:05:25 +08:00
info->src = render_image_tile_fault (info);
initial = TRUE;
1997-11-25 06:05:25 +08:00
}
error += step;
1997-11-25 06:05:25 +08:00
}
}
static void
render_image_init_info (RenderInfo *info,
GDisplay *gdisp,
int x,
int y,
int w,
int h)
{
info->gdisp = gdisp;
info->src_tiles = gimage_projection (gdisp->gimage);
1997-11-25 06:05:25 +08:00
info->x = x + gdisp->offset_x;
info->y = y + gdisp->offset_y;
info->w = w;
info->h = h;
info->scalex = SCALEFACTOR_X (gdisp);
info->scaley = SCALEFACTOR_Y (gdisp);
info->src_x = UNSCALEX (gdisp, info->x);
info->src_y = UNSCALEY (gdisp, info->y);
1997-11-25 06:05:25 +08:00
info->src_bpp = gimage_projection_bytes (gdisp->gimage);
info->dest = gximage_get_data ();
info->dest_bpp = gximage_get_bpp ();
info->dest_bpl = gximage_get_bpl ();
info->dest_width = info->w * info->dest_bpp;
info->byte_order = gximage_get_byte_order ();
info->scale = render_image_accelerate_scaling (w, info->x, info->scalex);
1997-11-25 06:05:25 +08:00
info->alpha = NULL;
switch (gimage_projection_type (gdisp->gimage))
{
case RGBA_GIMAGE:
case GRAYA_GIMAGE:
case INDEXEDA_GIMAGE:
info->alpha = render_image_init_alpha (gimage_projection_opacity (gdisp->gimage));
break;
Honest, guv, it's not a feature - it's a tightly integrated package of Mon Sep 20 12:51:30 EDT 1999 Austin Donnelly <austin@gimp.org> Honest, guv, it's not a feature - it's a tightly integrated package of undo system cleanups and fixes. NEW FILES: * app/undo_history.c: window showing recent undo (and redo) steps available. * app/undo_types.h: broken out of undo.h to fix circular includes. MODIFIED FILES: * app/Makefile.am: compile undo_history.c * app/channel.h: use enum for channel undo type, not just magic numbers. * app/layer.h: same for layer undos. * app/commands.c: edit_show_undo_history_cmd_callback() function to pull up undo history window. * app/commands.h: prototype for above. * app/gdisplay.c: make undo / redo menu items sensitive according to whether they would do anything. Would be easy to change the text to say what would be undone/redone, but I don't know the GTK. * app/gimpimage.c: new signal emitted by gimage: UNDO_EVENT. gimp_image_undo_event() function to emit it. * app/gimpimage.h: prototype for above. * app/gimpimageP.h: pushing_undo_group member is now an undo_type, not an int. Keep undo history widget here too (if created). * app/menus.c: add "Edit/Undo history..." to image menu. * app/undo.c: new types: enums undo_type and undo_state rather than ints and magic numbers. All undo_pop_* and undo_free_* functions made static. New static function undo_type_to_name(). Issue undo event signals on various important events (eg undo pushed, undo popped etc). undo_push() now takes a "dirties_image" arg to say whether image should be dirtied. Layer moves now dirty the image. A couple of g_return_if_fails () on undo_pop and undo_redo to assert we're not in the middle of an undo group. undo_get_{undo,redo}_name() to peek at names of top items on undo and redo stacks resp. undo_map_over_{undo,redo}_stack() to run a function for each item or group on stack. Layer and channel undos use symbolic names rather than 0 or 1. Array mapping undo types to names. * app/undo.h: split out undo types to undo_types.h. Prototypes for functions described above. undo_event_t enum. undo_history_new() prototype lives here too. Random other fixes: * app/gimpdrawable.c * app/image_render.c: default labels in switches to keep egcs happy. * app/nav_window.c: some fixes to (sort of) cope with image res != screen res. Still needs work to handle non-square pixels properly. * app/paths_dialog.c: bad idea to call gimp_image_dirty() directly. Even though it's currently commented out.
1999-09-21 01:15:20 +08:00
default:
/* nothing special needs doing */
break;
1997-11-25 06:05:25 +08:00
}
}
static guint*
render_image_init_alpha (int mult)
{
static guint *alpha_mult = NULL;
static int alpha_val = -1;
int i;
if (alpha_val != mult)
{
if (!alpha_mult)
alpha_mult = g_new (guint, 256);
1997-11-25 06:05:25 +08:00
alpha_val = mult;
for (i = 0; i < 256; i++)
alpha_mult[i] = ((mult * i) / 255) << 8;
}
return alpha_mult;
}
static guchar*
render_image_accelerate_scaling (int width,
int start,
float scalex)
1997-11-25 06:05:25 +08:00
{
static guchar *scale = NULL;
float error;
float step;
1997-11-25 06:05:25 +08:00
int i;
if (!scale)
scale = g_new (guchar, GXIMAGE_WIDTH + 1);
1997-11-25 06:05:25 +08:00
step = 1.0 / scalex;
1997-11-25 06:05:25 +08:00
error = start * step;
error -= ((int)error) - step;
for (i = 0; i <= width; i++)
{
scale[i] = ((int)error);
error += step - (int)error;
}
1997-11-25 06:05:25 +08:00
return scale;
}
static guchar*
render_image_tile_fault (RenderInfo *info)
{
Tile *tile;
guchar *data;
guchar *dest;
guchar *scale;
int width;
int tilex;
int tiley;
int srctilex, srctiley;
1997-11-25 06:05:25 +08:00
int step;
int bpp = info->src_bpp;
1997-11-25 06:05:25 +08:00
int x, b;
tilex = info->src_x / TILE_WIDTH;
tiley = info->src_y / TILE_HEIGHT;
tile = tile_manager_get_tile (info->src_tiles,
srctilex=info->src_x, srctiley=info->src_y,
TRUE, FALSE);
1997-11-25 06:05:25 +08:00
if (!tile)
return NULL;
1998-08-12 01:35:34 +08:00
data = tile_data_pointer (tile,
info->src_x % TILE_WIDTH,
info->src_y % TILE_HEIGHT);
1997-11-25 06:05:25 +08:00
scale = info->scale;
dest = tile_buf;
x = info->src_x;
width = info->w;
while (width--)
{
for (b = 0; b < bpp; b++)
1997-11-25 06:05:25 +08:00
*dest++ = data[b];
step = *scale++;
if (step != 0)
1997-11-25 06:05:25 +08:00
{
x += step;
data += step * bpp;
1997-11-25 06:05:25 +08:00
if ((x >> TILE_SHIFT) != tilex)
1997-11-25 06:05:25 +08:00
{
tile_release (tile, FALSE);
1997-11-25 06:05:25 +08:00
tilex += 1;
tile = tile_manager_get_tile (info->src_tiles, srctilex=x,
srctiley=info->src_y, TRUE, FALSE);
1998-08-12 01:35:34 +08:00
data = tile_data_pointer (tile,
x % TILE_WIDTH,
info->src_y % TILE_HEIGHT);
1997-11-25 06:05:25 +08:00
}
}
}
tile_release (tile, FALSE);
1997-11-25 06:05:25 +08:00
return tile_buf;
}