1 /* 2 * Copyright 2012 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_Base.h" 9 #include "SkBitmap.h" 10 #include "SkCanvas.h" 11 #include "SkColorTable.h" 12 #include "SkData.h" 13 #include "SkImagePriv.h" 14 #include "SkPixelRef.h" 15 #include "SkSurface.h" 16 17 #if SK_SUPPORT_GPU 18 #include "GrContext.h" 19 #include "SkGr.h" 20 #include "SkGrPriv.h" 21 #endif 22 23 class SkImage_Raster : public SkImage_Base { 24 public: 25 static bool ValidArgs(const Info& info, size_t rowBytes, bool hasColorTable, 26 size_t* minSize) { 27 const int maxDimension = SK_MaxS32 >> 2; 28 29 if (info.width() <= 0 || info.height() <= 0) { 30 return false; 31 } 32 if (info.width() > maxDimension || info.height() > maxDimension) { 33 return false; 34 } 35 if ((unsigned)info.colorType() > (unsigned)kLastEnum_SkColorType) { 36 return false; 37 } 38 if ((unsigned)info.alphaType() > (unsigned)kLastEnum_SkAlphaType) { 39 return false; 40 } 41 42 if (kUnknown_SkColorType == info.colorType()) { 43 return false; 44 } 45 46 const bool needsCT = kIndex_8_SkColorType == info.colorType(); 47 if (needsCT != hasColorTable) { 48 return false; 49 } 50 51 if (rowBytes < info.minRowBytes()) { 52 return false; 53 } 54 55 size_t size = info.getSafeSize(rowBytes); 56 if (0 == size) { 57 return false; 58 } 59 60 if (minSize) { 61 *minSize = size; 62 } 63 return true; 64 } 65 66 SkImage_Raster(const SkImageInfo&, SkData*, size_t rb, SkColorTable*); 67 virtual ~SkImage_Raster(); 68 69 bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY, CachingHint) const override; 70 const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const override; 71 SkData* onRefEncoded(GrContext*) const override; 72 bool getROPixels(SkBitmap*, CachingHint) const override; 73 GrTexture* asTextureRef(GrContext*, const GrTextureParams&) const override; 74 SkImage* onNewSubset(const SkIRect&) const override; 75 76 // exposed for SkSurface_Raster via SkNewImageFromPixelRef 77 SkImage_Raster(const SkImageInfo&, SkPixelRef*, const SkIPoint& origin, size_t rowBytes); 78 79 SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); } 80 81 bool isOpaque() const override; 82 bool onAsLegacyBitmap(SkBitmap*, LegacyBitmapMode) const override; 83 84 SkImage_Raster(const SkBitmap& bm) 85 : INHERITED(bm.width(), bm.height(), bm.getGenerationID()) 86 , fBitmap(bm) 87 { 88 if (bm.pixelRef()->isPreLocked()) { 89 // we only preemptively lock if there is no chance of triggering something expensive 90 // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already. 91 fBitmap.lockPixels(); 92 } 93 SkASSERT(fBitmap.isImmutable()); 94 } 95 96 bool onIsLazyGenerated() const override { 97 return fBitmap.pixelRef() && fBitmap.pixelRef()->isLazyGenerated(); 98 } 99 100 private: 101 SkBitmap fBitmap; 102 103 typedef SkImage_Base INHERITED; 104 }; 105 106 /////////////////////////////////////////////////////////////////////////////// 107 108 static void release_data(void* addr, void* context) { 109 SkData* data = static_cast<SkData*>(context); 110 data->unref(); 111 } 112 113 SkImage_Raster::SkImage_Raster(const Info& info, SkData* data, size_t rowBytes, 114 SkColorTable* ctable) 115 : INHERITED(info.width(), info.height(), kNeedNewImageUniqueID) 116 { 117 data->ref(); 118 void* addr = const_cast<void*>(data->data()); 119 120 fBitmap.installPixels(info, addr, rowBytes, ctable, release_data, data); 121 fBitmap.setImmutable(); 122 fBitmap.lockPixels(); 123 } 124 125 SkImage_Raster::SkImage_Raster(const Info& info, SkPixelRef* pr, const SkIPoint& pixelRefOrigin, 126 size_t rowBytes) 127 : INHERITED(info.width(), info.height(), pr->getGenerationID()) 128 { 129 fBitmap.setInfo(info, rowBytes); 130 fBitmap.setPixelRef(pr, pixelRefOrigin); 131 fBitmap.lockPixels(); 132 SkASSERT(fBitmap.isImmutable()); 133 } 134 135 SkImage_Raster::~SkImage_Raster() {} 136 137 bool SkImage_Raster::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, 138 int srcX, int srcY, CachingHint) const { 139 SkBitmap shallowCopy(fBitmap); 140 return shallowCopy.readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY); 141 } 142 143 const void* SkImage_Raster::onPeekPixels(SkImageInfo* infoPtr, size_t* rowBytesPtr) const { 144 const SkImageInfo info = fBitmap.info(); 145 if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) { 146 return nullptr; 147 } 148 *infoPtr = info; 149 *rowBytesPtr = fBitmap.rowBytes(); 150 return fBitmap.getPixels(); 151 } 152 153 SkData* SkImage_Raster::onRefEncoded(GrContext*) const { 154 SkPixelRef* pr = fBitmap.pixelRef(); 155 const SkImageInfo prInfo = pr->info(); 156 const SkImageInfo bmInfo = fBitmap.info(); 157 158 // we only try if we (the image) cover the entire area of the pixelRef 159 if (prInfo.width() == bmInfo.width() && prInfo.height() == bmInfo.height()) { 160 return pr->refEncodedData(); 161 } 162 return nullptr; 163 } 164 165 bool SkImage_Raster::getROPixels(SkBitmap* dst, CachingHint) const { 166 *dst = fBitmap; 167 return true; 168 } 169 170 GrTexture* SkImage_Raster::asTextureRef(GrContext* ctx, const GrTextureParams& params) const { 171 #if SK_SUPPORT_GPU 172 if (!ctx) { 173 return nullptr; 174 } 175 176 return GrRefCachedBitmapTexture(ctx, fBitmap, params); 177 #endif 178 179 return nullptr; 180 } 181 182 SkImage* SkImage_Raster::onNewSubset(const SkIRect& subset) const { 183 // TODO : could consider heurist of sharing pixels, if subset is pretty close to complete 184 185 SkImageInfo info = SkImageInfo::MakeN32(subset.width(), subset.height(), fBitmap.alphaType()); 186 SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info)); 187 if (!surface) { 188 return nullptr; 189 } 190 surface->getCanvas()->clear(0); 191 surface->getCanvas()->drawImage(this, SkIntToScalar(-subset.x()), SkIntToScalar(-subset.y()), 192 nullptr); 193 return surface->newImageSnapshot(); 194 } 195 196 /////////////////////////////////////////////////////////////////////////////// 197 198 SkImage* SkImage::NewRasterCopy(const SkImageInfo& info, const void* pixels, size_t rowBytes, 199 SkColorTable* ctable) { 200 size_t size; 201 if (!SkImage_Raster::ValidArgs(info, rowBytes, ctable != nullptr, &size) || !pixels) { 202 return nullptr; 203 } 204 205 // Here we actually make a copy of the caller's pixel data 206 SkAutoDataUnref data(SkData::NewWithCopy(pixels, size)); 207 return new SkImage_Raster(info, data, rowBytes, ctable); 208 } 209 210 211 SkImage* SkImage::NewRasterData(const SkImageInfo& info, SkData* data, size_t rowBytes) { 212 size_t size; 213 if (!SkImage_Raster::ValidArgs(info, rowBytes, false, &size) || !data) { 214 return nullptr; 215 } 216 217 // did they give us enough data? 218 if (data->size() < size) { 219 return nullptr; 220 } 221 222 SkColorTable* ctable = nullptr; 223 return new SkImage_Raster(info, data, rowBytes, ctable); 224 } 225 226 SkImage* SkImage::NewFromRaster(const SkImageInfo& info, const void* pixels, size_t rowBytes, 227 RasterReleaseProc proc, ReleaseContext ctx) { 228 size_t size; 229 if (!SkImage_Raster::ValidArgs(info, rowBytes, false, &size) || !pixels) { 230 return nullptr; 231 } 232 233 SkColorTable* ctable = nullptr; 234 SkAutoDataUnref data(SkData::NewWithProc(pixels, size, proc, ctx)); 235 return new SkImage_Raster(info, data, rowBytes, ctable); 236 } 237 238 SkImage* SkNewImageFromPixelRef(const SkImageInfo& info, SkPixelRef* pr, 239 const SkIPoint& pixelRefOrigin, size_t rowBytes) { 240 if (!SkImage_Raster::ValidArgs(info, rowBytes, false, nullptr)) { 241 return nullptr; 242 } 243 return new SkImage_Raster(info, pr, pixelRefOrigin, rowBytes); 244 } 245 246 SkImage* SkNewImageFromRasterBitmap(const SkBitmap& bm, ForceCopyMode forceCopy) { 247 SkASSERT(nullptr == bm.getTexture()); 248 249 bool hasColorTable = false; 250 if (kIndex_8_SkColorType == bm.colorType()) { 251 SkAutoLockPixels autoLockPixels(bm); 252 hasColorTable = bm.getColorTable() != nullptr; 253 } 254 255 if (!SkImage_Raster::ValidArgs(bm.info(), bm.rowBytes(), hasColorTable, nullptr)) { 256 return nullptr; 257 } 258 259 SkImage* image = nullptr; 260 if (kYes_ForceCopyMode == forceCopy || !bm.isImmutable()) { 261 SkBitmap tmp(bm); 262 tmp.lockPixels(); 263 if (tmp.getPixels()) { 264 image = SkImage::NewRasterCopy(tmp.info(), tmp.getPixels(), tmp.rowBytes(), 265 tmp.getColorTable()); 266 } 267 } else { 268 image = new SkImage_Raster(bm); 269 } 270 return image; 271 } 272 273 const SkPixelRef* SkBitmapImageGetPixelRef(const SkImage* image) { 274 return ((const SkImage_Raster*)image)->getPixelRef(); 275 } 276 277 bool SkImage_Raster::isOpaque() const { 278 return fBitmap.isOpaque(); 279 } 280 281 bool SkImage_Raster::onAsLegacyBitmap(SkBitmap* bitmap, LegacyBitmapMode mode) const { 282 if (kRO_LegacyBitmapMode == mode) { 283 // When we're a snapshot from a surface, our bitmap may not be marked immutable 284 // even though logically always we are, but in that case we can't physically share our 285 // pixelref since the caller might call setImmutable() themselves 286 // (thus changing our state). 287 if (fBitmap.isImmutable()) { 288 bitmap->setInfo(fBitmap.info(), fBitmap.rowBytes()); 289 bitmap->setPixelRef(fBitmap.pixelRef(), fBitmap.pixelRefOrigin()); 290 return true; 291 } 292 } 293 return this->INHERITED::onAsLegacyBitmap(bitmap, mode); 294 } 295