libgimp/Makefile.am libgimp/gimp.h libgimp/gimpadaptivesupersample.[ch]

2001-01-23  Michael Natterer  <mitch@gimp.org>

	* libgimp/Makefile.am
	* libgimp/gimp.h
	* libgimp/gimpadaptivesupersample.[ch]
	* libgimp/gimpbilinear.[ch]: new files cut out of LibGCK.

	* plug-ins/libgck/gck/gck.h
	* plug-ins/libgck/gck/gckcolor.c: removed the bilinear and
	supersample code.

	* app/apptypes.h
	* app/asupsample.[ch]
	* app/tools/blend.c: made the adaptive_supersample interface the
	same as in libgimp but don't use the libgimp function yet.

	The libgimp function takes total transparancy into account when
	weighting the 4 resulting RGBA values, the app function always
	weights them equally. Please have a look at the code.

	* plug-ins/Lighting/lighting_image.c
	* plug-ins/MapObject/mapobject_apply.c
	* plug-ins/MapObject/mapobject_image.[ch]: changed accordingly.

	* app/disp_callbacks.c: paranoia cleanups.
This commit is contained in:
Michael Natterer 2001-01-23 00:53:12 +00:00 committed by Michael Natterer
parent 5591b7cd2d
commit 75760de9d1
26 changed files with 1856 additions and 897 deletions

View File

@ -1,3 +1,29 @@
2001-01-23 Michael Natterer <mitch@gimp.org>
* libgimp/Makefile.am
* libgimp/gimp.h
* libgimp/gimpadaptivesupersample.[ch]
* libgimp/gimpbilinear.[ch]: new files cut out of LibGCK.
* plug-ins/libgck/gck/gck.h
* plug-ins/libgck/gck/gckcolor.c: removed the bilinear and
supersample code.
* app/apptypes.h
* app/asupsample.[ch]
* app/tools/blend.c: made the adaptive_supersample interface the
same as in libgimp but don't use the libgimp function yet.
The libgimp function takes total transparancy into account when
weighting the 4 resulting RGBA values, the app function always
weights them equally. Please have a look at the code.
* plug-ins/Lighting/lighting_image.c
* plug-ins/MapObject/mapobject_apply.c
* plug-ins/MapObject/mapobject_image.[ch]: changed accordingly.
* app/disp_callbacks.c: paranoia cleanups.
2001-01-22 Sven Neumann <sven@gimp.org>
* app/gdisplay.c

View File

