1
/* The GIMP -- an image manipulation program
2
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
#include "libgimpbase/gimpbase.h"
27
#include "libgimpwidgets/gimpwidgets.h"
29
#include "display-types.h"
31
#include "base/tile-manager.h"
32
#include "base/tile.h"
34
#include "core/gimp.h"
35
#include "core/gimpimage.h"
36
#include "core/gimpimage-colormap.h"
37
#include "core/gimpprojection.h"
39
#include "gimpcanvas.h"
40
#include "gimpdisplay.h"
41
#include "gimpdisplayshell.h"
42
#include "gimpdisplayshell-filter.h"
43
#include "gimpdisplayshell-render.h"
46
typedef struct _RenderInfo RenderInfo;
48
typedef void (* RenderFunc) (RenderInfo *info);
52
GimpDisplayShell *shell;
53
TileManager *src_tiles;
71
static void render_setup_notify (gpointer config,
72
GParamSpec *param_spec,
76
/* accelerate transparency of image scaling */
77
guchar *render_check_buf = NULL;
78
guchar *render_empty_buf = NULL;
79
guchar *render_white_buf = NULL;
80
guchar *render_temp_buf = NULL;
82
guchar *render_blend_dark_check = NULL;
83
guchar *render_blend_light_check = NULL;
84
guchar *render_blend_white = NULL;
87
static guchar *tile_buf = NULL;
88
static guint tile_shift = 0;
89
static guint check_mod = 0;
90
static guint check_shift = 0;
94
render_init (Gimp *gimp)
96
g_return_if_fail (GIMP_IS_GIMP (gimp));
98
g_signal_connect (gimp->config, "notify::transparency-size",
99
G_CALLBACK (render_setup_notify),
101
g_signal_connect (gimp->config, "notify::transparency-type",
102
G_CALLBACK (render_setup_notify),
105
render_setup_notify (gimp->config, NULL, gimp);
109
render_exit (Gimp *gimp)
111
g_return_if_fail (GIMP_IS_GIMP (gimp));
113
g_signal_handlers_disconnect_by_func (gimp->config,
123
if (render_blend_dark_check)
125
g_free (render_blend_dark_check);
126
render_blend_dark_check = NULL;
129
if (render_blend_light_check)
131
g_free (render_blend_light_check);
132
render_blend_light_check = NULL;
135
if (render_blend_white)
137
g_free (render_blend_white);
138
render_blend_white = NULL;
141
if (render_check_buf)
143
g_free (render_check_buf);
144
render_check_buf = NULL;
147
if (render_empty_buf)
149
g_free (render_empty_buf);
150
render_empty_buf = NULL;
153
if (render_white_buf)
155
g_free (render_white_buf);
156
render_white_buf = NULL;
161
g_free (render_temp_buf);
162
render_temp_buf = NULL;
168
render_setup_notify (gpointer config,
169
GParamSpec *param_spec,
172
GimpCheckType check_type;
173
GimpCheckSize check_size;
177
g_object_get (config,
178
"transparency-type", &check_type,
179
"transparency-size", &check_size,
182
/* based on the tile size, determine the tile shift amount
183
* (assume here that tile_height and tile_width are equal)
186
while ((1 << tile_shift) < TILE_WIDTH)
189
/* allocate a buffer for arranging information from a row of tiles */
191
tile_buf = g_new (guchar,
192
GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH * MAX_CHANNELS);
194
if (! render_blend_dark_check)
195
render_blend_dark_check = g_new (guchar, 65536);
196
if (! render_blend_light_check)
197
render_blend_light_check = g_new (guchar, 65536);
198
if (! render_blend_white)
199
render_blend_white = g_new (guchar, 65536);
201
gimp_checks_get_shades (check_type, &light, &dark);
203
for (i = 0; i < 256; i++)
204
for (j = 0; j < 256; j++)
206
render_blend_dark_check [(i << 8) + j] =
207
(guchar) ((j * i + dark * (255 - i)) / 255);
208
render_blend_light_check [(i << 8) + j] =
209
(guchar) ((j * i + light * (255 - i)) / 255);
210
render_blend_white [(i << 8) + j] =
211
(guchar) ((j * i + 255 * (255 - i)) / 255);
216
case GIMP_CHECK_SIZE_SMALL_CHECKS:
220
case GIMP_CHECK_SIZE_MEDIUM_CHECKS:
224
case GIMP_CHECK_SIZE_LARGE_CHECKS:
230
g_free (render_check_buf);
231
g_free (render_empty_buf);
232
g_free (render_white_buf);
233
g_free (render_temp_buf);
235
#define BUF_SIZE (MAX (GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH, \
236
GIMP_VIEWABLE_MAX_PREVIEW_SIZE) + 4)
238
render_check_buf = g_new (guchar, BUF_SIZE * 3);
239
render_empty_buf = g_new0 (guchar, BUF_SIZE * 3);
240
render_white_buf = g_new (guchar, BUF_SIZE * 3);
241
render_temp_buf = g_new (guchar, BUF_SIZE * 3);
243
/* calculate check buffer for previews */
245
memset (render_white_buf, 255, BUF_SIZE * 3);
247
for (i = 0; i < BUF_SIZE; i++)
251
render_check_buf[i * 3 + 0] = render_blend_dark_check[0];
252
render_check_buf[i * 3 + 1] = render_blend_dark_check[0];
253
render_check_buf[i * 3 + 2] = render_blend_dark_check[0];
257
render_check_buf[i * 3 + 0] = render_blend_light_check[0];
258
render_check_buf[i * 3 + 1] = render_blend_light_check[0];
259
render_check_buf[i * 3 + 2] = render_blend_light_check[0];
267
/* Render Image functions */
269
static void render_image_rgb (RenderInfo *info);
270
static void render_image_rgb_a (RenderInfo *info);
271
static void render_image_gray (RenderInfo *info);
272
static void render_image_gray_a (RenderInfo *info);
273
static void render_image_indexed (RenderInfo *info);
274
static void render_image_indexed_a (RenderInfo *info);
276
static void render_image_init_info (RenderInfo *info,
277
GimpDisplayShell *shell,
282
static guint * render_image_init_alpha (gint mult);
283
static guchar * render_image_accelerate_scaling (gint width,
286
static guchar * render_image_tile_fault (RenderInfo *info);
289
static RenderFunc render_funcs[6] =
295
render_image_indexed,
296
render_image_indexed_a,
300
static void gimp_display_shell_render_highlight (GimpDisplayShell *shell,
305
GdkRectangle *highlight);
308
/*****************************************************************/
309
/* This function is the core of the display--it offsets and */
310
/* scales the image according to the current parameters in the */
311
/* gdisp object. It handles color, grayscale, 8, 15, 16, 24, */
312
/* & 32 bit output depths. */
313
/*****************************************************************/
316
gimp_display_shell_render (GimpDisplayShell *shell,
321
GdkRectangle *highlight)
324
GimpImageType image_type;
326
render_image_init_info (&info, shell, x, y, w, h);
328
image_type = gimp_projection_get_image_type (shell->gdisp->gimage->projection);
330
if ((image_type < GIMP_RGB_IMAGE) || (image_type > GIMP_INDEXEDA_IMAGE))
332
g_message ("unknown gimage projection type: %d", image_type);
336
if ((info.dest_bpp < 1) || (info.dest_bpp > 4))
338
g_message ("unsupported destination bytes per pixel: %d", info.dest_bpp);
342
/* Currently, only RGBA and GRAYA projection types are used - the rest
343
* are in case of future need. -- austin, 28th Nov 1998.
345
if (image_type != GIMP_RGBA_IMAGE && image_type != GIMP_GRAYA_IMAGE)
346
g_warning ("using untested projection type %d", image_type);
348
(* render_funcs[image_type]) (&info);
350
/* apply filters to the rendered projection */
351
if (shell->filter_stack)
352
gimp_color_display_stack_convert (shell->filter_stack,
356
3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH);
358
/* dim pixels outside the highlighted rectangle */
360
gimp_display_shell_render_highlight (shell, x, y, w, h, highlight);
362
/* put it to the screen */
363
gimp_canvas_draw_rgb (GIMP_CANVAS (shell->canvas), GIMP_CANVAS_STYLE_RENDER,
364
x + shell->disp_xoffset, y + shell->disp_yoffset,
367
3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH,
368
shell->offset_x, shell->offset_y);
372
#define GIMP_DISPLAY_SHELL_DIM_PIXEL(buf,x) \
374
buf[3 * (x) + 0] >>= 1; \
375
buf[3 * (x) + 1] >>= 1; \
376
buf[3 * (x) + 2] >>= 1; \
379
/* This function highlights the given area by dimming all pixels outside. */
382
gimp_display_shell_render_highlight (GimpDisplayShell *shell,
387
GdkRectangle *highlight)
389
guchar *buf = shell->render_buf;
392
rect.x = shell->offset_x + x;
393
rect.y = shell->offset_y + y;
397
if (gdk_rectangle_intersect (highlight, &rect, &rect))
399
rect.x -= shell->offset_x + x;
400
rect.y -= shell->offset_y + y;
402
for (y = 0; y < rect.y; y++)
404
for (x = 0; x < w; x++)
405
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
407
buf += 3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH;
410
for ( ; y < rect.y + rect.height; y++)
412
for (x = 0; x < rect.x; x++)
413
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
415
for (x += rect.width; x < w; x++)
416
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
418
buf += 3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH;
423
for (x = 0; x < w; x++)
424
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
426
buf += 3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH;
431
for (y = 0; y < h; y++)
433
for (x = 0; x < w; x++)
434
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
436
buf += 3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH;
442
/*************************/
443
/* 8 Bit functions */
444
/*************************/
447
render_image_indexed (RenderInfo *info)
458
cmap = gimp_image_get_colormap (info->shell->gdisp->gimage);
461
ye = info->y + info->h;
462
xe = info->x + info->w;
465
byte_order = info->byte_order;
466
info->src = render_image_tile_fault (info);
470
gint error = RINT (floor ((y + 1) / info->scaley)
471
- floor (y / info->scaley));
473
if (!initial && (error == 0))
475
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
482
g_return_if_fail (src != NULL);
484
for (x = info->x; x < xe; x++)
486
val = src[INDEXED_PIX] * 3;
489
dest[0] = cmap[val+0];
490
dest[1] = cmap[val+1];
491
dest[2] = cmap[val+2];
496
info->dest += info->dest_bpl;
502
info->src_y += error;
503
info->src = render_image_tile_fault (info);
510
render_image_indexed_a (RenderInfo *info)
525
cmap = gimp_image_get_colormap (info->shell->gdisp->gimage);
529
ye = info->y + info->h;
530
xe = info->x + info->w;
533
byte_order = info->byte_order;
534
info->src = render_image_tile_fault (info);
538
gint error = RINT (floor ((y + 1) / info->scaley)
539
- floor (y / info->scaley));
541
if (!initial && (error == 0) && (y & check_mod))
543
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
550
dark_light = (y >> check_shift) + (info->x >> check_shift);
552
g_return_if_fail (src != NULL);
554
for (x = info->x; x < xe; x++)
556
a = alpha[src[ALPHA_I_PIX]];
557
val = src[INDEXED_PIX] * 3;
560
if (dark_light & 0x1)
562
r = render_blend_dark_check[(a | cmap[val + 0])];
563
g = render_blend_dark_check[(a | cmap[val + 1])];
564
b = render_blend_dark_check[(a | cmap[val + 2])];
568
r = render_blend_light_check[(a | cmap[val + 0])];
569
g = render_blend_light_check[(a | cmap[val + 1])];
570
b = render_blend_light_check[(a | cmap[val + 2])];
578
if (((x + 1) & check_mod) == 0)
583
info->dest += info->dest_bpl;
589
info->src_y += error;
590
info->src = render_image_tile_fault (info);
597
render_image_gray (RenderInfo *info)
608
ye = info->y + info->h;
609
xe = info->x + info->w;
612
byte_order = info->byte_order;
613
info->src = render_image_tile_fault (info);
617
gint error = RINT (floor ((y + 1) / info->scaley)
618
- floor (y / info->scaley));
620
if (!initial && (error == 0))
622
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
629
g_return_if_fail (src != NULL);
631
for (x = info->x; x < xe; x++)
643
info->dest += info->dest_bpl;
649
info->src_y += error;
650
info->src = render_image_tile_fault (info);
657
render_image_gray_a (RenderInfo *info)
673
ye = info->y + info->h;
674
xe = info->x + info->w;
677
byte_order = info->byte_order;
678
info->src = render_image_tile_fault (info);
682
gint error = RINT (floor ((y + 1) / info->scaley)
683
- floor (y / info->scaley));
685
if (!initial && (error == 0) && (y & check_mod))
687
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
694
dark_light = (y >> check_shift) + (info->x >> check_shift);
696
g_return_if_fail (src != NULL);
698
for (x = info->x; x < xe; x++)
700
a = alpha[src[ALPHA_G_PIX]];
701
if (dark_light & 0x1)
702
val = render_blend_dark_check[(a | src[GRAY_PIX])];
704
val = render_blend_light_check[(a | src[GRAY_PIX])];
712
if (((x + 1) & check_mod) == 0)
717
info->dest += info->dest_bpl;
723
info->src_y += error;
724
info->src = render_image_tile_fault (info);
731
render_image_rgb (RenderInfo *info)
739
ye = info->y + info->h;
740
xe = info->x + info->w;
743
byte_order = info->byte_order;
744
info->src = render_image_tile_fault (info);
748
gint error = RINT (floor ((y + 1) / info->scaley)
749
- floor (y / info->scaley));
751
if (!initial && (error == 0))
753
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
757
g_return_if_fail (info->src != NULL);
759
memcpy (info->dest, info->src, 3 * info->w);
762
info->dest += info->dest_bpl;
768
info->src_y += error;
769
info->src = render_image_tile_fault (info);
776
render_image_rgb_a (RenderInfo *info)
792
ye = info->y + info->h;
793
xe = info->x + info->w;
796
byte_order = info->byte_order;
797
info->src = render_image_tile_fault (info);
801
gint error = RINT (floor ((y + 1) / info->scaley)
802
- floor (y / info->scaley));
804
if (!initial && (error == 0) && (y & check_mod))
806
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
813
dark_light = (y >> check_shift) + (info->x >> check_shift);
815
g_return_if_fail (src != NULL);
817
for (x = info->x; x < xe; x++)
819
a = alpha[src[ALPHA_PIX]];
820
if (dark_light & 0x1)
822
r = render_blend_dark_check[(a | src[RED_PIX])];
823
g = render_blend_dark_check[(a | src[GREEN_PIX])];
824
b = render_blend_dark_check[(a | src[BLUE_PIX])];
828
r = render_blend_light_check[(a | src[RED_PIX])];
829
g = render_blend_light_check[(a | src[GREEN_PIX])];
830
b = render_blend_light_check[(a | src[BLUE_PIX])];
840
if (((x + 1) & check_mod) == 0)
845
info->dest += info->dest_bpl;
851
info->src_y += error;
852
info->src = render_image_tile_fault (info);
859
render_image_init_info (RenderInfo *info,
860
GimpDisplayShell *shell,
866
GimpImage *gimage = shell->gdisp->gimage;
869
info->src_tiles = gimp_projection_get_tiles (gimage->projection);
870
info->x = x + shell->offset_x;
871
info->y = y + shell->offset_y;
874
info->scalex = SCALEFACTOR_X (shell);
875
info->scaley = SCALEFACTOR_Y (shell);
876
info->src_x = (gdouble) info->x / info->scalex;
877
info->src_y = (gdouble) info->y / info->scaley;
878
info->src_bpp = gimp_projection_get_bytes (gimage->projection);
879
info->dest = shell->render_buf;
881
info->dest_bpl = info->dest_bpp * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH;
882
info->dest_width = info->w * info->dest_bpp;
883
info->byte_order = GDK_MSB_FIRST;
884
info->scale = render_image_accelerate_scaling (w,
885
info->x, info->scalex);
888
if (GIMP_IMAGE_TYPE_HAS_ALPHA (gimp_projection_get_image_type (gimage->projection)))
891
render_image_init_alpha (gimp_projection_get_opacity (gimage->projection) * 255.999);
896
render_image_init_alpha (gint mult)
898
static guint *alpha_mult = NULL;
899
static gint alpha_val = -1;
903
if (alpha_val != mult)
906
alpha_mult = g_new (guint, 256);
909
for (i = 0; i < 256; i++)
910
alpha_mult[i] = ((mult * i) / 255) << 8;
917
render_image_accelerate_scaling (gint width,
921
static guchar *scale = NULL;
926
scale = g_new (guchar, GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH + 1);
928
for (i = 0; i <= width; i++)
930
scale[i] = RINT (floor ((start + 1) / scalex) - floor (start / scalex));
938
render_image_tile_fault (RenderInfo *info)
947
gint bpp = info->src_bpp;
950
tile = tile_manager_get_tile (info->src_tiles,
951
info->src_x, info->src_y,
956
data = tile_data_pointer (tile,
957
info->src_x % TILE_WIDTH,
958
info->src_y % TILE_HEIGHT);
965
tilex = info->src_x / TILE_WIDTH;
969
for (b = 0; b < bpp; b++)
978
if ((x >> tile_shift) != tilex)
980
tile_release (tile, FALSE);
983
tile = tile_manager_get_tile (info->src_tiles,
990
data = tile_data_pointer (tile,
992
info->src_y % TILE_HEIGHT);
997
tile_release (tile, FALSE);