From 75760de9d110ccd015b9dd5984da178d3cf8825a Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Tue, 23 Jan 2001 00:53:12 +0000 Subject: [PATCH] libgimp/Makefile.am libgimp/gimp.h libgimp/gimpadaptivesupersample.[ch] 2001-01-23 Michael Natterer * 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. --- ChangeLog | 26 ++ app/apptypes.h | 8 +- app/asupsample.c | 200 ++++----- app/asupsample.h | 34 +- app/core/gimpdrawable-blend.c | 26 +- app/disp_callbacks.c | 44 +- app/display/gimpdisplay-callbacks.c | 44 +- app/display/gimpdisplayshell-callbacks.c | 44 +- app/tools/blend.c | 26 +- app/tools/gimpblendtool.c | 26 +- libgimp/Makefile.am | 196 ++++----- libgimp/gimp.h | 2 + libgimp/gimpadaptivesupersample.c | 380 +++++++++++++++++ libgimp/gimpadaptivesupersample.h | 65 +++ libgimp/gimpbilinear.c | 222 ++++++++++ libgimp/gimpbilinear.h | 57 +++ libgimpcolor/gimpadaptivesupersample.c | 380 +++++++++++++++++ libgimpcolor/gimpadaptivesupersample.h | 65 +++ libgimpcolor/gimpbilinear.c | 222 ++++++++++ libgimpcolor/gimpbilinear.h | 57 +++ plug-ins/Lighting/lighting_image.c | 6 +- plug-ins/MapObject/mapobject_apply.c | 33 +- plug-ins/MapObject/mapobject_image.c | 34 +- plug-ins/MapObject/mapobject_image.h | 21 +- plug-ins/libgck/gck/gck.h | 27 -- plug-ins/libgck/gck/gckcolor.c | 508 ----------------------- 26 files changed, 1856 insertions(+), 897 deletions(-) create mode 100644 libgimp/gimpadaptivesupersample.c create mode 100644 libgimp/gimpadaptivesupersample.h create mode 100644 libgimp/gimpbilinear.c create mode 100644 libgimp/gimpbilinear.h create mode 100644 libgimpcolor/gimpadaptivesupersample.c create mode 100644 libgimpcolor/gimpadaptivesupersample.h create mode 100644 libgimpcolor/gimpbilinear.c create mode 100644 libgimpcolor/gimpbilinear.h diff --git a/ChangeLog b/ChangeLog index 7e65c834c4..5185e4c7a5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2001-01-23 Michael Natterer + + * 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 * app/gdisplay.c diff --git a/app/apptypes.h b/app/apptypes.h index e0353f2bc8..242141914d 100644 --- a/app/apptypes.h +++ b/app/apptypes.h @@ -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, diff --git a/app/asupsample.c b/app/asupsample.c index 780deb1e32..50e398b445 100644 --- a/app/asupsample.c +++ b/app/asupsample.c @@ -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,52 +46,51 @@ typedef struct { gchar ready; GimpRGB color; -} sample_t; +} GimpSampleType; /***** Local functions *****/ -static gulong render_sub_pixel (gint max_depth, - gint depth, - sample_t **block, - gint x, - gint y, - gint x1, - gint y1, - gint x3, - gint y3, - gdouble threshold, - gint sub_pixel_size, - render_func_t render_func, - GimpRGB *color, - gpointer render_data); +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); /***** Functions *****/ gulong -adaptive_supersample_area (gint x1, - gint y1, - gint x2, - gint y2, - gint max_depth, - gdouble threshold, - render_func_t render_func, - gpointer render_data, - put_pixel_func_t put_pixel_func, - gpointer put_pixel_data, - GimpProgressFunc progress_func, - gpointer progress_data) +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; /* 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 */ - gulong num_samples; + gint x, y, width; /* Counters, width of region */ + gint xt, xtt, yt; /* Temporary counters */ + gint sub_pixel_size; /* Numbe 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 */ @@ -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, - sub_pixel_size, sub_pixel_size, - threshold, sub_pixel_size, - render_func, &color, - render_data); + 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); + (* put_pixel_func) (x, y, &color, put_pixel_data); /* Copy block information to rows */ @@ -195,8 +191,8 @@ adaptive_supersample_area (gint x1, for (yt = 0; yt < (sub_pixel_size + 1); yt++) { - tmp_sample = block[yt][0]; - block[yt][0] = block[yt][sub_pixel_size]; + tmp_sample = block[yt][0]; + block[yt][0] = block[yt][sub_pixel_size]; block[yt][sub_pixel_size] = tmp_sample; } } @@ -226,20 +222,20 @@ adaptive_supersample_area (gint x1, } static gulong -render_sub_pixel (gint max_depth, - gint depth, - sample_t **block, - gint x, - gint y, - gint x1, - gint y1, - gint x3, - gint y3, - gdouble threshold, - gint sub_pixel_size, - render_func_t render_func, - GimpRGB *color, - gpointer render_data) +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 */ @@ -262,9 +258,11 @@ render_sub_pixel (gint max_depth, if (!block[y1][x1].ready) { num_samples++; - (* render_func) (x + dx1, y + dy1, &c1, render_data); - block[y1][x1].ready = 1; + if (render_func) + (* render_func) (x + dx1, y + dy1, &c1, render_data); + + block[y1][x1].ready = TRUE; block[y1][x1].color = c1; } else @@ -274,12 +272,14 @@ render_sub_pixel (gint max_depth, /* Render upper right sample */ - if (!block[y1][x3].ready) + if (! block[y1][x3].ready) { num_samples++; - (* render_func) (x + dx3, y + dy1, &c2, render_data); - block[y1][x3].ready = 1; + if (render_func) + (* render_func) (x + dx3, y + dy1, &c2, render_data); + + block[y1][x3].ready = TRUE; block[y1][x3].color = c2; } else @@ -289,12 +289,14 @@ render_sub_pixel (gint max_depth, /* Render lower left sample */ - if (!block[y3][x1].ready) + if (! block[y3][x1].ready) { num_samples++; - (* render_func) (x + dx1, y + dy3, &c3, render_data); - block[y3][x1].ready = 1; + if (render_func) + (* render_func) (x + dx1, y + dy3, &c3, render_data); + + block[y3][x1].ready = TRUE; block[y3][x1].color = c3; } else @@ -304,12 +306,14 @@ render_sub_pixel (gint max_depth, /* Render lower right sample */ - if (!block[y3][x3].ready) + if (! block[y3][x3].ready) { num_samples++; - (* render_func) (x + dx3, y + dy3, &c4, render_data); - block[y3][x3].ready = 1; + if (render_func) + (* render_func) (x + dx3, y + dy3, &c4, render_data); + + 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); } } diff --git a/app/asupsample.h b/app/asupsample.h index 0f5c1c6e79..ceccd71904 100644 --- a/app/asupsample.h +++ b/app/asupsample.h @@ -24,28 +24,28 @@ #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, - gint y1, - gint x2, - gint y2, - gint max_depth, - gdouble threshold, - render_func_t render_func, - gpointer render_data, - put_pixel_func_t put_pixel_func, - gpointer put_pixel_data, - GimpProgressFunc progress_func, - gpointer progress_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); #endif /* __ASUPSAMPLE_H__ */ diff --git a/app/core/gimpdrawable-blend.c b/app/core/gimpdrawable-blend.c index 982df28bfd..72f335f9ec 100644 --- a/app/core/gimpdrawable-blend.c +++ b/app/core/gimpdrawable-blend.c @@ -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,11 +1588,11 @@ gradient_fill_region (GImage *gimage, /* Render! */ - adaptive_supersample_area (0, 0, (width - 1), (height - 1), - max_depth, threshold, - gradient_render_pixel, &rbd, - gradient_put_pixel, &ppd, - progress_callback, progress_data); + gimp_adaptive_supersample_area (0, 0, (width - 1), (height - 1), + max_depth, threshold, + gradient_render_pixel, &rbd, + gradient_put_pixel, &ppd, + progress_callback, progress_data); /* Clean up */ diff --git a/app/disp_callbacks.c b/app/disp_callbacks.c index 0ae09082c8..f7edc8ec1d 100644 --- a/app/disp_callbacks.c +++ b/app/disp_callbacks.c @@ -160,7 +160,7 @@ gdisplay_canvas_events (GtkWidget *canvas, gdisp = (GDisplay *) gtk_object_get_user_data (GTK_OBJECT (canvas)); - if (!canvas->window) + if (!canvas->window) return FALSE; /* If this is the first event... */ @@ -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 */ @@ -191,7 +191,7 @@ gdisplay_canvas_events (GtkWidget *canvas, } /* Find out what device the event occurred upon */ - if (!gimp_busy && devices_check_change (event)) + if (! gimp_busy && devices_check_change (event)) gdisplay_check_device_cursor (gdisp); switch (event->type) @@ -216,7 +216,7 @@ gdisplay_canvas_events (GtkWidget *canvas, break; case GDK_LEAVE_NOTIFY: - if (((GdkEventCrossing*) event)->mode != GDK_CROSSING_NORMAL) + if (((GdkEventCrossing *) event)->mode != GDK_CROSSING_NORMAL) return TRUE; gdisplay_update_cursor (gdisp, 0, 0); gtk_label_set_text (GTK_LABEL (gdisp->cursor_label), ""); @@ -227,7 +227,7 @@ gdisplay_canvas_events (GtkWidget *canvas, break; case GDK_ENTER_NOTIFY: - if (((GdkEventCrossing*) event)->mode != GDK_CROSSING_NORMAL) + if (((GdkEventCrossing *) event)->mode != GDK_CROSSING_NORMAL) return TRUE; /* Actually, should figure out tx,ty here */ break; @@ -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), @@ -261,7 +261,7 @@ gdisplay_canvas_events (GtkWidget *canvas, NULL); if (active_tool && ((active_tool->type == MOVE) || - !gimp_image_is_empty (gdisp->gimage))) + ! gimp_image_is_empty (gdisp->gimage))) { if (active_tool->auto_snap_to) { @@ -363,9 +363,8 @@ gdisplay_canvas_events (GtkWidget *canvas, * * ugly: fuzzy_select sets busy cursors while ACTIVE. */ - if (gimp_busy && - !(active_tool->type == FUZZY_SELECT && - active_tool->state == ACTIVE)) + if (gimp_busy && ! (active_tool->type == FUZZY_SELECT && + active_tool->state == ACTIVE)) return TRUE; switch (bevent->button) @@ -394,7 +393,7 @@ gdisplay_canvas_events (GtkWidget *canvas, bevent->y = ty; update_cursor = TRUE; } - + (* active_tool->button_release_func) (active_tool, bevent, gdisp); } @@ -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 && - active_tool->state == ACTIVE)) + 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, @@ -469,7 +467,7 @@ gdisplay_canvas_events (GtkWidget *canvas, } if (active_tool && ((active_tool->type == MOVE) || - !gimp_image_is_empty (gdisp->gimage)) && + ! gimp_image_is_empty (gdisp->gimage)) && (mevent->state & GDK_BUTTON1_MASK)) { if (active_tool->state == ACTIVE) diff --git a/app/display/gimpdisplay-callbacks.c b/app/display/gimpdisplay-callbacks.c index 0ae09082c8..f7edc8ec1d 100644 --- a/app/display/gimpdisplay-callbacks.c +++ b/app/display/gimpdisplay-callbacks.c @@ -160,7 +160,7 @@ gdisplay_canvas_events (GtkWidget *canvas, gdisp = (GDisplay *) gtk_object_get_user_data (GTK_OBJECT (canvas)); - if (!canvas->window) + if (!canvas->window) return FALSE; /* If this is the first event... */ @@ -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 */ @@ -191,7 +191,7 @@ gdisplay_canvas_events (GtkWidget *canvas, } /* Find out what device the event occurred upon */ - if (!gimp_busy && devices_check_change (event)) + if (! gimp_busy && devices_check_change (event)) gdisplay_check_device_cursor (gdisp); switch (event->type) @@ -216,7 +216,7 @@ gdisplay_canvas_events (GtkWidget *canvas, break; case GDK_LEAVE_NOTIFY: - if (((GdkEventCrossing*) event)->mode != GDK_CROSSING_NORMAL) + if (((GdkEventCrossing *) event)->mode != GDK_CROSSING_NORMAL) return TRUE; gdisplay_update_cursor (gdisp, 0, 0); gtk_label_set_text (GTK_LABEL (gdisp->cursor_label), ""); @@ -227,7 +227,7 @@ gdisplay_canvas_events (GtkWidget *canvas, break; case GDK_ENTER_NOTIFY: - if (((GdkEventCrossing*) event)->mode != GDK_CROSSING_NORMAL) + if (((GdkEventCrossing *) event)->mode != GDK_CROSSING_NORMAL) return TRUE; /* Actually, should figure out tx,ty here */ break; @@ -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), @@ -261,7 +261,7 @@ gdisplay_canvas_events (GtkWidget *canvas, NULL); if (active_tool && ((active_tool->type == MOVE) || - !gimp_image_is_empty (gdisp->gimage))) + ! gimp_image_is_empty (gdisp->gimage))) { if (active_tool->auto_snap_to) { @@ -363,9 +363,8 @@ gdisplay_canvas_events (GtkWidget *canvas, * * ugly: fuzzy_select sets busy cursors while ACTIVE. */ - if (gimp_busy && - !(active_tool->type == FUZZY_SELECT && - active_tool->state == ACTIVE)) + if (gimp_busy && ! (active_tool->type == FUZZY_SELECT && + active_tool->state == ACTIVE)) return TRUE; switch (bevent->button) @@ -394,7 +393,7 @@ gdisplay_canvas_events (GtkWidget *canvas, bevent->y = ty; update_cursor = TRUE; } - + (* active_tool->button_release_func) (active_tool, bevent, gdisp); } @@ -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 && - active_tool->state == ACTIVE)) + 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, @@ -469,7 +467,7 @@ gdisplay_canvas_events (GtkWidget *canvas, } if (active_tool && ((active_tool->type == MOVE) || - !gimp_image_is_empty (gdisp->gimage)) && + ! gimp_image_is_empty (gdisp->gimage)) && (mevent->state & GDK_BUTTON1_MASK)) { if (active_tool->state == ACTIVE) diff --git a/app/display/gimpdisplayshell-callbacks.c b/app/display/gimpdisplayshell-callbacks.c index 0ae09082c8..f7edc8ec1d 100644 --- a/app/display/gimpdisplayshell-callbacks.c +++ b/app/display/gimpdisplayshell-callbacks.c @@ -160,7 +160,7 @@ gdisplay_canvas_events (GtkWidget *canvas, gdisp = (GDisplay *) gtk_object_get_user_data (GTK_OBJECT (canvas)); - if (!canvas->window) + if (!canvas->window) return FALSE; /* If this is the first event... */ @@ -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 */ @@ -191,7 +191,7 @@ gdisplay_canvas_events (GtkWidget *canvas, } /* Find out what device the event occurred upon */ - if (!gimp_busy && devices_check_change (event)) + if (! gimp_busy && devices_check_change (event)) gdisplay_check_device_cursor (gdisp); switch (event->type) @@ -216,7 +216,7 @@ gdisplay_canvas_events (GtkWidget *canvas, break; case GDK_LEAVE_NOTIFY: - if (((GdkEventCrossing*) event)->mode != GDK_CROSSING_NORMAL) + if (((GdkEventCrossing *) event)->mode != GDK_CROSSING_NORMAL) return TRUE; gdisplay_update_cursor (gdisp, 0, 0); gtk_label_set_text (GTK_LABEL (gdisp->cursor_label), ""); @@ -227,7 +227,7 @@ gdisplay_canvas_events (GtkWidget *canvas, break; case GDK_ENTER_NOTIFY: - if (((GdkEventCrossing*) event)->mode != GDK_CROSSING_NORMAL) + if (((GdkEventCrossing *) event)->mode != GDK_CROSSING_NORMAL) return TRUE; /* Actually, should figure out tx,ty here */ break; @@ -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), @@ -261,7 +261,7 @@ gdisplay_canvas_events (GtkWidget *canvas, NULL); if (active_tool && ((active_tool->type == MOVE) || - !gimp_image_is_empty (gdisp->gimage))) + ! gimp_image_is_empty (gdisp->gimage))) { if (active_tool->auto_snap_to) { @@ -363,9 +363,8 @@ gdisplay_canvas_events (GtkWidget *canvas, * * ugly: fuzzy_select sets busy cursors while ACTIVE. */ - if (gimp_busy && - !(active_tool->type == FUZZY_SELECT && - active_tool->state == ACTIVE)) + if (gimp_busy && ! (active_tool->type == FUZZY_SELECT && + active_tool->state == ACTIVE)) return TRUE; switch (bevent->button) @@ -394,7 +393,7 @@ gdisplay_canvas_events (GtkWidget *canvas, bevent->y = ty; update_cursor = TRUE; } - + (* active_tool->button_release_func) (active_tool, bevent, gdisp); } @@ -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 && - active_tool->state == ACTIVE)) + 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, @@ -469,7 +467,7 @@ gdisplay_canvas_events (GtkWidget *canvas, } if (active_tool && ((active_tool->type == MOVE) || - !gimp_image_is_empty (gdisp->gimage)) && + ! gimp_image_is_empty (gdisp->gimage)) && (mevent->state & GDK_BUTTON1_MASK)) { if (active_tool->state == ACTIVE) diff --git a/app/tools/blend.c b/app/tools/blend.c index 982df28bfd..72f335f9ec 100644 --- a/app/tools/blend.c +++ b/app/tools/blend.c @@ -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,11 +1588,11 @@ gradient_fill_region (GImage *gimage, /* Render! */ - adaptive_supersample_area (0, 0, (width - 1), (height - 1), - max_depth, threshold, - gradient_render_pixel, &rbd, - gradient_put_pixel, &ppd, - progress_callback, progress_data); + gimp_adaptive_supersample_area (0, 0, (width - 1), (height - 1), + max_depth, threshold, + gradient_render_pixel, &rbd, + gradient_put_pixel, &ppd, + progress_callback, progress_data); /* Clean up */ diff --git a/app/tools/gimpblendtool.c b/app/tools/gimpblendtool.c index 982df28bfd..72f335f9ec 100644 --- a/app/tools/gimpblendtool.c +++ b/app/tools/gimpblendtool.c @@ -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,11 +1588,11 @@ gradient_fill_region (GImage *gimage, /* Render! */ - adaptive_supersample_area (0, 0, (width - 1), (height - 1), - max_depth, threshold, - gradient_render_pixel, &rbd, - gradient_put_pixel, &ppd, - progress_callback, progress_data); + gimp_adaptive_supersample_area (0, 0, (width - 1), (height - 1), + max_depth, threshold, + gradient_render_pixel, &rbd, + gradient_put_pixel, &ppd, + progress_callback, progress_data); /* Clean up */ diff --git a/libgimp/Makefile.am b/libgimp/Makefile.am index 8200e87199..116eb5c5b9 100644 --- a/libgimp/Makefile.am +++ b/libgimp/Makefile.am @@ -155,55 +155,59 @@ endif @: libgimp_la_SOURCES = \ - gimp.c \ - gimp.h \ - ${PDB_WRAPPERS_C} \ - ${PDB_WRAPPERS_H} \ - gimpcolor.c \ - gimpcolor.h \ - gimpcolorspace.c \ - gimpcolorspace.h \ - gimpchannel.c \ - gimpchannel.h \ - gimpdrawable.c \ - gimpdrawable.h \ - gimpenv.c \ - gimpenv.h \ - gimpgradientselect.c \ - gimpgradientselect.h \ - gimphelp.c \ - gimpimage.c \ - gimpimage.h \ - gimplayer.c \ - gimplayer.h \ - gimplimits.h \ - gimpmatrix.c \ - gimpmatrix.h \ - gimpparasite.c \ - gimpparasite.h \ - gimpparasiteio.c \ - gimpparasiteio.h \ - gimppixelrgn.c \ - gimppixelrgn.h \ - gimpproceduraldb.c \ - gimpproceduraldb.h \ - gimpprotocol.c \ - gimpprotocol.h \ - gimpselection.c \ - gimpselection.h \ - gimpsignal.c \ - gimpsignal.h \ - gimptile.c \ - gimptile.h \ - gimpunit.c \ - gimpunit.h \ - gimputils.c \ - gimputils.h \ - gimpvector.c \ - gimpvector.h \ - gimpwire.c \ - gimpwire.h \ - stdplugins-intl.h \ + gimp.c \ + gimp.h \ + ${PDB_WRAPPERS_C} \ + ${PDB_WRAPPERS_H} \ + gimpadaptivesupersample.c \ + gimpadaptivesupersample.h \ + gimpbilinear.c \ + gimpbilinear.h \ + gimpcolor.c \ + gimpcolor.h \ + gimpcolorspace.c \ + gimpcolorspace.h \ + gimpchannel.c \ + gimpchannel.h \ + gimpdrawable.c \ + gimpdrawable.h \ + gimpenv.c \ + gimpenv.h \ + gimpgradientselect.c \ + gimpgradientselect.h \ + gimphelp.c \ + gimpimage.c \ + gimpimage.h \ + gimplayer.c \ + gimplayer.h \ + gimplimits.h \ + gimpmatrix.c \ + gimpmatrix.h \ + gimpparasite.c \ + gimpparasite.h \ + gimpparasiteio.c \ + gimpparasiteio.h \ + gimppixelrgn.c \ + gimppixelrgn.h \ + gimpproceduraldb.c \ + gimpproceduraldb.h \ + gimpprotocol.c \ + gimpprotocol.h \ + gimpselection.c \ + gimpselection.h \ + gimpsignal.c \ + gimpsignal.h \ + gimptile.c \ + gimptile.h \ + gimpunit.c \ + gimpunit.h \ + gimputils.c \ + gimputils.h \ + gimpvector.c \ + gimpvector.h \ + gimpwire.c \ + gimpwire.h \ + stdplugins-intl.h \ libgimp-intl.h libgimpui_la_SOURCES = \ @@ -228,52 +232,54 @@ libgimpui_la_SOURCES = \ gimpwidgets.c gimpinclude_HEADERS = \ - gimp.h \ - ${PDB_WRAPPERS_H} \ - gimpchainbutton.h \ - gimpchannel.h \ - gimpcolor.h \ - gimpcolorarea.h \ - gimpcolorbutton.h \ - gimpcolordisplay.h \ - gimpcolorselector.h \ - gimpcolorspace.h \ - gimpcompat.h \ - gimpdrawable.h \ - gimpdialog.h \ - gimpenums.h \ - gimpenv.h \ - gimpexport.h \ - gimpfeatures.h \ - gimpfileselection.h \ - gimpgradientselect.h \ - gimphelpui.h \ - gimpimage.h \ - gimplayer.h \ - gimplimits.h \ - gimpmath.h \ - gimpmatrix.h \ - gimpmenu.h \ - gimpmodule.h \ - gimpparasite.h \ - gimpparasiteio.h \ - gimppatheditor.h \ - gimppixelrgn.h \ - gimppixmap.h \ - gimpproceduraldb.h \ - gimpquerybox.h \ - gimpselection.h \ - gimpsignal.h \ - gimpsizeentry.h \ - gimptile.h \ - gimptypes.h \ - gimpui.h \ - gimpuitypes.h \ - gimpunit.h \ - gimpunitmenu.h \ - gimputils.h \ - gimpvector.h \ - gimpwidgets.h \ + gimp.h \ + ${PDB_WRAPPERS_H} \ + gimpadaptivesupersample.h \ + gimpbilinear.h \ + gimpchainbutton.h \ + gimpchannel.h \ + gimpcolor.h \ + gimpcolorarea.h \ + gimpcolorbutton.h \ + gimpcolordisplay.h \ + gimpcolorselector.h \ + gimpcolorspace.h \ + gimpcompat.h \ + gimpdrawable.h \ + gimpdialog.h \ + gimpenums.h \ + gimpenv.h \ + gimpexport.h \ + gimpfeatures.h \ + gimpfileselection.h \ + gimpgradientselect.h \ + gimphelpui.h \ + gimpimage.h \ + gimplayer.h \ + gimplimits.h \ + gimpmath.h \ + gimpmatrix.h \ + gimpmenu.h \ + gimpmodule.h \ + gimpparasite.h \ + gimpparasiteio.h \ + gimppatheditor.h \ + gimppixelrgn.h \ + gimppixmap.h \ + gimpproceduraldb.h \ + gimpquerybox.h \ + gimpselection.h \ + gimpsignal.h \ + gimpsizeentry.h \ + gimptile.h \ + gimptypes.h \ + gimpui.h \ + gimpuitypes.h \ + gimpunit.h \ + gimpunitmenu.h \ + gimputils.h \ + gimpvector.h \ + gimpwidgets.h \ gimpintl.h diff --git a/libgimp/gimp.h b/libgimp/gimp.h index 5f00aa2709..4584ec5973 100644 --- a/libgimp/gimp.h +++ b/libgimp/gimp.h @@ -27,6 +27,8 @@ #include #include +#include +#include #include #include #include diff --git a/libgimp/gimpadaptivesupersample.c b/libgimp/gimpadaptivesupersample.c new file mode 100644 index 0000000000..e51adcac31 --- /dev/null +++ b/libgimp/gimpadaptivesupersample.c @@ -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 + +#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; +} diff --git a/libgimp/gimpadaptivesupersample.h b/libgimp/gimpadaptivesupersample.h new file mode 100644 index 0000000000..fe71bfe65d --- /dev/null +++ b/libgimp/gimpadaptivesupersample.h @@ -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__ */ diff --git a/libgimp/gimpbilinear.c b/libgimp/gimpbilinear.c new file mode 100644 index 0000000000..b1a8717df4 --- /dev/null +++ b/libgimp/gimpbilinear.c @@ -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 + +#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; +} diff --git a/libgimp/gimpbilinear.h b/libgimp/gimpbilinear.h new file mode 100644 index 0000000000..1b6ac57513 --- /dev/null +++ b/libgimp/gimpbilinear.h @@ -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__ */ diff --git a/libgimpcolor/gimpadaptivesupersample.c b/libgimpcolor/gimpadaptivesupersample.c new file mode 100644 index 0000000000..e51adcac31 --- /dev/null +++ b/libgimpcolor/gimpadaptivesupersample.c @@ -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 + +#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; +} diff --git a/libgimpcolor/gimpadaptivesupersample.h b/libgimpcolor/gimpadaptivesupersample.h new file mode 100644 index 0000000000..fe71bfe65d --- /dev/null +++ b/libgimpcolor/gimpadaptivesupersample.h @@ -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__ */ diff --git a/libgimpcolor/gimpbilinear.c b/libgimpcolor/gimpbilinear.c new file mode 100644 index 0000000000..b1a8717df4 --- /dev/null +++ b/libgimpcolor/gimpbilinear.c @@ -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 + +#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; +} diff --git a/libgimpcolor/gimpbilinear.h b/libgimpcolor/gimpbilinear.h new file mode 100644 index 0000000000..1b6ac57513 --- /dev/null +++ b/libgimpcolor/gimpbilinear.h @@ -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__ */ diff --git a/plug-ins/Lighting/lighting_image.c b/plug-ins/Lighting/lighting_image.c index eccb2ac209..b3f8aacc37 100644 --- a/plug-ins/Lighting/lighting_image.c +++ b/plug-ins/Lighting/lighting_image.c @@ -240,7 +240,7 @@ get_image_color (gdouble u, gdouble v, gint *inside) { - gint x1, y1, x2, y2; + gint x1, y1, x2, y2; GimpRGB p[4]; x1 = RINT (u); @@ -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 diff --git a/plug-ins/MapObject/mapobject_apply.c b/plug-ins/MapObject/mapobject_apply.c index 507f410d28..579ca06a90 100644 --- a/plug-ins/MapObject/mapobject_apply.c +++ b/plug-ins/MapObject/mapobject_apply.c @@ -187,9 +187,10 @@ init_compute (void) } void -render (gdouble x, - gdouble y, - GimpRGB *col) +render (gdouble x, + gdouble y, + GimpRGB *col, + gpointer data) { GimpVector3 pos; @@ -201,9 +202,10 @@ render (gdouble x, } void -show_progress (gint min, - gint max, - gint curr) +show_progress (gint min, + gint max, + 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, - width - 1, height - 1, - max_depth, - mapvals.pixeltreshold, - render, - poke, - show_progress); + gimp_adaptive_supersample_area (0, 0, + width - 1, height - 1, + max_depth, + mapvals.pixeltreshold, + render, + NULL, + poke, + NULL, + show_progress, + NULL); } /* Update the region */ diff --git a/plug-ins/MapObject/mapobject_image.c b/plug-ins/MapObject/mapobject_image.c index 5959ade180..7adbe9273d 100644 --- a/plug-ins/MapObject/mapobject_image.c +++ b/plug-ins/MapObject/mapobject_image.c @@ -134,18 +134,16 @@ peek_cylinder_image (gint image, } void -poke (gint x, - gint y, - GimpRGB *color) +poke (gint x, + gint y, + GimpRGB *color, + gpointer data) { - static guchar data[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); + static guchar col[4]; - gimp_pixel_rgn_set_pixel (&dest_region, data, x, y); + gimp_rgba_get_uchar (color, &col[0], &col[1], &col[2], &col[3]); + + gimp_pixel_rgn_set_pixel (&dest_region, col, x, y); } gint @@ -223,7 +221,7 @@ get_image_color (gdouble u, gdouble v, gint *inside) { - gint x1, y1, x2, y2; + gint x1, y1, x2, y2; GimpRGB p[4]; pos_to_int (u, v, &x1, &y1); @@ -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); } /****************************************/ diff --git a/plug-ins/MapObject/mapobject_image.h b/plug-ins/MapObject/mapobject_image.h index e18e1aa4ef..9be5bb27e9 100644 --- a/plug-ins/MapObject/mapobject_image.h +++ b/plug-ins/MapObject/mapobject_image.h @@ -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, @@ -48,14 +49,14 @@ extern void pos_to_int (gdouble x, gint *scr_x, gint *scr_y); -extern GimpRGB get_image_color (gdouble u, - gdouble v, - gint *inside); -extern GimpRGB get_box_image_color (gint image, - gdouble u, - gdouble v); -extern GimpRGB get_cylinder_image_color (gint image, - gdouble u, - gdouble v); +extern GimpRGB get_image_color (gdouble u, + gdouble v, + gint *inside); +extern GimpRGB get_box_image_color (gint image, + gdouble u, + gdouble v); +extern GimpRGB get_cylinder_image_color (gint image, + gdouble u, + gdouble v); #endif /* __MAPOBJECT_IMAGE_H__ */ diff --git a/plug-ins/libgck/gck/gck.h b/plug-ins/libgck/gck/gck.h index 1057bad672..0e728f5f9b 100644 --- a/plug-ins/libgck/gck/gck.h +++ b/plug-ins/libgck/gck/gck.h @@ -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 diff --git a/plug-ins/libgck/gck/gckcolor.c b/plug-ins/libgck/gck/gckcolor.c index 18fb230f41..1df9216c6d 100644 --- a/plug-ins/libgck/gck/gckcolor.c +++ b/plug-ins/libgck/gck/gckcolor.c @@ -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); -}