Home | History | Annotate | Download | only in gfx
      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
      3 // found in the LICENSE file.
      4 
      5 #include "ui/gfx/skbitmap_operations.h"
      6 
      7 #include <algorithm>
      8 #include <string.h>
      9 
     10 #include "base/logging.h"
     11 #include "skia/ext/refptr.h"
     12 #include "third_party/skia/include/core/SkBitmap.h"
     13 #include "third_party/skia/include/core/SkCanvas.h"
     14 #include "third_party/skia/include/core/SkColorFilter.h"
     15 #include "third_party/skia/include/core/SkColorPriv.h"
     16 #include "third_party/skia/include/core/SkUnPreMultiply.h"
     17 #include "third_party/skia/include/effects/SkBlurImageFilter.h"
     18 #include "ui/gfx/insets.h"
     19 #include "ui/gfx/point.h"
     20 #include "ui/gfx/size.h"
     21 
     22 // static
     23 SkBitmap SkBitmapOperations::CreateInvertedBitmap(const SkBitmap& image) {
     24   DCHECK(image.colorType() == kN32_SkColorType);
     25 
     26   SkAutoLockPixels lock_image(image);
     27 
     28   SkBitmap inverted;
     29   inverted.allocN32Pixels(image.width(), image.height());
     30 
     31   for (int y = 0; y < image.height(); ++y) {
     32     uint32* image_row = image.getAddr32(0, y);
     33     uint32* dst_row = inverted.getAddr32(0, y);
     34 
     35     for (int x = 0; x < image.width(); ++x) {
     36       uint32 image_pixel = image_row[x];
     37       dst_row[x] = (image_pixel & 0xFF000000) |
     38                    (0x00FFFFFF - (image_pixel & 0x00FFFFFF));
     39     }
     40   }
     41 
     42   return inverted;
     43 }
     44 
     45 // static
     46 SkBitmap SkBitmapOperations::CreateBlendedBitmap(const SkBitmap& first,
     47                                                  const SkBitmap& second,
     48                                                  double alpha) {
     49   DCHECK((alpha >= 0) && (alpha <= 1));
     50   DCHECK(first.width() == second.width());
     51   DCHECK(first.height() == second.height());
     52   DCHECK(first.bytesPerPixel() == second.bytesPerPixel());
     53   DCHECK(first.colorType() == kN32_SkColorType);
     54 
     55   // Optimize for case where we won't need to blend anything.
     56   static const double alpha_min = 1.0 / 255;
     57   static const double alpha_max = 254.0 / 255;
     58   if (alpha < alpha_min)
     59     return first;
     60   else if (alpha > alpha_max)
     61     return second;
     62 
     63   SkAutoLockPixels lock_first(first);
     64   SkAutoLockPixels lock_second(second);
     65 
     66   SkBitmap blended;
     67   blended.allocN32Pixels(first.width(), first.height());
     68 
     69   double first_alpha = 1 - alpha;
     70 
     71   for (int y = 0; y < first.height(); ++y) {
     72     uint32* first_row = first.getAddr32(0, y);
     73     uint32* second_row = second.getAddr32(0, y);
     74     uint32* dst_row = blended.getAddr32(0, y);
     75 
     76     for (int x = 0; x < first.width(); ++x) {
     77       uint32 first_pixel = first_row[x];
     78       uint32 second_pixel = second_row[x];
     79 
     80       int a = static_cast<int>((SkColorGetA(first_pixel) * first_alpha) +
     81                                (SkColorGetA(second_pixel) * alpha));
     82       int r = static_cast<int>((SkColorGetR(first_pixel) * first_alpha) +
     83                                (SkColorGetR(second_pixel) * alpha));
     84       int g = static_cast<int>((SkColorGetG(first_pixel) * first_alpha) +
     85                                (SkColorGetG(second_pixel) * alpha));
     86       int b = static_cast<int>((SkColorGetB(first_pixel) * first_alpha) +
     87                                (SkColorGetB(second_pixel) * alpha));
     88 
     89       dst_row[x] = SkColorSetARGB(a, r, g, b);
     90     }
     91   }
     92 
     93   return blended;
     94 }
     95 
     96 // static
     97 SkBitmap SkBitmapOperations::CreateMaskedBitmap(const SkBitmap& rgb,
     98                                                 const SkBitmap& alpha) {
     99   DCHECK(rgb.width() == alpha.width());
    100   DCHECK(rgb.height() == alpha.height());
    101   DCHECK(rgb.bytesPerPixel() == alpha.bytesPerPixel());
    102   DCHECK(rgb.colorType() == kN32_SkColorType);
    103   DCHECK(alpha.colorType() == kN32_SkColorType);
    104 
    105   SkBitmap masked;
    106   masked.allocN32Pixels(rgb.width(), rgb.height());
    107 
    108   SkAutoLockPixels lock_rgb(rgb);
    109   SkAutoLockPixels lock_alpha(alpha);
    110   SkAutoLockPixels lock_masked(masked);
    111 
    112   for (int y = 0; y < masked.height(); ++y) {
    113     uint32* rgb_row = rgb.getAddr32(0, y);
    114     uint32* alpha_row = alpha.getAddr32(0, y);
    115     uint32* dst_row = masked.getAddr32(0, y);
    116 
    117     for (int x = 0; x < masked.width(); ++x) {
    118       SkColor rgb_pixel = SkUnPreMultiply::PMColorToColor(rgb_row[x]);
    119       SkColor alpha_pixel = SkUnPreMultiply::PMColorToColor(alpha_row[x]);
    120       int alpha = SkAlphaMul(SkColorGetA(rgb_pixel),
    121                              SkAlpha255To256(SkColorGetA(alpha_pixel)));
    122       int alpha_256 = SkAlpha255To256(alpha);
    123       dst_row[x] = SkColorSetARGB(alpha,
    124                                   SkAlphaMul(SkColorGetR(rgb_pixel), alpha_256),
    125                                   SkAlphaMul(SkColorGetG(rgb_pixel), alpha_256),
    126                                   SkAlphaMul(SkColorGetB(rgb_pixel),
    127                                              alpha_256));
    128     }
    129   }
    130 
    131   return masked;
    132 }
    133 
    134 // static
    135 SkBitmap SkBitmapOperations::CreateButtonBackground(SkColor color,
    136                                                     const SkBitmap& image,
    137                                                     const SkBitmap& mask) {
    138   DCHECK(image.colorType() == kN32_SkColorType);
    139   DCHECK(mask.colorType() == kN32_SkColorType);
    140 
    141   SkBitmap background;
    142   background.allocN32Pixels(mask.width(), mask.height());
    143 
    144   double bg_a = SkColorGetA(color);
    145   double bg_r = SkColorGetR(color);
    146   double bg_g = SkColorGetG(color);
    147   double bg_b = SkColorGetB(color);
    148 
    149   SkAutoLockPixels lock_mask(mask);
    150   SkAutoLockPixels lock_image(image);
    151   SkAutoLockPixels lock_background(background);
    152 
    153   for (int y = 0; y < mask.height(); ++y) {
    154     uint32* dst_row = background.getAddr32(0, y);
    155     uint32* image_row = image.getAddr32(0, y % image.height());
    156     uint32* mask_row = mask.getAddr32(0, y);
    157 
    158     for (int x = 0; x < mask.width(); ++x) {
    159       uint32 image_pixel = image_row[x % image.width()];
    160 
    161       double img_a = SkColorGetA(image_pixel);
    162       double img_r = SkColorGetR(image_pixel);
    163       double img_g = SkColorGetG(image_pixel);
    164       double img_b = SkColorGetB(image_pixel);
    165 
    166       double img_alpha = static_cast<double>(img_a) / 255.0;
    167       double img_inv = 1 - img_alpha;
    168 
    169       double mask_a = static_cast<double>(SkColorGetA(mask_row[x])) / 255.0;
    170 
    171       dst_row[x] = SkColorSetARGB(
    172           static_cast<int>(std::min(255.0, bg_a + img_a) * mask_a),
    173           static_cast<int>(((bg_r * img_inv) + (img_r * img_alpha)) * mask_a),
    174           static_cast<int>(((bg_g * img_inv) + (img_g * img_alpha)) * mask_a),
    175           static_cast<int>(((bg_b * img_inv) + (img_b * img_alpha)) * mask_a));
    176     }
    177   }
    178 
    179   return background;
    180 }
    181 
    182 namespace {
    183 namespace HSLShift {
    184 
    185 // TODO(viettrungluu): Some things have yet to be optimized at all.
    186 
    187 // Notes on and conventions used in the following code
    188 //
    189 // Conventions:
    190 //  - R, G, B, A = obvious; as variables: |r|, |g|, |b|, |a| (see also below)
    191 //  - H, S, L = obvious; as variables: |h|, |s|, |l| (see also below)
    192 //  - variables derived from S, L shift parameters: |sdec| and |sinc| for S
    193 //    increase and decrease factors, |ldec| and |linc| for L (see also below)
    194 //
    195 // To try to optimize HSL shifts, we do several things:
    196 //  - Avoid unpremultiplying (then processing) then premultiplying. This means
    197 //    that R, G, B values (and also L, but not H and S) should be treated as
    198 //    having a range of 0..A (where A is alpha).
    199 //  - Do things in integer/fixed-point. This avoids costly conversions between
    200 //    floating-point and integer, though I should study the tradeoff more
    201 //    carefully (presumably, at some point of processing complexity, converting
    202 //    and processing using simpler floating-point code will begin to win in
    203 //    performance). Also to be studied is the speed/type of floating point
    204 //    conversions; see, e.g., <http://www.stereopsis.com/sree/fpu2006.html>.
    205 //
    206 // Conventions for fixed-point arithmetic
    207 //  - Each function has a constant denominator (called |den|, which should be a
    208 //    power of 2), appropriate for the computations done in that function.
    209 //  - A value |x| is then typically represented by a numerator, named |x_num|,
    210 //    so that its actual value is |x_num / den| (casting to floating-point
    211 //    before division).
    212 //  - To obtain |x_num| from |x|, simply multiply by |den|, i.e., |x_num = x *
    213 //    den| (casting appropriately).
    214 //  - When necessary, a value |x| may also be represented as a numerator over
    215 //    the denominator squared (set |den2 = den * den|). In such a case, the
    216 //    corresponding variable is called |x_num2| (so that its actual value is
    217 //    |x_num^2 / den2|.
    218 //  - The representation of the product of |x| and |y| is be called |x_y_num| if
    219 //    |x * y == x_y_num / den|, and |xy_num2| if |x * y == x_y_num2 / den2|. In
    220 //    the latter case, notice that one can calculate |x_y_num2 = x_num * y_num|.
    221 
    222 // Routine used to process a line; typically specialized for specific kinds of
    223 // HSL shifts (to optimize).
    224 typedef void (*LineProcessor)(const color_utils::HSL&,
    225                               const SkPMColor*,
    226                               SkPMColor*,
    227                               int width);
    228 
    229 enum OperationOnH { kOpHNone = 0, kOpHShift, kNumHOps };
    230 enum OperationOnS { kOpSNone = 0, kOpSDec, kOpSInc, kNumSOps };
    231 enum OperationOnL { kOpLNone = 0, kOpLDec, kOpLInc, kNumLOps };
    232 
    233 // Epsilon used to judge when shift values are close enough to various critical
    234 // values (typically 0.5, which yields a no-op for S and L shifts. 1/256 should
    235 // be small enough, but let's play it safe>
    236 const double epsilon = 0.0005;
    237 
    238 // Line processor: default/universal (i.e., old-school).
    239 void LineProcDefault(const color_utils::HSL& hsl_shift,
    240                      const SkPMColor* in,
    241                      SkPMColor* out,
    242                      int width) {
    243   for (int x = 0; x < width; x++) {
    244     out[x] = SkPreMultiplyColor(color_utils::HSLShift(
    245         SkUnPreMultiply::PMColorToColor(in[x]), hsl_shift));
    246   }
    247 }
    248 
    249 // Line processor: no-op (i.e., copy).
    250 void LineProcCopy(const color_utils::HSL& hsl_shift,
    251                   const SkPMColor* in,
    252                   SkPMColor* out,
    253                   int width) {
    254   DCHECK(hsl_shift.h < 0);
    255   DCHECK(hsl_shift.s < 0 || fabs(hsl_shift.s - 0.5) < HSLShift::epsilon);
    256   DCHECK(hsl_shift.l < 0 || fabs(hsl_shift.l - 0.5) < HSLShift::epsilon);
    257   memcpy(out, in, static_cast<size_t>(width) * sizeof(out[0]));
    258 }
    259 
    260 // Line processor: H no-op, S no-op, L decrease.
    261 void LineProcHnopSnopLdec(const color_utils::HSL& hsl_shift,
    262                           const SkPMColor* in,
    263                           SkPMColor* out,
    264                           int width) {
    265   const uint32_t den = 65536;
    266 
    267   DCHECK(hsl_shift.h < 0);
    268   DCHECK(hsl_shift.s < 0 || fabs(hsl_shift.s - 0.5) < HSLShift::epsilon);
    269   DCHECK(hsl_shift.l <= 0.5 - HSLShift::epsilon && hsl_shift.l >= 0);
    270 
    271   uint32_t ldec_num = static_cast<uint32_t>(hsl_shift.l * 2 * den);
    272   for (int x = 0; x < width; x++) {
    273     uint32_t a = SkGetPackedA32(in[x]);
    274     uint32_t r = SkGetPackedR32(in[x]);
    275     uint32_t g = SkGetPackedG32(in[x]);
    276     uint32_t b = SkGetPackedB32(in[x]);
    277     r = r * ldec_num / den;
    278     g = g * ldec_num / den;
    279     b = b * ldec_num / den;
    280     out[x] = SkPackARGB32(a, r, g, b);
    281   }
    282 }
    283 
    284 // Line processor: H no-op, S no-op, L increase.
    285 void LineProcHnopSnopLinc(const color_utils::HSL& hsl_shift,
    286                           const SkPMColor* in,
    287                           SkPMColor* out,
    288                           int width) {
    289   const uint32_t den = 65536;
    290 
    291   DCHECK(hsl_shift.h < 0);
    292   DCHECK(hsl_shift.s < 0 || fabs(hsl_shift.s - 0.5) < HSLShift::epsilon);
    293   DCHECK(hsl_shift.l >= 0.5 + HSLShift::epsilon && hsl_shift.l <= 1);
    294 
    295   uint32_t linc_num = static_cast<uint32_t>((hsl_shift.l - 0.5) * 2 * den);
    296   for (int x = 0; x < width; x++) {
    297     uint32_t a = SkGetPackedA32(in[x]);
    298     uint32_t r = SkGetPackedR32(in[x]);
    299     uint32_t g = SkGetPackedG32(in[x]);
    300     uint32_t b = SkGetPackedB32(in[x]);
    301     r += (a - r) * linc_num / den;
    302     g += (a - g) * linc_num / den;
    303     b += (a - b) * linc_num / den;
    304     out[x] = SkPackARGB32(a, r, g, b);
    305   }
    306 }
    307 
    308 // Saturation changes modifications in RGB
    309 //
    310 // (Note that as a further complication, the values we deal in are
    311 // premultiplied, so R/G/B values must be in the range 0..A. For mathematical
    312 // purposes, one may as well use r=R/A, g=G/A, b=B/A. Without loss of
    313 // generality, assume that R/G/B values are in the range 0..1.)
    314 //
    315 // Let Max = max(R,G,B), Min = min(R,G,B), and Med be the median value. Then L =
    316 // (Max+Min)/2. If L is to remain constant, Max+Min must also remain constant.
    317 //
    318 // For H to remain constant, first, the (numerical) order of R/G/B (from
    319 // smallest to largest) must remain the same. Second, all the ratios
    320 // (R-G)/(Max-Min), (R-B)/(Max-Min), (G-B)/(Max-Min) must remain constant (of
    321 // course, if Max = Min, then S = 0 and no saturation change is well-defined,
    322 // since H is not well-defined).
    323 //
    324 // Let C_max be a colour with value Max, C_min be one with value Min, and C_med
    325 // the remaining colour. Increasing saturation (to the maximum) is accomplished
    326 // by increasing the value of C_max while simultaneously decreasing C_min and
    327 // changing C_med so that the ratios are maintained; for the latter, it suffices
    328 // to keep (C_med-C_min)/(C_max-C_min) constant (and equal to
    329 // (Med-Min)/(Max-Min)).
    330 
    331 // Line processor: H no-op, S decrease, L no-op.
    332 void LineProcHnopSdecLnop(const color_utils::HSL& hsl_shift,
    333                           const SkPMColor* in,
    334                           SkPMColor* out,
    335                           int width) {
    336   DCHECK(hsl_shift.h < 0);
    337   DCHECK(hsl_shift.s >= 0 && hsl_shift.s <= 0.5 - HSLShift::epsilon);
    338   DCHECK(hsl_shift.l < 0 || fabs(hsl_shift.l - 0.5) < HSLShift::epsilon);
    339 
    340   const int32_t denom = 65536;
    341   int32_t s_numer = static_cast<int32_t>(hsl_shift.s * 2 * denom);
    342   for (int x = 0; x < width; x++) {
    343     int32_t a = static_cast<int32_t>(SkGetPackedA32(in[x]));
    344     int32_t r = static_cast<int32_t>(SkGetPackedR32(in[x]));
    345     int32_t g = static_cast<int32_t>(SkGetPackedG32(in[x]));
    346     int32_t b = static_cast<int32_t>(SkGetPackedB32(in[x]));
    347 
    348     int32_t vmax, vmin;
    349     if (r > g) {  // This uses 3 compares rather than 4.
    350       vmax = std::max(r, b);
    351       vmin = std::min(g, b);
    352     } else {
    353       vmax = std::max(g, b);
    354       vmin = std::min(r, b);
    355     }
    356 
    357     // Use denom * L to avoid rounding.
    358     int32_t denom_l = (vmax + vmin) * (denom / 2);
    359     int32_t s_numer_l = (vmax + vmin) * s_numer / 2;
    360 
    361     r = (denom_l + r * s_numer - s_numer_l) / denom;
    362     g = (denom_l + g * s_numer - s_numer_l) / denom;
    363     b = (denom_l + b * s_numer - s_numer_l) / denom;
    364     out[x] = SkPackARGB32(a, r, g, b);
    365   }
    366 }
    367 
    368 // Line processor: H no-op, S decrease, L decrease.
    369 void LineProcHnopSdecLdec(const color_utils::HSL& hsl_shift,
    370                           const SkPMColor* in,
    371                           SkPMColor* out,
    372                           int width) {
    373   DCHECK(hsl_shift.h < 0);
    374   DCHECK(hsl_shift.s >= 0 && hsl_shift.s <= 0.5 - HSLShift::epsilon);
    375   DCHECK(hsl_shift.l >= 0 && hsl_shift.l <= 0.5 - HSLShift::epsilon);
    376 
    377   // Can't be too big since we need room for denom*denom and a bit for sign.
    378   const int32_t denom = 1024;
    379   int32_t l_numer = static_cast<int32_t>(hsl_shift.l * 2 * denom);
    380   int32_t s_numer = static_cast<int32_t>(hsl_shift.s * 2 * denom);
    381   for (int x = 0; x < width; x++) {
    382     int32_t a = static_cast<int32_t>(SkGetPackedA32(in[x]));
    383     int32_t r = static_cast<int32_t>(SkGetPackedR32(in[x]));
    384     int32_t g = static_cast<int32_t>(SkGetPackedG32(in[x]));
    385     int32_t b = static_cast<int32_t>(SkGetPackedB32(in[x]));
    386 
    387     int32_t vmax, vmin;
    388     if (r > g) {  // This uses 3 compares rather than 4.
    389       vmax = std::max(r, b);
    390       vmin = std::min(g, b);
    391     } else {
    392       vmax = std::max(g, b);
    393       vmin = std::min(r, b);
    394     }
    395 
    396     // Use denom * L to avoid rounding.
    397     int32_t denom_l = (vmax + vmin) * (denom / 2);
    398     int32_t s_numer_l = (vmax + vmin) * s_numer / 2;
    399 
    400     r = (denom_l + r * s_numer - s_numer_l) * l_numer / (denom * denom);
    401     g = (denom_l + g * s_numer - s_numer_l) * l_numer / (denom * denom);
    402     b = (denom_l + b * s_numer - s_numer_l) * l_numer / (denom * denom);
    403     out[x] = SkPackARGB32(a, r, g, b);
    404   }
    405 }
    406 
    407 // Line processor: H no-op, S decrease, L increase.
    408 void LineProcHnopSdecLinc(const color_utils::HSL& hsl_shift,
    409                           const SkPMColor* in,
    410                           SkPMColor* out,
    411                           int width) {
    412   DCHECK(hsl_shift.h < 0);
    413   DCHECK(hsl_shift.s >= 0 && hsl_shift.s <= 0.5 - HSLShift::epsilon);
    414   DCHECK(hsl_shift.l >= 0.5 + HSLShift::epsilon && hsl_shift.l <= 1);
    415 
    416   // Can't be too big since we need room for denom*denom and a bit for sign.
    417   const int32_t denom = 1024;
    418   int32_t l_numer = static_cast<int32_t>((hsl_shift.l - 0.5) * 2 * denom);
    419   int32_t s_numer = static_cast<int32_t>(hsl_shift.s * 2 * denom);
    420   for (int x = 0; x < width; x++) {
    421     int32_t a = static_cast<int32_t>(SkGetPackedA32(in[x]));
    422     int32_t r = static_cast<int32_t>(SkGetPackedR32(in[x]));
    423     int32_t g = static_cast<int32_t>(SkGetPackedG32(in[x]));
    424     int32_t b = static_cast<int32_t>(SkGetPackedB32(in[x]));
    425 
    426     int32_t vmax, vmin;
    427     if (r > g) {  // This uses 3 compares rather than 4.
    428       vmax = std::max(r, b);
    429       vmin = std::min(g, b);
    430     } else {
    431       vmax = std::max(g, b);
    432       vmin = std::min(r, b);
    433     }
    434 
    435     // Use denom * L to avoid rounding.
    436     int32_t denom_l = (vmax + vmin) * (denom / 2);
    437     int32_t s_numer_l = (vmax + vmin) * s_numer / 2;
    438 
    439     r = denom_l + r * s_numer - s_numer_l;
    440     g = denom_l + g * s_numer - s_numer_l;
    441     b = denom_l + b * s_numer - s_numer_l;
    442 
    443     r = (r * denom + (a * denom - r) * l_numer) / (denom * denom);
    444     g = (g * denom + (a * denom - g) * l_numer) / (denom * denom);
    445     b = (b * denom + (a * denom - b) * l_numer) / (denom * denom);
    446     out[x] = SkPackARGB32(a, r, g, b);
    447   }
    448 }
    449 
    450 const LineProcessor kLineProcessors[kNumHOps][kNumSOps][kNumLOps] = {
    451   { // H: kOpHNone
    452     { // S: kOpSNone
    453       LineProcCopy,         // L: kOpLNone
    454       LineProcHnopSnopLdec, // L: kOpLDec
    455       LineProcHnopSnopLinc  // L: kOpLInc
    456     },
    457     { // S: kOpSDec
    458       LineProcHnopSdecLnop, // L: kOpLNone
    459       LineProcHnopSdecLdec, // L: kOpLDec
    460       LineProcHnopSdecLinc  // L: kOpLInc
    461     },
    462     { // S: kOpSInc
    463       LineProcDefault, // L: kOpLNone
    464       LineProcDefault, // L: kOpLDec
    465       LineProcDefault  // L: kOpLInc
    466     }
    467   },
    468   { // H: kOpHShift
    469     { // S: kOpSNone
    470       LineProcDefault, // L: kOpLNone
    471       LineProcDefault, // L: kOpLDec
    472       LineProcDefault  // L: kOpLInc
    473     },
    474     { // S: kOpSDec
    475       LineProcDefault, // L: kOpLNone
    476       LineProcDefault, // L: kOpLDec
    477       LineProcDefault  // L: kOpLInc
    478     },
    479     { // S: kOpSInc
    480       LineProcDefault, // L: kOpLNone
    481       LineProcDefault, // L: kOpLDec
    482       LineProcDefault  // L: kOpLInc
    483     }
    484   }
    485 };
    486 
    487 }  // namespace HSLShift
    488 }  // namespace
    489 
    490 // static
    491 SkBitmap SkBitmapOperations::CreateHSLShiftedBitmap(
    492     const SkBitmap& bitmap,
    493     const color_utils::HSL& hsl_shift) {
    494   // Default to NOPs.
    495   HSLShift::OperationOnH H_op = HSLShift::kOpHNone;
    496   HSLShift::OperationOnS S_op = HSLShift::kOpSNone;
    497   HSLShift::OperationOnL L_op = HSLShift::kOpLNone;
    498 
    499   if (hsl_shift.h >= 0 && hsl_shift.h <= 1)
    500     H_op = HSLShift::kOpHShift;
    501 
    502   // Saturation shift: 0 -> fully desaturate, 0.5 -> NOP, 1 -> fully saturate.
    503   if (hsl_shift.s >= 0 && hsl_shift.s <= (0.5 - HSLShift::epsilon))
    504     S_op = HSLShift::kOpSDec;
    505   else if (hsl_shift.s >= (0.5 + HSLShift::epsilon))
    506     S_op = HSLShift::kOpSInc;
    507 
    508   // Lightness shift: 0 -> black, 0.5 -> NOP, 1 -> white.
    509   if (hsl_shift.l >= 0 && hsl_shift.l <= (0.5 - HSLShift::epsilon))
    510     L_op = HSLShift::kOpLDec;
    511   else if (hsl_shift.l >= (0.5 + HSLShift::epsilon))
    512     L_op = HSLShift::kOpLInc;
    513 
    514   HSLShift::LineProcessor line_proc =
    515       HSLShift::kLineProcessors[H_op][S_op][L_op];
    516 
    517   DCHECK(bitmap.empty() == false);
    518   DCHECK(bitmap.colorType() == kN32_SkColorType);
    519 
    520   SkBitmap shifted;
    521   shifted.allocN32Pixels(bitmap.width(), bitmap.height());
    522 
    523   SkAutoLockPixels lock_bitmap(bitmap);
    524   SkAutoLockPixels lock_shifted(shifted);
    525 
    526   // Loop through the pixels of the original bitmap.
    527   for (int y = 0; y < bitmap.height(); ++y) {
    528     SkPMColor* pixels = bitmap.getAddr32(0, y);
    529     SkPMColor* tinted_pixels = shifted.getAddr32(0, y);
    530 
    531     (*line_proc)(hsl_shift, pixels, tinted_pixels, bitmap.width());
    532   }
    533 
    534   return shifted;
    535 }
    536 
    537 // static
    538 SkBitmap SkBitmapOperations::CreateTiledBitmap(const SkBitmap& source,
    539                                                int src_x, int src_y,
    540                                                int dst_w, int dst_h) {
    541   DCHECK(source.colorType() == kN32_SkColorType);
    542 
    543   SkBitmap cropped;
    544   cropped.allocN32Pixels(dst_w, dst_h);
    545 
    546   SkAutoLockPixels lock_source(source);
    547   SkAutoLockPixels lock_cropped(cropped);
    548 
    549   // Loop through the pixels of the original bitmap.
    550   for (int y = 0; y < dst_h; ++y) {
    551     int y_pix = (src_y + y) % source.height();
    552     while (y_pix < 0)
    553       y_pix += source.height();
    554 
    555     uint32* source_row = source.getAddr32(0, y_pix);
    556     uint32* dst_row = cropped.getAddr32(0, y);
    557 
    558     for (int x = 0; x < dst_w; ++x) {
    559       int x_pix = (src_x + x) % source.width();
    560       while (x_pix < 0)
    561         x_pix += source.width();
    562 
    563       dst_row[x] = source_row[x_pix];
    564     }
    565   }
    566 
    567   return cropped;
    568 }
    569 
    570 // static
    571 SkBitmap SkBitmapOperations::DownsampleByTwoUntilSize(const SkBitmap& bitmap,
    572                                                       int min_w, int min_h) {
    573   if ((bitmap.width() <= min_w) || (bitmap.height() <= min_h) ||
    574       (min_w < 0) || (min_h < 0))
    575     return bitmap;
    576 
    577   // Since bitmaps are refcounted, this copy will be fast.
    578   SkBitmap current = bitmap;
    579   while ((current.width() >= min_w * 2) && (current.height() >= min_h * 2) &&
    580          (current.width() > 1) && (current.height() > 1))
    581     current = DownsampleByTwo(current);
    582   return current;
    583 }
    584 
    585 // static
    586 SkBitmap SkBitmapOperations::DownsampleByTwo(const SkBitmap& bitmap) {
    587   // Handle the nop case.
    588   if ((bitmap.width() <= 1) || (bitmap.height() <= 1))
    589     return bitmap;
    590 
    591   SkBitmap result;
    592   result.allocN32Pixels((bitmap.width() + 1) / 2, (bitmap.height() + 1) / 2);
    593 
    594   SkAutoLockPixels lock(bitmap);
    595 
    596   const int resultLastX = result.width() - 1;
    597   const int srcLastX = bitmap.width() - 1;
    598 
    599   for (int dest_y = 0; dest_y < result.height(); ++dest_y) {
    600     const int src_y = dest_y << 1;
    601     const SkPMColor* SK_RESTRICT cur_src0 = bitmap.getAddr32(0, src_y);
    602     const SkPMColor* SK_RESTRICT cur_src1 = cur_src0;
    603     if (src_y + 1 < bitmap.height())
    604       cur_src1 = bitmap.getAddr32(0, src_y + 1);
    605 
    606     SkPMColor* SK_RESTRICT cur_dst = result.getAddr32(0, dest_y);
    607 
    608     for (int dest_x = 0; dest_x <= resultLastX; ++dest_x) {
    609       // This code is based on downsampleby2_proc32 in SkBitmap.cpp. It is very
    610       // clever in that it does two channels at once: alpha and green ("ag")
    611       // and red and blue ("rb"). Each channel gets averaged across 4 pixels
    612       // to get the result.
    613       int bump_x = (dest_x << 1) < srcLastX;
    614       SkPMColor tmp, ag, rb;
    615 
    616       // Top left pixel of the 2x2 block.
    617       tmp = cur_src0[0];
    618       ag = (tmp >> 8) & 0xFF00FF;
    619       rb = tmp & 0xFF00FF;
    620 
    621       // Top right pixel of the 2x2 block.
    622       tmp = cur_src0[bump_x];
    623       ag += (tmp >> 8) & 0xFF00FF;
    624       rb += tmp & 0xFF00FF;
    625 
    626       // Bottom left pixel of the 2x2 block.
    627       tmp = cur_src1[0];
    628       ag += (tmp >> 8) & 0xFF00FF;
    629       rb += tmp & 0xFF00FF;
    630 
    631       // Bottom right pixel of the 2x2 block.
    632       tmp = cur_src1[bump_x];
    633       ag += (tmp >> 8) & 0xFF00FF;
    634       rb += tmp & 0xFF00FF;
    635 
    636       // Put the channels back together, dividing each by 4 to get the average.
    637       // |ag| has the alpha and green channels shifted right by 8 bits from
    638       // there they should end up, so shifting left by 6 gives them in the
    639       // correct position divided by 4.
    640       *cur_dst++ = ((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00);
    641 
    642       cur_src0 += 2;
    643       cur_src1 += 2;
    644     }
    645   }
    646 
    647   return result;
    648 }
    649 
    650 // static
    651 SkBitmap SkBitmapOperations::UnPreMultiply(const SkBitmap& bitmap) {
    652   if (bitmap.isNull())
    653     return bitmap;
    654   if (bitmap.isOpaque())
    655     return bitmap;
    656 
    657   SkImageInfo info = bitmap.info();
    658   info.fAlphaType = kOpaque_SkAlphaType;
    659   SkBitmap opaque_bitmap;
    660   opaque_bitmap.allocPixels(info);
    661 
    662   {
    663     SkAutoLockPixels bitmap_lock(bitmap);
    664     SkAutoLockPixels opaque_bitmap_lock(opaque_bitmap);
    665     for (int y = 0; y < opaque_bitmap.height(); y++) {
    666       for (int x = 0; x < opaque_bitmap.width(); x++) {
    667         uint32 src_pixel = *bitmap.getAddr32(x, y);
    668         uint32* dst_pixel = opaque_bitmap.getAddr32(x, y);
    669         SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(src_pixel);
    670         *dst_pixel = unmultiplied;
    671       }
    672     }
    673   }
    674 
    675   return opaque_bitmap;
    676 }
    677 
    678 // static
    679 SkBitmap SkBitmapOperations::CreateTransposedBitmap(const SkBitmap& image) {
    680   DCHECK(image.colorType() == kN32_SkColorType);
    681 
    682   SkBitmap transposed;
    683   transposed.allocN32Pixels(image.height(), image.width());
    684 
    685   SkAutoLockPixels lock_image(image);
    686   SkAutoLockPixels lock_transposed(transposed);
    687 
    688   for (int y = 0; y < image.height(); ++y) {
    689     uint32* image_row = image.getAddr32(0, y);
    690     for (int x = 0; x < image.width(); ++x) {
    691       uint32* dst = transposed.getAddr32(y, x);
    692       *dst = image_row[x];
    693     }
    694   }
    695 
    696   return transposed;
    697 }
    698 
    699 // static
    700 SkBitmap SkBitmapOperations::CreateColorMask(const SkBitmap& bitmap,
    701                                              SkColor c) {
    702   DCHECK(bitmap.colorType() == kN32_SkColorType);
    703 
    704   SkBitmap color_mask;
    705   color_mask.allocN32Pixels(bitmap.width(), bitmap.height());
    706   color_mask.eraseARGB(0, 0, 0, 0);
    707 
    708   SkCanvas canvas(color_mask);
    709 
    710   skia::RefPtr<SkColorFilter> color_filter = skia::AdoptRef(
    711       SkColorFilter::CreateModeFilter(c, SkXfermode::kSrcIn_Mode));
    712   SkPaint paint;
    713   paint.setColorFilter(color_filter.get());
    714   canvas.drawBitmap(bitmap, SkIntToScalar(0), SkIntToScalar(0), &paint);
    715   return color_mask;
    716 }
    717 
    718 // static
    719 SkBitmap SkBitmapOperations::CreateDropShadow(
    720     const SkBitmap& bitmap,
    721     const gfx::ShadowValues& shadows) {
    722   DCHECK(bitmap.colorType() == kN32_SkColorType);
    723 
    724   // Shadow margin insets are negative values because they grow outside.
    725   // Negate them here as grow direction is not important and only pixel value
    726   // is of interest here.
    727   gfx::Insets shadow_margin = -gfx::ShadowValue::GetMargin(shadows);
    728 
    729   SkBitmap image_with_shadow;
    730   image_with_shadow.allocN32Pixels(bitmap.width() + shadow_margin.width(),
    731                                    bitmap.height() + shadow_margin.height());
    732   image_with_shadow.eraseARGB(0, 0, 0, 0);
    733 
    734   SkCanvas canvas(image_with_shadow);
    735   canvas.translate(SkIntToScalar(shadow_margin.left()),
    736                    SkIntToScalar(shadow_margin.top()));
    737 
    738   SkPaint paint;
    739   for (size_t i = 0; i < shadows.size(); ++i) {
    740     const gfx::ShadowValue& shadow = shadows[i];
    741     SkBitmap shadow_image = SkBitmapOperations::CreateColorMask(bitmap,
    742                                                                 shadow.color());
    743 
    744     skia::RefPtr<SkBlurImageFilter> filter =
    745         skia::AdoptRef(SkBlurImageFilter::Create(
    746             SkDoubleToScalar(shadow.blur()), SkDoubleToScalar(shadow.blur())));
    747     paint.setImageFilter(filter.get());
    748 
    749     canvas.saveLayer(0, &paint);
    750     canvas.drawBitmap(shadow_image,
    751                       SkIntToScalar(shadow.x()),
    752                       SkIntToScalar(shadow.y()));
    753     canvas.restore();
    754   }
    755 
    756   canvas.drawBitmap(bitmap, SkIntToScalar(0), SkIntToScalar(0));
    757   return image_with_shadow;
    758 }
    759 
    760 // static
    761 SkBitmap SkBitmapOperations::Rotate(const SkBitmap& source,
    762                                     RotationAmount rotation) {
    763   SkBitmap result;
    764   SkScalar angle = SkFloatToScalar(0.0f);
    765 
    766   switch (rotation) {
    767    case ROTATION_90_CW:
    768      angle = SkFloatToScalar(90.0f);
    769      result.allocN32Pixels(source.height(), source.width());
    770      break;
    771    case ROTATION_180_CW:
    772      angle = SkFloatToScalar(180.0f);
    773      result.allocN32Pixels(source.width(), source.height());
    774      break;
    775    case ROTATION_270_CW:
    776      angle = SkFloatToScalar(270.0f);
    777      result.allocN32Pixels(source.height(), source.width());
    778      break;
    779   }
    780 
    781   SkCanvas canvas(result);
    782   canvas.clear(SkColorSetARGB(0, 0, 0, 0));
    783 
    784   canvas.translate(SkFloatToScalar(result.width() * 0.5f),
    785                    SkFloatToScalar(result.height() * 0.5f));
    786   canvas.rotate(angle);
    787   canvas.translate(-SkFloatToScalar(source.width() * 0.5f),
    788                    -SkFloatToScalar(source.height() * 0.5f));
    789   canvas.drawBitmap(source, 0, 0);
    790   canvas.flush();
    791 
    792   return result;
    793 }
    794