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 "testing/gtest/include/gtest/gtest.h" 8#include "third_party/skia/include/core/SkBitmap.h" 9#include "third_party/skia/include/core/SkCanvas.h" 10#include "third_party/skia/include/core/SkColorPriv.h" 11#include "third_party/skia/include/core/SkRect.h" 12#include "third_party/skia/include/core/SkRegion.h" 13#include "third_party/skia/include/core/SkUnPreMultiply.h" 14 15namespace { 16 17// Returns true if each channel of the given two colors are "close." This is 18// used for comparing colors where rounding errors may cause off-by-one. 19inline bool ColorsClose(uint32_t a, uint32_t b) { 20 return abs(static_cast<int>(SkColorGetB(a) - SkColorGetB(b))) <= 2 && 21 abs(static_cast<int>(SkColorGetG(a) - SkColorGetG(b))) <= 2 && 22 abs(static_cast<int>(SkColorGetR(a) - SkColorGetR(b))) <= 2 && 23 abs(static_cast<int>(SkColorGetA(a) - SkColorGetA(b))) <= 2; 24} 25 26inline bool MultipliedColorsClose(uint32_t a, uint32_t b) { 27 return ColorsClose(SkUnPreMultiply::PMColorToColor(a), 28 SkUnPreMultiply::PMColorToColor(b)); 29} 30 31bool BitmapsClose(const SkBitmap& a, const SkBitmap& b) { 32 SkAutoLockPixels a_lock(a); 33 SkAutoLockPixels b_lock(b); 34 35 for (int y = 0; y < a.height(); y++) { 36 for (int x = 0; x < a.width(); x++) { 37 SkColor a_pixel = *a.getAddr32(x, y); 38 SkColor b_pixel = *b.getAddr32(x, y); 39 if (!ColorsClose(a_pixel, b_pixel)) 40 return false; 41 } 42 } 43 return true; 44} 45 46void FillDataToBitmap(int w, int h, SkBitmap* bmp) { 47 bmp->allocN32Pixels(w, h); 48 49 unsigned char* src_data = 50 reinterpret_cast<unsigned char*>(bmp->getAddr32(0, 0)); 51 for (int i = 0; i < w * h; i++) { 52 src_data[i * 4 + 0] = static_cast<unsigned char>(i % 255); 53 src_data[i * 4 + 1] = static_cast<unsigned char>(i % 255); 54 src_data[i * 4 + 2] = static_cast<unsigned char>(i % 255); 55 src_data[i * 4 + 3] = static_cast<unsigned char>(i % 255); 56 } 57} 58 59// The reference (i.e., old) implementation of |CreateHSLShiftedBitmap()|. 60SkBitmap ReferenceCreateHSLShiftedBitmap( 61 const SkBitmap& bitmap, 62 color_utils::HSL hsl_shift) { 63 SkBitmap shifted; 64 shifted.allocN32Pixels(bitmap.width(), bitmap.height()); 65 shifted.eraseARGB(0, 0, 0, 0); 66 67 SkAutoLockPixels lock_bitmap(bitmap); 68 SkAutoLockPixels lock_shifted(shifted); 69 70 // Loop through the pixels of the original bitmap. 71 for (int y = 0; y < bitmap.height(); ++y) { 72 SkPMColor* pixels = bitmap.getAddr32(0, y); 73 SkPMColor* tinted_pixels = shifted.getAddr32(0, y); 74 75 for (int x = 0; x < bitmap.width(); ++x) { 76 tinted_pixels[x] = SkPreMultiplyColor(color_utils::HSLShift( 77 SkUnPreMultiply::PMColorToColor(pixels[x]), hsl_shift)); 78 } 79 } 80 81 return shifted; 82} 83 84} // namespace 85 86// Invert bitmap and verify the each pixel is inverted and the alpha value is 87// not changed. 88TEST(SkBitmapOperationsTest, CreateInvertedBitmap) { 89 int src_w = 16, src_h = 16; 90 SkBitmap src; 91 src.allocN32Pixels(src_w, src_h); 92 93 for (int y = 0; y < src_h; y++) { 94 for (int x = 0; x < src_w; x++) { 95 int i = y * src_w + x; 96 *src.getAddr32(x, y) = 97 SkColorSetARGB((255 - i) % 255, i % 255, i * 4 % 255, 0); 98 } 99 } 100 101 SkBitmap inverted = SkBitmapOperations::CreateInvertedBitmap(src); 102 SkAutoLockPixels src_lock(src); 103 SkAutoLockPixels inverted_lock(inverted); 104 105 for (int y = 0; y < src_h; y++) { 106 for (int x = 0; x < src_w; x++) { 107 int i = y * src_w + x; 108 EXPECT_EQ(static_cast<unsigned int>((255 - i) % 255), 109 SkColorGetA(*inverted.getAddr32(x, y))); 110 EXPECT_EQ(static_cast<unsigned int>(255 - (i % 255)), 111 SkColorGetR(*inverted.getAddr32(x, y))); 112 EXPECT_EQ(static_cast<unsigned int>(255 - (i * 4 % 255)), 113 SkColorGetG(*inverted.getAddr32(x, y))); 114 EXPECT_EQ(static_cast<unsigned int>(255), 115 SkColorGetB(*inverted.getAddr32(x, y))); 116 } 117 } 118} 119 120// Blend two bitmaps together at 50% alpha and verify that the result 121// is the middle-blend of the two. 122TEST(SkBitmapOperationsTest, CreateBlendedBitmap) { 123 int src_w = 16, src_h = 16; 124 SkBitmap src_a; 125 src_a.allocN32Pixels(src_w, src_h); 126 127 SkBitmap src_b; 128 src_b.allocN32Pixels(src_w, src_h); 129 130 for (int y = 0, i = 0; y < src_h; y++) { 131 for (int x = 0; x < src_w; x++) { 132 *src_a.getAddr32(x, y) = SkColorSetARGB(255, 0, i * 2 % 255, i % 255); 133 *src_b.getAddr32(x, y) = 134 SkColorSetARGB((255 - i) % 255, i % 255, i * 4 % 255, 0); 135 i++; 136 } 137 } 138 139 // Shift to red. 140 SkBitmap blended = SkBitmapOperations::CreateBlendedBitmap( 141 src_a, src_b, 0.5); 142 SkAutoLockPixels srca_lock(src_a); 143 SkAutoLockPixels srcb_lock(src_b); 144 SkAutoLockPixels blended_lock(blended); 145 146 for (int y = 0; y < src_h; y++) { 147 for (int x = 0; x < src_w; x++) { 148 int i = y * src_w + x; 149 EXPECT_EQ(static_cast<unsigned int>((255 + ((255 - i) % 255)) / 2), 150 SkColorGetA(*blended.getAddr32(x, y))); 151 EXPECT_EQ(static_cast<unsigned int>(i % 255 / 2), 152 SkColorGetR(*blended.getAddr32(x, y))); 153 EXPECT_EQ((static_cast<unsigned int>((i * 2) % 255 + (i * 4) % 255) / 2), 154 SkColorGetG(*blended.getAddr32(x, y))); 155 EXPECT_EQ(static_cast<unsigned int>(i % 255 / 2), 156 SkColorGetB(*blended.getAddr32(x, y))); 157 } 158 } 159} 160 161// Test our masking functions. 162TEST(SkBitmapOperationsTest, CreateMaskedBitmap) { 163 int src_w = 16, src_h = 16; 164 165 SkBitmap src; 166 FillDataToBitmap(src_w, src_h, &src); 167 168 // Generate alpha mask 169 SkBitmap alpha; 170 alpha.allocN32Pixels(src_w, src_h); 171 for (int y = 0, i = 0; y < src_h; y++) { 172 for (int x = 0; x < src_w; x++) { 173 *alpha.getAddr32(x, y) = SkColorSetARGB((i + 128) % 255, 174 (i + 128) % 255, 175 (i + 64) % 255, 176 (i + 0) % 255); 177 i++; 178 } 179 } 180 181 SkBitmap masked = SkBitmapOperations::CreateMaskedBitmap(src, alpha); 182 183 SkAutoLockPixels src_lock(src); 184 SkAutoLockPixels alpha_lock(alpha); 185 SkAutoLockPixels masked_lock(masked); 186 for (int y = 0; y < src_h; y++) { 187 for (int x = 0; x < src_w; x++) { 188 // Test that the alpha is equal. 189 SkColor src_pixel = SkUnPreMultiply::PMColorToColor(*src.getAddr32(x, y)); 190 SkColor alpha_pixel = 191 SkUnPreMultiply::PMColorToColor(*alpha.getAddr32(x, y)); 192 SkColor masked_pixel = *masked.getAddr32(x, y); 193 194 int alpha_value = SkAlphaMul(SkColorGetA(src_pixel), 195 SkAlpha255To256(SkColorGetA(alpha_pixel))); 196 int alpha_value_256 = SkAlpha255To256(alpha_value); 197 SkColor expected_pixel = SkColorSetARGB( 198 alpha_value, 199 SkAlphaMul(SkColorGetR(src_pixel), alpha_value_256), 200 SkAlphaMul(SkColorGetG(src_pixel), alpha_value_256), 201 SkAlphaMul(SkColorGetB(src_pixel), alpha_value_256)); 202 203 EXPECT_EQ(expected_pixel, masked_pixel); 204 } 205 } 206} 207 208// Make sure that when shifting a bitmap without any shift parameters, 209// the end result is close enough to the original (rounding errors 210// notwithstanding). 211TEST(SkBitmapOperationsTest, CreateHSLShiftedBitmapToSame) { 212 int src_w = 16, src_h = 16; 213 SkBitmap src; 214 src.allocN32Pixels(src_w, src_h); 215 216 for (int y = 0, i = 0; y < src_h; y++) { 217 for (int x = 0; x < src_w; x++) { 218 *src.getAddr32(x, y) = SkPreMultiplyColor(SkColorSetARGB((i + 128) % 255, 219 (i + 128) % 255, (i + 64) % 255, (i + 0) % 255)); 220 i++; 221 } 222 } 223 224 color_utils::HSL hsl = { -1, -1, -1 }; 225 SkBitmap shifted = ReferenceCreateHSLShiftedBitmap(src, hsl); 226 227 SkAutoLockPixels src_lock(src); 228 SkAutoLockPixels shifted_lock(shifted); 229 230 for (int y = 0; y < src_h; y++) { 231 for (int x = 0; x < src_w; x++) { 232 SkColor src_pixel = *src.getAddr32(x, y); 233 SkColor shifted_pixel = *shifted.getAddr32(x, y); 234 EXPECT_TRUE(MultipliedColorsClose(src_pixel, shifted_pixel)) << 235 "source: (a,r,g,b) = (" << SkColorGetA(src_pixel) << "," << 236 SkColorGetR(src_pixel) << "," << 237 SkColorGetG(src_pixel) << "," << 238 SkColorGetB(src_pixel) << "); " << 239 "shifted: (a,r,g,b) = (" << SkColorGetA(shifted_pixel) << "," << 240 SkColorGetR(shifted_pixel) << "," << 241 SkColorGetG(shifted_pixel) << "," << 242 SkColorGetB(shifted_pixel) << ")"; 243 } 244 } 245} 246 247// Shift a blue bitmap to red. 248TEST(SkBitmapOperationsTest, CreateHSLShiftedBitmapHueOnly) { 249 int src_w = 16, src_h = 16; 250 SkBitmap src; 251 src.allocN32Pixels(src_w, src_h); 252 253 for (int y = 0, i = 0; y < src_h; y++) { 254 for (int x = 0; x < src_w; x++) { 255 *src.getAddr32(x, y) = SkColorSetARGB(255, 0, 0, i % 255); 256 i++; 257 } 258 } 259 260 // Shift to red. 261 color_utils::HSL hsl = { 0, -1, -1 }; 262 263 SkBitmap shifted = SkBitmapOperations::CreateHSLShiftedBitmap(src, hsl); 264 265 SkAutoLockPixels src_lock(src); 266 SkAutoLockPixels shifted_lock(shifted); 267 268 for (int y = 0, i = 0; y < src_h; y++) { 269 for (int x = 0; x < src_w; x++) { 270 EXPECT_TRUE(ColorsClose(shifted.getColor(x, y), 271 SkColorSetARGB(255, i % 255, 0, 0))); 272 i++; 273 } 274 } 275} 276 277// Validate HSL shift. 278TEST(SkBitmapOperationsTest, ValidateHSLShift) { 279 // Note: 255/51 = 5 (exactly) => 6 including 0! 280 const int inc = 51; 281 const int dim = 255 / inc + 1; 282 SkBitmap src; 283 src.allocN32Pixels(dim*dim, dim*dim); 284 285 for (int a = 0, y = 0; a <= 255; a += inc) { 286 for (int r = 0; r <= 255; r += inc, y++) { 287 for (int g = 0, x = 0; g <= 255; g += inc) { 288 for (int b = 0; b <= 255; b+= inc, x++) { 289 *src.getAddr32(x, y) = 290 SkPreMultiplyColor(SkColorSetARGB(a, r, g, b)); 291 } 292 } 293 } 294 } 295 296 // Shhhh. The spec says I should set things to -1 for "no change", but 297 // actually -0.1 will do. Don't tell anyone I did this. 298 for (double h = -0.1; h <= 1.0001; h += 0.1) { 299 for (double s = -0.1; s <= 1.0001; s += 0.1) { 300 for (double l = -0.1; l <= 1.0001; l += 0.1) { 301 color_utils::HSL hsl = { h, s, l }; 302 SkBitmap ref_shifted = ReferenceCreateHSLShiftedBitmap(src, hsl); 303 SkBitmap shifted = SkBitmapOperations::CreateHSLShiftedBitmap(src, hsl); 304 EXPECT_TRUE(BitmapsClose(ref_shifted, shifted)) 305 << "h = " << h << ", s = " << s << ", l = " << l; 306 } 307 } 308 } 309} 310 311// Test our cropping. 312TEST(SkBitmapOperationsTest, CreateCroppedBitmap) { 313 int src_w = 16, src_h = 16; 314 SkBitmap src; 315 FillDataToBitmap(src_w, src_h, &src); 316 317 SkBitmap cropped = SkBitmapOperations::CreateTiledBitmap(src, 4, 4, 318 8, 8); 319 ASSERT_EQ(8, cropped.width()); 320 ASSERT_EQ(8, cropped.height()); 321 322 SkAutoLockPixels src_lock(src); 323 SkAutoLockPixels cropped_lock(cropped); 324 for (int y = 4; y < 12; y++) { 325 for (int x = 4; x < 12; x++) { 326 EXPECT_EQ(*src.getAddr32(x, y), 327 *cropped.getAddr32(x - 4, y - 4)); 328 } 329 } 330} 331 332// Test whether our cropping correctly wraps across image boundaries. 333TEST(SkBitmapOperationsTest, CreateCroppedBitmapWrapping) { 334 int src_w = 16, src_h = 16; 335 SkBitmap src; 336 FillDataToBitmap(src_w, src_h, &src); 337 338 SkBitmap cropped = SkBitmapOperations::CreateTiledBitmap( 339 src, src_w / 2, src_h / 2, src_w, src_h); 340 ASSERT_EQ(src_w, cropped.width()); 341 ASSERT_EQ(src_h, cropped.height()); 342 343 SkAutoLockPixels src_lock(src); 344 SkAutoLockPixels cropped_lock(cropped); 345 for (int y = 0; y < src_h; y++) { 346 for (int x = 0; x < src_w; x++) { 347 EXPECT_EQ(*src.getAddr32(x, y), 348 *cropped.getAddr32((x + src_w / 2) % src_w, 349 (y + src_h / 2) % src_h)); 350 } 351 } 352} 353 354TEST(SkBitmapOperationsTest, DownsampleByTwo) { 355 // Use an odd-sized bitmap to make sure the edge cases where there isn't a 356 // 2x2 block of pixels is handled correctly. 357 // Here's the ARGB example 358 // 359 // 50% transparent green opaque 50% blue white 360 // 80008000 FF000080 FFFFFFFF 361 // 362 // 50% transparent red opaque 50% gray black 363 // 80800000 80808080 FF000000 364 // 365 // black white 50% gray 366 // FF000000 FFFFFFFF FF808080 367 // 368 // The result of this computation should be: 369 // A0404040 FF808080 370 // FF808080 FF808080 371 SkBitmap input; 372 input.allocN32Pixels(3, 3); 373 374 // The color order may be different, but we don't care (the channels are 375 // trated the same). 376 *input.getAddr32(0, 0) = 0x80008000; 377 *input.getAddr32(1, 0) = 0xFF000080; 378 *input.getAddr32(2, 0) = 0xFFFFFFFF; 379 *input.getAddr32(0, 1) = 0x80800000; 380 *input.getAddr32(1, 1) = 0x80808080; 381 *input.getAddr32(2, 1) = 0xFF000000; 382 *input.getAddr32(0, 2) = 0xFF000000; 383 *input.getAddr32(1, 2) = 0xFFFFFFFF; 384 *input.getAddr32(2, 2) = 0xFF808080; 385 386 SkBitmap result = SkBitmapOperations::DownsampleByTwo(input); 387 EXPECT_EQ(2, result.width()); 388 EXPECT_EQ(2, result.height()); 389 390 // Some of the values are off-by-one due to rounding. 391 SkAutoLockPixels lock(result); 392 EXPECT_EQ(0x9f404040, *result.getAddr32(0, 0)); 393 EXPECT_EQ(0xFF7f7f7f, *result.getAddr32(1, 0)); 394 EXPECT_EQ(0xFF7f7f7f, *result.getAddr32(0, 1)); 395 EXPECT_EQ(0xFF808080, *result.getAddr32(1, 1)); 396} 397 398// Test edge cases for DownsampleByTwo. 399TEST(SkBitmapOperationsTest, DownsampleByTwoSmall) { 400 SkPMColor reference = 0xFF4080FF; 401 402 // Test a 1x1 bitmap. 403 SkBitmap one_by_one; 404 one_by_one.allocN32Pixels(1, 1); 405 *one_by_one.getAddr32(0, 0) = reference; 406 SkBitmap result = SkBitmapOperations::DownsampleByTwo(one_by_one); 407 SkAutoLockPixels lock1(result); 408 EXPECT_EQ(1, result.width()); 409 EXPECT_EQ(1, result.height()); 410 EXPECT_EQ(reference, *result.getAddr32(0, 0)); 411 412 // Test an n by 1 bitmap. 413 SkBitmap one_by_n; 414 one_by_n.allocN32Pixels(300, 1); 415 result = SkBitmapOperations::DownsampleByTwo(one_by_n); 416 SkAutoLockPixels lock2(result); 417 EXPECT_EQ(300, result.width()); 418 EXPECT_EQ(1, result.height()); 419 420 // Test a 1 by n bitmap. 421 SkBitmap n_by_one; 422 n_by_one.allocN32Pixels(1, 300); 423 result = SkBitmapOperations::DownsampleByTwo(n_by_one); 424 SkAutoLockPixels lock3(result); 425 EXPECT_EQ(1, result.width()); 426 EXPECT_EQ(300, result.height()); 427 428 // Test an empty bitmap 429 SkBitmap empty; 430 result = SkBitmapOperations::DownsampleByTwo(empty); 431 EXPECT_TRUE(result.isNull()); 432 EXPECT_EQ(0, result.width()); 433 EXPECT_EQ(0, result.height()); 434} 435 436// Here we assume DownsampleByTwo works correctly (it's tested above) and 437// just make sure that the wrapper function does the right thing. 438TEST(SkBitmapOperationsTest, DownsampleByTwoUntilSize) { 439 // First make sure a "too small" bitmap doesn't get modified at all. 440 SkBitmap too_small; 441 too_small.allocN32Pixels(10, 10); 442 SkBitmap result = SkBitmapOperations::DownsampleByTwoUntilSize( 443 too_small, 16, 16); 444 EXPECT_EQ(10, result.width()); 445 EXPECT_EQ(10, result.height()); 446 447 // Now make sure giving it a 0x0 target returns something reasonable. 448 result = SkBitmapOperations::DownsampleByTwoUntilSize(too_small, 0, 0); 449 EXPECT_EQ(1, result.width()); 450 EXPECT_EQ(1, result.height()); 451 452 // Test multiple steps of downsampling. 453 SkBitmap large; 454 large.allocN32Pixels(100, 43); 455 result = SkBitmapOperations::DownsampleByTwoUntilSize(large, 6, 6); 456 457 // The result should be divided in half 100x43 -> 50x22 -> 25x11 458 EXPECT_EQ(25, result.width()); 459 EXPECT_EQ(11, result.height()); 460} 461 462TEST(SkBitmapOperationsTest, UnPreMultiply) { 463 SkBitmap input; 464 input.allocN32Pixels(2, 2); 465 466 // Set PMColors into the bitmap 467 *input.getAddr32(0, 0) = SkPackARGB32NoCheck(0x80, 0x00, 0x00, 0x00); 468 *input.getAddr32(1, 0) = SkPackARGB32NoCheck(0x80, 0x80, 0x80, 0x80); 469 *input.getAddr32(0, 1) = SkPackARGB32NoCheck(0xFF, 0x00, 0xCC, 0x88); 470 *input.getAddr32(1, 1) = SkPackARGB32NoCheck(0x00, 0x00, 0xCC, 0x88); 471 472 SkBitmap result = SkBitmapOperations::UnPreMultiply(input); 473 EXPECT_EQ(2, result.width()); 474 EXPECT_EQ(2, result.height()); 475 476 SkAutoLockPixels lock(result); 477 EXPECT_EQ(0x80000000, *result.getAddr32(0, 0)); 478 EXPECT_EQ(0x80FFFFFF, *result.getAddr32(1, 0)); 479 EXPECT_EQ(0xFF00CC88, *result.getAddr32(0, 1)); 480 EXPECT_EQ(0x00000000u, *result.getAddr32(1, 1)); // "Division by zero". 481} 482 483TEST(SkBitmapOperationsTest, CreateTransposedBitmap) { 484 SkBitmap input; 485 input.allocN32Pixels(2, 3); 486 487 for (int x = 0; x < input.width(); ++x) { 488 for (int y = 0; y < input.height(); ++y) { 489 *input.getAddr32(x, y) = x * input.width() + y; 490 } 491 } 492 493 SkBitmap result = SkBitmapOperations::CreateTransposedBitmap(input); 494 EXPECT_EQ(3, result.width()); 495 EXPECT_EQ(2, result.height()); 496 497 SkAutoLockPixels lock(result); 498 for (int x = 0; x < input.width(); ++x) { 499 for (int y = 0; y < input.height(); ++y) { 500 EXPECT_EQ(*input.getAddr32(x, y), *result.getAddr32(y, x)); 501 } 502 } 503} 504 505// Check that Rotate provides the desired results 506TEST(SkBitmapOperationsTest, RotateImage) { 507 const int src_w = 6, src_h = 4; 508 SkBitmap src; 509 // Create a simple 4 color bitmap: 510 // RRRBBB 511 // RRRBBB 512 // GGGYYY 513 // GGGYYY 514 src.allocN32Pixels(src_w, src_h); 515 516 SkCanvas canvas(src); 517 src.eraseARGB(0, 0, 0, 0); 518 SkRegion region; 519 520 region.setRect(0, 0, src_w / 2, src_h / 2); 521 canvas.setClipRegion(region); 522 // This region is a semi-transparent red to test non-opaque pixels. 523 canvas.drawColor(0x1FFF0000, SkXfermode::kSrc_Mode); 524 region.setRect(src_w / 2, 0, src_w, src_h / 2); 525 canvas.setClipRegion(region); 526 canvas.drawColor(SK_ColorBLUE, SkXfermode::kSrc_Mode); 527 region.setRect(0, src_h / 2, src_w / 2, src_h); 528 canvas.setClipRegion(region); 529 canvas.drawColor(SK_ColorGREEN, SkXfermode::kSrc_Mode); 530 region.setRect(src_w / 2, src_h / 2, src_w, src_h); 531 canvas.setClipRegion(region); 532 canvas.drawColor(SK_ColorYELLOW, SkXfermode::kSrc_Mode); 533 canvas.flush(); 534 535 SkBitmap rotate90, rotate180, rotate270; 536 rotate90 = SkBitmapOperations::Rotate(src, 537 SkBitmapOperations::ROTATION_90_CW); 538 rotate180 = SkBitmapOperations::Rotate(src, 539 SkBitmapOperations::ROTATION_180_CW); 540 rotate270 = SkBitmapOperations::Rotate(src, 541 SkBitmapOperations::ROTATION_270_CW); 542 543 ASSERT_EQ(rotate90.width(), src.height()); 544 ASSERT_EQ(rotate90.height(), src.width()); 545 ASSERT_EQ(rotate180.width(), src.width()); 546 ASSERT_EQ(rotate180.height(), src.height()); 547 ASSERT_EQ(rotate270.width(), src.height()); 548 ASSERT_EQ(rotate270.height(), src.width()); 549 550 SkAutoLockPixels lock_src(src); 551 SkAutoLockPixels lock_90(rotate90); 552 SkAutoLockPixels lock_180(rotate180); 553 SkAutoLockPixels lock_270(rotate270); 554 555 for (int x=0; x < src_w; ++x) { 556 for (int y=0; y < src_h; ++y) { 557 ASSERT_EQ(*src.getAddr32(x,y), *rotate90.getAddr32(src_h - (y+1),x)); 558 ASSERT_EQ(*src.getAddr32(x,y), *rotate270.getAddr32(y, src_w - (x+1))); 559 ASSERT_EQ(*src.getAddr32(x,y), 560 *rotate180.getAddr32(src_w - (x+1), src_h - (y+1))); 561 } 562 } 563} 564