1 /* 2 * Copyright 2013 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 8 #include "SkBitmap.h" 9 #include "SkCanvas.h" 10 #include "SkData.h" 11 #include "SkDiscardableMemoryPool.h" 12 #include "SkImage.h" 13 #include "SkImageEncoder.h" 14 #include "SkImageGeneratorPriv.h" 15 #include "SkResourceCache.h" 16 #include "SkStream.h" 17 #include "SkUtils.h" 18 19 #include "Test.h" 20 21 /** 22 * Fill this bitmap with some color. 23 */ 24 static void make_test_image(SkBitmap* bm) { 25 const int W = 50, H = 50; 26 bm->allocN32Pixels(W, H); 27 bm->eraseColor(SK_ColorBLACK); 28 SkCanvas canvas(*bm); 29 SkPaint paint; 30 paint.setColor(SK_ColorBLUE); 31 canvas.drawRectCoords(0, 0, SkIntToScalar(W/2), 32 SkIntToScalar(H/2), paint); 33 paint.setColor(SK_ColorWHITE); 34 canvas.drawRectCoords(SkIntToScalar(W/2), SkIntToScalar(H/2), 35 SkIntToScalar(W), SkIntToScalar(H), paint); 36 } 37 38 /** 39 * encode this bitmap into some data via SkImageEncoder 40 */ 41 static SkData* create_data_from_bitmap(const SkBitmap& bm, 42 SkImageEncoder::Type type) { 43 SkDynamicMemoryWStream stream; 44 if (SkImageEncoder::EncodeStream(&stream, bm, type, 100)) { 45 return stream.copyToData(); 46 } 47 return nullptr; 48 } 49 50 //////////////////////////////////////////////////////////////////////////////// 51 52 static void compare_bitmaps(skiatest::Reporter* reporter, 53 const SkBitmap& b1, const SkBitmap& b2, 54 bool pixelPerfect = true) { 55 REPORTER_ASSERT(reporter, b1.empty() == b2.empty()); 56 REPORTER_ASSERT(reporter, b1.width() == b2.width()); 57 REPORTER_ASSERT(reporter, b1.height() == b2.height()); 58 REPORTER_ASSERT(reporter, b1.isNull() == b2.isNull()); 59 SkAutoLockPixels autoLockPixels1(b1); 60 SkAutoLockPixels autoLockPixels2(b2); 61 REPORTER_ASSERT(reporter, b1.isNull() == b2.isNull()); 62 if (b1.isNull() || b1.empty()) { 63 return; 64 } 65 REPORTER_ASSERT(reporter, b1.getPixels()); 66 REPORTER_ASSERT(reporter, b2.getPixels()); 67 if ((!(b1.getPixels())) || (!(b2.getPixels()))) { 68 return; 69 } 70 if ((b1.width() != b2.width()) || 71 (b1.height() != b2.height())) { 72 return; 73 } 74 if (!pixelPerfect) { 75 return; 76 } 77 78 int pixelErrors = 0; 79 for (int y = 0; y < b2.height(); ++y) { 80 for (int x = 0; x < b2.width(); ++x) { 81 if (b1.getColor(x, y) != b2.getColor(x, y)) { 82 ++pixelErrors; 83 } 84 } 85 } 86 REPORTER_ASSERT(reporter, 0 == pixelErrors); 87 } 88 89 typedef bool (*InstallEncoded)(SkData* encoded, SkBitmap* dst); 90 91 /** 92 This function tests three differently encoded images against the 93 original bitmap */ 94 static void test_three_encodings(skiatest::Reporter* reporter, 95 InstallEncoded install) { 96 SkBitmap original; 97 make_test_image(&original); 98 REPORTER_ASSERT(reporter, !original.empty()); 99 REPORTER_ASSERT(reporter, !original.isNull()); 100 if (original.empty() || original.isNull()) { 101 return; 102 } 103 static const SkImageEncoder::Type types[] = { 104 SkImageEncoder::kPNG_Type, 105 SkImageEncoder::kJPEG_Type, 106 SkImageEncoder::kWEBP_Type 107 }; 108 for (size_t i = 0; i < SK_ARRAY_COUNT(types); i++) { 109 SkImageEncoder::Type type = types[i]; 110 SkAutoDataUnref encoded(create_data_from_bitmap(original, type)); 111 REPORTER_ASSERT(reporter, encoded.get() != nullptr); 112 if (nullptr == encoded.get()) { 113 continue; 114 } 115 SkBitmap lazy; 116 bool installSuccess = install(encoded.get(), &lazy); 117 REPORTER_ASSERT(reporter, installSuccess); 118 if (!installSuccess) { 119 continue; 120 } 121 REPORTER_ASSERT(reporter, nullptr == lazy.getPixels()); 122 { 123 SkAutoLockPixels autoLockPixels(lazy); // now pixels are good. 124 REPORTER_ASSERT(reporter, lazy.getPixels()); 125 if (nullptr == lazy.getPixels()) { 126 continue; 127 } 128 } 129 // pixels should be gone! 130 REPORTER_ASSERT(reporter, nullptr == lazy.getPixels()); 131 { 132 SkAutoLockPixels autoLockPixels(lazy); // now pixels are good. 133 REPORTER_ASSERT(reporter, lazy.getPixels()); 134 if (nullptr == lazy.getPixels()) { 135 continue; 136 } 137 } 138 bool comparePixels = (SkImageEncoder::kPNG_Type == type); 139 compare_bitmaps(reporter, original, lazy, comparePixels); 140 } 141 } 142 143 //////////////////////////////////////////////////////////////////////////////// 144 static bool install_skDiscardablePixelRef(SkData* encoded, SkBitmap* dst) { 145 // Use system-default discardable memory. 146 return SkDEPRECATED_InstallDiscardablePixelRef(encoded, dst); 147 } 148 149 //////////////////////////////////////////////////////////////////////////////// 150 /** 151 * This checks to see that SkDiscardablePixelRef works as advertised with a 152 * SkDecodingImageGenerator. 153 */ 154 DEF_TEST(DecodingImageGenerator, reporter) { 155 test_three_encodings(reporter, install_skDiscardablePixelRef); 156 } 157 158 class TestImageGenerator : public SkImageGenerator { 159 public: 160 enum TestType { 161 kFailGetPixels_TestType, 162 kSucceedGetPixels_TestType, 163 kLast_TestType = kSucceedGetPixels_TestType 164 }; 165 static int Width() { return 10; } 166 static int Height() { return 10; } 167 // value choosen so that there is no loss when converting to to RGB565 and back 168 static SkColor Color() { return 0xff10345a; } 169 static SkPMColor PMColor() { return SkPreMultiplyColor(Color()); } 170 171 TestImageGenerator(TestType type, skiatest::Reporter* reporter, 172 SkColorType colorType = kN32_SkColorType) 173 : INHERITED(GetMyInfo(colorType)), fType(type), fReporter(reporter) { 174 SkASSERT((fType <= kLast_TestType) && (fType >= 0)); 175 } 176 virtual ~TestImageGenerator() { } 177 178 protected: 179 static SkImageInfo GetMyInfo(SkColorType colorType) { 180 return SkImageInfo::Make(TestImageGenerator::Width(), TestImageGenerator::Height(), 181 colorType, kOpaque_SkAlphaType); 182 } 183 184 bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, 185 SkPMColor ctable[], int* ctableCount) override { 186 REPORTER_ASSERT(fReporter, pixels != nullptr); 187 REPORTER_ASSERT(fReporter, rowBytes >= info.minRowBytes()); 188 if (fType != kSucceedGetPixels_TestType) { 189 return false; 190 } 191 if (info.colorType() != kN32_SkColorType && info.colorType() != getInfo().colorType()) { 192 return false; 193 } 194 char* bytePtr = static_cast<char*>(pixels); 195 switch (info.colorType()) { 196 case kN32_SkColorType: 197 for (int y = 0; y < info.height(); ++y) { 198 sk_memset32((uint32_t*)bytePtr, 199 TestImageGenerator::PMColor(), info.width()); 200 bytePtr += rowBytes; 201 } 202 break; 203 case kIndex_8_SkColorType: 204 *ctableCount = 1; 205 ctable[0] = TestImageGenerator::PMColor(); 206 for (int y = 0; y < info.height(); ++y) { 207 memset(bytePtr, 0, info.width()); 208 bytePtr += rowBytes; 209 } 210 break; 211 case kRGB_565_SkColorType: 212 for (int y = 0; y < info.height(); ++y) { 213 sk_memset16((uint16_t*)bytePtr, 214 SkPixel32ToPixel16(TestImageGenerator::PMColor()), info.width()); 215 bytePtr += rowBytes; 216 } 217 break; 218 default: 219 return false; 220 } 221 return true; 222 } 223 224 private: 225 const TestType fType; 226 skiatest::Reporter* const fReporter; 227 228 typedef SkImageGenerator INHERITED; 229 }; 230 231 static void check_test_image_generator_bitmap(skiatest::Reporter* reporter, 232 const SkBitmap& bm) { 233 REPORTER_ASSERT(reporter, TestImageGenerator::Width() == bm.width()); 234 REPORTER_ASSERT(reporter, TestImageGenerator::Height() == bm.height()); 235 SkAutoLockPixels autoLockPixels(bm); 236 REPORTER_ASSERT(reporter, bm.getPixels()); 237 if (nullptr == bm.getPixels()) { 238 return; 239 } 240 int errors = 0; 241 for (int y = 0; y < bm.height(); ++y) { 242 for (int x = 0; x < bm.width(); ++x) { 243 if (TestImageGenerator::Color() != bm.getColor(x, y)) { 244 ++errors; 245 } 246 } 247 } 248 REPORTER_ASSERT(reporter, 0 == errors); 249 } 250 251 static void check_pixelref(TestImageGenerator::TestType type, 252 skiatest::Reporter* reporter, 253 SkDiscardableMemory::Factory* factory, 254 SkColorType colorType) { 255 SkAutoTDelete<SkImageGenerator> gen(new TestImageGenerator(type, reporter, colorType)); 256 REPORTER_ASSERT(reporter, gen.get() != nullptr); 257 SkBitmap lazy; 258 bool success = SkDEPRECATED_InstallDiscardablePixelRef(gen.detach(), nullptr, &lazy, factory); 259 260 REPORTER_ASSERT(reporter, success); 261 if (TestImageGenerator::kSucceedGetPixels_TestType == type) { 262 check_test_image_generator_bitmap(reporter, lazy); 263 } else if (TestImageGenerator::kFailGetPixels_TestType == type) { 264 SkAutoLockPixels autoLockPixels(lazy); 265 REPORTER_ASSERT(reporter, nullptr == lazy.getPixels()); 266 } 267 } 268 269 /** 270 * This tests the basic functionality of SkDiscardablePixelRef with a 271 * basic SkImageGenerator implementation and several 272 * SkDiscardableMemory::Factory choices. 273 */ 274 DEF_TEST(DiscardableAndCachingPixelRef, reporter) { 275 const SkColorType testColorTypes[] = { 276 kN32_SkColorType, 277 kIndex_8_SkColorType, 278 kRGB_565_SkColorType 279 }; 280 for (const SkColorType testColorType : testColorTypes) { 281 check_pixelref(TestImageGenerator::kFailGetPixels_TestType, reporter, nullptr, 282 testColorType); 283 check_pixelref(TestImageGenerator::kSucceedGetPixels_TestType, reporter, nullptr, 284 testColorType); 285 286 SkAutoTUnref<SkDiscardableMemoryPool> pool( 287 SkDiscardableMemoryPool::Create(1, nullptr)); 288 REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed()); 289 check_pixelref(TestImageGenerator::kFailGetPixels_TestType, reporter, pool, 290 testColorType); 291 REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed()); 292 check_pixelref(TestImageGenerator::kSucceedGetPixels_TestType, reporter, pool, 293 testColorType); 294 REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed()); 295 296 SkDiscardableMemoryPool* globalPool = SkGetGlobalDiscardableMemoryPool(); 297 // Only acts differently from nullptr on a platform that has a 298 // default discardable memory implementation that differs from the 299 // global DM pool. 300 check_pixelref(TestImageGenerator::kFailGetPixels_TestType, reporter, globalPool, 301 testColorType); 302 check_pixelref(TestImageGenerator::kSucceedGetPixels_TestType, reporter, globalPool, 303 testColorType); 304 } 305 } 306 307 //////////////////////////////////////////////////////////////////////////////// 308 309 DEF_TEST(Image_NewFromGenerator, r) { 310 const TestImageGenerator::TestType testTypes[] = { 311 TestImageGenerator::kFailGetPixels_TestType, 312 TestImageGenerator::kSucceedGetPixels_TestType, 313 }; 314 const SkColorType testColorTypes[] = { 315 kN32_SkColorType, 316 kIndex_8_SkColorType, 317 kRGB_565_SkColorType 318 }; 319 for (size_t i = 0; i < SK_ARRAY_COUNT(testTypes); ++i) { 320 TestImageGenerator::TestType test = testTypes[i]; 321 for (const SkColorType testColorType : testColorTypes) { 322 SkImageGenerator* gen = new TestImageGenerator(test, r, testColorType); 323 SkAutoTUnref<SkImage> image(SkImage::NewFromGenerator(gen)); 324 if (nullptr == image.get()) { 325 ERRORF(r, "SkImage::NewFromGenerator unexpecedly failed [" 326 SK_SIZE_T_SPECIFIER "]", i); 327 continue; 328 } 329 REPORTER_ASSERT(r, TestImageGenerator::Width() == image->width()); 330 REPORTER_ASSERT(r, TestImageGenerator::Height() == image->height()); 331 REPORTER_ASSERT(r, image->isLazyGenerated()); 332 333 SkBitmap bitmap; 334 bitmap.allocN32Pixels(TestImageGenerator::Width(), TestImageGenerator::Height()); 335 SkCanvas canvas(bitmap); 336 const SkColor kDefaultColor = 0xffabcdef; 337 canvas.clear(kDefaultColor); 338 canvas.drawImage(image, 0, 0, nullptr); 339 if (TestImageGenerator::kSucceedGetPixels_TestType == test) { 340 REPORTER_ASSERT( 341 r, TestImageGenerator::Color() == bitmap.getColor(0, 0)); 342 } 343 else { 344 REPORTER_ASSERT(r, kDefaultColor == bitmap.getColor(0, 0)); 345 } 346 } 347 } 348 } 349