Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(121)

Unified Diff: skia/ext/convolver.cc

Issue 13947013: Complete (but inefficient) implementation of the image retargetting method. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: skia/ext/convolver.cc
diff --git a/skia/ext/convolver.cc b/skia/ext/convolver.cc
index ee9d056fa436336338d92f8a3620d285c1d634cb..ab285dc4a39cfab3a639248d11622978f3f254a9 100644
--- a/skia/ext/convolver.cc
+++ b/skia/ext/convolver.cc
@@ -5,6 +5,7 @@
#include <algorithm>
#include "skia/ext/convolver.h"
+#include "third_party/skia/include/core/SkSize.h"
#include "third_party/skia/include/core/SkTypes.h"
#if defined(SIMD_SSE2)
@@ -682,6 +683,7 @@ void ConvolutionFilter1D::AddFilter(int filter_offset,
// cases it is beneficial to only store the central factors.
// For a scaling to 1/4th in each dimension using a Lanczos-2 filter on
// a 1080p image this optimization gives a ~10% speed improvement.
+ int filter_size = filter_length;
int first_non_zero = 0;
while (first_non_zero < filter_length && filter_values[first_non_zero] == 0)
first_non_zero++;
@@ -710,6 +712,7 @@ void ConvolutionFilter1D::AddFilter(int filter_offset,
filter_length);
instance.offset = filter_offset;
instance.length = filter_length;
+ instance.filter_size = filter_size;
filters_.push_back(instance);
max_filter_ = std::max(max_filter_, filter_length);
@@ -857,4 +860,114 @@ void BGRAConvolve2D(const unsigned char* source_data,
}
}
+void SingleChannelConvolve1D_X(const unsigned char* source_data,
+ int source_byte_row_stride,
+ int input_channel_index,
+ int input_channel_count,
+ const ConvolutionFilter1D& filter,
+ const SkISize& image_size,
+ unsigned char* output,
+ int output_byte_row_stride,
+ int output_channel_index,
+ int output_channel_count,
+ bool absolute_values) {
+ int filter_offset, filter_length, filter_size;
+ // Very much unlike BGRAConvolve2D, here we expect to have the same filter
+ // for all pixels.
+ const ConvolutionFilter1D::Fixed* filter_values =
+ filter.GetSingleFilter(&filter_size, &filter_offset, &filter_length);
+
+ if (filter_values == NULL)
+ return;
+
+ int centrepoint = filter_length / 2;
+ if (filter_size - filter_offset != 2 * filter_offset) {
+ // This means the original filter was not symmetrical AND
+ // got clipped from one side more than from the other.
+ centrepoint = filter_size / 2 - filter_offset;
+ }
+
+ const unsigned char* source_data_row = source_data;
+ unsigned char* output_row = output;
+
+ for (int r = 0; r < image_size.height(); ++r) {
+ unsigned char* target_byte = output_row + output_channel_index;
+ for (int c = 0; c < image_size.width(); ++c) {
+ int accval = 0;
+ for (int i = 0; i < filter_length; ++i) {
+ ConvolutionFilter1D::Fixed cur_filter = filter_values[i];
+ int pixel_index = c + i - centrepoint;
Stephen White 2013/04/10 15:20:31 Perf: could probably hoist this out of the loop.
motek. 2013/04/11 16:18:38 I have reworked that from the perf angle.
+ // Handling of edges is always wrap-around. Clip to 0 / width.
Stephen White 2013/04/10 15:20:31 Seems strange to wrap-around instead of clamp, but
motek. 2013/04/11 16:18:38 Padding would be most reasonable for this applicat
+ pixel_index = (pixel_index + image_size.width()) % image_size.width();
Stephen White 2013/04/10 15:20:31 Perf: could compute the margins in separate inner
motek. 2013/04/11 16:18:38 Done.
+ const unsigned char src_value = source_data_row[
+ pixel_index * input_channel_count + input_channel_index];
+ accval += cur_filter * src_value;
+ }
+ // Bring this value back in range. All of the filter scaling factors
+ // are in fixed point with kShiftBits bits of fractional part.
+ accval >>= ConvolutionFilter1D::kShiftBits;
+ if (absolute_values)
+ accval = std::abs(accval);
+ *target_byte = ClampTo8(accval);
+ target_byte += output_channel_count;
+ }
+
+ source_data_row += source_byte_row_stride;
+ output_row += output_byte_row_stride;
+ }
+}
+
+void SingleChannelConvolve1D_Y(const unsigned char* source_data,
+ int source_byte_row_stride,
+ int input_channel_index,
+ int input_channel_count,
+ const ConvolutionFilter1D& filter,
+ const SkISize& image_size,
+ unsigned char* output,
+ int output_byte_row_stride,
+ int output_channel_index,
+ int output_channel_count,
+ bool absolute_values) {
+ int filter_offset, filter_length, filter_size;
+ // Very much unlike BGRAConvolve2D, here we expect to have the same filter
+ // for all pixels.
+ const ConvolutionFilter1D::Fixed* filter_values =
+ filter.GetSingleFilter(&filter_size, &filter_offset, &filter_length);
+
+ if (filter_values == NULL)
+ return;
+
+ int centrepoint = filter_length / 2;
+ if (filter_size - filter_offset != 2 * filter_offset) {
+ // This means the original filter was not symmetrical AND
+ // got clipped from one side more than from the other.
+ centrepoint = filter_size / 2 - filter_offset;
+ }
+
+ for (int c = 0; c < image_size.width(); ++c) {
+ for (int r = 0; r < image_size.height(); ++r) {
+ unsigned char* target_byte = output +
+ r * output_byte_row_stride +
+ c * output_channel_count +
+ output_channel_index;
+ int accval = 0;
+ for (int i = 0; i < filter_length; ++i) {
+ ConvolutionFilter1D::Fixed cur_filter = filter_values[i];
+ int pixel_index = r + i - centrepoint;
+ pixel_index = (pixel_index + image_size.height()) % image_size.height();
+
+ const unsigned char src_value = source_data[
+ pixel_index * source_byte_row_stride +
+ c * input_channel_count +
+ input_channel_index];
+ accval += cur_filter * src_value;
+ }
+ accval >>= ConvolutionFilter1D::kShiftBits;
+ if (absolute_values)
+ accval = std::abs(accval);
+ *target_byte = ClampTo8(accval);
+ }
+ }
+}
+
} // namespace skia

Powered by Google App Engine
This is Rietveld 408576698