From b4b6e9c6f7dca6891f586984f1b26f81c61174ba Mon Sep 17 00:00:00 2001 From: kiirala Date: Sat, 28 Mar 2009 17:20:57 +0000 Subject: [PATCH] Fixed redraw-area dependent result when using filters with low quality --- src/display/nr-filter-slot.cpp | 4 ++-- src/display/pixblock-scaler.cpp | 38 ++++++++++++++++++++++----------- src/display/pixblock-scaler.h | 3 ++- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/display/nr-filter-slot.cpp b/src/display/nr-filter-slot.cpp index dc4de5bd3..7631d9eb6 100644 --- a/src/display/nr-filter-slot.cpp +++ b/src/display/nr-filter-slot.cpp @@ -167,7 +167,7 @@ void FilterSlot::get_final(int slot_nr, NRPixBlock *result) { NR::transform_nearest(result, final_usr, trans); } } else if (fabs(trans[0] - 1) > 1e-6 || fabs(trans[3] - 1) > 1e-6) { - NR::scale_bicubic(result, final_usr); + NR::scale_bicubic(result, final_usr, trans); } else { nr_blit_pixblock_pixblock(result, final_usr); } @@ -255,7 +255,7 @@ void FilterSlot::set(int slot_nr, NRPixBlock *pb) g_warning("Memory allocation failed in Inkscape::Filters::FilterSlot::set (scaling)"); return; } - NR::scale_bicubic(trans_pb, pb); + NR::scale_bicubic(trans_pb, pb, trans); nr_pixblock_release(pb); delete pb; pb = trans_pb; diff --git a/src/display/pixblock-scaler.cpp b/src/display/pixblock-scaler.cpp index 84274d0ff..1f2b1db3f 100644 --- a/src/display/pixblock-scaler.cpp +++ b/src/display/pixblock-scaler.cpp @@ -17,10 +17,12 @@ #include "round.h" using Inkscape::round; #endif +using std::floor; #include "display/nr-filter-utils.h" #include "libnr/nr-pixblock.h" #include "libnr/nr-blit.h" +#include <2geom/forward.h> namespace NR { @@ -67,7 +69,8 @@ inline static void _check_index(NRPixBlock const * const pb, int const location, } } -static void scale_bicubic_rgba(NRPixBlock *to, NRPixBlock *from) +static void scale_bicubic_rgba(NRPixBlock *to, NRPixBlock *from, + Geom::Matrix const &trans) { if (NR_PIXBLOCK_BPP(from) != 4 || NR_PIXBLOCK_BPP(to) != 4) { g_warning("A non-32-bpp image passed to scale_bicubic_rgba: scaling aborted."); @@ -91,12 +94,16 @@ static void scale_bicubic_rgba(NRPixBlock *to, NRPixBlock *from) // from_step: when advancing one pixel in destination image, // how much we should advance in source image - double from_stepx = (double)from_width / (double)to_width; - double from_stepy = (double)from_height / (double)to_height; + double from_stepx = 1.0 / trans[0]; + double from_stepy = 1.0 / trans[3]; + double from_diffx = from_stepx * (-trans[4]); + double from_diffy = from_stepy * (-trans[5]); + from_diffx = (to->area.x0 * from_stepx + from_diffx) - from->area.x0; + from_diffy = (to->area.y0 * from_stepy + from_diffy) - from->area.y0; // Loop through every pixel of destination image, a line at a time for (int to_y = 0 ; to_y < to_height ; to_y++) { - double from_y = to_y * from_stepy + from_stepy / 2; + double from_y = (to_y + 0.5) * from_stepy + from_diffy; // Pre-calculate beginning of the four horizontal lines, from // which we should read int from_line[4]; @@ -116,7 +123,7 @@ static void scale_bicubic_rgba(NRPixBlock *to, NRPixBlock *from) // For every pixel, calculate the color of pixel with // bicubic interpolation and set the pixel value in destination image for (int to_x = 0 ; to_x < to_width ; to_x++) { - double from_x = to_x * from_stepx + from_stepx / 2; + double from_x = (to_x + 0.5) * from_stepx + from_diffx; RGBA line[4]; for (int i = 0 ; i < 4 ; i++) { int k = (int)round(from_x) + i - 2; @@ -195,7 +202,8 @@ static void scale_bicubic_rgba(NRPixBlock *to, NRPixBlock *from) } -void scale_bicubic_alpha(NRPixBlock *to, NRPixBlock *from) +void scale_bicubic_alpha(NRPixBlock *to, NRPixBlock *from, + Geom::Matrix const &trans) { if (NR_PIXBLOCK_BPP(from) != 1 || NR_PIXBLOCK_BPP(to) != 1) { g_warning("A non-8-bpp image passed to scale_bicubic_alpha: scaling aborted."); @@ -210,12 +218,16 @@ void scale_bicubic_alpha(NRPixBlock *to, NRPixBlock *from) // from_step: when advancing one pixel in destination image, // how much we should advance in source image - double from_stepx = (double)from_width / (double)to_width; - double from_stepy = (double)from_height / (double)to_height; + double from_stepx = 1.0 / trans[0]; + double from_stepy = 1.0 / trans[3]; + double from_diffx = from_stepx * (-trans[4]); + double from_diffy = from_stepy * (-trans[5]); + from_diffx = (to->area.x0 * from_stepx + from_diffx) - from->area.x0; + from_diffy = (to->area.y0 * from_stepy + from_diffy) - from->area.y0; // Loop through every pixel of destination image, a line at a time for (int to_y = 0 ; to_y < to_height ; to_y++) { - double from_y = to_y * from_stepy + from_stepy / 2; + double from_y = (to_y + 0.5) * from_stepy - from_diffy; // Pre-calculate beginning of the four horizontal lines, from // which we should read int from_line[4]; @@ -235,7 +247,7 @@ void scale_bicubic_alpha(NRPixBlock *to, NRPixBlock *from) // For every pixel, calculate the color of pixel with // bicubic interpolation and set the pixel value in destination image for (int to_x = 0 ; to_x < to_width ; to_x++) { - double from_x = to_x * from_stepx + from_stepx / 2; + double from_x = (to_x + 0.5) * from_stepx - from_diffx; double line[4]; for (int i = 0 ; i < 4 ; i++) { int k = (int)round(from_x) + i - 2; @@ -263,12 +275,12 @@ void scale_bicubic_alpha(NRPixBlock *to, NRPixBlock *from) } } -void scale_bicubic(NRPixBlock *to, NRPixBlock *from) +void scale_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &trans) { if (NR_PIXBLOCK_BPP(to) == 4 && NR_PIXBLOCK_BPP(from) == 4) { - scale_bicubic_rgba(to, from); + scale_bicubic_rgba(to, from, trans); } else if (NR_PIXBLOCK_BPP(to) == 1 && NR_PIXBLOCK_BPP(from) == 1) { - scale_bicubic_alpha(to, from); + scale_bicubic_alpha(to, from, trans); } else { g_warning("NR::scale_bicubic: unsupported bitdepths for scaling: to %d, from %d", NR_PIXBLOCK_BPP(to), NR_PIXBLOCK_BPP(from)); } diff --git a/src/display/pixblock-scaler.h b/src/display/pixblock-scaler.h index 907429257..8e9b1ec62 100644 --- a/src/display/pixblock-scaler.h +++ b/src/display/pixblock-scaler.h @@ -13,6 +13,7 @@ */ #include "libnr/nr-pixblock.h" +#include <2geom/forward.h> namespace NR { @@ -22,7 +23,7 @@ namespace NR { * Source pixblock is not modified in process. * Only works for 32-bpp images. */ -void scale_bicubic(NRPixBlock *to, NRPixBlock *from); +void scale_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &trans); } /* namespace NR */ -- 2.30.2