OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #define _USE_MATH_DEFINES | 5 #define _USE_MATH_DEFINES |
| 6 |
| 7 #include <stddef.h> |
| 8 #include <stdint.h> |
| 9 |
6 #include <algorithm> | 10 #include <algorithm> |
7 #include <cmath> | 11 #include <cmath> |
8 #include <limits> | 12 #include <limits> |
9 | 13 |
10 #include "skia/ext/image_operations.h" | 14 #include "skia/ext/image_operations.h" |
11 | 15 |
12 // TODO(pkasting): skia/ext should not depend on base/! | 16 // TODO(pkasting): skia/ext should not depend on base/! |
13 #include "base/containers/stack_container.h" | 17 #include "base/containers/stack_container.h" |
14 #include "base/logging.h" | 18 #include "base/logging.h" |
| 19 #include "base/macros.h" |
15 #include "base/metrics/histogram.h" | 20 #include "base/metrics/histogram.h" |
16 #include "base/time/time.h" | 21 #include "base/time/time.h" |
17 #include "base/trace_event/trace_event.h" | 22 #include "base/trace_event/trace_event.h" |
18 #include "build/build_config.h" | 23 #include "build/build_config.h" |
19 #include "skia/ext/convolver.h" | 24 #include "skia/ext/convolver.h" |
20 #include "third_party/skia/include/core/SkColorPriv.h" | 25 #include "third_party/skia/include/core/SkColorPriv.h" |
21 #include "third_party/skia/include/core/SkRect.h" | 26 #include "third_party/skia/include/core/SkRect.h" |
22 | 27 |
23 namespace skia { | 28 namespace skia { |
24 | 29 |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 float clamped_scale = std::min(1.0f, scale); | 220 float clamped_scale = std::min(1.0f, scale); |
216 | 221 |
217 // This is how many source pixels from the center we need to count | 222 // This is how many source pixels from the center we need to count |
218 // to support the filtering function. | 223 // to support the filtering function. |
219 float src_support = GetFilterSupport(clamped_scale) / clamped_scale; | 224 float src_support = GetFilterSupport(clamped_scale) / clamped_scale; |
220 | 225 |
221 // Speed up the divisions below by turning them into multiplies. | 226 // Speed up the divisions below by turning them into multiplies. |
222 float inv_scale = 1.0f / scale; | 227 float inv_scale = 1.0f / scale; |
223 | 228 |
224 base::StackVector<float, 64> filter_values; | 229 base::StackVector<float, 64> filter_values; |
225 base::StackVector<int16, 64> fixed_filter_values; | 230 base::StackVector<int16_t, 64> fixed_filter_values; |
226 | 231 |
227 // Loop over all pixels in the output range. We will generate one set of | 232 // Loop over all pixels in the output range. We will generate one set of |
228 // filter values for each one. Those values will tell us how to blend the | 233 // filter values for each one. Those values will tell us how to blend the |
229 // source pixels to compute the destination pixel. | 234 // source pixels to compute the destination pixel. |
230 for (int dest_subset_i = dest_subset_lo; dest_subset_i < dest_subset_hi; | 235 for (int dest_subset_i = dest_subset_lo; dest_subset_i < dest_subset_hi; |
231 dest_subset_i++) { | 236 dest_subset_i++) { |
232 // Reset the arrays. We don't declare them inside so they can re-use the | 237 // Reset the arrays. We don't declare them inside so they can re-use the |
233 // same malloc-ed buffer. | 238 // same malloc-ed buffer. |
234 filter_values->clear(); | 239 filter_values->clear(); |
235 fixed_filter_values->clear(); | 240 fixed_filter_values->clear(); |
(...skipping 30 matching lines...) Expand all Loading... |
266 // Compute the filter value at that location. | 271 // Compute the filter value at that location. |
267 float filter_value = ComputeFilter(dest_filter_dist); | 272 float filter_value = ComputeFilter(dest_filter_dist); |
268 filter_values->push_back(filter_value); | 273 filter_values->push_back(filter_value); |
269 | 274 |
270 filter_sum += filter_value; | 275 filter_sum += filter_value; |
271 } | 276 } |
272 DCHECK(!filter_values->empty()) << "We should always get a filter!"; | 277 DCHECK(!filter_values->empty()) << "We should always get a filter!"; |
273 | 278 |
274 // The filter must be normalized so that we don't affect the brightness of | 279 // The filter must be normalized so that we don't affect the brightness of |
275 // the image. Convert to normalized fixed point. | 280 // the image. Convert to normalized fixed point. |
276 int16 fixed_sum = 0; | 281 int16_t fixed_sum = 0; |
277 for (size_t i = 0; i < filter_values->size(); i++) { | 282 for (size_t i = 0; i < filter_values->size(); i++) { |
278 int16 cur_fixed = output->FloatToFixed(filter_values[i] / filter_sum); | 283 int16_t cur_fixed = output->FloatToFixed(filter_values[i] / filter_sum); |
279 fixed_sum += cur_fixed; | 284 fixed_sum += cur_fixed; |
280 fixed_filter_values->push_back(cur_fixed); | 285 fixed_filter_values->push_back(cur_fixed); |
281 } | 286 } |
282 | 287 |
283 // The conversion to fixed point will leave some rounding errors, which | 288 // The conversion to fixed point will leave some rounding errors, which |
284 // we add back in to avoid affecting the brightness of the image. We | 289 // we add back in to avoid affecting the brightness of the image. We |
285 // arbitrarily add this to the center of the filter array (this won't always | 290 // arbitrarily add this to the center of the filter array (this won't always |
286 // be the center of the filter function since it could get clipped on the | 291 // be the center of the filter function since it could get clipped on the |
287 // edges, but it doesn't matter enough to worry about that case). | 292 // edges, but it doesn't matter enough to worry about that case). |
288 int16 leftovers = output->FloatToFixed(1.0f) - fixed_sum; | 293 int16_t leftovers = output->FloatToFixed(1.0f) - fixed_sum; |
289 fixed_filter_values[fixed_filter_values->size() / 2] += leftovers; | 294 fixed_filter_values[fixed_filter_values->size() / 2] += leftovers; |
290 | 295 |
291 // Now it's ready to go. | 296 // Now it's ready to go. |
292 output->AddFilter(src_begin, &fixed_filter_values[0], | 297 output->AddFilter(src_begin, &fixed_filter_values[0], |
293 static_cast<int>(fixed_filter_values->size())); | 298 static_cast<int>(fixed_filter_values->size())); |
294 } | 299 } |
295 | 300 |
296 output->PaddingForSIMD(); | 301 output->PaddingForSIMD(); |
297 } | 302 } |
298 | 303 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 SkAutoLockPixels locker(source); | 370 SkAutoLockPixels locker(source); |
366 if (!source.readyToDraw() || source.colorType() != kN32_SkColorType) | 371 if (!source.readyToDraw() || source.colorType() != kN32_SkColorType) |
367 return SkBitmap(); | 372 return SkBitmap(); |
368 | 373 |
369 ResizeFilter filter(method, source.width(), source.height(), | 374 ResizeFilter filter(method, source.width(), source.height(), |
370 dest_width, dest_height, dest_subset); | 375 dest_width, dest_height, dest_subset); |
371 | 376 |
372 // Get a source bitmap encompassing this touched area. We construct the | 377 // Get a source bitmap encompassing this touched area. We construct the |
373 // offsets and row strides such that it looks like a new bitmap, while | 378 // offsets and row strides such that it looks like a new bitmap, while |
374 // referring to the old data. | 379 // referring to the old data. |
375 const uint8* source_subset = | 380 const uint8_t* source_subset = |
376 reinterpret_cast<const uint8*>(source.getPixels()); | 381 reinterpret_cast<const uint8_t*>(source.getPixels()); |
377 | 382 |
378 // Convolve into the result. | 383 // Convolve into the result. |
379 SkBitmap result; | 384 SkBitmap result; |
380 result.setInfo(SkImageInfo::MakeN32(dest_subset.width(), dest_subset.height(),
source.alphaType())); | 385 result.setInfo(SkImageInfo::MakeN32(dest_subset.width(), dest_subset.height(),
source.alphaType())); |
381 result.allocPixels(allocator, NULL); | 386 result.allocPixels(allocator, NULL); |
382 if (!result.readyToDraw()) | 387 if (!result.readyToDraw()) |
383 return SkBitmap(); | 388 return SkBitmap(); |
384 | 389 |
385 BGRAConvolve2D(source_subset, static_cast<int>(source.rowBytes()), | 390 BGRAConvolve2D(source_subset, static_cast<int>(source.rowBytes()), |
386 !source.isOpaque(), filter.x_filter(), filter.y_filter(), | 391 !source.isOpaque(), filter.x_filter(), filter.y_filter(), |
(...skipping 11 matching lines...) Expand all Loading... |
398 SkBitmap ImageOperations::Resize(const SkBitmap& source, | 403 SkBitmap ImageOperations::Resize(const SkBitmap& source, |
399 ResizeMethod method, | 404 ResizeMethod method, |
400 int dest_width, int dest_height, | 405 int dest_width, int dest_height, |
401 SkBitmap::Allocator* allocator) { | 406 SkBitmap::Allocator* allocator) { |
402 SkIRect dest_subset = { 0, 0, dest_width, dest_height }; | 407 SkIRect dest_subset = { 0, 0, dest_width, dest_height }; |
403 return Resize(source, method, dest_width, dest_height, dest_subset, | 408 return Resize(source, method, dest_width, dest_height, dest_subset, |
404 allocator); | 409 allocator); |
405 } | 410 } |
406 | 411 |
407 } // namespace skia | 412 } // namespace skia |
OLD | NEW |