BitmapCopyTest.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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/SkBitmap.h"
  8. #include "include/core/SkColor.h"
  9. #include "include/core/SkColorSpace.h"
  10. #include "include/core/SkImageInfo.h"
  11. #include "include/core/SkPoint.h"
  12. #include "include/core/SkRect.h"
  13. #include "include/core/SkRefCnt.h"
  14. #include "include/core/SkSize.h"
  15. #include "include/core/SkTypes.h"
  16. #include "tests/Test.h"
  17. #include "tools/ToolUtils.h"
  18. static void init_src(const SkBitmap& bitmap) {
  19. if (bitmap.getPixels()) {
  20. bitmap.eraseColor(SK_ColorWHITE);
  21. }
  22. }
  23. struct Pair {
  24. SkColorType fColorType;
  25. const char* fValid;
  26. };
  27. // Utility functions for copyPixelsTo()/copyPixelsFrom() tests.
  28. // getPixel()
  29. // setPixel()
  30. // getSkConfigName()
  31. // struct Coordinates
  32. // reportCopyVerification()
  33. // writeCoordPixels()
  34. // Helper struct to contain pixel locations, while avoiding need for STL.
  35. struct Coordinates {
  36. const int length;
  37. SkIPoint* const data;
  38. explicit Coordinates(int _length): length(_length)
  39. , data(new SkIPoint[length]) { }
  40. ~Coordinates(){
  41. delete [] data;
  42. }
  43. SkIPoint* operator[](int i) const {
  44. // Use with care, no bounds checking.
  45. return data + i;
  46. }
  47. };
  48. static const Pair gPairs[] = {
  49. { kUnknown_SkColorType, "0000000" },
  50. { kAlpha_8_SkColorType, "0100000" },
  51. { kRGB_565_SkColorType, "0101011" },
  52. { kARGB_4444_SkColorType, "0101111" },
  53. { kN32_SkColorType, "0101111" },
  54. { kRGBA_F16_SkColorType, "0101011" },
  55. };
  56. static const int W = 20;
  57. static const int H = 33;
  58. static void setup_src_bitmaps(SkBitmap* srcOpaque, SkBitmap* srcPremul,
  59. SkColorType ct) {
  60. sk_sp<SkColorSpace> colorSpace = nullptr;
  61. if (kRGBA_F16_SkColorType == ct) {
  62. colorSpace = SkColorSpace::MakeSRGB();
  63. }
  64. srcOpaque->allocPixels(SkImageInfo::Make(W, H, ct, kOpaque_SkAlphaType, colorSpace));
  65. srcPremul->allocPixels(SkImageInfo::Make(W, H, ct, kPremul_SkAlphaType, colorSpace));
  66. init_src(*srcOpaque);
  67. init_src(*srcPremul);
  68. }
  69. DEF_TEST(BitmapCopy_extractSubset, reporter) {
  70. for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
  71. SkBitmap srcOpaque, srcPremul;
  72. setup_src_bitmaps(&srcOpaque, &srcPremul, gPairs[i].fColorType);
  73. SkBitmap bitmap(srcOpaque);
  74. SkBitmap subset;
  75. SkIRect r;
  76. // Extract a subset which has the same width as the original. This
  77. // catches a bug where we cloned the genID incorrectly.
  78. r.set(0, 1, W, 3);
  79. bitmap.setIsVolatile(true);
  80. // Relies on old behavior of extractSubset failing if colortype is unknown
  81. if (kUnknown_SkColorType != bitmap.colorType() && bitmap.extractSubset(&subset, r)) {
  82. REPORTER_ASSERT(reporter, subset.width() == W);
  83. REPORTER_ASSERT(reporter, subset.height() == 2);
  84. REPORTER_ASSERT(reporter, subset.alphaType() == bitmap.alphaType());
  85. REPORTER_ASSERT(reporter, subset.isVolatile() == true);
  86. // Test copying an extracted subset.
  87. for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) {
  88. SkBitmap copy;
  89. bool success = ToolUtils::copy_to(&copy, gPairs[j].fColorType, subset);
  90. if (!success) {
  91. // Skip checking that success matches fValid, which is redundant
  92. // with the code below.
  93. REPORTER_ASSERT(reporter, gPairs[i].fColorType != gPairs[j].fColorType);
  94. continue;
  95. }
  96. // When performing a copy of an extracted subset, the gen id should
  97. // change.
  98. REPORTER_ASSERT(reporter, copy.getGenerationID() != subset.getGenerationID());
  99. REPORTER_ASSERT(reporter, copy.width() == W);
  100. REPORTER_ASSERT(reporter, copy.height() == 2);
  101. }
  102. }
  103. bitmap = srcPremul;
  104. bitmap.setIsVolatile(false);
  105. if (bitmap.extractSubset(&subset, r)) {
  106. REPORTER_ASSERT(reporter, subset.alphaType() == bitmap.alphaType());
  107. REPORTER_ASSERT(reporter, subset.isVolatile() == false);
  108. }
  109. }
  110. }
  111. #include "include/core/SkColorPriv.h"
  112. #include "src/core/SkUtils.h"
  113. /**
  114. * Construct 4x4 pixels where we can look at a color and determine where it should be in the grid.
  115. * alpha = 0xFF, blue = 0x80, red = x, green = y
  116. */
  117. static void fill_4x4_pixels(SkPMColor colors[16]) {
  118. for (int y = 0; y < 4; ++y) {
  119. for (int x = 0; x < 4; ++x) {
  120. colors[y*4+x] = SkPackARGB32(0xFF, x, y, 0x80);
  121. }
  122. }
  123. }
  124. static bool check_4x4_pixel(SkPMColor color, unsigned x, unsigned y) {
  125. SkASSERT(x < 4 && y < 4);
  126. return 0xFF == SkGetPackedA32(color) &&
  127. x == SkGetPackedR32(color) &&
  128. y == SkGetPackedG32(color) &&
  129. 0x80 == SkGetPackedB32(color);
  130. }
  131. /**
  132. * Fill with all zeros, which will never match any value from fill_4x4_pixels
  133. */
  134. static void clear_4x4_pixels(SkPMColor colors[16]) {
  135. sk_memset32(colors, 0, 16);
  136. }
  137. // Much of readPixels is exercised by copyTo testing, since readPixels is the backend for that
  138. // method. Here we explicitly test subset copies.
  139. //
  140. DEF_TEST(BitmapReadPixels, reporter) {
  141. const int W = 4;
  142. const int H = 4;
  143. const size_t rowBytes = W * sizeof(SkPMColor);
  144. const SkImageInfo srcInfo = SkImageInfo::MakeN32Premul(W, H);
  145. SkPMColor srcPixels[16];
  146. fill_4x4_pixels(srcPixels);
  147. SkBitmap srcBM;
  148. srcBM.installPixels(srcInfo, srcPixels, rowBytes);
  149. SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(W, H);
  150. SkPMColor dstPixels[16];
  151. const struct {
  152. bool fExpectedSuccess;
  153. SkIPoint fRequestedSrcLoc;
  154. SkISize fRequestedDstSize;
  155. // If fExpectedSuccess, check these, otherwise ignore
  156. SkIPoint fExpectedDstLoc;
  157. SkIRect fExpectedSrcR;
  158. } gRec[] = {
  159. { true, { 0, 0 }, { 4, 4 }, { 0, 0 }, { 0, 0, 4, 4 } },
  160. { true, { 1, 1 }, { 2, 2 }, { 0, 0 }, { 1, 1, 3, 3 } },
  161. { true, { 2, 2 }, { 4, 4 }, { 0, 0 }, { 2, 2, 4, 4 } },
  162. { true, {-1,-1 }, { 2, 2 }, { 1, 1 }, { 0, 0, 1, 1 } },
  163. { false, {-1,-1 }, { 1, 1 }, { 0, 0 }, { 0, 0, 0, 0 } },
  164. };
  165. for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
  166. clear_4x4_pixels(dstPixels);
  167. dstInfo = dstInfo.makeWH(gRec[i].fRequestedDstSize.width(),
  168. gRec[i].fRequestedDstSize.height());
  169. bool success = srcBM.readPixels(dstInfo, dstPixels, rowBytes,
  170. gRec[i].fRequestedSrcLoc.x(), gRec[i].fRequestedSrcLoc.y());
  171. REPORTER_ASSERT(reporter, gRec[i].fExpectedSuccess == success);
  172. if (success) {
  173. const SkIRect srcR = gRec[i].fExpectedSrcR;
  174. const int dstX = gRec[i].fExpectedDstLoc.x();
  175. const int dstY = gRec[i].fExpectedDstLoc.y();
  176. // Walk the dst pixels, and check if we got what we expected
  177. for (int y = 0; y < H; ++y) {
  178. for (int x = 0; x < W; ++x) {
  179. SkPMColor dstC = dstPixels[y*4+x];
  180. // get into src coordinates
  181. int sx = x - dstX + srcR.x();
  182. int sy = y - dstY + srcR.y();
  183. if (srcR.contains(sx, sy)) {
  184. REPORTER_ASSERT(reporter, check_4x4_pixel(dstC, sx, sy));
  185. } else {
  186. REPORTER_ASSERT(reporter, 0 == dstC);
  187. }
  188. }
  189. }
  190. }
  191. }
  192. }