diff --git a/docs/changes.txt b/docs/changes.txt index dc1d948b26..5917d9c43d 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -93,6 +93,7 @@ All (GUI): - Fix wxTextEntry::SetHint() with wxTE_PASSWORD in generic implementation. - Many fixes and improvements in Direct2D, Cairo, and GDI+ graphics renderers. - Fix and unify clipping region support for MSW and GTK+. +- Fix rescaling of wxImage wxGTK: diff --git a/src/common/image.cpp b/src/common/image.cpp index f28abb2e66..b0ca1d8fd0 100644 --- a/src/common/image.cpp +++ b/src/common/image.cpp @@ -576,20 +576,33 @@ inline int BoxBetween(int value, int low, int high) void ResampleBoxPrecalc(wxVector& boxes, int oldDim) { const int newDim = boxes.size(); - const double scale_factor_1 = double(oldDim) / newDim; - const int scale_factor_2 = (int)(scale_factor_1 / 2); - - for ( int dst = 0; dst < newDim; ++dst ) + wxASSERT( oldDim > 0 && newDim > 0 ); + if ( newDim > 1 ) { - // Source pixel in the Y direction - const int src_p = int(dst * scale_factor_1); + // We want to map pixels in the range [0..newDim-1] + // to the range [0..oldDim-1] + const double scale_factor_1 = double(oldDim-1) / (newDim-1); + const int scale_factor_2 = (int)(scale_factor_1 / 2); - BoxPrecalc& precalc = boxes[dst]; - precalc.boxStart = BoxBetween(int(src_p - scale_factor_1/2.0 + 1), - 0, oldDim - 1); - precalc.boxEnd = BoxBetween(wxMax(precalc.boxStart + 1, - int(src_p + scale_factor_2)), - 0, oldDim - 1); + for ( int dst = 0; dst < newDim; ++dst ) + { + // Source pixel in the Y direction + const int src_p = int(dst * scale_factor_1); + + BoxPrecalc& precalc = boxes[dst]; + precalc.boxStart = BoxBetween(int(src_p - scale_factor_1/2.0 + 1), + 0, oldDim - 1); + precalc.boxEnd = BoxBetween(wxMax(precalc.boxStart + 1, + int(src_p + scale_factor_2)), + 0, oldDim - 1); + } + } + else + { + // Let's take entire source image. + BoxPrecalc& precalc = boxes[0]; + precalc.boxStart = 0; + precalc.boxEnd = oldDim - 1; } } @@ -680,33 +693,50 @@ struct BilinearPrecalc double dd1; }; +inline void DoCalc(BilinearPrecalc& precalc, double srcpix, int srcpixmax) +{ + int srcpix1 = int(srcpix); + int srcpix2 = srcpix1 == srcpixmax ? srcpix1 : srcpix1 + 1; + + precalc.dd = srcpix - (int)srcpix; + precalc.dd1 = 1.0 - precalc.dd; + precalc.offset1 = srcpix1 < 0.0 + ? 0 + : srcpix1 > srcpixmax + ? srcpixmax + : (int)srcpix1; + precalc.offset2 = srcpix2 < 0.0 + ? 0 + : srcpix2 > srcpixmax + ? srcpixmax + : (int)srcpix2; +} + void ResampleBilinearPrecalc(wxVector& precalcs, int oldDim) { const int newDim = precalcs.size(); - const double scale_factor = double(oldDim) / newDim; + wxASSERT( oldDim > 0 && newDim > 0 ); const int srcpixmax = oldDim - 1; - - for ( int dsty = 0; dsty < newDim; dsty++ ) + if ( newDim > 1 ) { - // We need to calculate the source pixel to interpolate from - Y-axis - double srcpix = double(dsty) * scale_factor; - double srcpix1 = int(srcpix); - double srcpix2 = srcpix1 == srcpixmax ? srcpix1 : srcpix1 + 1.0; + // We want to map pixels in the range [0..newDim-1] + // to the range [0..oldDim-1] + const double scale_factor = double(oldDim-1) / (newDim-1); - BilinearPrecalc& precalc = precalcs[dsty]; + for ( int dsty = 0; dsty < newDim; dsty++ ) + { + // We need to calculate the source pixel to interpolate from - Y-axis + double srcpix = (double)dsty * scale_factor; - precalc.dd = srcpix - (int)srcpix; - precalc.dd1 = 1.0 - precalc.dd; - precalc.offset1 = srcpix1 < 0.0 - ? 0 - : srcpix1 > srcpixmax - ? srcpixmax - : (int)srcpix1; - precalc.offset2 = srcpix2 < 0.0 - ? 0 - : srcpix2 > srcpixmax - ? srcpixmax - : (int)srcpix2; + DoCalc(precalcs[dsty], srcpix, srcpixmax); + } + } + else + { + // Let's take the pixel from the center of the source image. + double srcpix = (double)srcpixmax / 2.0; + + DoCalc(precalcs[0], srcpix, srcpixmax); } } @@ -816,28 +846,48 @@ struct BicubicPrecalc int offset[4]; }; +inline void DoCalc(BicubicPrecalc& precalc, double srcpixd, int oldDim) +{ + const double dd = srcpixd - static_cast(srcpixd); + + for ( int k = -1; k <= 2; k++ ) + { + precalc.offset[k + 1] = srcpixd + k < 0.0 + ? 0 + : srcpixd + k >= oldDim + ? oldDim - 1 + : static_cast(srcpixd + k); + + precalc.weight[k + 1] = spline_weight(k - dd); + } +} + void ResampleBicubicPrecalc(wxVector &aWeight, int oldDim) { const int newDim = aWeight.size(); - for ( int dstd = 0; dstd < newDim; dstd++ ) + wxASSERT( oldDim > 0 && newDim > 0 ); + + if ( newDim > 1 ) { - // We need to calculate the source pixel to interpolate from - Y-axis - const double srcpixd = static_cast(dstd * oldDim) / newDim; - const double dd = srcpixd - static_cast(srcpixd); + // We want to map pixels in the range [0..newDim-1] + // to the range [0..oldDim-1] + const double scale_factor = static_cast(oldDim-1) / (newDim-1); - BicubicPrecalc &precalc = aWeight[dstd]; - - for ( int k = -1; k <= 2; k++ ) + for ( int dstd = 0; dstd < newDim; dstd++ ) { - precalc.offset[k + 1] = srcpixd + k < 0.0 - ? 0 - : srcpixd + k >= oldDim - ? oldDim - 1 - : static_cast(srcpixd + k); + // We need to calculate the source pixel to interpolate from - Y-axis + const double srcpixd = static_cast(dstd) * scale_factor; - precalc.weight[k + 1] = spline_weight(k - dd); + DoCalc(aWeight[dstd], srcpixd, oldDim); } } + else + { + // Let's take the pixel from the center of the source image. + const double srcpixd = static_cast(oldDim - 1) / 2.0; + + DoCalc(aWeight[0], srcpixd, oldDim); + } } } // anonymous namespace diff --git a/tests/image/horse_bicubic_100x100.png b/tests/image/horse_bicubic_100x100.png index 1ac57b0585..9c8d9bc7f6 100644 Binary files a/tests/image/horse_bicubic_100x100.png and b/tests/image/horse_bicubic_100x100.png differ diff --git a/tests/image/horse_bicubic_150x150.png b/tests/image/horse_bicubic_150x150.png index 7e4c81de25..be90d9bdd3 100644 Binary files a/tests/image/horse_bicubic_150x150.png and b/tests/image/horse_bicubic_150x150.png differ diff --git a/tests/image/horse_bicubic_300x300.png b/tests/image/horse_bicubic_300x300.png index 1bcce1ca8a..4dd8310f80 100644 Binary files a/tests/image/horse_bicubic_300x300.png and b/tests/image/horse_bicubic_300x300.png differ diff --git a/tests/image/horse_bicubic_50x50.png b/tests/image/horse_bicubic_50x50.png index 1ad94a2609..dcf547dc20 100644 Binary files a/tests/image/horse_bicubic_50x50.png and b/tests/image/horse_bicubic_50x50.png differ diff --git a/tests/image/horse_bilinear_100x100.png b/tests/image/horse_bilinear_100x100.png index 32a4d57f75..7f489e8307 100644 Binary files a/tests/image/horse_bilinear_100x100.png and b/tests/image/horse_bilinear_100x100.png differ diff --git a/tests/image/horse_bilinear_150x150.png b/tests/image/horse_bilinear_150x150.png index 5a669dddc0..9787727454 100644 Binary files a/tests/image/horse_bilinear_150x150.png and b/tests/image/horse_bilinear_150x150.png differ diff --git a/tests/image/horse_bilinear_300x300.png b/tests/image/horse_bilinear_300x300.png index ce7c824d42..63f4446389 100644 Binary files a/tests/image/horse_bilinear_300x300.png and b/tests/image/horse_bilinear_300x300.png differ diff --git a/tests/image/horse_bilinear_50x50.png b/tests/image/horse_bilinear_50x50.png index defc189b8e..8acaa3b1d6 100644 Binary files a/tests/image/horse_bilinear_50x50.png and b/tests/image/horse_bilinear_50x50.png differ diff --git a/tests/image/horse_box_average_100x100.png b/tests/image/horse_box_average_100x100.png index 7e4b0a069d..63180cd979 100644 Binary files a/tests/image/horse_box_average_100x100.png and b/tests/image/horse_box_average_100x100.png differ diff --git a/tests/image/horse_box_average_150x150.png b/tests/image/horse_box_average_150x150.png index bd42d0ca70..486cdeeee1 100644 Binary files a/tests/image/horse_box_average_150x150.png and b/tests/image/horse_box_average_150x150.png differ diff --git a/tests/image/horse_box_average_300x300.png b/tests/image/horse_box_average_300x300.png index bb4bb6bbf6..a002e27287 100644 Binary files a/tests/image/horse_box_average_300x300.png and b/tests/image/horse_box_average_300x300.png differ diff --git a/tests/image/horse_box_average_50x50.png b/tests/image/horse_box_average_50x50.png index 5d06ced576..432e983e63 100644 Binary files a/tests/image/horse_box_average_50x50.png and b/tests/image/horse_box_average_50x50.png differ