blob: 5b55c44685ef01c2582c9b526013e08d313150f2 [file] [log] [blame]
reed@google.com58b21ec2012-07-30 18:20:12 +00001/*
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"
reed@google.com58b21ec2012-07-30 18:20:12 +00009#include "SkBitmap.h"
reed4c1abdc2016-08-05 14:50:19 -070010#include "SkBitmapProcShader.h"
reed@google.com58b21ec2012-07-30 18:20:12 +000011#include "SkCanvas.h"
Matt Sarett5b1dba82017-04-03 11:42:52 -040012#include "SkColorSpaceXform_Base.h"
13#include "SkColorSpaceXformPriv.h"
reed759373a2015-07-03 21:01:10 -070014#include "SkColorTable.h"
reed@google.com58b21ec2012-07-30 18:20:12 +000015#include "SkData.h"
Matt Sarettd21fd4b2017-06-08 09:08:34 -040016#include "SkImageInfoPriv.h"
kkinnunen73953e72015-02-23 22:12:12 -080017#include "SkImagePriv.h"
18#include "SkPixelRef.h"
reed4af267b2014-11-21 08:46:37 -080019#include "SkSurface.h"
Matt Sarett0887c702017-03-21 13:05:41 -040020#include "SkTLazy.h"
Matt Sarett5b1dba82017-04-03 11:42:52 -040021#include "SkUnPreMultiplyPriv.h"
reed@google.com58b21ec2012-07-30 18:20:12 +000022
reed746f31f2015-09-16 12:53:29 -070023#if SK_SUPPORT_GPU
24#include "GrContext.h"
Brian Osmane8e54582016-11-28 10:06:27 -050025#include "GrTextureAdjuster.h"
reed746f31f2015-09-16 12:53:29 -070026#include "SkGr.h"
reed746f31f2015-09-16 12:53:29 -070027#endif
28
halcanary8d3ad5a2016-03-24 09:18:14 -070029// fixes https://bug.skia.org/5096
30static bool is_not_subset(const SkBitmap& bm) {
31 SkASSERT(bm.pixelRef());
Matt Saretta6e976a2017-04-28 15:43:35 -040032 SkISize dim = SkISize::Make(bm.pixelRef()->width(), bm.pixelRef()->height());
halcanary8d3ad5a2016-03-24 09:18:14 -070033 SkASSERT(dim != bm.dimensions() || bm.pixelRefOrigin().isZero());
34 return dim == bm.dimensions();
35}
36
reed@google.com58b21ec2012-07-30 18:20:12 +000037class SkImage_Raster : public SkImage_Base {
38public:
halcanaryc56c6ef2015-09-28 11:55:28 -070039 static bool ValidArgs(const Info& info, size_t rowBytes, bool hasColorTable,
reed759373a2015-07-03 21:01:10 -070040 size_t* minSize) {
reed@google.com58b21ec2012-07-30 18:20:12 +000041 const int maxDimension = SK_MaxS32 >> 2;
reed@google.com58b21ec2012-07-30 18:20:12 +000042
reedb2497c22014-12-31 12:31:43 -080043 if (info.width() <= 0 || info.height() <= 0) {
reed@google.com58b21ec2012-07-30 18:20:12 +000044 return false;
45 }
reede5ea5002014-09-03 11:54:58 -070046 if (info.width() > maxDimension || info.height() > maxDimension) {
reed@google.com58b21ec2012-07-30 18:20:12 +000047 return false;
48 }
reede5ea5002014-09-03 11:54:58 -070049 if ((unsigned)info.colorType() > (unsigned)kLastEnum_SkColorType) {
reed@google.com58b21ec2012-07-30 18:20:12 +000050 return false;
51 }
reede5ea5002014-09-03 11:54:58 -070052 if ((unsigned)info.alphaType() > (unsigned)kLastEnum_SkAlphaType) {
reed@google.com58b21ec2012-07-30 18:20:12 +000053 return false;
54 }
55
commit-bot@chromium.orga3264e52014-05-30 13:26:10 +000056 if (kUnknown_SkColorType == info.colorType()) {
reed@google.com58b21ec2012-07-30 18:20:12 +000057 return false;
58 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000059
reed759373a2015-07-03 21:01:10 -070060 const bool needsCT = kIndex_8_SkColorType == info.colorType();
halcanaryc56c6ef2015-09-28 11:55:28 -070061 if (needsCT != hasColorTable) {
reed759373a2015-07-03 21:01:10 -070062 return false;
63 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000064
scroggodb7dc092015-12-18 06:56:01 -080065 if (rowBytes < info.minRowBytes()) {
reed@google.com58b21ec2012-07-30 18:20:12 +000066 return false;
67 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000068
reedde499882015-06-18 13:41:40 -070069 size_t size = info.getSafeSize(rowBytes);
70 if (0 == size) {
reed@google.com58b21ec2012-07-30 18:20:12 +000071 return false;
72 }
reedde499882015-06-18 13:41:40 -070073
74 if (minSize) {
75 *minSize = size;
76 }
reed@google.com58b21ec2012-07-30 18:20:12 +000077 return true;
78 }
79
reed7fb4f8b2016-03-11 04:33:52 -080080 SkImage_Raster(const SkImageInfo&, sk_sp<SkData>, size_t rb, SkColorTable*);
Brian Salomond3b65972017-03-22 12:05:03 -040081 ~SkImage_Raster() override;
reed@google.com58b21ec2012-07-30 18:20:12 +000082
herba7c9d632016-04-19 12:30:22 -070083 SkImageInfo onImageInfo() const override {
84 return fBitmap.info();
85 }
brianosman69c166d2016-08-17 14:01:05 -070086 SkAlphaType onAlphaType() const override {
87 return fBitmap.alphaType();
88 }
herba7c9d632016-04-19 12:30:22 -070089
reed09553032015-11-23 12:32:16 -080090 bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY, CachingHint) const override;
reed6ceeebd2016-03-09 14:26:26 -080091 bool onPeekPixels(SkPixmap*) const override;
reedf1ac1822016-08-01 11:24:14 -070092 const SkBitmap* onPeekBitmap() const override { return &fBitmap; }
93
Robert Phillipsb726d582017-03-09 16:36:32 -050094#if SK_SUPPORT_GPU
95 sk_sp<GrTextureProxy> asTextureProxyRef(GrContext*, const GrSamplerParams&,
96 SkColorSpace*, sk_sp<SkColorSpace>*,
97 SkScalar scaleAdjust[2]) const override;
98#endif
99
Robert Phillipsb726d582017-03-09 16:36:32 -0500100 bool getROPixels(SkBitmap*, SkColorSpace* dstColorSpace, CachingHint) const override;
reed7fb4f8b2016-03-11 04:33:52 -0800101 sk_sp<SkImage> onMakeSubset(const SkIRect&) const override;
reed@google.com58b21ec2012-07-30 18:20:12 +0000102
reed@google.com97af1a62012-08-28 12:19:02 +0000103 SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }
104
reed3c065112015-07-08 12:46:22 -0700105 bool onAsLegacyBitmap(SkBitmap*, LegacyBitmapMode) const override;
piotaixrd2a35222014-08-19 14:29:02 -0700106
reed2dad7692016-08-01 11:12:58 -0700107 SkImage_Raster(const SkBitmap& bm, bool bitmapMayBeMutable = false)
halcanary8d3ad5a2016-03-24 09:18:14 -0700108 : INHERITED(bm.width(), bm.height(),
109 is_not_subset(bm) ? bm.getGenerationID()
110 : (uint32_t)kNeedNewImageUniqueID)
reed02d91d12015-07-30 20:13:43 -0700111 , fBitmap(bm)
112 {
reed2dad7692016-08-01 11:12:58 -0700113 SkASSERT(bitmapMayBeMutable || fBitmap.isImmutable());
fmalita9a5d1ab2015-07-27 10:27:28 -0700114 }
halcanaryea4673f2014-08-18 08:27:09 -0700115
Matt Sarett9f3dcb32017-05-04 08:53:32 -0400116 sk_sp<SkImage> onMakeColorSpace(sk_sp<SkColorSpace>, SkColorType,
117 SkTransferFunctionBehavior) const override;
Matt Sarett6de13102017-03-14 14:10:48 -0400118
Brian Osman5bbd0762017-05-08 11:07:42 -0400119 bool onIsValid(GrContext* context) const override { return true; }
120
reed2d5b7142016-08-17 11:12:33 -0700121#if SK_SUPPORT_GPU
Robert Phillips3798c862017-03-27 11:08:16 -0400122 sk_sp<GrTextureProxy> refPinnedTextureProxy(uint32_t* uniqueID) const override;
Derek Sollenbergerd3ea9b72016-11-09 11:25:13 -0500123 bool onPinAsTexture(GrContext*) const override;
reed2d5b7142016-08-17 11:12:33 -0700124 void onUnpinAsTexture(GrContext*) const override;
125#endif
126
reed@google.com58b21ec2012-07-30 18:20:12 +0000127private:
reedaf3fbfc2015-10-04 11:28:36 -0700128 SkBitmap fBitmap;
reed@google.com58b21ec2012-07-30 18:20:12 +0000129
reed2d5b7142016-08-17 11:12:33 -0700130#if SK_SUPPORT_GPU
Robert Phillips3798c862017-03-27 11:08:16 -0400131 mutable sk_sp<GrTextureProxy> fPinnedProxy;
reed2d5b7142016-08-17 11:12:33 -0700132 mutable int32_t fPinnedCount = 0;
133 mutable uint32_t fPinnedUniqueID = 0;
134#endif
135
reed@google.com58b21ec2012-07-30 18:20:12 +0000136 typedef SkImage_Base INHERITED;
137};
138
139///////////////////////////////////////////////////////////////////////////////
140
reed@google.com4f7c6152014-02-06 14:11:56 +0000141static void release_data(void* addr, void* context) {
142 SkData* data = static_cast<SkData*>(context);
143 data->unref();
144}
145
reed7fb4f8b2016-03-11 04:33:52 -0800146SkImage_Raster::SkImage_Raster(const Info& info, sk_sp<SkData> data, size_t rowBytes,
reedaf3fbfc2015-10-04 11:28:36 -0700147 SkColorTable* ctable)
148 : INHERITED(info.width(), info.height(), kNeedNewImageUniqueID)
reed@google.com4f7c6152014-02-06 14:11:56 +0000149{
reed@google.com4f7c6152014-02-06 14:11:56 +0000150 void* addr = const_cast<void*>(data->data());
151
reed7fb4f8b2016-03-11 04:33:52 -0800152 fBitmap.installPixels(info, addr, rowBytes, ctable, release_data, data.release());
reed@google.com58b21ec2012-07-30 18:20:12 +0000153 fBitmap.setImmutable();
154}
155
reed2d5b7142016-08-17 11:12:33 -0700156SkImage_Raster::~SkImage_Raster() {
157#if SK_SUPPORT_GPU
Robert Phillips3798c862017-03-27 11:08:16 -0400158 SkASSERT(nullptr == fPinnedProxy.get()); // want the caller to have manually unpinned
reed2d5b7142016-08-17 11:12:33 -0700159#endif
160}
reed@google.com58b21ec2012-07-30 18:20:12 +0000161
reed96472de2014-12-10 09:53:42 -0800162bool SkImage_Raster::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
reed09553032015-11-23 12:32:16 -0800163 int srcX, int srcY, CachingHint) const {
reedb4f629c2014-12-25 13:55:08 -0800164 SkBitmap shallowCopy(fBitmap);
165 return shallowCopy.readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
reed@google.com4f7c6152014-02-06 14:11:56 +0000166}
167
reed6ceeebd2016-03-09 14:26:26 -0800168bool SkImage_Raster::onPeekPixels(SkPixmap* pm) const {
169 return fBitmap.peekPixels(pm);
reed@google.com4f7c6152014-02-06 14:11:56 +0000170}
171
Brian Osman61624f02016-12-09 14:51:59 -0500172bool SkImage_Raster::getROPixels(SkBitmap* dst, SkColorSpace* dstColorSpace, CachingHint) const {
reed@google.com4b0757b2013-05-20 16:33:41 +0000173 *dst = fBitmap;
174 return true;
175}
176
Robert Phillipsb726d582017-03-09 16:36:32 -0500177#if SK_SUPPORT_GPU
178sk_sp<GrTextureProxy> SkImage_Raster::asTextureProxyRef(GrContext* context,
179 const GrSamplerParams& params,
180 SkColorSpace* dstColorSpace,
181 sk_sp<SkColorSpace>* texColorSpace,
182 SkScalar scaleAdjust[2]) const {
Robert Phillips30a38ff2017-03-22 10:31:11 -0400183 if (!context) {
reed746f31f2015-09-16 12:53:29 -0700184 return nullptr;
185 }
186
Brian Osman7992da32016-11-18 11:28:24 -0500187 if (texColorSpace) {
188 *texColorSpace = sk_ref_sp(fBitmap.colorSpace());
189 }
190
reed2d5b7142016-08-17 11:12:33 -0700191 uint32_t uniqueID;
Robert Phillips3798c862017-03-27 11:08:16 -0400192 sk_sp<GrTextureProxy> tex = this->refPinnedTextureProxy(&uniqueID);
reed2d5b7142016-08-17 11:12:33 -0700193 if (tex) {
Robert Phillips3798c862017-03-27 11:08:16 -0400194 GrTextureAdjuster adjuster(context, fPinnedProxy,
Robert Phillips0c984a02017-03-16 07:51:56 -0400195 fBitmap.alphaType(), fBitmap.bounds(),
reed2d5b7142016-08-17 11:12:33 -0700196 fPinnedUniqueID, fBitmap.colorSpace());
Robert Phillips3798c862017-03-27 11:08:16 -0400197 return adjuster.refTextureProxySafeForParams(params, nullptr, scaleAdjust);
reed2d5b7142016-08-17 11:12:33 -0700198 }
199
Robert Phillips78075802017-03-23 11:11:59 -0400200 return GrRefCachedBitmapTextureProxy(context, fBitmap, params, scaleAdjust);
reed746f31f2015-09-16 12:53:29 -0700201}
Robert Phillips30a38ff2017-03-22 10:31:11 -0400202#endif
reed746f31f2015-09-16 12:53:29 -0700203
reed2d5b7142016-08-17 11:12:33 -0700204#if SK_SUPPORT_GPU
205
Robert Phillips3798c862017-03-27 11:08:16 -0400206sk_sp<GrTextureProxy> SkImage_Raster::refPinnedTextureProxy(uint32_t* uniqueID) const {
207 if (fPinnedProxy) {
reed2d5b7142016-08-17 11:12:33 -0700208 SkASSERT(fPinnedCount > 0);
209 SkASSERT(fPinnedUniqueID != 0);
210 *uniqueID = fPinnedUniqueID;
Robert Phillips3798c862017-03-27 11:08:16 -0400211 return fPinnedProxy;
reed2d5b7142016-08-17 11:12:33 -0700212 }
213 return nullptr;
214}
215
Derek Sollenbergerd3ea9b72016-11-09 11:25:13 -0500216bool SkImage_Raster::onPinAsTexture(GrContext* ctx) const {
Robert Phillips3798c862017-03-27 11:08:16 -0400217 if (fPinnedProxy) {
reed2d5b7142016-08-17 11:12:33 -0700218 SkASSERT(fPinnedCount > 0);
219 SkASSERT(fPinnedUniqueID != 0);
reed2d5b7142016-08-17 11:12:33 -0700220 } else {
221 SkASSERT(fPinnedCount == 0);
222 SkASSERT(fPinnedUniqueID == 0);
Robert Phillips3798c862017-03-27 11:08:16 -0400223 fPinnedProxy = GrRefCachedBitmapTextureProxy(ctx, fBitmap,
224 GrSamplerParams::ClampNoFilter(), nullptr);
225 if (!fPinnedProxy) {
Derek Sollenbergerd3ea9b72016-11-09 11:25:13 -0500226 return false;
227 }
reed2d5b7142016-08-17 11:12:33 -0700228 fPinnedUniqueID = fBitmap.getGenerationID();
229 }
Derek Sollenbergerd3ea9b72016-11-09 11:25:13 -0500230 // Note: we only increment if the texture was successfully pinned
reed2d5b7142016-08-17 11:12:33 -0700231 ++fPinnedCount;
Derek Sollenbergerd3ea9b72016-11-09 11:25:13 -0500232 return true;
reed2d5b7142016-08-17 11:12:33 -0700233}
234
235void SkImage_Raster::onUnpinAsTexture(GrContext* ctx) const {
236 // Note: we always decrement, even if fPinnedTexture is null
237 SkASSERT(fPinnedCount > 0);
238 SkASSERT(fPinnedUniqueID != 0);
reed2d5b7142016-08-17 11:12:33 -0700239
240 if (0 == --fPinnedCount) {
Robert Phillips3798c862017-03-27 11:08:16 -0400241 fPinnedProxy.reset(nullptr);
reed2d5b7142016-08-17 11:12:33 -0700242 fPinnedUniqueID = 0;
243 }
244}
245#endif
246
reed7fb4f8b2016-03-11 04:33:52 -0800247sk_sp<SkImage> SkImage_Raster::onMakeSubset(const SkIRect& subset) const {
reed7b6945b2015-09-24 00:50:58 -0700248 // TODO : could consider heurist of sharing pixels, if subset is pretty close to complete
249
250 SkImageInfo info = SkImageInfo::MakeN32(subset.width(), subset.height(), fBitmap.alphaType());
reede8f30622016-03-23 18:59:25 -0700251 auto surface(SkSurface::MakeRaster(info));
reed7b6945b2015-09-24 00:50:58 -0700252 if (!surface) {
253 return nullptr;
254 }
255 surface->getCanvas()->clear(0);
256 surface->getCanvas()->drawImage(this, SkIntToScalar(-subset.x()), SkIntToScalar(-subset.y()),
257 nullptr);
reed9ce9d672016-03-17 10:51:11 -0700258 return surface->makeImageSnapshot();
reed7b6945b2015-09-24 00:50:58 -0700259}
260
reed@google.com58b21ec2012-07-30 18:20:12 +0000261///////////////////////////////////////////////////////////////////////////////
262
reed7fb4f8b2016-03-11 04:33:52 -0800263sk_sp<SkImage> SkImage::MakeRasterCopy(const SkPixmap& pmap) {
reedde499882015-06-18 13:41:40 -0700264 size_t size;
reed7fb4f8b2016-03-11 04:33:52 -0800265 if (!SkImage_Raster::ValidArgs(pmap.info(), pmap.rowBytes(),
266 pmap.ctable() != nullptr, &size) || !pmap.addr()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700267 return nullptr;
reed@google.com58b21ec2012-07-30 18:20:12 +0000268 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000269
reed@google.com58b21ec2012-07-30 18:20:12 +0000270 // Here we actually make a copy of the caller's pixel data
bungeman38d909e2016-08-02 14:40:46 -0700271 sk_sp<SkData> data(SkData::MakeWithCopy(pmap.addr(), size));
reed7fb4f8b2016-03-11 04:33:52 -0800272 return sk_make_sp<SkImage_Raster>(pmap.info(), std::move(data), pmap.rowBytes(), pmap.ctable());
reed@google.com58b21ec2012-07-30 18:20:12 +0000273}
274
275
reed7fb4f8b2016-03-11 04:33:52 -0800276sk_sp<SkImage> SkImage::MakeRasterData(const SkImageInfo& info, sk_sp<SkData> data,
277 size_t rowBytes) {
reedde499882015-06-18 13:41:40 -0700278 size_t size;
halcanaryc56c6ef2015-09-28 11:55:28 -0700279 if (!SkImage_Raster::ValidArgs(info, rowBytes, false, &size) || !data) {
halcanary96fcdcc2015-08-27 07:41:13 -0700280 return nullptr;
reed@google.com58b21ec2012-07-30 18:20:12 +0000281 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000282
reed@google.com58b21ec2012-07-30 18:20:12 +0000283 // did they give us enough data?
reed@google.com999da9c2014-02-06 13:43:07 +0000284 if (data->size() < size) {
halcanary96fcdcc2015-08-27 07:41:13 -0700285 return nullptr;
reed@google.com58b21ec2012-07-30 18:20:12 +0000286 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000287
halcanary96fcdcc2015-08-27 07:41:13 -0700288 SkColorTable* ctable = nullptr;
reed7fb4f8b2016-03-11 04:33:52 -0800289 return sk_make_sp<SkImage_Raster>(info, std::move(data), rowBytes, ctable);
reed@google.com58b21ec2012-07-30 18:20:12 +0000290}
291
reed7fb4f8b2016-03-11 04:33:52 -0800292sk_sp<SkImage> SkImage::MakeFromRaster(const SkPixmap& pmap, RasterReleaseProc proc,
293 ReleaseContext ctx) {
reedde499882015-06-18 13:41:40 -0700294 size_t size;
Matt Sarett8572d852017-02-14 11:21:02 -0500295 if (!SkImage_Raster::ValidArgs(pmap.info(), pmap.rowBytes(), pmap.ctable(), &size) ||
296 !pmap.addr())
297 {
halcanary96fcdcc2015-08-27 07:41:13 -0700298 return nullptr;
reedde499882015-06-18 13:41:40 -0700299 }
300
bungeman38d909e2016-08-02 14:40:46 -0700301 sk_sp<SkData> data(SkData::MakeWithProc(pmap.addr(), size, proc, ctx));
reed7fb4f8b2016-03-11 04:33:52 -0800302 return sk_make_sp<SkImage_Raster>(pmap.info(), std::move(data), pmap.rowBytes(), pmap.ctable());
reedde499882015-06-18 13:41:40 -0700303}
304
Matt Sarettd21fd4b2017-06-08 09:08:34 -0400305sk_sp<SkImage> SkMakeImageFromRasterBitmapPriv(const SkBitmap& bm, SkCopyPixelsMode cpm) {
306 if (kAlways_SkCopyPixelsMode == cpm || (!bm.isImmutable() && kNever_SkCopyPixelsMode != cpm)) {
307 SkPixmap pmap;
308 SkAssertResult(bm.peekPixels(&pmap));
309 return SkImage::MakeRasterCopy(pmap);
halcanaryc56c6ef2015-09-28 11:55:28 -0700310 }
311
Matt Sarettd21fd4b2017-06-08 09:08:34 -0400312 return sk_make_sp<SkImage_Raster>(bm, kNever_SkCopyPixelsMode == cpm);
313}
314
315sk_sp<SkImage> SkMakeImageFromRasterBitmap(const SkBitmap& bm, SkCopyPixelsMode cpm) {
316 if (!SkImageInfoIsValidAllowNumericalCS(bm.info()) || !bm.getPixels() ||
317 bm.rowBytes() < bm.info().minRowBytes()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700318 return nullptr;
kkinnunen73953e72015-02-23 22:12:12 -0800319 }
320
Matt Sarettd21fd4b2017-06-08 09:08:34 -0400321 return SkMakeImageFromRasterBitmapPriv(bm, cpm);
reed@google.com58b21ec2012-07-30 18:20:12 +0000322}
323
piotaixr65151752014-10-16 11:58:39 -0700324const SkPixelRef* SkBitmapImageGetPixelRef(const SkImage* image) {
325 return ((const SkImage_Raster*)image)->getPixelRef();
reed@google.com97af1a62012-08-28 12:19:02 +0000326}
piotaixrd2a35222014-08-19 14:29:02 -0700327
reed3c065112015-07-08 12:46:22 -0700328bool SkImage_Raster::onAsLegacyBitmap(SkBitmap* bitmap, LegacyBitmapMode mode) const {
329 if (kRO_LegacyBitmapMode == mode) {
330 // When we're a snapshot from a surface, our bitmap may not be marked immutable
331 // even though logically always we are, but in that case we can't physically share our
332 // pixelref since the caller might call setImmutable() themselves
333 // (thus changing our state).
334 if (fBitmap.isImmutable()) {
fmalitaea561bf2015-07-09 17:10:31 -0700335 bitmap->setInfo(fBitmap.info(), fBitmap.rowBytes());
Hal Canary1b3387b2016-12-12 13:48:12 -0500336 bitmap->setPixelRef(sk_ref_sp(fBitmap.pixelRef()),
337 fBitmap.pixelRefOrigin().x(),
338 fBitmap.pixelRefOrigin().y());
reed3c065112015-07-08 12:46:22 -0700339 return true;
340 }
341 }
342 return this->INHERITED::onAsLegacyBitmap(bitmap, mode);
343}
Matt Sarett6de13102017-03-14 14:10:48 -0400344
Matt Sarett5b1dba82017-04-03 11:42:52 -0400345///////////////////////////////////////////////////////////////////////////////
346
Matt Sarett9f3dcb32017-05-04 08:53:32 -0400347sk_sp<SkImage> SkImage_Raster::onMakeColorSpace(sk_sp<SkColorSpace> target,
348 SkColorType targetColorType,
349 SkTransferFunctionBehavior premulBehavior) const {
Matt Sarett6de13102017-03-14 14:10:48 -0400350 SkPixmap src;
Matt Sarett9f3dcb32017-05-04 08:53:32 -0400351 SkAssertResult(fBitmap.peekPixels(&src));
Matt Sarett6de13102017-03-14 14:10:48 -0400352
Mike Klein919cc452017-03-18 15:36:52 +0000353 // Treat nullptr srcs as sRGB.
354 if (!src.colorSpace()) {
Matt Sarettd3df9ec2017-06-05 10:45:30 -0400355 if (target->isSRGB()) {
356 return sk_ref_sp(const_cast<SkImage*>((SkImage*)this));
357 }
358
Mike Klein919cc452017-03-18 15:36:52 +0000359 src.setColorSpace(SkColorSpace::MakeSRGB());
360 }
361
Matt Sarettd3df9ec2017-06-05 10:45:30 -0400362 SkImageInfo dstInfo = fBitmap.info().makeColorType(targetColorType).makeColorSpace(target);
363 SkBitmap dst;
364 dst.allocPixels(dstInfo);
365
Matt Sarett9f3dcb32017-05-04 08:53:32 -0400366 SkAssertResult(dst.writePixels(src, 0, 0, premulBehavior));
Matt Sarett6de13102017-03-14 14:10:48 -0400367 dst.setImmutable();
368 return SkImage::MakeFromBitmap(dst);
369}