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

Side by Side Diff: skia/ext/convolver.cc

Issue 5575010: Integration of most changes from the GoogleTV project around the convolver/sc... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Remove some lint errors Created 9 years, 11 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <algorithm> 5 #include <algorithm>
6 6
7 #include "skia/ext/convolver.h" 7 #include "skia/ext/convolver.h"
8 #include "third_party/skia/include/core/SkTypes.h" 8 #include "third_party/skia/include/core/SkTypes.h"
9 9
10 namespace skia { 10 namespace skia {
11 11
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 ConvolutionFilter1D::ConvolutionFilter1D() 226 ConvolutionFilter1D::ConvolutionFilter1D()
227 : max_filter_(0) { 227 : max_filter_(0) {
228 } 228 }
229 229
230 ConvolutionFilter1D::~ConvolutionFilter1D() { 230 ConvolutionFilter1D::~ConvolutionFilter1D() {
231 } 231 }
232 232
233 void ConvolutionFilter1D::AddFilter(int filter_offset, 233 void ConvolutionFilter1D::AddFilter(int filter_offset,
234 const float* filter_values, 234 const float* filter_values,
235 int filter_length) { 235 int filter_length) {
236 FilterInstance instance; 236 SkASSERT(filter_length > 0);
237 instance.data_location = static_cast<int>(filter_values_.size());
238 instance.offset = filter_offset;
239 instance.length = filter_length;
240 filters_.push_back(instance);
241 237
242 SkASSERT(filter_length > 0); 238 std::vector<Fixed> fixed_values;
243 for (int i = 0; i < filter_length; i++) 239 fixed_values.reserve(filter_length);
244 filter_values_.push_back(FloatToFixed(filter_values[i]));
245 240
246 max_filter_ = std::max(max_filter_, filter_length); 241 for (int i = 0; i < filter_length; ++i)
242 fixed_values.push_back(FloatToFixed(filter_values[i]));
243
244 AddFilter(filter_offset, &fixed_values[0], filter_length);
247 } 245 }
248 246
249 void ConvolutionFilter1D::AddFilter(int filter_offset, 247 void ConvolutionFilter1D::AddFilter(int filter_offset,
250 const Fixed* filter_values, 248 const Fixed* filter_values,
251 int filter_length) { 249 int filter_length) {
250 // It is common for leading/trailing filter values to be zeros. In such
251 // cases it is beneficial to only store the central factors.
252 // For a scaling to 1/4th in each dimension using a Lanczos-2 filter on
253 // a 1080p image this optimization gives a ~10% speed improvement.
254 int first_non_zero = 0;
255 while (first_non_zero < filter_length && filter_values[first_non_zero] == 0) {
brettw 2011/01/20 21:48:06 Be consistent about usage for {} for single-line c
evannier 2011/01/24 21:09:58 Done.
256 first_non_zero++;
257 }
258
259 if (first_non_zero < filter_length) {
260 // Here we have at least one non-zero factor.
261 int last_non_zero = filter_length - 1;
262 while (last_non_zero >= 0 && filter_values[last_non_zero] == 0) {
263 last_non_zero--;
264 }
265
266 filter_offset += first_non_zero;
267 filter_length = last_non_zero + 1 - first_non_zero;
268 SkASSERT(filter_length > 0);
269
270 for (int i = first_non_zero; i <= last_non_zero; i++)
271 filter_values_.push_back(filter_values[i]);
272 } else {
273 // Here all the factors were zeroes.
274 filter_length = 0;
275 }
276
252 FilterInstance instance; 277 FilterInstance instance;
253 instance.data_location = static_cast<int>(filter_values_.size()); 278
279 // We pushed filter_length elements onto filter_values_
280 instance.data_location = (static_cast<int>(filter_values_.size()) -
281 filter_length);
254 instance.offset = filter_offset; 282 instance.offset = filter_offset;
255 instance.length = filter_length; 283 instance.length = filter_length;
256 filters_.push_back(instance); 284 filters_.push_back(instance);
257 285
258 SkASSERT(filter_length > 0);
259 for (int i = 0; i < filter_length; i++)
260 filter_values_.push_back(filter_values[i]);
261
262 max_filter_ = std::max(max_filter_, filter_length); 286 max_filter_ = std::max(max_filter_, filter_length);
263 } 287 }
264 288
265 // BGRAConvolve2D ------------------------------------------------------------- 289 // BGRAConvolve2D -------------------------------------------------------------
266 290
267 void BGRAConvolve2D(const unsigned char* source_data, 291 void BGRAConvolve2D(const unsigned char* source_data,
268 int source_byte_row_stride, 292 int source_byte_row_stride,
269 bool source_has_alpha, 293 bool source_has_alpha,
270 const ConvolutionFilter1D& filter_x, 294 const ConvolutionFilter1D& filter_x,
271 const ConvolutionFilter1D& filter_y, 295 const ConvolutionFilter1D& filter_y,
296 int output_byte_row_stride,
272 unsigned char* output) { 297 unsigned char* output) {
273 int max_y_filter_size = filter_y.max_filter(); 298 int max_y_filter_size = filter_y.max_filter();
274 299
275 // The next row in the input that we will generate a horizontally 300 // The next row in the input that we will generate a horizontally
276 // convolved row for. If the filter doesn't start at the beginning of the 301 // convolved row for. If the filter doesn't start at the beginning of the
277 // image (this is the case when we are only resizing a subset), then we 302 // image (this is the case when we are only resizing a subset), then we
278 // don't want to generate any output rows before that. Compute the starting 303 // don't want to generate any output rows before that. Compute the starting
279 // row for convolution as the first pixel for the first vertical filter. 304 // row for convolution as the first pixel for the first vertical filter.
280 int filter_offset, filter_length; 305 int filter_offset, filter_length;
281 const ConvolutionFilter1D::Fixed* filter_values = 306 const ConvolutionFilter1D::Fixed* filter_values =
282 filter_y.FilterForValue(0, &filter_offset, &filter_length); 307 filter_y.FilterForValue(0, &filter_offset, &filter_length);
283 int next_x_row = filter_offset; 308 int next_x_row = filter_offset;
284 309
285 // We loop over each row in the input doing a horizontal convolution. This 310 // We loop over each row in the input doing a horizontal convolution. This
286 // will result in a horizontally convolved image. We write the results into 311 // will result in a horizontally convolved image. We write the results into
287 // a circular buffer of convolved rows and do vertical convolution as rows 312 // a circular buffer of convolved rows and do vertical convolution as rows
288 // are available. This prevents us from having to store the entire 313 // are available. This prevents us from having to store the entire
289 // intermediate image and helps cache coherency. 314 // intermediate image and helps cache coherency.
290 CircularRowBuffer row_buffer(filter_x.num_values(), max_y_filter_size, 315 CircularRowBuffer row_buffer(filter_x.num_values(), max_y_filter_size,
291 filter_offset); 316 filter_offset);
292 317
293 // Loop over every possible output row, processing just enough horizontal 318 // Loop over every possible output row, processing just enough horizontal
294 // convolutions to run each subsequent vertical convolution. 319 // convolutions to run each subsequent vertical convolution.
295 int output_row_byte_width = filter_x.num_values() * 4; 320 SkASSERT(output_byte_row_stride >= filter_x.num_values() * 4);
296 int num_output_rows = filter_y.num_values(); 321 int num_output_rows = filter_y.num_values();
297 for (int out_y = 0; out_y < num_output_rows; out_y++) { 322 for (int out_y = 0; out_y < num_output_rows; out_y++) {
298 filter_values = filter_y.FilterForValue(out_y, 323 filter_values = filter_y.FilterForValue(out_y,
299 &filter_offset, &filter_length); 324 &filter_offset, &filter_length);
300 325
301 // Generate output rows until we have enough to run the current filter. 326 // Generate output rows until we have enough to run the current filter.
302 while (next_x_row < filter_offset + filter_length) { 327 while (next_x_row < filter_offset + filter_length) {
303 if (source_has_alpha) { 328 if (source_has_alpha) {
304 ConvolveHorizontally<true>( 329 ConvolveHorizontally<true>(
305 &source_data[next_x_row * source_byte_row_stride], 330 &source_data[next_x_row * source_byte_row_stride],
306 filter_x, row_buffer.AdvanceRow()); 331 filter_x, row_buffer.AdvanceRow());
307 } else { 332 } else {
308 ConvolveHorizontally<false>( 333 ConvolveHorizontally<false>(
309 &source_data[next_x_row * source_byte_row_stride], 334 &source_data[next_x_row * source_byte_row_stride],
310 filter_x, row_buffer.AdvanceRow()); 335 filter_x, row_buffer.AdvanceRow());
311 } 336 }
312 next_x_row++; 337 next_x_row++;
313 } 338 }
314 339
315 // Compute where in the output image this row of final data will go. 340 // Compute where in the output image this row of final data will go.
316 unsigned char* cur_output_row = &output[out_y * output_row_byte_width]; 341 unsigned char* cur_output_row = &output[out_y * output_byte_row_stride];
317 342
318 // Get the list of rows that the circular buffer has, in order. 343 // Get the list of rows that the circular buffer has, in order.
319 int first_row_in_circular_buffer; 344 int first_row_in_circular_buffer;
320 unsigned char* const* rows_to_convolve = 345 unsigned char* const* rows_to_convolve =
321 row_buffer.GetRowAddresses(&first_row_in_circular_buffer); 346 row_buffer.GetRowAddresses(&first_row_in_circular_buffer);
322 347
323 // Now compute the start of the subset of those rows that the filter 348 // Now compute the start of the subset of those rows that the filter
324 // needs. 349 // needs.
325 unsigned char* const* first_row_for_filter = 350 unsigned char* const* first_row_for_filter =
326 &rows_to_convolve[filter_offset - first_row_in_circular_buffer]; 351 &rows_to_convolve[filter_offset - first_row_in_circular_buffer];
327 352
328 if (source_has_alpha) { 353 if (source_has_alpha) {
329 ConvolveVertically<true>(filter_values, filter_length, 354 ConvolveVertically<true>(filter_values, filter_length,
330 first_row_for_filter, 355 first_row_for_filter,
331 filter_x.num_values(), cur_output_row); 356 filter_x.num_values(), cur_output_row);
332 } else { 357 } else {
333 ConvolveVertically<false>(filter_values, filter_length, 358 ConvolveVertically<false>(filter_values, filter_length,
334 first_row_for_filter, 359 first_row_for_filter,
335 filter_x.num_values(), cur_output_row); 360 filter_x.num_values(), cur_output_row);
336 } 361 }
337 } 362 }
338 } 363 }
339 364
340 } // namespace skia 365 } // namespace skia
341
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698