| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 <stdlib.h> | 5 #include <stdlib.h> |
| 6 | 6 |
| 7 #include "skia/ext/image_operations.h" | 7 #include "skia/ext/image_operations.h" |
| 8 #include "skia/include/SkColorPriv.h" | |
| 9 #include "testing/gtest/include/gtest/gtest.h" | 8 #include "testing/gtest/include/gtest/gtest.h" |
| 10 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
| 11 | 10 |
| 12 namespace { | 11 namespace { |
| 13 | 12 |
| 14 // Computes the average pixel value for the given range, inclusive. | 13 // Computes the average pixel value for the given range, inclusive. |
| 15 uint32_t AveragePixel(const SkBitmap& bmp, | 14 uint32_t AveragePixel(const SkBitmap& bmp, |
| 16 int x_min, int x_max, | 15 int x_min, int x_max, |
| 17 int y_min, int y_max) { | 16 int y_min, int y_max) { |
| 18 float accum[4] = {0, 0, 0, 0}; | 17 float accum[4] = {0, 0, 0, 0}; |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 ASSERT_EQ(src_h, results.height()); | 138 ASSERT_EQ(src_h, results.height()); |
| 140 | 139 |
| 141 SkAutoLockPixels src_lock(src); | 140 SkAutoLockPixels src_lock(src); |
| 142 SkAutoLockPixels results_lock(results); | 141 SkAutoLockPixels results_lock(results); |
| 143 for (int y = 0; y < src_h; y++) { | 142 for (int y = 0; y < src_h; y++) { |
| 144 for (int x = 0; x < src_w; x++) { | 143 for (int x = 0; x < src_w; x++) { |
| 145 EXPECT_EQ(*src.getAddr32(x, y), *results.getAddr32(x, y)); | 144 EXPECT_EQ(*src.getAddr32(x, y), *results.getAddr32(x, y)); |
| 146 } | 145 } |
| 147 } | 146 } |
| 148 } | 147 } |
| 149 | |
| 150 // Blend two bitmaps together at 50% alpha and verify that the result | |
| 151 // is the middle-blend of the two. | |
| 152 TEST(ImageOperations, CreateBlendedBitmap) { | |
| 153 int src_w = 16, src_h = 16; | |
| 154 SkBitmap src_a; | |
| 155 src_a.setConfig(SkBitmap::kARGB_8888_Config, src_w, src_h); | |
| 156 src_a.allocPixels(); | |
| 157 | |
| 158 SkBitmap src_b; | |
| 159 src_b.setConfig(SkBitmap::kARGB_8888_Config, src_w, src_h); | |
| 160 src_b.allocPixels(); | |
| 161 | |
| 162 for (int y = 0, i = 0; y < src_h; y++) { | |
| 163 for (int x = 0; x < src_w; x++) { | |
| 164 *src_a.getAddr32(x, y) = SkColorSetARGB(255, 0, i * 2 % 255, i % 255); | |
| 165 *src_b.getAddr32(x, y) = | |
| 166 SkColorSetARGB((255 - i) % 255, i % 255, i * 4 % 255, 0); | |
| 167 i++; | |
| 168 } | |
| 169 } | |
| 170 | |
| 171 // Shift to red. | |
| 172 SkBitmap blended = skia::ImageOperations::CreateBlendedBitmap( | |
| 173 src_a, src_b, 0.5); | |
| 174 SkAutoLockPixels srca_lock(src_a); | |
| 175 SkAutoLockPixels srcb_lock(src_b); | |
| 176 SkAutoLockPixels blended_lock(blended); | |
| 177 | |
| 178 for (int y = 0; y < src_h; y++) { | |
| 179 for (int x = 0; x < src_w; x++) { | |
| 180 int i = y * src_w + x; | |
| 181 EXPECT_EQ((255 + ((255 - i) % 255)) / 2, | |
| 182 SkColorGetA(*blended.getAddr32(x, y))); | |
| 183 EXPECT_EQ(i % 255 / 2, | |
| 184 SkColorGetR(*blended.getAddr32(x, y))); | |
| 185 EXPECT_EQ(((i * 2) % 255 + (i * 4) % 255) / 2, | |
| 186 SkColorGetG(*blended.getAddr32(x, y))); | |
| 187 EXPECT_EQ(i % 255 / 2, | |
| 188 SkColorGetB(*blended.getAddr32(x, y))); | |
| 189 } | |
| 190 } | |
| 191 } | |
| 192 | |
| 193 // Test our masking functions. | |
| 194 TEST(ImageOperations, CreateMaskedBitmap) { | |
| 195 int src_w = 16, src_h = 16; | |
| 196 | |
| 197 SkBitmap src; | |
| 198 FillDataToBitmap(src_w, src_h, &src); | |
| 199 | |
| 200 // Generate alpha mask | |
| 201 SkBitmap alpha; | |
| 202 alpha.setConfig(SkBitmap::kARGB_8888_Config, src_w, src_h); | |
| 203 alpha.allocPixels(); | |
| 204 | |
| 205 unsigned char* src_data = | |
| 206 reinterpret_cast<unsigned char*>(alpha.getAddr32(0, 0)); | |
| 207 for (int i = 0; i < src_w * src_h; i++) { | |
| 208 src_data[i * 4] = SkColorSetARGB(i + 128 % 255, | |
| 209 i + 128 % 255, | |
| 210 i + 64 % 255, | |
| 211 i + 0 % 255); | |
| 212 } | |
| 213 | |
| 214 SkBitmap masked = skia::ImageOperations::CreateMaskedBitmap(src, alpha); | |
| 215 | |
| 216 SkAutoLockPixels src_lock(src); | |
| 217 SkAutoLockPixels masked_lock(masked); | |
| 218 for (int y = 0; y < src_h; y++) { | |
| 219 for (int x = 0; x < src_w; x++) { | |
| 220 // Test that the alpha is equal. | |
| 221 SkColor src_pixel = *src.getAddr32(x, y); | |
| 222 SkColor alpha_pixel = *alpha.getAddr32(x, y); | |
| 223 SkColor masked_pixel = *masked.getAddr32(x, y); | |
| 224 | |
| 225 // Test that the alpha is equal. | |
| 226 int alpha = (alpha_pixel & 0xff000000) >> SK_A32_SHIFT; | |
| 227 EXPECT_EQ(alpha, (masked_pixel & 0xff000000) >> SK_A32_SHIFT); | |
| 228 | |
| 229 // Test that the colors are right - SkBitmaps have premultiplied alpha, | |
| 230 // so we can't just do a direct comparison. | |
| 231 EXPECT_EQ(SkColorGetR(masked_pixel), | |
| 232 SkAlphaMul(SkColorGetR(src_pixel), alpha)); | |
| 233 } | |
| 234 } | |
| 235 } | |
| 236 | |
| 237 // Testing blur without reimplementing the blur algorithm here is tough, | |
| 238 // so we just check to see if the pixels have moved in the direction we | |
| 239 // think they should move in (and also checking the wrapping behavior). | |
| 240 // This will allow us to tweak the blur algorithm to suit speed/visual | |
| 241 // needs without breaking the fundamentals. | |
| 242 TEST(ImageOperations, CreateBlurredBitmap) { | |
| 243 int src_w = 4, src_h = 4; | |
| 244 SkBitmap src; | |
| 245 src.setConfig(SkBitmap::kARGB_8888_Config, src_w, src_h); | |
| 246 src.allocPixels(); | |
| 247 | |
| 248 for (int y = 0, i = 0; y < src_h; y++) { | |
| 249 for (int x = 0; x < src_w; x++) { | |
| 250 int r = (y == 0) ? 255 : 0; // Make the top row red. | |
| 251 int g = (i % 2 == 0) ? 255 : 0; // Make green alternate in each pixel. | |
| 252 int b = (y == src_h - 1) ? 255 : 0; // Make the bottom row blue. | |
| 253 | |
| 254 *src.getAddr32(x, y) = SkColorSetARGB(255, r, g, b); | |
| 255 i++; | |
| 256 } | |
| 257 } | |
| 258 | |
| 259 // Perform a small blur (enough to shove the values in the direction we | |
| 260 // need - more would just be an unneccessary unit test slowdown). | |
| 261 SkBitmap blurred = skia::ImageOperations::CreateBlurredBitmap(src, 2); | |
| 262 | |
| 263 SkAutoLockPixels src_lock(src); | |
| 264 SkAutoLockPixels blurred_lock(blurred); | |
| 265 for (int y = 0, i = 0; y < src_w; y++) { | |
| 266 for (int x = 0; x < src_h; x++) { | |
| 267 SkColor src_pixel = *src.getAddr32(x, y); | |
| 268 SkColor blurred_pixel = *blurred.getAddr32(x, y); | |
| 269 if (y == 0) { | |
| 270 // We expect our red to have decreased, but our blue to have | |
| 271 // increased (from the wrapping from the bottom line). | |
| 272 EXPECT_TRUE(SkColorGetR(blurred_pixel) < SkColorGetR(src_pixel)); | |
| 273 EXPECT_TRUE(SkColorGetB(blurred_pixel) > SkColorGetB(src_pixel)); | |
| 274 } else if (y == src_h - 1) { | |
| 275 // Now for the opposite. | |
| 276 EXPECT_TRUE(SkColorGetB(blurred_pixel) < SkColorGetB(src_pixel)); | |
| 277 EXPECT_TRUE(SkColorGetR(blurred_pixel) > SkColorGetR(src_pixel)); | |
| 278 } | |
| 279 | |
| 280 // Expect the green channel to have moved towards the center (but | |
| 281 // not past it). | |
| 282 if (i % 2 == 0) { | |
| 283 EXPECT_LT(SkColorGetG(blurred_pixel), SkColorGetG(src_pixel)); | |
| 284 EXPECT_GE(SkColorGetG(blurred_pixel), static_cast<uint32>(128)); | |
| 285 } else { | |
| 286 EXPECT_GT(SkColorGetG(blurred_pixel), SkColorGetG(src_pixel)); | |
| 287 EXPECT_LE(SkColorGetG(blurred_pixel), static_cast<uint32>(128)); | |
| 288 } | |
| 289 | |
| 290 i++; | |
| 291 } | |
| 292 } | |
| 293 } | |
| 294 | |
| 295 // Make sure that when shifting a bitmap without any shift parameters, | |
| 296 // the end result is close enough to the original (rounding errors | |
| 297 // notwithstanding). | |
| 298 TEST(ImageOperations, CreateHSLShiftedBitmapToSame) { | |
| 299 int src_w = 4, src_h = 4; | |
| 300 SkBitmap src; | |
| 301 src.setConfig(SkBitmap::kARGB_8888_Config, src_w, src_h); | |
| 302 src.allocPixels(); | |
| 303 | |
| 304 for (int y = 0, i = 0; y < src_h; y++) { | |
| 305 for (int x = 0; x < src_w; x++) { | |
| 306 *src.getAddr32(x, y) = SkColorSetARGB(i + 128 % 255, | |
| 307 i + 128 % 255, i + 64 % 255, i + 0 % 255); | |
| 308 i++; | |
| 309 } | |
| 310 } | |
| 311 | |
| 312 float hsl[3] = { -1, -1, -1 }; | |
| 313 | |
| 314 SkBitmap shifted = skia::ImageOperations::CreateHSLShiftedBitmap(src, hsl); | |
| 315 | |
| 316 SkAutoLockPixels src_lock(src); | |
| 317 SkAutoLockPixels shifted_lock(shifted); | |
| 318 | |
| 319 for (int y = 0; y < src_w; y++) { | |
| 320 for (int x = 0; x < src_h; x++) { | |
| 321 SkColor src_pixel = *src.getAddr32(x, y); | |
| 322 SkColor shifted_pixel = *shifted.getAddr32(x, y); | |
| 323 EXPECT_TRUE(ColorsClose(src_pixel, shifted_pixel)); | |
| 324 } | |
| 325 } | |
| 326 } | |
| 327 | |
| 328 // Shift a blue bitmap to red. | |
| 329 TEST(ImageOperations, CreateHSLShiftedBitmapHueOnly) { | |
| 330 int src_w = 16, src_h = 16; | |
| 331 SkBitmap src; | |
| 332 src.setConfig(SkBitmap::kARGB_8888_Config, src_w, src_h); | |
| 333 src.allocPixels(); | |
| 334 | |
| 335 for (int y = 0, i = 0; y < src_h; y++) { | |
| 336 for (int x = 0; x < src_w; x++) { | |
| 337 *src.getAddr32(x, y) = SkColorSetARGB(255, 0, 0, i % 255); | |
| 338 i++; | |
| 339 } | |
| 340 } | |
| 341 | |
| 342 // Shift to red. | |
| 343 float hsl[3] = { 0, -1, -1 }; | |
| 344 | |
| 345 SkBitmap shifted = skia::ImageOperations::CreateHSLShiftedBitmap(src, hsl); | |
| 346 | |
| 347 SkAutoLockPixels src_lock(src); | |
| 348 SkAutoLockPixels shifted_lock(shifted); | |
| 349 | |
| 350 for (int y = 0, i = 0; y < src_h; y++) { | |
| 351 for (int x = 0; x < src_w; x++) { | |
| 352 EXPECT_TRUE(ColorsClose(*shifted.getAddr32(x, y), | |
| 353 SkColorSetARGB(255, i % 255, 0, 0))); | |
| 354 i++; | |
| 355 } | |
| 356 } | |
| 357 } | |
| 358 | |
| 359 // Test our cropping. | |
| 360 TEST(ImageOperations, CreateCroppedBitmap) { | |
| 361 int src_w = 16, src_h = 16; | |
| 362 SkBitmap src; | |
| 363 FillDataToBitmap(src_w, src_h, &src); | |
| 364 | |
| 365 SkBitmap cropped = skia::ImageOperations::CreateTiledBitmap(src, 4, 4, | |
| 366 8, 8); | |
| 367 ASSERT_EQ(8, cropped.width()); | |
| 368 ASSERT_EQ(8, cropped.height()); | |
| 369 | |
| 370 SkAutoLockPixels src_lock(src); | |
| 371 SkAutoLockPixels cropped_lock(cropped); | |
| 372 for (int y = 4; y < 12; y++) { | |
| 373 for (int x = 4; x < 12; x++) { | |
| 374 EXPECT_EQ(*src.getAddr32(x, y), | |
| 375 *cropped.getAddr32(x - 4, y - 4)); | |
| 376 } | |
| 377 } | |
| 378 } | |
| 379 | |
| 380 // Test whether our cropping correctly wraps across image boundaries. | |
| 381 TEST(ImageOperations, CreateCroppedBitmapWrapping) { | |
| 382 int src_w = 16, src_h = 16; | |
| 383 SkBitmap src; | |
| 384 FillDataToBitmap(src_w, src_h, &src); | |
| 385 | |
| 386 SkBitmap cropped = skia::ImageOperations::CreateTiledBitmap( | |
| 387 src, src_w / 2, src_h / 2, src_w, src_h); | |
| 388 ASSERT_EQ(src_w, cropped.width()); | |
| 389 ASSERT_EQ(src_h, cropped.height()); | |
| 390 | |
| 391 SkAutoLockPixels src_lock(src); | |
| 392 SkAutoLockPixels cropped_lock(cropped); | |
| 393 for (int y = 0; y < src_h; y++) { | |
| 394 for (int x = 0; x < src_w; x++) { | |
| 395 EXPECT_EQ(*src.getAddr32(x, y), | |
| 396 *cropped.getAddr32((x + src_w / 2) % src_w, | |
| 397 (y + src_h / 2) % src_h)); | |
| 398 } | |
| 399 } | |
| 400 } | |
| 401 | |
| OLD | NEW |