OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "core/html/ImageData.h" | 5 #include "core/html/ImageData.h" |
6 | 6 |
7 #include "core/dom/ExceptionCode.h" | 7 #include "core/dom/ExceptionCode.h" |
8 #include "platform/geometry/IntSize.h" | 8 #include "platform/geometry/IntSize.h" |
9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
10 #include "third_party/skia/include/core/SkColorSpaceXform.h" | 10 #include "third_party/skia/include/core/SkColorSpaceXform.h" |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 return false; | 243 return false; |
244 } | 244 } |
245 | 245 |
246 SkColorSpaceXform::ColorFormat dst_color_format = | 246 SkColorSpaceXform::ColorFormat dst_color_format = |
247 SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat; | 247 SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat; |
248 if (dst_pixel_format == kF16CanvasPixelFormat) | 248 if (dst_pixel_format == kF16CanvasPixelFormat) |
249 dst_color_format = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat; | 249 dst_color_format = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat; |
250 | 250 |
251 sk_sp<SkColorSpace> src_sk_color_space = nullptr; | 251 sk_sp<SkColorSpace> src_sk_color_space = nullptr; |
252 if (u8_array) { | 252 if (u8_array) { |
253 src_sk_color_space = ImageData::GetSkColorSpaceForTest( | 253 src_sk_color_space = |
254 src_color_space, kRGBA8CanvasPixelFormat); | 254 CanvasColorParams(src_color_space, kRGBA8CanvasPixelFormat) |
| 255 .GetSkColorSpaceForSkSurfaces(); |
255 } else { | 256 } else { |
256 src_sk_color_space = ImageData::GetSkColorSpaceForTest( | 257 src_sk_color_space = |
257 src_color_space, kF16CanvasPixelFormat); | 258 CanvasColorParams(src_color_space, kF16CanvasPixelFormat) |
| 259 .GetSkColorSpaceForSkSurfaces(); |
258 } | 260 } |
259 | 261 |
260 sk_sp<SkColorSpace> dst_sk_color_space = | 262 sk_sp<SkColorSpace> dst_sk_color_space = |
261 ImageData::GetSkColorSpaceForTest(dst_color_space, dst_pixel_format); | 263 CanvasColorParams(dst_color_space, dst_pixel_format) |
| 264 .GetSkColorSpaceForSkSurfaces(); |
262 | 265 |
263 // When the input dataArray is in Uint16, we normally should convert the | 266 // When the input dataArray is in Uint16, we normally should convert the |
264 // values from Little Endian to Big Endian before passing the buffer to | 267 // values from Little Endian to Big Endian before passing the buffer to |
265 // SkColorSpaceXform::apply. However, in this test scenario we are creating | 268 // SkColorSpaceXform::apply. However, in this test scenario we are creating |
266 // the Uin16 dataArray by multiplying a Uint8Clamped array members by 257, | 269 // the Uin16 dataArray by multiplying a Uint8Clamped array members by 257, |
267 // hence the Big Endian and Little Endian representations are the same. | 270 // hence the Big Endian and Little Endian representations are the same. |
268 | 271 |
269 std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New( | 272 std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New( |
270 src_sk_color_space.get(), dst_sk_color_space.get()); | 273 src_sk_color_space.get(), dst_sk_color_space.get()); |
271 | 274 |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 EXPECT_EQ(0, | 396 EXPECT_EQ(0, |
394 memcmp(pixels_converted_manually.get(), | 397 memcmp(pixels_converted_manually.get(), |
395 pixels_converted_in_image_data.get(), output_length)); | 398 pixels_converted_in_image_data.get(), output_length)); |
396 } | 399 } |
397 } | 400 } |
398 } | 401 } |
399 delete[] u16_pixels; | 402 delete[] u16_pixels; |
400 delete[] f32_pixels; | 403 delete[] f32_pixels; |
401 } | 404 } |
402 | 405 |
| 406 // This test examines ImageData::MakeCopy() |
| 407 TEST_F(ImageDataTest, TestMakeCopy) { |
| 408 const int num_image_data_storage_formats = 3; |
| 409 ImageDataStorageFormat image_data_storage_formats[] = { |
| 410 kUint8ClampedArrayStorageFormat, kUint16ArrayStorageFormat, |
| 411 kFloat32ArrayStorageFormat, |
| 412 }; |
| 413 String image_data_storage_format_names[] = { |
| 414 kUint8ClampedArrayStorageFormatName, kUint16ArrayStorageFormatName, |
| 415 kFloat32ArrayStorageFormatName, |
| 416 }; |
| 417 |
| 418 // Source pixels |
| 419 unsigned width = 2; |
| 420 unsigned height = 2; |
| 421 unsigned data_length = width * height * 4; |
| 422 uint8_t* u8_pixels = new uint8_t[data_length]; |
| 423 uint16_t* u16_pixels = new uint16_t[data_length]; |
| 424 float* f32_pixels = new float[data_length]; |
| 425 |
| 426 // Fill the pixels with numbers related to their positions |
| 427 unsigned set_value = 0; |
| 428 unsigned index = 0; |
| 429 for (unsigned i = 0; i < height; i++) |
| 430 for (unsigned j = 0; j < width; j++) |
| 431 for (unsigned k = 0; k < 4; k++) { |
| 432 index = i * width * 4 + j * 4 + k; |
| 433 set_value = (i + 1) * (j + 1) * (k + 1); |
| 434 u8_pixels[index] = set_value % 255; |
| 435 u16_pixels[index] = (set_value * 257) % 65535; |
| 436 f32_pixels[index] = (set_value % 255) / 255.0f; |
| 437 } |
| 438 |
| 439 // Create ImageData objects |
| 440 DOMArrayBufferView* data_array = nullptr; |
| 441 |
| 442 DOMUint8ClampedArray* data_u8 = |
| 443 DOMUint8ClampedArray::Create(u8_pixels, data_length); |
| 444 DCHECK(data_u8); |
| 445 EXPECT_EQ(data_length, data_u8->length()); |
| 446 DOMUint16Array* data_u16 = DOMUint16Array::Create(u16_pixels, data_length); |
| 447 DCHECK(data_u16); |
| 448 EXPECT_EQ(data_length, data_u16->length()); |
| 449 DOMFloat32Array* data_f32 = DOMFloat32Array::Create(f32_pixels, data_length); |
| 450 DCHECK(data_f32); |
| 451 EXPECT_EQ(data_length, data_f32->length()); |
| 452 |
| 453 ImageData* image_data = nullptr; |
| 454 ImageData* copy_image_data = nullptr; |
| 455 |
| 456 for (int i = 0; i < num_image_data_storage_formats; i++) { |
| 457 if (image_data_storage_formats[i] == kUint8ClampedArrayStorageFormat) |
| 458 data_array = static_cast<DOMArrayBufferView*>(data_u8); |
| 459 else if (image_data_storage_formats[i] == kUint16ArrayStorageFormat) |
| 460 data_array = static_cast<DOMArrayBufferView*>(data_u16); |
| 461 else |
| 462 data_array = static_cast<DOMArrayBufferView*>(data_f32); |
| 463 |
| 464 ImageDataColorSettings color_settings; |
| 465 color_settings.setStorageFormat(image_data_storage_format_names[i]); |
| 466 image_data = ImageData::CreateForTest(IntSize(width, height), data_array, |
| 467 &color_settings); |
| 468 copy_image_data = image_data->MakeCopy(); |
| 469 EXPECT_TRUE(copy_image_data->Size() == image_data->Size()); |
| 470 EXPECT_TRUE(ImageData::CompareImageDataColorSettingsForTest(copy_image_data, |
| 471 image_data)); |
| 472 |
| 473 int data_size = |
| 474 image_data->Size().Width() * image_data->Size().Height() * 4 * |
| 475 ImageData::StorageFormatDataSize(color_settings.storageFormat()); |
| 476 |
| 477 if (image_data_storage_formats[i] == kUint8ClampedArrayStorageFormat) { |
| 478 EXPECT_TRUE(std::memcmp(image_data->data()->Data(), |
| 479 copy_image_data->data()->Data(), data_size) == 0); |
| 480 } else if (image_data_storage_formats[i] == kUint16ArrayStorageFormat) { |
| 481 EXPECT_TRUE( |
| 482 std::memcmp( |
| 483 image_data->dataUnion().getAsUint16Array().View()->Data(), |
| 484 copy_image_data->dataUnion().getAsUint16Array().View()->Data(), |
| 485 data_size) == 0); |
| 486 } else { |
| 487 EXPECT_TRUE( |
| 488 std::memcmp( |
| 489 image_data->dataUnion().getAsFloat32Array().View()->Data(), |
| 490 copy_image_data->dataUnion().getAsFloat32Array().View()->Data(), |
| 491 data_size) == 0); |
| 492 } |
| 493 } |
| 494 |
| 495 delete[] u8_pixels; |
| 496 delete[] u16_pixels; |
| 497 delete[] f32_pixels; |
| 498 } |
| 499 |
| 500 // This test examines ImageData::MakeSubset() |
| 501 TEST_F(ImageDataTest, TestMakeSubset) { |
| 502 const int num_image_data_storage_formats = 3; |
| 503 ImageDataStorageFormat image_data_storage_formats[] = { |
| 504 kUint8ClampedArrayStorageFormat, kUint16ArrayStorageFormat, |
| 505 kFloat32ArrayStorageFormat, |
| 506 }; |
| 507 String image_data_storage_format_names[] = { |
| 508 kUint8ClampedArrayStorageFormatName, kUint16ArrayStorageFormatName, |
| 509 kFloat32ArrayStorageFormatName, |
| 510 }; |
| 511 |
| 512 // Source pixels |
| 513 unsigned width = 40; |
| 514 unsigned height = 40; |
| 515 unsigned data_length = width * height * 4; |
| 516 uint8_t* u8_pixels = new uint8_t[data_length]; |
| 517 uint16_t* u16_pixels = new uint16_t[data_length]; |
| 518 float* f32_pixels = new float[data_length]; |
| 519 |
| 520 // Test scenarios |
| 521 const int num_test_cases = 8; |
| 522 const IntRect crop_test_cases[8] = { |
| 523 IntRect(1, 2, 1, 2), IntRect(10, 10, 20, 20), IntRect(10, 10, 40, 40), |
| 524 IntRect(0, 0, 10, 10), IntRect(0, 0, 10, 0), IntRect(0, 0, 0, 10), |
| 525 IntRect(10, 0, 10, 10), IntRect(0, 10, 10, 10), |
| 526 }; |
| 527 |
| 528 // Fill the pixels with numbers related to their positions |
| 529 unsigned set_value = 0; |
| 530 unsigned expected_value = 0; |
| 531 float fexpected_value = 0; |
| 532 unsigned index = 0; |
| 533 for (unsigned i = 0; i < height; i++) |
| 534 for (unsigned j = 0; j < width; j++) |
| 535 for (unsigned k = 0; k < 4; k++) { |
| 536 index = i * width * 4 + j * 4 + k; |
| 537 set_value = (i + 1) * (j + 1) * (k + 1); |
| 538 u8_pixels[index] = set_value % 255; |
| 539 u16_pixels[index] = (set_value * 257) % 65535; |
| 540 f32_pixels[index] = (set_value % 255) / 255.0f; |
| 541 } |
| 542 |
| 543 // Create ImageData objects |
| 544 DOMArrayBufferView* data_array = nullptr; |
| 545 |
| 546 DOMUint8ClampedArray* data_u8 = |
| 547 DOMUint8ClampedArray::Create(u8_pixels, data_length); |
| 548 DCHECK(data_u8); |
| 549 EXPECT_EQ(data_length, data_u8->length()); |
| 550 DOMUint16Array* data_u16 = DOMUint16Array::Create(u16_pixels, data_length); |
| 551 DCHECK(data_u16); |
| 552 EXPECT_EQ(data_length, data_u16->length()); |
| 553 DOMFloat32Array* data_f32 = DOMFloat32Array::Create(f32_pixels, data_length); |
| 554 DCHECK(data_f32); |
| 555 EXPECT_EQ(data_length, data_f32->length()); |
| 556 |
| 557 ImageData* image_data = nullptr; |
| 558 ImageData* cropped_image_data = nullptr; |
| 559 |
| 560 bool test_passed = true; |
| 561 for (int i = 0; i < num_image_data_storage_formats; i++) { |
| 562 if (image_data_storage_formats[i] == kUint8ClampedArrayStorageFormat) |
| 563 data_array = static_cast<DOMArrayBufferView*>(data_u8); |
| 564 else if (image_data_storage_formats[i] == kUint16ArrayStorageFormat) |
| 565 data_array = static_cast<DOMArrayBufferView*>(data_u16); |
| 566 else |
| 567 data_array = static_cast<DOMArrayBufferView*>(data_f32); |
| 568 |
| 569 ImageDataColorSettings color_settings; |
| 570 color_settings.setStorageFormat(image_data_storage_format_names[i]); |
| 571 image_data = ImageData::CreateForTest(IntSize(width, height), data_array, |
| 572 &color_settings); |
| 573 for (int j = 0; j < num_test_cases; j++) { |
| 574 // Test the size of the cropped image data |
| 575 IntRect src_rect(IntPoint(), image_data->Size()); |
| 576 IntRect crop_rect = Intersection(src_rect, crop_test_cases[j]); |
| 577 |
| 578 cropped_image_data = image_data->MakeSubset(crop_test_cases[j]); |
| 579 if (crop_rect.IsEmpty()) { |
| 580 EXPECT_FALSE(cropped_image_data); |
| 581 continue; |
| 582 } |
| 583 EXPECT_TRUE(cropped_image_data->Size() == crop_rect.Size()); |
| 584 |
| 585 // Test the content |
| 586 for (int k = 0; k < crop_rect.Height(); k++) |
| 587 for (int m = 0; m < crop_rect.Width(); m++) |
| 588 for (int n = 0; n < 4; n++) { |
| 589 index = k * cropped_image_data->Size().Width() * 4 + m * 4 + n; |
| 590 expected_value = |
| 591 (k + crop_rect.X() + 1) * (m + crop_rect.Y() + 1) * (n + 1); |
| 592 if (image_data_storage_formats[i] == |
| 593 kUint8ClampedArrayStorageFormat) |
| 594 expected_value %= 255; |
| 595 else if (image_data_storage_formats[i] == kUint16ArrayStorageFormat) |
| 596 expected_value = (expected_value * 257) % 65535; |
| 597 else |
| 598 fexpected_value = (expected_value % 255) / 255.0f; |
| 599 |
| 600 if (image_data_storage_formats[i] == |
| 601 kUint8ClampedArrayStorageFormat) { |
| 602 if (cropped_image_data->data()->Data()[index] != expected_value) { |
| 603 test_passed = false; |
| 604 break; |
| 605 } |
| 606 } else if (image_data_storage_formats[i] == |
| 607 kUint16ArrayStorageFormat) { |
| 608 if (cropped_image_data->dataUnion() |
| 609 .getAsUint16Array() |
| 610 .View() |
| 611 ->Data()[index] != expected_value) { |
| 612 test_passed = false; |
| 613 break; |
| 614 } |
| 615 } else { |
| 616 if (cropped_image_data->dataUnion() |
| 617 .getAsFloat32Array() |
| 618 .View() |
| 619 ->Data()[index] != fexpected_value) { |
| 620 test_passed = false; |
| 621 break; |
| 622 } |
| 623 } |
| 624 } |
| 625 EXPECT_TRUE(test_passed); |
| 626 } |
| 627 } |
| 628 |
| 629 delete[] u8_pixels; |
| 630 delete[] u16_pixels; |
| 631 delete[] f32_pixels; |
| 632 } |
| 633 |
403 } // namspace | 634 } // namspace |
404 } // namespace blink | 635 } // namespace blink |
OLD | NEW |