@ -167,10 +167,10 @@ typedef void (* TileValidateProc) (TileManager *tm,
typedef void (* ToolOptionsResetFunc) (void);
typedef void (* GimpProgressFunc) (gint ymin,
gint ymax,
gint curr_y,
gpointer progress_data);
typedef void (* GimpProgressFunc) (gint min,
gint max,
gint current,
gpointer data);
typedef void (* ImageMapApplyFunc) (PixelRegion *srcPR,
PixelRegion *destPR,

View File

@ -20,7 +20,6 @@
*
*/
/* This code is *largely* based on the sources for POV-Ray 3.0. I am
* grateful to the POV-Team for such a great program and for making
* their sources available. All comments / bug reports /
@ -47,14 +46,14 @@ typedef struct
{
gchar ready;
GimpRGB color;
} sample_t;
} GimpSampleType;
/***** Local functions *****/
static gulong render_sub_pixel (gint max_depth,
static gulong gimp_render_sub_pixel (gint max_depth,
gint depth,
sample_t **block,
GimpSampleType **block,
gint x,
gint y,
gint x1,
@ -63,23 +62,23 @@ static gulong render_sub_pixel (gint max_depth,
gint y3,
gdouble threshold,
gint sub_pixel_size,
render_func_t render_func,
GimpRGB *color,
GimpRenderFunc render_func,
gpointer render_data);
/***** Functions *****/
gulong
adaptive_supersample_area (gint x1,
gimp_adaptive_supersample_area (gint x1,
gint y1,
gint x2,
gint y2,
gint max_depth,
gdouble threshold,
render_func_t render_func,
GimpRenderFunc render_func,
gpointer render_data,
put_pixel_func_t put_pixel_func,
GimpPutPixelFunc put_pixel_func,
gpointer put_pixel_data,
GimpProgressFunc progress_func,
gpointer progress_data)
@ -87,11 +86,10 @@ adaptive_supersample_area (gint x1,
gint x, y, width; /* Counters, width of region */
gint xt, xtt, yt; /* Temporary counters */
gint sub_pixel_size; /* Numbe of samples per pixel (1D) */
size_t row_size; /* Memory needed for one row */
GimpRGB color; /* Rendered pixel's color */
sample_t tmp_sample; /* For swapping samples */
sample_t *top_row, *bot_row, *tmp_row; /* Sample rows */
sample_t **block; /* Sample block matrix */
GimpSampleType tmp_sample; /* For swapping samples */
GimpSampleType *top_row, *bot_row, *tmp_row; /* Sample rows */
GimpSampleType **block; /* Sample block matrix */
gulong num_samples;
/* Initialize color */
@ -100,39 +98,37 @@ adaptive_supersample_area (gint x1,
/* Calculate sub-pixel size */
sub_pixel_size = 1 << max_depth; /* 2**max_depth */
sub_pixel_size = 1 << max_depth;
/* Create row arrays */
width = x2 - x1 + 1;
row_size = (sub_pixel_size * width + 1) * sizeof (sample_t);
top_row = g_malloc (row_size);
bot_row = g_malloc (row_size);
top_row = g_new (GimpSampleType, sub_pixel_size * width + 1);
bot_row = g_new (GimpSampleType, sub_pixel_size * width + 1);
for (x = 0; x < (sub_pixel_size * width + 1); x++)
{
top_row[x].ready = 0;
top_row[x].ready = FALSE;
gimp_rgba_set (&top_row[x].color, 0.0, 0.0, 0.0, 0.0);
bot_row[x].ready = 0;
bot_row[x].ready = FALSE;
gimp_rgba_set (&bot_row[x].color, 0.0, 0.0, 0.0, 0.0);
}
/* Allocate block matrix */
block = g_malloc((sub_pixel_size + 1) * sizeof(sample_t *)); /* Rows */
block = g_new (GimpSampleType *, sub_pixel_size + 1); /* Rows */
for (y = 0; y < (sub_pixel_size + 1); y++)
{
block[y] = g_malloc((sub_pixel_size + 1) * sizeof(sample_t)); /* Columns */
block[y] = g_new (GimpSampleType, sub_pixel_size + 1); /* Columns */
for (x = 0; x < (sub_pixel_size + 1); x++)
{
block[y][x].ready = 0;
block[y][x].ready = FALSE;
gimp_rgba_set (&block[y][x].color, 0.0, 0.0, 0.0, 0.0);
}
@ -147,7 +143,7 @@ adaptive_supersample_area (gint x1,
/* Clear the bottom row */
for (xt = 0; xt < (sub_pixel_size * width + 1); xt++)
bot_row[xt].ready = 0;
bot_row[xt].ready = FALSE;
/* Clear first column */
@ -162,7 +158,7 @@ adaptive_supersample_area (gint x1,
for (yt = 1; yt < (sub_pixel_size + 1); yt++)
for (xt = 1; xt < (sub_pixel_size + 1); xt++)
block[yt][xt].ready = 0;
block[yt][xt].ready = FALSE;
/* Copy samples from top row to block */
@ -173,14 +169,14 @@ adaptive_supersample_area (gint x1,
/* Render pixel on (x, y) */
num_samples += render_sub_pixel (max_depth, 1, block, x, y, 0, 0,
num_samples += gimp_render_sub_pixel (max_depth, 1, block, x, y, 0, 0,
sub_pixel_size, sub_pixel_size,
threshold, sub_pixel_size,
render_func, &color,
render_data);
&color,
render_func, render_data);
if (put_pixel_func)
(* put_pixel_func) (x, y, color, put_pixel_data);
(* put_pixel_func) (x, y, &color, put_pixel_data);
/* Copy block information to rows */
@ -226,9 +222,9 @@ adaptive_supersample_area (gint x1,
}
static gulong
render_sub_pixel (gint max_depth,
gimp_render_sub_pixel (gint max_depth,
gint depth,
sample_t **block,
GimpSampleType **block,
gint x,
gint y,
gint x1,
@ -237,8 +233,8 @@ render_sub_pixel (gint max_depth,
gint y3,
gdouble threshold,
gint sub_pixel_size,
render_func_t render_func,
GimpRGB *color,
GimpRenderFunc render_func,
gpointer render_data)
{
gint x2, y2; /* Coords of center sample */
@ -262,9 +258,11 @@ render_sub_pixel (gint max_depth,
if (!block[y1][x1].ready)
{
num_samples++;
if (render_func)
(* render_func) (x + dx1, y + dy1, &c1, render_data);
block[y1][x1].ready = 1;
block[y1][x1].ready = TRUE;
block[y1][x1].color = c1;
}
else
@ -277,9 +275,11 @@ render_sub_pixel (gint max_depth,
if (! block[y1][x3].ready)
{
num_samples++;
if (render_func)
(* render_func) (x + dx3, y + dy1, &c2, render_data);
block[y1][x3].ready = 1;
block[y1][x3].ready = TRUE;
block[y1][x3].color = c2;
}
else
@ -292,9 +292,11 @@ render_sub_pixel (gint max_depth,
if (! block[y3][x1].ready)
{
num_samples++;
if (render_func)
(* render_func) (x + dx1, y + dy3, &c3, render_data);
block[y3][x1].ready = 1;
block[y3][x1].ready = TRUE;
block[y3][x1].color = c3;
}
else
@ -307,9 +309,11 @@ render_sub_pixel (gint max_depth,
if (! block[y3][x3].ready)
{
num_samples++;
if (render_func)
(* render_func) (x + dx3, y + dy3, &c4, render_data);
block[y3][x3].ready = 1;
block[y3][x3].ready = TRUE;
block[y3][x3].color = c4;
}
else
@ -337,21 +341,29 @@ render_sub_pixel (gint max_depth,
/* Render sub-blocks */
num_samples += render_sub_pixel (max_depth, depth + 1, block, x, y, x1, y1, x2, y2,
threshold, sub_pixel_size, render_func, &c1,
render_data);
num_samples += gimp_render_sub_pixel (max_depth, depth + 1, block,
x, y, x1, y1, x2, y2,
threshold, sub_pixel_size,
&c1,
render_func, render_data);
num_samples += render_sub_pixel(max_depth, depth + 1, block, x, y, x2, y1, x3, y2,
threshold, sub_pixel_size, render_func, &c2,
render_data);
num_samples += gimp_render_sub_pixel (max_depth, depth + 1, block,
x, y, x2, y1, x3, y2,
threshold, sub_pixel_size,
&c2,
render_func, render_data);
num_samples += render_sub_pixel(max_depth, depth + 1, block, x, y, x1, y2, x2, y3,
threshold, sub_pixel_size, render_func, &c3,
render_data);
num_samples += gimp_render_sub_pixel (max_depth, depth + 1, block,
x, y, x1, y2, x2, y3,
threshold, sub_pixel_size,
&c3,
render_func, render_data);
num_samples += render_sub_pixel(max_depth, depth + 1, block, x, y, x2, y2, x3, y3,
threshold, sub_pixel_size, render_func, &c4,
render_data);
num_samples += gimp_render_sub_pixel (max_depth, depth + 1, block,
x, y, x2, y2, x3, y3,
threshold, sub_pixel_size,
&c4,
render_func, render_data);
}
}

View File

@ -24,25 +24,25 @@
#define __ASUPSAMPLE_H__
typedef void (* render_func_t) (gdouble x,
typedef void (* GimpRenderFunc) (gdouble x,
gdouble y,
GimpRGB *color,
gpointer render_data);
typedef void (* put_pixel_func_t) (gint x,
gpointer data);
typedef void (* GimpPutPixelFunc) (gint x,
gint y,
GimpRGB color,
gpointer put_pixel_data);
GimpRGB *color,
gpointer data);
gulong adaptive_supersample_area (gint x1,
gulong gimp_adaptive_supersample_area (gint x1,
gint y1,
gint x2,
gint y2,
gint max_depth,
gdouble threshold,
render_func_t render_func,
GimpRenderFunc render_func,
gpointer render_data,
put_pixel_func_t put_pixel_func,
GimpPutPixelFunc put_pixel_func,
gpointer put_pixel_data,
GimpProgressFunc progress_func,
gpointer progress_data);

View File

@ -245,7 +245,7 @@ static void gradient_render_pixel (gdouble x,
gpointer render_data);
static void gradient_put_pixel (gint x,
gint y,
GimpRGB color,
GimpRGB *color,
gpointer put_pixel_data);
static void gradient_fill_region (GImage *gimage,
@ -1403,7 +1403,7 @@ gradient_render_pixel (double x,
static void
gradient_put_pixel (int x,
int y,
GimpRGB color,
GimpRGB *color,
void *put_pixel_data)
{
PutPixelData *ppd;
@ -1417,17 +1417,17 @@ gradient_put_pixel (int x,
if (ppd->bytes >= 3)
{
*data++ = color.r * 255.0;
*data++ = color.g * 255.0;
*data++ = color.b * 255.0;
*data++ = color.a * 255.0;
*data++ = color->r * 255.0;
*data++ = color->g * 255.0;
*data++ = color->b * 255.0;
*data++ = color->a * 255.0;
}
else
{
/* Convert to grayscale */
*data++ = 255.0 * INTENSITY (color.r, color.g, color.b);
*data++ = color.a * 255.0;
*data++ = 255.0 * INTENSITY (color->r, color->g, color->b);
*data++ = color->a * 255.0;
}
/* Paint whole row if we are on the rightmost pixel */
@ -1588,7 +1588,7 @@ gradient_fill_region (GImage *gimage,
/* Render! */
adaptive_supersample_area (0, 0, (width - 1), (height - 1),
gimp_adaptive_supersample_area (0, 0, (width - 1), (height - 1),
max_depth, threshold,
gradient_render_pixel, &rbd,
gradient_put_pixel, &ppd,

View File

@ -180,10 +180,10 @@ gdisplay_canvas_events (GtkWidget *canvas,
/* set up the scrollbar observers */
gtk_signal_connect (GTK_OBJECT (gdisp->hsbdata), "value_changed",
(GtkSignalFunc) scrollbar_horz_update,
GTK_SIGNAL_FUNC(scrollbar_horz_update),
gdisp);
gtk_signal_connect (GTK_OBJECT (gdisp->vsbdata), "value_changed",
(GtkSignalFunc) scrollbar_vert_update,
GTK_SIGNAL_FUNC (scrollbar_vert_update),
gdisp);
/* setup scale properly */
@ -247,12 +247,12 @@ gdisplay_canvas_events (GtkWidget *canvas,
gtk_grab_add (canvas);
/* This is a hack to prevent other stuff being run in the middle of
a tool operation (like changing image types.... brrrr). We just
block all the keypress event. A better solution is to implement
some sort of locking for images.
Note that this is dependent on specific GTK behavior, and isn't
guaranteed to work in future versions of GTK.
-Yosh
* a tool operation (like changing image types.... brrrr). We just
* block all the keypress event. A better solution is to implement
* some sort of locking for images.
* Note that this is dependent on specific GTK behavior, and isn't
* guaranteed to work in future versions of GTK.
* -Yosh
*/
if (key_signal_id == 0)
key_signal_id = gtk_signal_connect (GTK_OBJECT (canvas),
@ -363,8 +363,7 @@ gdisplay_canvas_events (GtkWidget *canvas,
*
* ugly: fuzzy_select sets busy cursors while ACTIVE.
*/
if (gimp_busy &&
!(active_tool->type == FUZZY_SELECT &&
if (gimp_busy && ! (active_tool->type == FUZZY_SELECT &&
active_tool->state == ACTIVE))
return TRUE;
@ -437,14 +436,13 @@ gdisplay_canvas_events (GtkWidget *canvas,
*
* ugly: fuzzy_select sets busy cursors while ACTIVE.
*/
if (gimp_busy &&
!(active_tool->type == FUZZY_SELECT &&
if (gimp_busy && ! (active_tool->type == FUZZY_SELECT &&
active_tool->state == ACTIVE))
return TRUE;
/* Ask for the pointer position, but ignore it except for cursor
* handling, so motion events sync with the button press/release events */
* handling, so motion events sync with the button press/release events
*/
if (mevent->is_hint)
{
gdk_input_window_get_pointer (canvas->window, current_device, &tx, &ty,

View File

@ -180,10 +180,10 @@ gdisplay_canvas_events (GtkWidget *canvas,
/* set up the scrollbar observers */
gtk_signal_connect (GTK_OBJECT (gdisp->hsbdata), "value_changed",
(GtkSignalFunc) scrollbar_horz_update,
GTK_SIGNAL_FUNC(scrollbar_horz_update),
gdisp);
gtk_signal_connect (GTK_OBJECT (gdisp->vsbdata), "value_changed",
(GtkSignalFunc) scrollbar_vert_update,
GTK_SIGNAL_FUNC (scrollbar_vert_update),
gdisp);
/* setup scale properly */
@ -247,12 +247,12 @@ gdisplay_canvas_events (GtkWidget *canvas,
gtk_grab_add (canvas);
/* This is a hack to prevent other stuff being run in the middle of
a tool operation (like changing image types.... brrrr). We just
block all the keypress event. A better solution is to implement
some sort of locking for images.
Note that this is dependent on specific GTK behavior, and isn't
guaranteed to work in future versions of GTK.
-Yosh
* a tool operation (like changing image types.... brrrr). We just
* block all the keypress event. A better solution is to implement
* some sort of locking for images.
* Note that this is dependent on specific GTK behavior, and isn't
* guaranteed to work in future versions of GTK.
* -Yosh
*/
if (key_signal_id == 0)
key_signal_id = gtk_signal_connect (GTK_OBJECT (canvas),
@ -363,8 +363,7 @@ gdisplay_canvas_events (GtkWidget *canvas,
*
* ugly: fuzzy_select sets busy cursors while ACTIVE.
*/
if (gimp_busy &&
!(active_tool->type == FUZZY_SELECT &&
if (gimp_busy && ! (active_tool->type == FUZZY_SELECT &&
active_tool->state == ACTIVE))
return TRUE;
@ -437,14 +436,13 @@ gdisplay_canvas_events (GtkWidget *canvas,
*
* ugly: fuzzy_select sets busy cursors while ACTIVE.
*/
if (gimp_busy &&
!(active_tool->type == FUZZY_SELECT &&
if (gimp_busy && ! (active_tool->type == FUZZY_SELECT &&
active_tool->state == ACTIVE))
return TRUE;
/* Ask for the pointer position, but ignore it except for cursor
* handling, so motion events sync with the button press/release events */
* handling, so motion events sync with the button press/release events
*/
if (mevent->is_hint)
{
gdk_input_window_get_pointer (canvas->window, current_device, &tx, &ty,

View File

@ -180,10 +180,10 @@ gdisplay_canvas_events (GtkWidget *canvas,
/* set up the scrollbar observers */
gtk_signal_connect (GTK_OBJECT (gdisp->hsbdata), "value_changed",
(GtkSignalFunc) scrollbar_horz_update,
GTK_SIGNAL_FUNC(scrollbar_horz_update),
gdisp);
gtk_signal_connect (GTK_OBJECT (gdisp->vsbdata), "value_changed",
(GtkSignalFunc) scrollbar_vert_update,
GTK_SIGNAL_FUNC (scrollbar_vert_update),
gdisp);
/* setup scale properly */
@ -247,12 +247,12 @@ gdisplay_canvas_events (GtkWidget *canvas,
gtk_grab_add (canvas);
/* This is a hack to prevent other stuff being run in the middle of
a tool operation (like changing image types.... brrrr). We just
block all the keypress event. A better solution is to implement
some sort of locking for images.
Note that this is dependent on specific GTK behavior, and isn't
guaranteed to work in future versions of GTK.
-Yosh
* a tool operation (like changing image types.... brrrr). We just
* block all the keypress event. A better solution is to implement
* some sort of locking for images.
* Note that this is dependent on specific GTK behavior, and isn't
* guaranteed to work in future versions of GTK.
* -Yosh
*/
if (key_signal_id == 0)
key_signal_id = gtk_signal_connect (GTK_OBJECT (canvas),
@ -363,8 +363,7 @@ gdisplay_canvas_events (GtkWidget *canvas,
*
* ugly: fuzzy_select sets busy cursors while ACTIVE.
*/
if (gimp_busy &&
!(active_tool->type == FUZZY_SELECT &&
if (gimp_busy && ! (active_tool->type == FUZZY_SELECT &&
active_tool->state == ACTIVE))
return TRUE;
@ -437,14 +436,13 @@ gdisplay_canvas_events (GtkWidget *canvas,
*
* ugly: fuzzy_select sets busy cursors while ACTIVE.
*/
if (gimp_busy &&
!(active_tool->type == FUZZY_SELECT &&
if (gimp_busy && ! (active_tool->type == FUZZY_SELECT &&
active_tool->state == ACTIVE))
return TRUE;
/* Ask for the pointer position, but ignore it except for cursor
* handling, so motion events sync with the button press/release events */
* handling, so motion events sync with the button press/release events
*/
if (mevent->is_hint)
{
gdk_input_window_get_pointer (canvas->window, current_device, &tx, &ty,

View File

@ -245,7 +245,7 @@ static void gradient_render_pixel (gdouble x,
gpointer render_data);
static void gradient_put_pixel (gint x,
gint y,
GimpRGB color,
GimpRGB *color,
gpointer put_pixel_data);
static void gradient_fill_region (GImage *gimage,
@ -1403,7 +1403,7 @@ gradient_render_pixel (double x,
static void
gradient_put_pixel (int x,
int y,
GimpRGB color,
GimpRGB *color,
void *put_pixel_data)
{
PutPixelData *ppd;
@ -1417,17 +1417,17 @@ gradient_put_pixel (int x,
if (ppd->bytes >= 3)
{
*data++ = color.r * 255.0;
*data++ = color.g * 255.0;
*data++ = color.b * 255.0;
*data++ = color.a * 255.0;
*data++ = color->r * 255.0;
*data++ = color->g * 255.0;
*data++ = color->b * 255.0;
*data++ = color->a * 255.0;
}
else
{
/* Convert to grayscale */
*data++ = 255.0 * INTENSITY (color.r, color.g, color.b);
*data++ = color.a * 255.0;
*data++ = 255.0 * INTENSITY (color->r, color->g, color->b);
*data++ = color->a * 255.0;
}
/* Paint whole row if we are on the rightmost pixel */
@ -1588,7 +1588,7 @@ gradient_fill_region (GImage *gimage,
/* Render! */
adaptive_supersample_area (0, 0, (width - 1), (height - 1),
gimp_adaptive_supersample_area (0, 0, (width - 1), (height - 1),
max_depth, threshold,
gradient_render_pixel, &rbd,
gradient_put_pixel, &ppd,

View File

@ -245,7 +245,7 @@ static void gradient_render_pixel (gdouble x,
gpointer render_data);
static void gradient_put_pixel (gint x,
gint y,
GimpRGB color,
GimpRGB *color,
gpointer put_pixel_data);
static void gradient_fill_region (GImage *gimage,
@ -1403,7 +1403,7 @@ gradient_render_pixel (double x,
static void
gradient_put_pixel (int x,
int y,
GimpRGB color,
GimpRGB *color,
void *put_pixel_data)
{
PutPixelData *ppd;
@ -1417,17 +1417,17 @@ gradient_put_pixel (int x,
if (ppd->bytes >= 3)
{
*data++ = color.r * 255.0;
*data++ = color.g * 255.0;
*data++ = color.b * 255.0;
*data++ = color.a * 255.0;
*data++ = color->r * 255.0;
*data++ = color->g * 255.0;
*data++ = color->b * 255.0;
*data++ = color->a * 255.0;
}
else
{
/* Convert to grayscale */
*data++ = 255.0 * INTENSITY (color.r, color.g, color.b);
*data++ = color.a * 255.0;
*data++ = 255.0 * INTENSITY (color->r, color->g, color->b);
*data++ = color->a * 255.0;
}
/* Paint whole row if we are on the rightmost pixel */
@ -1588,7 +1588,7 @@ gradient_fill_region (GImage *gimage,
/* Render! */
adaptive_supersample_area (0, 0, (width - 1), (height - 1),
gimp_adaptive_supersample_area (0, 0, (width - 1), (height - 1),
max_depth, threshold,
gradient_render_pixel, &rbd,
gradient_put_pixel, &ppd,

View File

@ -159,6 +159,10 @@ libgimp_la_SOURCES = \
gimp.h \
${PDB_WRAPPERS_C} \
${PDB_WRAPPERS_H} \
gimpadaptivesupersample.c \
gimpadaptivesupersample.h \
gimpbilinear.c \
gimpbilinear.h \
gimpcolor.c \
gimpcolor.h \
gimpcolorspace.c \
@ -230,6 +234,8 @@ libgimpui_la_SOURCES = \
gimpinclude_HEADERS = \
gimp.h \
${PDB_WRAPPERS_H} \
gimpadaptivesupersample.h \
gimpbilinear.h \
gimpchainbutton.h \
gimpchannel.h \
gimpcolor.h \

View File

@ -27,6 +27,8 @@
#include <libgimp/gimpenums.h>
#include <libgimp/gimptypes.h>
#include <libgimp/gimpadaptivesupersample.h>
#include <libgimp/gimpbilinear.h>
#include <libgimp/gimpchannel.h>
#include <libgimp/gimpcolor.h>
#include <libgimp/gimpcolorspace.h>

View File

@ -0,0 +1,380 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <glib.h>
#include "gimpcolor.h"
#include "gimpadaptivesupersample.h"
#include "gimpmath.h"
/*********************************************************************/
/* Sumpersampling code (Quartic) */
/* This code is *largely* based on the sources for POV-Ray 3.0. I am */
/* grateful to the POV-Team for such a great program and for making */
/* their sources available. All comments / bug reports / */
/* etc. regarding this code should be addressed to me, not to the */
/* POV-Ray team. Any bugs are my responsibility, not theirs. */
/*********************************************************************/
typedef struct _GimpSampleType GimpSampleType;
struct _GimpSampleType
{
guchar ready;
GimpRGB color;
};
static gulong
gimp_render_sub_pixel (gint max_depth,
gint depth,
GimpSampleType **block,
gint x,
gint y,
gint x1,
gint y1,
gint x3,
gint y3,
gdouble threshold,
gint sub_pixel_size,
GimpRGB *color,
GimpRenderFunc render_func,
gpointer render_data)
{
gint x2, y2; /* Coords of center sample */
gdouble dx1, dy1; /* Delta to upper left sample */
gdouble dx3, dy3; /* Delta to lower right sample */
GimpRGB c[4]; /* Sample colors */
gulong num_samples = 0;
gint cnt;
/* Get offsets for corners */
dx1 = (gdouble) (x1 - sub_pixel_size / 2) / sub_pixel_size;
dx3 = (gdouble) (x3 - sub_pixel_size / 2) / sub_pixel_size;
dy1 = (gdouble) (y1 - sub_pixel_size / 2) / sub_pixel_size;
dy3 = (gdouble) (y3 - sub_pixel_size / 2) / sub_pixel_size;
/* Render upper left sample */
if (! block[y1][x1].ready)
{
num_samples++;
if (render_func)
(* render_func) (x + dx1, y + dy1, &c[0], render_data);
block[y1][x1].ready = TRUE;
block[y1][x1].color = c[0];
}
else
{
c[0] = block[y1][x1].color;
}
/* Render upper right sample */
if (! block[y1][x3].ready)
{
num_samples++;
if (render_func)
(* render_func) (x + dx3, y + dy1, &c[1], render_data);
block[y1][x3].ready = TRUE;
block[y1][x3].color = c[1];
}
else
{
c[1] = block[y1][x3].color;
}
/* Render lower left sample */
if (! block[y3][x1].ready)
{
num_samples++;
if (render_func)
(* render_func) (x + dx1, y + dy3, &c[2], render_data);
block[y3][x1].ready = TRUE;
block[y3][x1].color = c[2];
}
else
{
c[2] = block[y3][x1].color;
}
/* Render lower right sample */
if (! block[y3][x3].ready)
{
num_samples++;
if (render_func)
(* render_func) (x + dx3, y + dy3, &c[3], render_data);
block[y3][x3].ready = TRUE;
block[y3][x3].color = c[3];
}
else
{
c[3] = block[y3][x3].color;
}
/* Check for supersampling */
if (depth <= max_depth)
{
/* Check whether we have to supersample */
if ((gimp_rgba_distance (&c[0], &c[1]) >= threshold) ||
(gimp_rgba_distance (&c[0], &c[2]) >= threshold) ||
(gimp_rgba_distance (&c[0], &c[3]) >= threshold) ||
(gimp_rgba_distance (&c[1], &c[2]) >= threshold) ||
(gimp_rgba_distance (&c[1], &c[3]) >= threshold) ||
(gimp_rgba_distance (&c[2], &c[3]) >= threshold))
{
/* Calc coordinates of center subsample */
x2 = (x1 + x3) / 2;
y2 = (y1 + y3) / 2;
/* Render sub-blocks */
num_samples += gimp_render_sub_pixel (max_depth, depth + 1, block,
x, y, x1, y1, x2, y2,
threshold, sub_pixel_size,
&c[0],
render_func, render_data);
num_samples += gimp_render_sub_pixel (max_depth, depth + 1, block,
x, y, x2, y1, x3, y2,
threshold, sub_pixel_size,
&c[1],
render_func, render_data);
num_samples += gimp_render_sub_pixel (max_depth, depth + 1, block,
x, y, x1, y2, x2, y3,
threshold, sub_pixel_size,
&c[2],
render_func, render_data);
num_samples += gimp_render_sub_pixel (max_depth, depth + 1, block,
x, y, x2, y2, x3, y3,
threshold, sub_pixel_size,
&c[3],
render_func, render_data);
}
}
if (c[0].a == 0.0 || c[1].a == 0.0 || c[2].a == 0.0 || c[3].a == 0.0)
{
GimpRGB tmpcol;
gdouble weight;
gimp_rgb_set (&tmpcol, 0.0, 0.0, 0.0);
weight = 2.0;
for (cnt = 0; cnt < 4; cnt++)
{
if (c[cnt].a != 0.0)
{
tmpcol.r += c[cnt].r;
tmpcol.g += c[cnt].g;
tmpcol.b += c[cnt].b;
weight /= 2.0;
}
}
color->r = weight * tmpcol.r;
color->g = weight * tmpcol.g;
color->b = weight * tmpcol.b;
}
else
{
color->r = 0.25 * (c[0].r + c[1].r + c[2].r + c[3].r);
color->g = 0.25 * (c[0].g + c[1].g + c[2].g + c[3].g);
color->b = 0.25 * (c[0].b + c[1].b + c[2].b + c[3].b);
}
color->a = 0.25 * (c[0].a + c[1].a + c[2].a + c[3].a);
return num_samples;
}
gulong
gimp_adaptive_supersample_area (gint x1,
gint y1,
gint x2,
gint y2,
gint max_depth,
gdouble threshold,
GimpRenderFunc render_func,
gpointer render_data,
GimpPutPixelFunc put_pixel_func,
gpointer put_pixel_data,
GimpProgressFunc progress_func,
gpointer progress_data)
{
gint x, y, width; /* Counters, width of region */
gint xt, xtt, yt; /* Temporary counters */
gint sub_pixel_size; /* Number of samples per pixel (1D) */
GimpRGB color; /* Rendered pixel's color */
GimpSampleType tmp_sample; /* For swapping samples */
GimpSampleType *top_row, *bot_row, *tmp_row; /* Sample rows */
GimpSampleType **block; /* Sample block matrix */
gulong num_samples;
/* Initialize color */
gimp_rgba_set (&color, 0.0, 0.0, 0.0, 0.0);
/* Calculate sub-pixel size */
sub_pixel_size = 1 << max_depth;
/* Create row arrays */
width = x2 - x1 + 1;
top_row = g_new (GimpSampleType, sub_pixel_size * width + 1);
bot_row = g_new (GimpSampleType, sub_pixel_size * width + 1);
for (x = 0; x < (sub_pixel_size * width + 1); x++)
{
top_row[x].ready = FALSE;
gimp_rgba_set (&top_row[x].color, 0.0, 0.0, 0.0, 0.0);
bot_row[x].ready = FALSE;
gimp_rgba_set (&bot_row[x].color, 0.0, 0.0, 0.0, 0.0);
}
/* Allocate block matrix */
block = g_new (GimpSampleType *, sub_pixel_size + 1); /* Rows */
for (y = 0; y < (sub_pixel_size + 1); y++)
{
block[y] = g_new (GimpSampleType, sub_pixel_size + 1); /* Columns */
for (x = 0; x < (sub_pixel_size + 1); x++)
{
block[y][x].ready = FALSE;
gimp_rgba_set (&block[y][x].color, 0.0, 0.0, 0.0, 0.0);
}
}
/* Render region */
num_samples = 0;
for (y = y1; y <= y2; y++)
{
/* Clear the bottom row */
for (xt = 0; xt < (sub_pixel_size * width + 1); xt++)
bot_row[xt].ready = FALSE;
/* Clear first column */
for (yt = 0; yt < (sub_pixel_size + 1); yt++)
block[yt][0].ready = FALSE;
/* Render row */
for (x = x1; x <= x2; x++)
{
/* Initialize block by clearing all but first row/column */
for (yt = 1; yt < (sub_pixel_size + 1); yt++)
for (xt = 1; xt < (sub_pixel_size + 1); xt++)
block[yt][xt].ready = FALSE;
/* Copy samples from top row to block */
for (xtt = 0, xt = (x - x1) * sub_pixel_size;
xtt < (sub_pixel_size + 1);
xtt++, xt++)
block[0][xtt] = top_row[xt];
/* Render pixel on (x, y) */
num_samples += gimp_render_sub_pixel (max_depth, 1, block, x, y, 0, 0,
sub_pixel_size, sub_pixel_size,
threshold, sub_pixel_size,
&color,
render_func, render_data);
if (put_pixel_func)
(* put_pixel_func) (x, y, &color, put_pixel_data);
/* Copy block information to rows */
top_row[(x - x1 + 1) * sub_pixel_size] = block[0][sub_pixel_size];
for (xtt = 0, xt = (x - x1) * sub_pixel_size;
xtt < (sub_pixel_size + 1);
xtt++, xt++)
bot_row[xt] = block[sub_pixel_size][xtt];
/* Swap first and last columns */
for (yt = 0; yt < (sub_pixel_size + 1); yt++)
{
tmp_sample = block[yt][0];
block[yt][0] = block[yt][sub_pixel_size];
block[yt][sub_pixel_size] = tmp_sample;
}
}
/* Swap rows */
tmp_row = top_row;
top_row = bot_row;
bot_row = tmp_row;
/* Call progress display function (if any) */
if (progress_func != NULL)
(* progress_func) (y1, y2, y, progress_data);
}
/* Free memory */
for (y = 0; y < (sub_pixel_size + 1); y++)
g_free (block[y]);
g_free (block);
g_free (top_row);
g_free (bot_row);
return num_samples;
}

View File

@ -0,0 +1,65 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GIMP_ADAPTIVE_SUPERSAMPLE_H__
#define __GIMP_ADAPTIVE_SUPERSAMPLE_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* For information look into the C source or the html documentation */
/* adaptive supersampling function taken from LibGCK */
typedef void (* GimpRenderFunc) (gdouble x,
gdouble y,
GimpRGB *color,
gpointer data);
typedef void (* GimpPutPixelFunc) (gint x,
gint y,
GimpRGB *color,
gpointer data);
typedef void (* GimpProgressFunc) (gint min,
gint max,
gint current,
gpointer data);
gulong gimp_adaptive_supersample_area (gint x1,
gint y1,
gint x2,
gint y2,
gint max_depth,
gdouble threshold,
GimpRenderFunc render_func,
gpointer render_data,
GimpPutPixelFunc put_pixel_func,
gpointer put_pixel_data,
GimpProgressFunc progress_func,
gpointer progress_data);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GIMP_ADAPTIVE_SUPERSAMPLE_H__ */

222
libgimp/gimpbilinear.c Normal file
View File

@ -0,0 +1,222 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <glib.h>
#include "gimpcolor.h"
#include "gimpbilinear.h"
#include "gimpmath.h"
gdouble
gimp_bilinear (gdouble x,
gdouble y,
gdouble *values)
{
gdouble xx, yy;
gdouble m0, m1;
g_assert (values != NULL);
xx = fmod (x, 1.0);
yy = fmod (y, 1.0);
if (x < 0.0)
x += 1.0;
if (y < 0.0)
y += 1.0;
m0 = (1.0 - xx) * values[0] + xx * values[1];
m1 = (1.0 - xx) * values[2] + xx * values[3];
return (1.0 - yy) * m0 + yy * m1;
}
guchar
gimp_bilinear_8 (gdouble x,
gdouble y,
guchar *values)
{
gdouble xx, yy;
gdouble m0, m1;
g_assert (values != NULL);
xx = fmod (x, 1.0);
yy = fmod (y, 1.0);
if (x < 0.0)
x += 1.0;
if (y < 0.0)
y += 1.0;
m0 = (1.0 - xx) * values[0] + xx * values[1];
m1 = (1.0 - xx) * values[2] + xx * values[3];
return (guchar) ((1.0 - yy) * m0 + yy * m1);
}
guint16
gimp_bilinear_16 (gdouble x,
gdouble y,
guint16 *values)
{
gdouble xx, yy;
gdouble m0, m1;
g_assert (values != NULL);
xx = fmod (x, 1.0);
yy = fmod (y, 1.0);
if (x < 0.0)
x += 1.0;
if (y < 0.0)
y += 1.0;
m0 = (1.0 - xx) * values[0] + xx * values[1];
m1 = (1.0 - xx) * values[2] + xx * values[3];
return (guint16) ((1.0 - yy) * m0 + yy * m1);
}
guint32
gimp_bilinear_32 (gdouble x,
gdouble y,
guint32 *values)
{
gdouble xx, yy;
gdouble m0, m1;
g_assert (values != NULL);
xx = fmod (x, 1.0);
yy = fmod (y, 1.0);
if (x < 0.0)
x += 1.0;
if (y < 0.0)
y += 1.0;
m0 = (1.0 - xx) * values[0] + xx * values[1];
m1 = (1.0 - xx) * values[2] + xx * values[3];
return (guint32) ((1.0 - yy) * m0 + yy * m1);
}
GimpRGB
gimp_bilinear_rgb (gdouble x,
gdouble y,
GimpRGB *values)
{
gdouble m0, m1;
gdouble ix, iy;
GimpRGB v;
g_assert (values != NULL);
x = fmod(x, 1.0);
y = fmod(y, 1.0);
if (x < 0)
x += 1.0;
if (y < 0)
y += 1.0;
ix = 1.0 - x;
iy = 1.0 - y;
/* Red */
m0 = ix * values[0].r + x * values[1].r;
m1 = ix * values[2].r + x * values[3].r;
v.r = iy * m0 + y * m1;
/* Green */
m0 = ix * values[0].g + x * values[1].g;
m1 = ix * values[2].g + x * values[3].g;
v.g = iy * m0 + y * m1;
/* Blue */
m0 = ix * values[0].b + x * values[1].b;
m1 = ix * values[2].b + x * values[3].b;
v.b = iy * m0 + y * m1;
return v;
}
GimpRGB
gimp_bilinear_rgba (gdouble x,
gdouble y,
GimpRGB *values)
{
gdouble m0, m1;
gdouble ix, iy;
GimpRGB v;
g_assert (values != NULL);
x = fmod (x, 1.0);
y = fmod (y, 1.0);
if (x < 0)
x += 1.0;
if (y < 0)
y += 1.0;
ix = 1.0 - x;
iy = 1.0 - y;
/* Red */
m0 = ix * values[0].r + x * values[1].r;
m1 = ix * values[2].r + x * values[3].r;
v.r = iy * m0 + y * m1;
/* Green */
m0 = ix * values[0].g + x * values[1].g;
m1 = ix * values[2].g + x * values[3].g;
v.g = iy * m0 + y * m1;
/* Blue */
m0 = ix * values[0].b + x * values[1].b;
m1 = ix * values[2].b + x * values[3].b;
v.b = iy * m0 + y * m1;
/* Alpha */
m0 = ix * values[0].a + x * values[1].a;
m1 = ix * values[2].a + x * values[3].a;
v.a = iy * m0 + y * m1;
return v;
}

57
libgimp/gimpbilinear.h Normal file
View File

@ -0,0 +1,57 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GIMP_BILINEAR_H__
#define __GIMP_BILINEAR_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* For information look into the C source or the html documentation */
/* bilinear interpolation functions taken from LibGCK */
gdouble gimp_bilinear (gdouble x,
gdouble y,
gdouble *values);
guchar gimp_bilinear_8 (gdouble x,
gdouble y,
guchar *values);
guint16 gimp_bilinear_16 (gdouble x,
gdouble y,
guint16 *values);
guint32 gimp_bilinear_32 (gdouble x,
gdouble y,
guint32 *values);
GimpRGB gimp_bilinear_rgb (gdouble x,
gdouble y,
GimpRGB *values);
GimpRGB gimp_bilinear_rgba (gdouble x,
gdouble y,
GimpRGB *values);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GIMP_BILINEAR_H__ */

View File

@ -0,0 +1,380 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <glib.h>
#include "gimpcolor.h"
#include "gimpadaptivesupersample.h"
#include "gimpmath.h"
/*********************************************************************/
/* Sumpersampling code (Quartic) */
/* This code is *largely* based on the sources for POV-Ray 3.0. I am */
/* grateful to the POV-Team for such a great program and for making */
/* their sources available. All comments / bug reports / */
/* etc. regarding this code should be addressed to me, not to the */
/* POV-Ray team. Any bugs are my responsibility, not theirs. */
/*********************************************************************/
typedef struct _GimpSampleType GimpSampleType;
struct _GimpSampleType
{
guchar ready;
GimpRGB color;
};
static gulong
gimp_render_sub_pixel (gint max_depth,
gint depth,
GimpSampleType **block,
gint x,
gint y,
gint x1,
gint y1,
gint x3,
gint y3,
gdouble threshold,
gint sub_pixel_size,
GimpRGB *color,
GimpRenderFunc render_func,
gpointer render_data)
{
gint x2, y2; /* Coords of center sample */
gdouble dx1, dy1; /* Delta to upper left sample */
gdouble dx3, dy3; /* Delta to lower right sample */
GimpRGB c[4]; /* Sample colors */
gulong num_samples = 0;
gint cnt;
/* Get offsets for corners */
dx1 = (gdouble) (x1 - sub_pixel_size / 2) / sub_pixel_size;
dx3 = (gdouble) (x3 - sub_pixel_size / 2) / sub_pixel_size;
dy1 = (gdouble) (y1 - sub_pixel_size / 2) / sub_pixel_size;
dy3 = (gdouble) (y3 - sub_pixel_size / 2) / sub_pixel_size;
/* Render upper left sample */
if (! block[y1][x1].ready)
{
num_samples++;
if (render_func)
(* render_func) (x + dx1, y + dy1, &c[0], render_data);
block[y1][x1].ready = TRUE;
block[y1][x1].color = c[0];
}
else
{
c[0] = block[y1][x1].color;
}
/* Render upper right sample */
if (! block[y1][x3].ready)
{
num_samples++;
if (render_func)
(* render_func) (x + dx3, y + dy1, &c[1], render_data);
block[y1][x3].ready = TRUE;
block[y1][x3].color = c[1];
}
else
{
c[1] = block[y1][x3].color;
}
/* Render lower left sample */
if (! block[y3][x1].ready)
{
num_samples++;
if (render_func)
(* render_func) (x + dx1, y + dy3, &c[2], render_data);
block[y3][x1].ready = TRUE;
block[y3][x1].color = c[2];
}
else
{
c[2] = block[y3][x1].color;
}
/* Render lower right sample */
if (! block[y3][x3].ready)
{
num_samples++;
if (render_func)
(* render_func) (x + dx3, y + dy3, &c[3], render_data);
block[y3][x3].ready = TRUE;
block[y3][x3].color = c[3];
}
else
{
c[3] = block[y3][x3].color;
}
/* Check for supersampling */
if (depth <= max_depth)
{
/* Check whether we have to supersample */
if ((gimp_rgba_distance (&c[0], &c[1]) >= threshold) ||
(gimp_rgba_distance (&c[0], &c[2]) >= threshold) ||
(gimp_rgba_distance (&c[0], &c[3]) >= threshold) ||
(gimp_rgba_distance (&c[1], &c[2]) >= threshold) ||
(gimp_rgba_distance (&c[1], &c[3]) >= threshold) ||
(gimp_rgba_distance (&c[2], &c[3]) >= threshold))
{
/* Calc coordinates of center subsample */
x2 = (x1 + x3) / 2;
y2 = (y1 + y3) / 2;
/* Render sub-blocks */
num_samples += gimp_render_sub_pixel (max_depth, depth + 1, block,
x, y, x1, y1, x2, y2,
threshold, sub_pixel_size,
&c[0],
render_func, render_data);
num_samples += gimp_render_sub_pixel (max_depth, depth + 1, block,
x, y, x2, y1, x3, y2,
threshold, sub_pixel_size,
&c[1],
render_func, render_data);
num_samples += gimp_render_sub_pixel (max_depth, depth + 1, block,
x, y, x1, y2, x2, y3,
threshold, sub_pixel_size,
&c[2],
render_func, render_data);
num_samples += gimp_render_sub_pixel (max_depth, depth + 1, block,
x, y, x2, y2, x3, y3,
threshold, sub_pixel_size,
&c[3],
render_func, render_data);
}
}
if (c[0].a == 0.0 || c[1].a == 0.0 || c[2].a == 0.0 || c[3].a == 0.0)
{
GimpRGB tmpcol;
gdouble weight;
gimp_rgb_set (&tmpcol, 0.0, 0.0, 0.0);
weight = 2.0;
for (cnt = 0; cnt < 4; cnt++)
{
if (c[cnt].a != 0.0)
{
tmpcol.r += c[cnt].r;
tmpcol.g += c[cnt].g;
tmpcol.b += c[cnt].b;
weight /= 2.0;
}
}
color->r = weight * tmpcol.r;
color->g = weight * tmpcol.g;
color->b = weight * tmpcol.b;
}
else
{
color->r = 0.25 * (c[0].r + c[1].r + c[2].r + c[3].r);
color->g = 0.25 * (c[0].g + c[1].g + c[2].g + c[3].g);
color->b = 0.25 * (c[0].b + c[1].b + c[2].b + c[3].b);
}
color->a = 0.25 * (c[0].a + c[1].a + c[2].a + c[3].a);
return num_samples;
}
gulong
gimp_adaptive_supersample_area (gint x1,
gint y1,
gint x2,
gint y2,
gint max_depth,
gdouble threshold,
GimpRenderFunc render_func,
gpointer render_data,
GimpPutPixelFunc put_pixel_func,
gpointer put_pixel_data,
GimpProgressFunc progress_func,
gpointer progress_data)
{
gint x, y, width; /* Counters, width of region */
gint xt, xtt, yt; /* Temporary counters */
gint sub_pixel_size; /* Number of samples per pixel (1D) */
GimpRGB color; /* Rendered pixel's color */
GimpSampleType tmp_sample; /* For swapping samples */
GimpSampleType *top_row, *bot_row, *tmp_row; /* Sample rows */
GimpSampleType **block; /* Sample block matrix */
gulong num_samples;
/* Initialize color */
gimp_rgba_set (&color, 0.0, 0.0, 0.0, 0.0);
/* Calculate sub-pixel size */
sub_pixel_size = 1 << max_depth;
/* Create row arrays */
width = x2 - x1 + 1;
top_row = g_new (GimpSampleType, sub_pixel_size * width + 1);
bot_row = g_new (GimpSampleType, sub_pixel_size * width + 1);
for (x = 0; x < (sub_pixel_size * width + 1); x++)
{
top_row[x].ready = FALSE;
gimp_rgba_set (&top_row[x].color, 0.0, 0.0, 0.0, 0.0);
bot_row[x].ready = FALSE;
gimp_rgba_set (&bot_row[x].color, 0.0, 0.0, 0.0, 0.0);
}
/* Allocate block matrix */
block = g_new (GimpSampleType *, sub_pixel_size + 1); /* Rows */
for (y = 0; y < (sub_pixel_size + 1); y++)
{
block[y] = g_new (GimpSampleType, sub_pixel_size + 1); /* Columns */
for (x = 0; x < (sub_pixel_size + 1); x++)
{
block[y][x].ready = FALSE;
gimp_rgba_set (&block[y][x].color, 0.0, 0.0, 0.0, 0.0);
}
}
/* Render region */
num_samples = 0;
for (y = y1; y <= y2; y++)
{
/* Clear the bottom row */
for (xt = 0; xt < (sub_pixel_size * width + 1); xt++)
bot_row[xt].ready = FALSE;
/* Clear first column */
for (yt = 0; yt < (sub_pixel_size + 1); yt++)
block[yt][0].ready = FALSE;
/* Render row */
for (x = x1; x <= x2; x++)
{
/* Initialize block by clearing all but first row/column */
for (yt = 1; yt < (sub_pixel_size + 1); yt++)
for (xt = 1; xt < (sub_pixel_size + 1); xt++)
block[yt][xt].ready = FALSE;
/* Copy samples from top row to block */
for (xtt = 0, xt = (x - x1) * sub_pixel_size;
xtt < (sub_pixel_size + 1);
xtt++, xt++)
block[0][xtt] = top_row[xt];
/* Render pixel on (x, y) */
num_samples += gimp_render_sub_pixel (max_depth, 1, block, x, y, 0, 0,
sub_pixel_size, sub_pixel_size,
threshold, sub_pixel_size,
&color,
render_func, render_data);
if (put_pixel_func)
(* put_pixel_func) (x, y, &color, put_pixel_data);
/* Copy block information to rows */
top_row[(x - x1 + 1) * sub_pixel_size] = block[0][sub_pixel_size];
for (xtt = 0, xt = (x - x1) * sub_pixel_size;
xtt < (sub_pixel_size + 1);
xtt++, xt++)
bot_row[xt] = block[sub_pixel_size][xtt];
/* Swap first and last columns */
for (yt = 0; yt < (sub_pixel_size + 1); yt++)
{
tmp_sample = block[yt][0];
block[yt][0] = block[yt][sub_pixel_size];
block[yt][sub_pixel_size] = tmp_sample;
}
}
/* Swap rows */
tmp_row = top_row;
top_row = bot_row;
bot_row = tmp_row;
/* Call progress display function (if any) */
if (progress_func != NULL)
(* progress_func) (y1, y2, y, progress_data);
}
/* Free memory */
for (y = 0; y < (sub_pixel_size + 1); y++)
g_free (block[y]);
g_free (block);
g_free (top_row);
g_free (bot_row);
return num_samples;
}

View File

@ -0,0 +1,65 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GIMP_ADAPTIVE_SUPERSAMPLE_H__
#define __GIMP_ADAPTIVE_SUPERSAMPLE_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* For information look into the C source or the html documentation */
/* adaptive supersampling function taken from LibGCK */
typedef void (* GimpRenderFunc) (gdouble x,
gdouble y,
GimpRGB *color,
gpointer data);
typedef void (* GimpPutPixelFunc) (gint x,
gint y,
GimpRGB *color,
gpointer data);
typedef void (* GimpProgressFunc) (gint min,
gint max,
gint current,
gpointer data);
gulong gimp_adaptive_supersample_area (gint x1,
gint y1,
gint x2,
gint y2,
gint max_depth,
gdouble threshold,
GimpRenderFunc render_func,
gpointer render_data,
GimpPutPixelFunc put_pixel_func,
gpointer put_pixel_data,
GimpProgressFunc progress_func,
gpointer progress_data);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GIMP_ADAPTIVE_SUPERSAMPLE_H__ */

222
libgimpcolor/gimpbilinear.c Normal file
View File

@ -0,0 +1,222 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <glib.h>
#include "gimpcolor.h"
#include "gimpbilinear.h"
#include "gimpmath.h"
gdouble
gimp_bilinear (gdouble x,
gdouble y,
gdouble *values)
{
gdouble xx, yy;
gdouble m0, m1;
g_assert (values != NULL);
xx = fmod (x, 1.0);
yy = fmod (y, 1.0);
if (x < 0.0)
x += 1.0;
if (y < 0.0)
y += 1.0;
m0 = (1.0 - xx) * values[0] + xx * values[1];
m1 = (1.0 - xx) * values[2] + xx * values[3];
return (1.0 - yy) * m0 + yy * m1;
}
guchar
gimp_bilinear_8 (gdouble x,
gdouble y,
guchar *values)
{
gdouble xx, yy;
gdouble m0, m1;
g_assert (values != NULL);
xx = fmod (x, 1.0);
yy = fmod (y, 1.0);
if (x < 0.0)
x += 1.0;
if (y < 0.0)
y += 1.0;
m0 = (1.0 - xx) * values[0] + xx * values[1];
m1 = (1.0 - xx) * values[2] + xx * values[3];
return (guchar) ((1.0 - yy) * m0 + yy * m1);
}
guint16
gimp_bilinear_16 (gdouble x,
gdouble y,
guint16 *values)
{
gdouble xx, yy;
gdouble m0, m1;
g_assert (values != NULL);
xx = fmod (x, 1.0);
yy = fmod (y, 1.0);
if (x < 0.0)
x += 1.0;
if (y < 0.0)
y += 1.0;
m0 = (1.0 - xx) * values[0] + xx * values[1];
m1 = (1.0 - xx) * values[2] + xx * values[3];
return (guint16) ((1.0 - yy) * m0 + yy * m1);
}
guint32
gimp_bilinear_32 (gdouble x,
gdouble y,
guint32 *values)
{
gdouble xx, yy;
gdouble m0, m1;
g_assert (values != NULL);
xx = fmod (x, 1.0);
yy = fmod (y, 1.0);
if (x < 0.0)
x += 1.0;
if (y < 0.0)
y += 1.0;
m0 = (1.0 - xx) * values[0] + xx * values[1];
m1 = (1.0 - xx) * values[2] + xx * values[3];
return (guint32) ((1.0 - yy) * m0 + yy * m1);
}
GimpRGB
gimp_bilinear_rgb (gdouble x,
gdouble y,
GimpRGB *values)
{
gdouble m0, m1;
gdouble ix, iy;
GimpRGB v;
g_assert (values != NULL);
x = fmod(x, 1.0);
y = fmod(y, 1.0);
if (x < 0)
x += 1.0;
if (y < 0)
y += 1.0;
ix = 1.0 - x;
iy = 1.0 - y;
/* Red */
m0 = ix * values[0].r + x * values[1].r;
m1 = ix * values[2].r + x * values[3].r;
v.r = iy * m0 + y * m1;
/* Green */
m0 = ix * values[0].g + x * values[1].g;
m1 = ix * values[2].g + x * values[3].g;
v.g = iy * m0 + y * m1;
/* Blue */
m0 = ix * values[0].b + x * values[1].b;
m1 = ix * values[2].b + x * values[3].b;
v.b = iy * m0 + y * m1;
return v;
}
GimpRGB
gimp_bilinear_rgba (gdouble x,
gdouble y,
GimpRGB *values)
{
gdouble m0, m1;
gdouble ix, iy;
GimpRGB v;
g_assert (values != NULL);
x = fmod (x, 1.0);
y = fmod (y, 1.0);
if (x < 0)
x += 1.0;
if (y < 0)
y += 1.0;
ix = 1.0 - x;
iy = 1.0 - y;
/* Red */
m0 = ix * values[0].r + x * values[1].r;
m1 = ix * values[2].r + x * values[3].r;
v.r = iy * m0 + y * m1;
/* Green */
m0 = ix * values[0].g + x * values[1].g;
m1 = ix * values[2].g + x * values[3].g;
v.g = iy * m0 + y * m1;
/* Blue */
m0 = ix * values[0].b + x * values[1].b;
m1 = ix * values[2].b + x * values[3].b;
v.b = iy * m0 + y * m1;
/* Alpha */
m0 = ix * values[0].a + x * values[1].a;
m1 = ix * values[2].a + x * values[3].a;
v.a = iy * m0 + y * m1;
return v;
}

View File

@ -0,0 +1,57 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GIMP_BILINEAR_H__
#define __GIMP_BILINEAR_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* For information look into the C source or the html documentation */
/* bilinear interpolation functions taken from LibGCK */
gdouble gimp_bilinear (gdouble x,
gdouble y,
gdouble *values);
guchar gimp_bilinear_8 (gdouble x,
gdouble y,
guchar *values);
guint16 gimp_bilinear_16 (gdouble x,
gdouble y,
guint16 *values);
guint32 gimp_bilinear_32 (gdouble x,
gdouble y,
guint32 *values);
GimpRGB gimp_bilinear_rgb (gdouble x,
gdouble y,
GimpRGB *values);
GimpRGB gimp_bilinear_rgba (gdouble x,
gdouble y,
GimpRGB *values);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GIMP_BILINEAR_H__ */

View File

@ -267,7 +267,7 @@ get_image_color (gdouble u,
p[2] = peek (x1, y2);
p[3] = peek (x2, y2);
return gck_bilinear_rgba (u, v, p);
return gimp_bilinear_rgba (u, v, p);
}
gdouble
@ -297,7 +297,7 @@ get_map_value (GimpPixelRgn *region,
p[2] = (gdouble) peek_map (region, x1, y2);
p[3] = (gdouble) peek_map (region, x2, y2);
return gck_bilinear (u, v, p);
return gimp_bilinear (u, v, p);
}
static void

View File

@ -189,7 +189,8 @@ init_compute (void)
void
render (gdouble x,
gdouble y,
GimpRGB *col)
GimpRGB *col,
gpointer data)
{
GimpVector3 pos;
@ -203,7 +204,8 @@ render (gdouble x,
void
show_progress (gint min,
gint max,
gint curr)
gint curr,
gpointer data)
{
gimp_progress_update ((gdouble) curr / (gdouble) max);
}
@ -288,7 +290,7 @@ compute_image (void)
{
p = int_to_pos (xcount, ycount);
color = (* get_ray_color) (&p);
poke (xcount, ycount, &color);
poke (xcount, ycount, &color, NULL);
if ((progress_counter++ % width) == 0)
gimp_progress_update ((gdouble) progress_counter /
@ -298,13 +300,16 @@ compute_image (void)
}
else
{
gck_adaptive_supersample_area (0, 0,
gimp_adaptive_supersample_area (0, 0,
width - 1, height - 1,
max_depth,
mapvals.pixeltreshold,
render,
NULL,
poke,
show_progress);
NULL,
show_progress,
NULL);
}
/* Update the region */

View File

@ -136,16 +136,14 @@ peek_cylinder_image (gint image,
void
poke (gint x,
gint y,
GimpRGB *color)
GimpRGB *color,
gpointer data)
{
static guchar data[4];
static guchar col[4];
data[0] = (guchar) (color->r * 255.0);
data[1] = (guchar) (color->g * 255.0);
data[2] = (guchar) (color->b * 255.0);
data[3] = (guchar) (color->a * 255.0);
gimp_rgba_get_uchar (color, &col[0], &col[1], &col[2], &col[3]);
gimp_pixel_rgn_set_pixel (&dest_region, data, x, y);
gimp_pixel_rgn_set_pixel (&dest_region, col, x, y);
}
gint
@ -246,7 +244,7 @@ get_image_color (gdouble u,
p[2] = peek (x1, y2);
p[3] = peek (x2, y2);
return gck_bilinear_rgba (u * width, v * height, p);
return gimp_bilinear_rgba (u * width, v * height, p);
}
if (checkbounds (x1, y1) == FALSE)
@ -273,7 +271,7 @@ get_image_color (gdouble u,
p[2] = peek (x1, y2);
p[3] = peek (x2, y2);
return gck_bilinear_rgba (u * width, v * height, p);
return gimp_bilinear_rgba (u * width, v * height, p);
}
GimpRGB
@ -281,7 +279,8 @@ get_box_image_color (gint image,
gdouble u,
gdouble v)
{
gint w,h, x1, y1, x2, y2;
gint w, h;
gint x1, y1, x2, y2;
GimpRGB p[4];
w = box_drawables[image]->width;
@ -304,7 +303,7 @@ get_box_image_color (gint image,
p[2] = peek_box_image (image, x1, y2);
p[3] = peek_box_image (image, x2, y2);
return gck_bilinear_rgba (u * w, v * h, p);
return gimp_bilinear_rgba (u * w, v * h, p);
}
GimpRGB
@ -312,7 +311,8 @@ get_cylinder_image_color (gint image,
gdouble u,
gdouble v)
{
gint w,h, x1, y1, x2, y2;
gint w, h;
gint x1, y1, x2, y2;
GimpRGB p[4];
w = cylinder_drawables[image]->width;
@ -335,7 +335,7 @@ get_cylinder_image_color (gint image,
p[2] = peek_cylinder_image (image, x1, y2);
p[3] = peek_cylinder_image (image, x2, y2);
return gck_bilinear_rgba (u * w, v * h, p);
return gimp_bilinear_rgba (u * w, v * h, p);
}
/****************************************/

View File

@ -40,7 +40,8 @@ extern GimpRGB peek (gint x,
gint y);
extern void poke (gint x,
gint y,
GimpRGB *color);
GimpRGB *color,
gpointer data);
extern GimpVector3 int_to_pos (gint x,
gint y);
extern void pos_to_int (gdouble x,

View File

@ -56,12 +56,6 @@ typedef struct
GckDitherType dithermethod;
} GckVisualInfo;
typedef void (* GckRenderFunction) (gdouble, gdouble, GimpRGB *);
typedef void (* GckPutPixelFunction) (gint, gint, GimpRGB *);
typedef void (* GckProgressFunction) (gint, gint, gint);
typedef void (* GckColorUpdateFunction) (GimpRGB *);
GckVisualInfo *gck_visualinfo_new (void);
void gck_visualinfo_destroy (GckVisualInfo *visinfo);
@ -80,27 +74,6 @@ void gck_gc_set_foreground (GckVisualInfo *visinfo,GdkGC *gc,
void gck_gc_set_background (GckVisualInfo *visinfo,GdkGC *gc,
guchar r, guchar g, guchar b);
/********************/
/* Color operations */
/********************/
double gck_bilinear (double x,double y, double *values);
guchar gck_bilinear_8 (double x,double y, guchar *values);
guint16 gck_bilinear_16 (double x,double y, guint16 *values);
guint32 gck_bilinear_32 (double x,double y, guint32 *values);
GimpRGB gck_bilinear_rgb (double x,double y, GimpRGB *values);
GimpRGB gck_bilinear_rgba (double x,double y, GimpRGB *values);
/* Supersampling */
/* ============= */
gulong gck_adaptive_supersample_area (int x1,int y1,int x2,int y2,
int max_depth,
double threshold,
GckRenderFunction render_func,
GckPutPixelFunction put_pixel_func,
GckProgressFunction progress_func);
#ifdef __cplusplus
}
#endif

View File

@ -42,12 +42,6 @@
#define ROUND_TO_INT(val) ((val) + 0.5)
typedef struct
{
guchar ready;
GimpRGB color;
} _GckSampleType;
/* returns a static storage */
static GdkColor *gck_rgb_to_gdkcolor (GckVisualInfo *visinfo,
@ -1278,505 +1272,3 @@ gck_rgb_to_gdkcolor_r(GckVisualInfo * visinfo, guchar r, guchar g, guchar b)
return (color);
}
/********************/
/* Color operations */
/********************/
/******************************************/
/* Bilinear interpolation stuff (Quartic) */
/******************************************/
double gck_bilinear(double x, double y, double *values)
{
double xx, yy, m0, m1;
g_assert(values!=NULL);
xx = fmod(x, 1.0);
yy = fmod(y, 1.0);
if (x < 0.0)
x += 1.0;
if (y < 0.0)
y += 1.0;
m0 = (1.0 - xx) * values[0] + xx * values[1];
m1 = (1.0 - xx) * values[2] + xx * values[3];
return ((1.0 - yy) * m0 + yy * m1);
}
guchar gck_bilinear_8(double x, double y, guchar * values)
{
double xx, yy, m0, m1;
g_assert(values!=NULL);
xx = fmod(x, 1.0);
yy = fmod(y, 1.0);
if (x < 0.0)
x += 1.0;
if (y < 0.0)
y += 1.0;
m0 = (1.0 - xx) * values[0] + xx * values[1];
m1 = (1.0 - xx) * values[2] + xx * values[3];
return ((guchar) ((1.0 - yy) * m0 + yy * m1));
}
guint16 gck_bilinear_16(double x, double y, guint16 * values)
{
double xx, yy, m0, m1;
g_assert(values!=NULL);
xx = fmod(x, 1.0);
yy = fmod(y, 1.0);
if (x < 0.0)
x += 1.0;
if (y < 0.0)
y += 1.0;
m0 = (1.0 - xx) * values[0] + xx * values[1];
m1 = (1.0 - xx) * values[2] + xx * values[3];
return ((guint16) ((1.0 - yy) * m0 + yy * m1));
}
guint32 gck_bilinear_32(double x, double y, guint32 * values)
{
double xx, yy, m0, m1;
g_assert(values!=NULL);
xx = fmod(x, 1.0);
yy = fmod(y, 1.0);
if (x < 0.0)
x += 1.0;
if (y < 0.0)
y += 1.0;
m0 = (1.0 - xx) * values[0] + xx * values[1];
m1 = (1.0 - xx) * values[2] + xx * values[3];
return ((guint32) ((1.0 - yy) * m0 + yy * m1));
}
GimpRGB gck_bilinear_rgb(double x, double y, GimpRGB *values)
{
double m0, m1;
double ix, iy;
GimpRGB v;
g_assert(values!=NULL);
x = fmod(x, 1.0);
y = fmod(y, 1.0);
if (x < 0)
x += 1.0;
if (y < 0)
y += 1.0;
ix = 1.0 - x;
iy = 1.0 - y;
/* Red */
/* === */
m0 = ix * values[0].r + x * values[1].r;
m1 = ix * values[2].r + x * values[3].r;
v.r = iy * m0 + y * m1;
/* Green */
/* ===== */
m0 = ix * values[0].g + x * values[1].g;
m1 = ix * values[2].g + x * values[3].g;
v.g = iy * m0 + y * m1;
/* Blue */
/* ==== */
m0 = ix * values[0].b + x * values[1].b;
m1 = ix * values[2].b + x * values[3].b;
v.b = iy * m0 + y * m1;
return (v);
} /* bilinear */
GimpRGB gck_bilinear_rgba(double x, double y, GimpRGB *values)
{
double m0, m1;
double ix, iy;
GimpRGB v;
g_assert(values!=NULL);
x = fmod(x, 1.0);
y = fmod(y, 1.0);
if (x < 0)
x += 1.0;
if (y < 0)
y += 1.0;
ix = 1.0 - x;
iy = 1.0 - y;
/* Red */
/* === */
m0 = ix * values[0].r + x * values[1].r;
m1 = ix * values[2].r + x * values[3].r;
v.r = iy * m0 + y * m1;
/* Green */
/* ===== */
m0 = ix * values[0].g + x * values[1].g;
m1 = ix * values[2].g + x * values[3].g;
v.g = iy * m0 + y * m1;
/* Blue */
/* ==== */
m0 = ix * values[0].b + x * values[1].b;
m1 = ix * values[2].b + x * values[3].b;
v.b = iy * m0 + y * m1;
/* Alpha */
/* ===== */
m0 = ix * values[0].a + x * values[1].a;
m1 = ix * values[2].a + x * values[3].a;
v.a = iy * m0 + y * m1;
return (v);
} /* bilinear */
/*********************************************************************/
/* Sumpersampling code (Quartic) */
/* This code is *largely* based on the sources for POV-Ray 3.0. I am */
/* grateful to the POV-Team for such a great program and for making */
/* their sources available. All comments / bug reports / */
/* etc. regarding this code should be addressed to me, not to the */
/* POV-Ray team. Any bugs are my responsibility, not theirs. */
/*********************************************************************/
gulong gck_render_sub_pixel(int max_depth, int depth, _GckSampleType ** block,
int x, int y, int x1, int y1, int x3, int y3, double threshold,
int sub_pixel_size, GckRenderFunction render_func, GimpRGB * color)
{
int x2, y2, cnt; /* Coords of center sample */
double dx1, dy1; /* Delta to upper left sample */
double dx3, dy3, weight; /* Delta to lower right sample */
GimpRGB c[4],tmpcol;
unsigned long num_samples = 0;
/* Get offsets for corners */
/* ======================= */
dx1 = (double)(x1 - sub_pixel_size / 2) / sub_pixel_size;
dx3 = (double)(x3 - sub_pixel_size / 2) / sub_pixel_size;
dy1 = (double)(y1 - sub_pixel_size / 2) / sub_pixel_size;
dy3 = (double)(y3 - sub_pixel_size / 2) / sub_pixel_size;
/* Render upper left sample */
/* ======================== */
if (!block[y1][x1].ready)
{
num_samples++;
(*render_func) (x + dx1, y + dy1, &c[0]);
block[y1][x1].ready = 1;
block[y1][x1].color = c[0];
}
else
c[0] = block[y1][x1].color;
/* Render upper right sample */
/* ========================= */
if (!block[y1][x3].ready)
{
num_samples++;
(*render_func) (x + dx3, y + dy1, &c[1]);
block[y1][x3].ready = 1;
block[y1][x3].color = c[1];
}
else
c[1] = block[y1][x3].color;
/* Render lower left sample */
/* ======================== */
if (!block[y3][x1].ready)
{
num_samples++;
(*render_func) (x + dx1, y + dy3, &c[2]);
block[y3][x1].ready = 1;
block[y3][x1].color = c[2];
}
else
c[2] = block[y3][x1].color;
/* Render lower right sample */
/* ========================= */
if (!block[y3][x3].ready)
{
num_samples++;
(*render_func) (x + dx3, y + dy3, &c[3]);
block[y3][x3].ready = 1;
block[y3][x3].color = c[3];
}
else
c[3] = block[y3][x3].color;
/* Check for supersampling */
/* ======================= */
if (depth <= max_depth)
{
/* Check whether we have to supersample */
/* ==================================== */
if ((gimp_rgba_distance (&c[0], &c[1]) >= threshold) ||
(gimp_rgba_distance (&c[0], &c[2]) >= threshold) ||
(gimp_rgba_distance (&c[0], &c[3]) >= threshold) ||
(gimp_rgba_distance (&c[1], &c[2]) >= threshold) ||
(gimp_rgba_distance (&c[1], &c[3]) >= threshold) ||
(gimp_rgba_distance (&c[2], &c[3]) >= threshold))
{
/* Calc coordinates of center subsample */
/* ==================================== */
x2 = (x1 + x3) / 2;
y2 = (y1 + y3) / 2;
/* Render sub-blocks */
/* ================= */
num_samples += gck_render_sub_pixel(max_depth, depth + 1, block, x, y, x1, y1, x2, y2,
threshold, sub_pixel_size, render_func, &c[0]);
num_samples += gck_render_sub_pixel(max_depth, depth + 1, block, x, y, x2, y1, x3, y2,
threshold, sub_pixel_size, render_func, &c[1]);
num_samples += gck_render_sub_pixel(max_depth, depth + 1, block, x, y, x1, y2, x2, y3,
threshold, sub_pixel_size, render_func, &c[2]);
num_samples += gck_render_sub_pixel(max_depth, depth + 1, block, x, y, x2, y2, x3, y3,
threshold, sub_pixel_size, render_func, &c[3]);
}
}
if (c[0].a==0.0 || c[1].a==0.0 || c[2].a==0.0 || c[3].a==0.0)
{
tmpcol.r=0.0;
tmpcol.g=0.0;
tmpcol.b=0.0;
weight=2.0;
for (cnt=0;cnt<4;cnt++)
{
if (c[cnt].a!=0.0)
{
tmpcol.r+=c[cnt].r;
tmpcol.g+=c[cnt].g;
tmpcol.b+=c[cnt].b;
weight/=2.0;
}
}
color->r=weight*tmpcol.r;
color->g=weight*tmpcol.g;
color->b=weight*tmpcol.b;
}
else
{
color->r = 0.25 * (c[0].r + c[1].r + c[2].r + c[3].r);
color->g = 0.25 * (c[0].g + c[1].g + c[2].g + c[3].g);
color->b = 0.25 * (c[0].b + c[1].b + c[2].b + c[3].b);
}
color->a = 0.25 * (c[0].a + c[1].a + c[2].a + c[3].a);
return (num_samples);
} /* Render_Sub_Pixel */
gulong gck_adaptive_supersample_area(int x1, int y1, int x2, int y2, int max_depth,
double threshold,
GckRenderFunction render_func,
GckPutPixelFunction put_pixel_func,
GckProgressFunction progress_func)
{
int x, y, width; /* Counters, width of region */
int xt, xtt, yt; /* Temporary counters */
int sub_pixel_size; /* Numbe of samples per pixel (1D) */
size_t row_size; /* Memory needed for one row */
GimpRGB color; /* Rendered pixel's color */
_GckSampleType tmp_sample; /* For swapping samples */
_GckSampleType *top_row, *bot_row, *tmp_row; /* Sample rows */
_GckSampleType **block; /* Sample block matrix */
unsigned long num_samples;
/* Initialize color */
/* ================ */
color.r = color.b = color.g = color.a = 0.0;
/* Calculate sub-pixel size */
/* ======================== */
sub_pixel_size = 1 << max_depth;
/* Create row arrays */
/* ================= */
width = x2 - x1 + 1;
row_size = (sub_pixel_size * width + 1) * sizeof(_GckSampleType);
top_row = (_GckSampleType *) g_malloc(row_size);
bot_row = (_GckSampleType *) g_malloc(row_size);
for (x = 0; x < (sub_pixel_size * width + 1); x++)
{
top_row[x].ready = 0;
top_row[x].color.r = 0.0;
top_row[x].color.g = 0.0;
top_row[x].color.b = 0.0;
top_row[x].color.a = 0.0;
bot_row[x].ready = 0;
bot_row[x].color.r = 0.0;
bot_row[x].color.g = 0.0;
bot_row[x].color.b = 0.0;
bot_row[x].color.a = 0.0;
}
/* Allocate block matrix */
/* ===================== */
block = g_malloc((sub_pixel_size + 1) * sizeof(_GckSampleType *)); /* Rows */
for (y = 0; y < (sub_pixel_size + 1); y++)
block[y] = g_malloc((sub_pixel_size + 1) * sizeof(_GckSampleType));
for (y = 0; y < (sub_pixel_size + 1); y++)
for (x = 0; x < (sub_pixel_size + 1); x++)
{
block[y][x].ready = 0;
block[y][x].color.r = 0.0;
block[y][x].color.g = 0.0;
block[y][x].color.b = 0.0;
block[y][x].color.a = 0.0;
}
/* Render region */
/* ============= */
num_samples = 0;
for (y = y1; y <= y2; y++)
{
/* Clear the bottom row */
/* ==================== */
for (xt = 0; xt < (sub_pixel_size * width + 1); xt++)
bot_row[xt].ready = 0;
/* Clear first column */
/* ================== */
for (yt = 0; yt < (sub_pixel_size + 1); yt++)
block[yt][0].ready = 0;
/* Render row */
/* ========== */
for (x = x1; x <= x2; x++)
{
/* Initialize block by clearing all but first row/column */
/* ===================================================== */
for (yt = 1; yt < (sub_pixel_size + 1); yt++)
for (xt = 1; xt < (sub_pixel_size + 1); xt++)
block[yt][xt].ready = 0;
/* Copy samples from top row to block */
/* ================================== */
for (xtt = 0, xt = (x - x1) * sub_pixel_size; xtt < (sub_pixel_size + 1); xtt++, xt++)
block[0][xtt] = top_row[xt];
/* Render pixel on (x, y) */
/* ====================== */
num_samples += gck_render_sub_pixel(max_depth, 1, block, x, y, 0, 0, sub_pixel_size,
sub_pixel_size, threshold, sub_pixel_size, render_func, &color);
(*put_pixel_func) (x, y, &color);
/* Copy block information to rows */
/* ============================== */
top_row[(x - x1 + 1) * sub_pixel_size] = block[0][sub_pixel_size];
for (xtt = 0, xt = (x - x1) * sub_pixel_size; xtt < (sub_pixel_size + 1); xtt++, xt++)
bot_row[xt] = block[sub_pixel_size][xtt];
/* Swap first and last columns */
/* =========================== */
for (yt = 0; yt < (sub_pixel_size + 1); yt++)
{
tmp_sample = block[yt][0];
block[yt][0] = block[yt][sub_pixel_size];
block[yt][sub_pixel_size] = tmp_sample;
}
}
/* Swap rows */
/* ========= */
tmp_row = top_row;
top_row = bot_row;
bot_row = tmp_row;
/* Call progress display function (if any) */
/* ======================================= */
if (progress_func != NULL)
(*progress_func) (y1, y2, y);
} /* for */
/* Free memory */
/* =========== */
for (y = 0; y < (sub_pixel_size + 1); y++)
g_free(block[y]);
g_free(block);
g_free(top_row);
g_free(bot_row);
return (num_samples);
}