diff options
Diffstat (limited to 'skia/ext/image_operations.cc')
-rw-r--r-- | skia/ext/image_operations.cc | 132 |
1 files changed, 70 insertions, 62 deletions
diff --git a/skia/ext/image_operations.cc b/skia/ext/image_operations.cc index fb0bd40..5e6c3ab 100644 --- a/skia/ext/image_operations.cc +++ b/skia/ext/image_operations.cc @@ -9,11 +9,14 @@ #include "skia/ext/image_operations.h" +#include "base/gfx/rect.h" +#include "base/gfx/size.h" +#include "base/logging.h" +#include "base/stack_container.h" #include "SkBitmap.h" -#include "SkRect.h" #include "skia/ext/convolver.h" -namespace skia { +namespace gfx { namespace { @@ -59,13 +62,13 @@ float EvalLanczos(int filter_size, float x) { class ResizeFilter { public: ResizeFilter(ImageOperations::ResizeMethod method, - int src_full_width, int src_full_height, - int dest_width, int dest_height, - const SkIRect& dest_subset); + const Size& src_full_size, + const Size& dest_size, + const Rect& dest_subset); // Returns the bounds in the input bitmap of data that is used in the output. // The filter offsets are within this rectangle. - const SkIRect& src_depend() { return src_depend_; } + const Rect& src_depend() { return src_depend_; } // Returns the filled filter values. const ConvolusionFilter1D& x_filter() { return x_filter_; } @@ -84,7 +87,7 @@ class ResizeFilter { // each direction as the size of the window = 3 for Lanczos3. return 3.0f; default: - SkASSERT(false); + NOTREACHED(); return 1.0f; } } @@ -112,7 +115,7 @@ class ResizeFilter { case ImageOperations::RESIZE_LANCZOS3: return EvalLanczos(3, pos); default: - SkASSERT(false); + NOTREACHED(); return 0; } } @@ -120,7 +123,7 @@ class ResizeFilter { ImageOperations::ResizeMethod method_; // Subset of source the filters will touch. - SkIRect src_depend_; + Rect src_depend_; // Size of the filter support on one side only in the destination space. // See GetFilterSupport. @@ -128,38 +131,40 @@ class ResizeFilter { float y_filter_support_; // Subset of scaled destination bitmap to compute. - SkIRect out_bounds_; + Rect out_bounds_; ConvolusionFilter1D x_filter_; ConvolusionFilter1D y_filter_; + + DISALLOW_EVIL_CONSTRUCTORS(ResizeFilter); }; ResizeFilter::ResizeFilter(ImageOperations::ResizeMethod method, - int src_full_width, int src_full_height, - int dest_width, int dest_height, - const SkIRect& dest_subset) + const Size& src_full_size, + const Size& dest_size, + const Rect& dest_subset) : method_(method), out_bounds_(dest_subset) { - float scale_x = static_cast<float>(dest_width) / - static_cast<float>(src_full_width); - float scale_y = static_cast<float>(dest_height) / - static_cast<float>(src_full_height); + float scale_x = static_cast<float>(dest_size.width()) / + static_cast<float>(src_full_size.width()); + float scale_y = static_cast<float>(dest_size.height()) / + static_cast<float>(src_full_size.height()); x_filter_support_ = GetFilterSupport(scale_x); y_filter_support_ = GetFilterSupport(scale_y); - SkIRect src_full = {0, 0, src_full_width, src_full_height}; - SkIRect dest_full = {0, 0, - static_cast<int>(src_full_width * scale_x + 0.5), - static_cast<int>(src_full_height * scale_y + 0.5)}; + gfx::Rect src_full(0, 0, src_full_size.width(), src_full_size.height()); + gfx::Rect dest_full(0, 0, + static_cast<int>(src_full_size.width() * scale_x + 0.5), + static_cast<int>(src_full_size.height() * scale_y + 0.5)); // Support of the filter in source space. float src_x_support = x_filter_support_ / scale_x; float src_y_support = y_filter_support_ / scale_y; - ComputeFilters(src_full_width, dest_subset.fLeft, dest_subset.width(), + ComputeFilters(src_full_size.width(), dest_subset.x(), dest_subset.width(), scale_x, src_x_support, &x_filter_); - ComputeFilters(src_full_height, dest_subset.fTop, dest_subset.height(), + ComputeFilters(src_full_size.height(), dest_subset.y(), dest_subset.height(), scale_y, src_y_support, &y_filter_); } @@ -179,10 +184,8 @@ void ResizeFilter::ComputeFilters(int src_size, // Speed up the divisions below by turning them into multiplies. float inv_scale = 1.0f / scale; - std::vector<float> filter_values; - filter_values.reserve(64); - std::vector<short> fixed_filter_values; - fixed_filter_values.reserve(64); + StackVector<float, 64> filter_values; + StackVector<int16, 64> fixed_filter_values; // Loop over all pixels in the output range. We will generate one set of // filter values for each one. Those values will tell us how to blend the @@ -191,8 +194,8 @@ void ResizeFilter::ComputeFilters(int src_size, dest_subset_i++) { // Reset the arrays. We don't declare them inside so they can re-use the // same malloc-ed buffer. - filter_values.clear(); - fixed_filter_values.clear(); + filter_values->clear(); + fixed_filter_values->clear(); // This is the pixel in the source directly under the pixel in the dest. float src_pixel = dest_subset_i * inv_scale; @@ -215,19 +218,19 @@ void ResizeFilter::ComputeFilters(int src_size, // Compute the filter value at that location. float filter_value = ComputeFilter(dest_filter_pos); - filter_values.push_back(filter_value); + filter_values->push_back(filter_value); filter_sum += filter_value; } - SkASSERT(!filter_values->empty()); + DCHECK(!filter_values->empty()) << "We should always get a filter!"; // The filter must be normalized so that we don't affect the brightness of // the image. Convert to normalized fixed point. - short fixed_sum = 0; - for (size_t i = 0; i < filter_values.size(); i++) { - short cur_fixed = output->FloatToFixed(filter_values[i] / filter_sum); + int16 fixed_sum = 0; + for (size_t i = 0; i < filter_values->size(); i++) { + int16 cur_fixed = output->FloatToFixed(filter_values[i] / filter_sum); fixed_sum += cur_fixed; - fixed_filter_values.push_back(cur_fixed); + fixed_filter_values->push_back(cur_fixed); } // The conversion to fixed point will leave some rounding errors, which @@ -235,12 +238,12 @@ void ResizeFilter::ComputeFilters(int src_size, // arbitrarily add this to the center of the filter array (this won't always // be the center of the filter function since it could get clipped on the // edges, but it doesn't matter enough to worry about that case). - short leftovers = output->FloatToFixed(1.0f) - fixed_sum; - fixed_filter_values[fixed_filter_values.size() / 2] += leftovers; + int16 leftovers = output->FloatToFixed(1.0f) - fixed_sum; + fixed_filter_values[fixed_filter_values->size() / 2] += leftovers; // Now it's ready to go. output->AddFilter(src_begin, &fixed_filter_values[0], - static_cast<int>(fixed_filter_values.size())); + static_cast<int>(fixed_filter_values->size())); } } @@ -251,24 +254,27 @@ void ResizeFilter::ComputeFilters(int src_size, // static SkBitmap ImageOperations::Resize(const SkBitmap& source, ResizeMethod method, - int dest_width, int dest_height, - const SkIRect& dest_subset) { + const Size& dest_size, + const Rect& dest_subset) { + DCHECK(Rect(dest_size.width(), dest_size.height()).Contains(dest_subset)) << + "The supplied subset does not fall within the destination image."; + // If the size of source or destination is 0, i.e. 0x0, 0xN or Nx0, just // return empty if (source.width() < 1 || source.height() < 1 || - dest_width < 1 || dest_height < 1) - return SkBitmap(); + dest_size.width() < 1 || dest_size.height() < 1) + return SkBitmap(); SkAutoLockPixels locker(source); - ResizeFilter filter(method, source.width(), source.height(), - dest_width, dest_height, dest_subset); + ResizeFilter filter(method, Size(source.width(), source.height()), + dest_size, dest_subset); // Get a source bitmap encompassing this touched area. We construct the // offsets and row strides such that it looks like a new bitmap, while // referring to the old data. - const unsigned char* source_subset = - reinterpret_cast<const unsigned char*>(source.getPixels()); + const uint8* source_subset = + reinterpret_cast<const uint8*>(source.getPixels()); // Convolve into the result. SkBitmap result; @@ -288,28 +294,29 @@ SkBitmap ImageOperations::Resize(const SkBitmap& source, // static SkBitmap ImageOperations::Resize(const SkBitmap& source, ResizeMethod method, - int dest_width, int dest_height) { - SkIRect dest_subset = {0, 0, dest_width, dest_height}; - return Resize(source, method, dest_width, dest_height, dest_subset); + const Size& dest_size) { + Rect dest_subset(0, 0, dest_size.width(), dest_size.height()); + return Resize(source, method, dest_size, dest_subset); } // static SkBitmap ImageOperations::CreateBlendedBitmap(const SkBitmap& first, const SkBitmap& second, double alpha) { - SkASSERT(alpha <= 1 && alpha >= 0); - SkASSERT(first.width() == second.width()); - SkASSERT(first.height() == second.height()); - SkASSERT(first.bytesPerPixel() == second.bytesPerPixel()); - SkASSERT(first.config() == SkBitmap::kARGB_8888_Config); + DCHECK(alpha <= 1 && alpha >= 0); + DCHECK(first.width() == second.width()); + DCHECK(first.height() == second.height()); + DCHECK(first.bytesPerPixel() == second.bytesPerPixel()); + DCHECK(first.config() == SkBitmap::kARGB_8888_Config); // Optimize for case where we won't need to blend anything. static const double alpha_min = 1.0 / 255; static const double alpha_max = 254.0 / 255; - if (alpha < alpha_min) + if (alpha < alpha_min) { return first; - else if (alpha > alpha_max) + } else if (alpha > alpha_max) { return second; + } SkAutoLockPixels lock_first(first); SkAutoLockPixels lock_second(second); @@ -323,13 +330,13 @@ SkBitmap ImageOperations::CreateBlendedBitmap(const SkBitmap& first, double first_alpha = 1 - alpha; for (int y = 0; y < first.height(); y++) { - uint32_t* first_row = first.getAddr32(0, y); - uint32_t* second_row = second.getAddr32(0, y); - uint32_t* dst_row = blended.getAddr32(0, y); + uint32* first_row = first.getAddr32(0, y); + uint32* second_row = second.getAddr32(0, y); + uint32* dst_row = blended.getAddr32(0, y); for (int x = 0; x < first.width(); x++) { - uint32_t first_pixel = first_row[x]; - uint32_t second_pixel = second_row[x]; + uint32 first_pixel = first_row[x]; + uint32 second_pixel = second_row[x]; int a = static_cast<int>( SkColorGetA(first_pixel) * first_alpha + @@ -351,4 +358,5 @@ SkBitmap ImageOperations::CreateBlendedBitmap(const SkBitmap& first, return blended; } -} // namespace skia +} // namespace gfx + |