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" |
8 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
9 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
10 | 11 |
11 namespace { | 12 namespace { |
12 | 13 |
13 // Computes the average pixel value for the given range, inclusive. | 14 // Computes the average pixel value for the given range, inclusive. |
14 uint32_t AveragePixel(const SkBitmap& bmp, | 15 uint32_t AveragePixel(const SkBitmap& bmp, |
15 int x_min, int x_max, | 16 int x_min, int x_max, |
16 int y_min, int y_max) { | 17 int y_min, int y_max) { |
17 float accum[4] = {0, 0, 0, 0}; | 18 float accum[4] = {0, 0, 0, 0}; |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 ASSERT_EQ(src_h, results.height()); | 139 ASSERT_EQ(src_h, results.height()); |
139 | 140 |
140 SkAutoLockPixels src_lock(src); | 141 SkAutoLockPixels src_lock(src); |
141 SkAutoLockPixels results_lock(results); | 142 SkAutoLockPixels results_lock(results); |
142 for (int y = 0; y < src_h; y++) { | 143 for (int y = 0; y < src_h; y++) { |
143 for (int x = 0; x < src_w; x++) { | 144 for (int x = 0; x < src_w; x++) { |
144 EXPECT_EQ(*src.getAddr32(x, y), *results.getAddr32(x, y)); | 145 EXPECT_EQ(*src.getAddr32(x, y), *results.getAddr32(x, y)); |
145 } | 146 } |
146 } | 147 } |
147 } | 148 } |
| 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 |