PremulAlphaRoundTripTest.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /*
  2. * Copyright 2011 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "include/core/SkCanvas.h"
  8. #include "include/core/SkSurface.h"
  9. #include "tests/Test.h"
  10. #include "tools/ToolUtils.h"
  11. #include "include/gpu/GrContext.h"
  12. static uint32_t pack_unpremul_rgba(SkColor c) {
  13. uint32_t packed;
  14. uint8_t* byte = reinterpret_cast<uint8_t*>(&packed);
  15. byte[0] = SkColorGetR(c);
  16. byte[1] = SkColorGetG(c);
  17. byte[2] = SkColorGetB(c);
  18. byte[3] = SkColorGetA(c);
  19. return packed;
  20. }
  21. static uint32_t pack_unpremul_bgra(SkColor c) {
  22. uint32_t packed;
  23. uint8_t* byte = reinterpret_cast<uint8_t*>(&packed);
  24. byte[0] = SkColorGetB(c);
  25. byte[1] = SkColorGetG(c);
  26. byte[2] = SkColorGetR(c);
  27. byte[3] = SkColorGetA(c);
  28. return packed;
  29. }
  30. typedef uint32_t (*PackUnpremulProc)(SkColor);
  31. const struct {
  32. SkColorType fColorType;
  33. PackUnpremulProc fPackProc;
  34. } gUnpremul[] = {
  35. { kRGBA_8888_SkColorType, pack_unpremul_rgba },
  36. { kBGRA_8888_SkColorType, pack_unpremul_bgra },
  37. };
  38. static void fill_surface(SkSurface* surf, SkColorType colorType, PackUnpremulProc proc) {
  39. // Don't strictly need a bitmap, but its a handy way to allocate the pixels
  40. SkBitmap bmp;
  41. bmp.allocN32Pixels(256, 256);
  42. for (int a = 0; a < 256; ++a) {
  43. uint32_t* pixels = bmp.getAddr32(0, a);
  44. for (int r = 0; r < 256; ++r) {
  45. pixels[r] = proc(SkColorSetARGB(a, r, 0, 0));
  46. }
  47. }
  48. const SkImageInfo info = SkImageInfo::Make(bmp.width(), bmp.height(),
  49. colorType, kUnpremul_SkAlphaType);
  50. surf->writePixels({info, bmp.getPixels(), bmp.rowBytes()}, 0, 0);
  51. }
  52. static void test_premul_alpha_roundtrip(skiatest::Reporter* reporter, SkSurface* surf) {
  53. for (size_t upmaIdx = 0; upmaIdx < SK_ARRAY_COUNT(gUnpremul); ++upmaIdx) {
  54. fill_surface(surf, gUnpremul[upmaIdx].fColorType, gUnpremul[upmaIdx].fPackProc);
  55. const SkImageInfo info = SkImageInfo::Make(256, 256, gUnpremul[upmaIdx].fColorType,
  56. kUnpremul_SkAlphaType);
  57. SkBitmap readBmp1;
  58. readBmp1.allocPixels(info);
  59. SkBitmap readBmp2;
  60. readBmp2.allocPixels(info);
  61. readBmp1.eraseColor(0);
  62. readBmp2.eraseColor(0);
  63. surf->readPixels(readBmp1, 0, 0);
  64. surf->writePixels(readBmp1, 0, 0);
  65. surf->readPixels(readBmp2, 0, 0);
  66. bool success = true;
  67. for (int y = 0; y < 256 && success; ++y) {
  68. const uint32_t* pixels1 = readBmp1.getAddr32(0, y);
  69. const uint32_t* pixels2 = readBmp2.getAddr32(0, y);
  70. for (int x = 0; x < 256 && success; ++x) {
  71. // We see sporadic failures here. May help to see where it goes wrong.
  72. if (pixels1[x] != pixels2[x]) {
  73. SkDebugf("%x != %x, x = %d, y = %d\n", pixels1[x], pixels2[x], x, y);
  74. }
  75. REPORTER_ASSERT(reporter, success = pixels1[x] == pixels2[x]);
  76. }
  77. }
  78. }
  79. }
  80. DEF_TEST(PremulAlphaRoundTrip, reporter) {
  81. const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256);
  82. sk_sp<SkSurface> surf(SkSurface::MakeRaster(info));
  83. test_premul_alpha_roundtrip(reporter, surf.get());
  84. }
  85. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PremulAlphaRoundTrip_Gpu, reporter, ctxInfo) {
  86. const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256);
  87. sk_sp<SkSurface> surf(SkSurface::MakeRenderTarget(ctxInfo.grContext(),
  88. SkBudgeted::kNo,
  89. info));
  90. test_premul_alpha_roundtrip(reporter, surf.get());
  91. }