1 /* 2 * Copyright 2014 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 "SkImage.h" 9 #include "SkImageGenerator.h" 10 #include "SkNextID.h" 11 12 SkImageGenerator::SkImageGenerator(const SkImageInfo& info, uint32_t uniqueID) 13 : fInfo(info) 14 , fUniqueID(kNeedNewImageUniqueID == uniqueID ? SkNextID::ImageID() : uniqueID) 15 {} 16 17 bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, 18 SkPMColor ctable[], int* ctableCount) { 19 if (kUnknown_SkColorType == info.colorType()) { 20 return false; 21 } 22 if (nullptr == pixels) { 23 return false; 24 } 25 if (rowBytes < info.minRowBytes()) { 26 return false; 27 } 28 29 if (kIndex_8_SkColorType == info.colorType()) { 30 if (nullptr == ctable || nullptr == ctableCount) { 31 return false; 32 } 33 } else { 34 if (ctableCount) { 35 *ctableCount = 0; 36 } 37 ctableCount = nullptr; 38 ctable = nullptr; 39 } 40 41 const bool success = this->onGetPixels(info, pixels, rowBytes, ctable, ctableCount); 42 if (success && ctableCount) { 43 SkASSERT(*ctableCount >= 0 && *ctableCount <= 256); 44 } 45 return success; 46 } 47 48 bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) { 49 SkASSERT(kIndex_8_SkColorType != info.colorType()); 50 if (kIndex_8_SkColorType == info.colorType()) { 51 return false; 52 } 53 return this->getPixels(info, pixels, rowBytes, nullptr, nullptr); 54 } 55 56 bool SkImageGenerator::queryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const { 57 SkASSERT(sizeInfo); 58 59 return this->onQueryYUV8(sizeInfo, colorSpace); 60 } 61 62 bool SkImageGenerator::getYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) { 63 SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth >= 0); 64 SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight >= 0); 65 SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kU].fWidth >= 0); 66 SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kU].fHeight >= 0); 67 SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kV].fWidth >= 0); 68 SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kV].fHeight >= 0); 69 SkASSERT(sizeInfo.fWidthBytes[SkYUVSizeInfo::kY] >= 70 (size_t) sizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth); 71 SkASSERT(sizeInfo.fWidthBytes[SkYUVSizeInfo::kU] >= 72 (size_t) sizeInfo.fSizes[SkYUVSizeInfo::kU].fWidth); 73 SkASSERT(sizeInfo.fWidthBytes[SkYUVSizeInfo::kV] >= 74 (size_t) sizeInfo.fSizes[SkYUVSizeInfo::kV].fWidth); 75 SkASSERT(planes && planes[0] && planes[1] && planes[2]); 76 77 return this->onGetYUV8Planes(sizeInfo, planes); 78 } 79 80 #if SK_SUPPORT_GPU 81 #include "GrTextureProxy.h" 82 83 sk_sp<GrTextureProxy> SkImageGenerator::generateTexture(GrContext* ctx, const SkImageInfo& info, 84 const SkIPoint& origin) { 85 SkIRect srcRect = SkIRect::MakeXYWH(origin.x(), origin.y(), info.width(), info.height()); 86 if (!SkIRect::MakeWH(fInfo.width(), fInfo.height()).contains(srcRect)) { 87 return nullptr; 88 } 89 return this->onGenerateTexture(ctx, info, origin); 90 } 91 92 sk_sp<GrTextureProxy> SkImageGenerator::onGenerateTexture(GrContext*, const SkImageInfo&, 93 const SkIPoint&) { 94 return nullptr; 95 } 96 #endif 97 98 ///////////////////////////////////////////////////////////////////////////////////////////// 99 100 SkData* SkImageGenerator::onRefEncodedData(GrContext* ctx) { 101 return nullptr; 102 } 103 104 bool SkImageGenerator::onGetPixels(const SkImageInfo& info, void* dst, size_t rb, 105 SkPMColor* colors, int* colorCount) { 106 return false; 107 } 108 109 /////////////////////////////////////////////////////////////////////////////////////////////////// 110 111 #include "SkBitmap.h" 112 #include "SkColorTable.h" 113 114 static bool reset_and_return_false(SkBitmap* bitmap) { 115 bitmap->reset(); 116 return false; 117 } 118 119 bool SkImageGenerator::tryGenerateBitmap(SkBitmap* bitmap, const SkImageInfo& info, 120 SkBitmap::Allocator* allocator) { 121 if (0 == info.getSafeSize(info.minRowBytes())) { 122 return false; 123 } 124 if (!bitmap->setInfo(info)) { 125 return reset_and_return_false(bitmap); 126 } 127 128 SkPMColor ctStorage[256]; 129 memset(ctStorage, 0xFF, sizeof(ctStorage)); // init with opaque-white for the moment 130 sk_sp<SkColorTable> ctable(new SkColorTable(ctStorage, 256)); 131 if (!bitmap->tryAllocPixels(allocator, ctable.get())) { 132 // SkResourceCache's custom allcator can'thandle ctables, so it may fail on 133 // kIndex_8_SkColorTable. 134 // https://bug.skia.org/4355 135 #if 1 136 // ignore the allocator, and see if we can succeed without it 137 if (!bitmap->tryAllocPixels(nullptr, ctable.get())) { 138 return reset_and_return_false(bitmap); 139 } 140 #else 141 // this is the up-scale technique, not fully debugged, but we keep it here at the moment 142 // to remind ourselves that this might be better than ignoring the allocator. 143 144 info = SkImageInfo::MakeN32(info.width(), info.height(), info.alphaType()); 145 if (!bitmap->setInfo(info)) { 146 return reset_and_return_false(bitmap); 147 } 148 // we pass nullptr for the ctable arg, since we are now explicitly N32 149 if (!bitmap->tryAllocPixels(allocator, nullptr)) { 150 return reset_and_return_false(bitmap); 151 } 152 #endif 153 } 154 155 bitmap->lockPixels(); 156 if (!bitmap->getPixels()) { 157 return reset_and_return_false(bitmap); 158 } 159 160 int ctCount = 0; 161 if (!this->getPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), 162 ctStorage, &ctCount)) { 163 return reset_and_return_false(bitmap); 164 } 165 166 if (ctCount > 0) { 167 SkASSERT(kIndex_8_SkColorType == bitmap->colorType()); 168 // we and bitmap should be owners 169 SkASSERT(!ctable->unique()); 170 171 // Now we need to overwrite the ctable we built earlier, with the correct colors. 172 // This does mean that we may have made the table too big, but that cannot be avoided 173 // until we can change SkImageGenerator's API to return us the ctable *before* we have to 174 // allocate space for all the pixels. 175 ctable->dangerous_overwriteColors(ctStorage, ctCount); 176 } else { 177 SkASSERT(kIndex_8_SkColorType != bitmap->colorType()); 178 // we should be the only owner 179 SkASSERT(ctable->unique()); 180 } 181 return true; 182 } 183 184 #include "SkGraphics.h" 185 186 static SkGraphics::ImageGeneratorFromEncodedDataFactory gFactory; 187 188 SkGraphics::ImageGeneratorFromEncodedDataFactory 189 SkGraphics::SetImageGeneratorFromEncodedDataFactory(ImageGeneratorFromEncodedDataFactory factory) 190 { 191 ImageGeneratorFromEncodedDataFactory prev = gFactory; 192 gFactory = factory; 193 return prev; 194 } 195 196 std::unique_ptr<SkImageGenerator> SkImageGenerator::MakeFromEncoded(sk_sp<SkData> data) { 197 if (!data) { 198 return nullptr; 199 } 200 if (gFactory) { 201 if (std::unique_ptr<SkImageGenerator> generator = gFactory(data)) { 202 return generator; 203 } 204 } 205 return SkImageGenerator::MakeFromEncodedImpl(std::move(data)); 206 } 207