xref: /aosp_15_r20/external/skia/src/image/SkImage_Raster.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2012 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker #include "src/image/SkImage_Raster.h"
8*c8dee2aaSAndroid Build Coastguard Worker 
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPixelRef.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPixmap.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRectMemcpy.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkImageInfoPriv.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkImagePriv.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/image/SkImage_Base.h"
26*c8dee2aaSAndroid Build Coastguard Worker 
27*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
28*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
29*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
30*c8dee2aaSAndroid Build Coastguard Worker 
31*c8dee2aaSAndroid Build Coastguard Worker class GrDirectContext;
32*c8dee2aaSAndroid Build Coastguard Worker class SkSurfaceProps;
33*c8dee2aaSAndroid Build Coastguard Worker 
34*c8dee2aaSAndroid Build Coastguard Worker // fixes https://bug.skia.org/5096
is_not_subset(const SkBitmap & bm)35*c8dee2aaSAndroid Build Coastguard Worker static bool is_not_subset(const SkBitmap& bm) {
36*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(bm.pixelRef());
37*c8dee2aaSAndroid Build Coastguard Worker     SkISize dim = SkISize::Make(bm.pixelRef()->width(), bm.pixelRef()->height());
38*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(dim != bm.dimensions() || bm.pixelRefOrigin().isZero());
39*c8dee2aaSAndroid Build Coastguard Worker     return dim == bm.dimensions();
40*c8dee2aaSAndroid Build Coastguard Worker }
41*c8dee2aaSAndroid Build Coastguard Worker 
release_data(void * addr,void * context)42*c8dee2aaSAndroid Build Coastguard Worker static void release_data(void* addr, void* context) {
43*c8dee2aaSAndroid Build Coastguard Worker     SkData* data = static_cast<SkData*>(context);
44*c8dee2aaSAndroid Build Coastguard Worker     data->unref();
45*c8dee2aaSAndroid Build Coastguard Worker }
46*c8dee2aaSAndroid Build Coastguard Worker 
SkImage_Raster(const SkImageInfo & info,sk_sp<SkData> data,size_t rowBytes,uint32_t id)47*c8dee2aaSAndroid Build Coastguard Worker SkImage_Raster::SkImage_Raster(const SkImageInfo& info, sk_sp<SkData> data, size_t rowBytes,
48*c8dee2aaSAndroid Build Coastguard Worker                                uint32_t id)
49*c8dee2aaSAndroid Build Coastguard Worker         : SkImage_Base(info, id) {
50*c8dee2aaSAndroid Build Coastguard Worker     void* addr = const_cast<void*>(data->data());
51*c8dee2aaSAndroid Build Coastguard Worker 
52*c8dee2aaSAndroid Build Coastguard Worker     fBitmap.installPixels(info, addr, rowBytes, release_data, data.release());
53*c8dee2aaSAndroid Build Coastguard Worker     fBitmap.setImmutable();
54*c8dee2aaSAndroid Build Coastguard Worker }
55*c8dee2aaSAndroid Build Coastguard Worker 
SkImage_Raster(const SkBitmap & bm,bool bitmapMayBeMutable)56*c8dee2aaSAndroid Build Coastguard Worker SkImage_Raster::SkImage_Raster(const SkBitmap& bm, bool bitmapMayBeMutable)
57*c8dee2aaSAndroid Build Coastguard Worker         : SkImage_Base(bm.info(),
58*c8dee2aaSAndroid Build Coastguard Worker                     is_not_subset(bm) ? bm.getGenerationID() : (uint32_t)kNeedNewImageUniqueID)
59*c8dee2aaSAndroid Build Coastguard Worker         , fBitmap(bm) {
60*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(bitmapMayBeMutable || fBitmap.isImmutable());
61*c8dee2aaSAndroid Build Coastguard Worker }
62*c8dee2aaSAndroid Build Coastguard Worker 
~SkImage_Raster()63*c8dee2aaSAndroid Build Coastguard Worker SkImage_Raster::~SkImage_Raster() {}
64*c8dee2aaSAndroid Build Coastguard Worker 
onReadPixels(GrDirectContext *,const SkImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int srcX,int srcY,CachingHint) const65*c8dee2aaSAndroid Build Coastguard Worker bool SkImage_Raster::onReadPixels(GrDirectContext*,
66*c8dee2aaSAndroid Build Coastguard Worker                                   const SkImageInfo& dstInfo,
67*c8dee2aaSAndroid Build Coastguard Worker                                   void* dstPixels,
68*c8dee2aaSAndroid Build Coastguard Worker                                   size_t dstRowBytes,
69*c8dee2aaSAndroid Build Coastguard Worker                                   int srcX,
70*c8dee2aaSAndroid Build Coastguard Worker                                   int srcY,
71*c8dee2aaSAndroid Build Coastguard Worker                                   CachingHint) const {
72*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap shallowCopy(fBitmap);
73*c8dee2aaSAndroid Build Coastguard Worker     return shallowCopy.readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
74*c8dee2aaSAndroid Build Coastguard Worker }
75*c8dee2aaSAndroid Build Coastguard Worker 
onPeekPixels(SkPixmap * pm) const76*c8dee2aaSAndroid Build Coastguard Worker bool SkImage_Raster::onPeekPixels(SkPixmap* pm) const {
77*c8dee2aaSAndroid Build Coastguard Worker     return fBitmap.peekPixels(pm);
78*c8dee2aaSAndroid Build Coastguard Worker }
79*c8dee2aaSAndroid Build Coastguard Worker 
getROPixels(GrDirectContext *,SkBitmap * dst,CachingHint) const80*c8dee2aaSAndroid Build Coastguard Worker bool SkImage_Raster::getROPixels(GrDirectContext*, SkBitmap* dst, CachingHint) const {
81*c8dee2aaSAndroid Build Coastguard Worker     *dst = fBitmap;
82*c8dee2aaSAndroid Build Coastguard Worker     return true;
83*c8dee2aaSAndroid Build Coastguard Worker }
84*c8dee2aaSAndroid Build Coastguard Worker 
onMakeSurface(skgpu::graphite::Recorder *,const SkImageInfo & info) const85*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> SkImage_Raster::onMakeSurface(skgpu::graphite::Recorder*,
86*c8dee2aaSAndroid Build Coastguard Worker                                                const SkImageInfo& info) const {
87*c8dee2aaSAndroid Build Coastguard Worker     const SkSurfaceProps* props = nullptr;
88*c8dee2aaSAndroid Build Coastguard Worker     const size_t rowBytes = 0;
89*c8dee2aaSAndroid Build Coastguard Worker     return SkSurfaces::Raster(info, rowBytes, props);
90*c8dee2aaSAndroid Build Coastguard Worker }
91*c8dee2aaSAndroid Build Coastguard Worker 
copy_bitmap_subset(const SkBitmap & orig,const SkIRect & subset)92*c8dee2aaSAndroid Build Coastguard Worker static SkBitmap copy_bitmap_subset(const SkBitmap& orig, const SkIRect& subset) {
93*c8dee2aaSAndroid Build Coastguard Worker     SkImageInfo info = orig.info().makeDimensions(subset.size());
94*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bitmap;
95*c8dee2aaSAndroid Build Coastguard Worker     if (!bitmap.tryAllocPixels(info)) {
96*c8dee2aaSAndroid Build Coastguard Worker         return {};
97*c8dee2aaSAndroid Build Coastguard Worker     }
98*c8dee2aaSAndroid Build Coastguard Worker 
99*c8dee2aaSAndroid Build Coastguard Worker     void* dst = bitmap.getPixels();
100*c8dee2aaSAndroid Build Coastguard Worker     void* src = orig.getAddr(subset.x(), subset.y());
101*c8dee2aaSAndroid Build Coastguard Worker     if (!dst || !src) {
102*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGFAIL("SkImage_Raster::onMakeSubset with nullptr src or dst");
103*c8dee2aaSAndroid Build Coastguard Worker         return {};
104*c8dee2aaSAndroid Build Coastguard Worker     }
105*c8dee2aaSAndroid Build Coastguard Worker 
106*c8dee2aaSAndroid Build Coastguard Worker     SkRectMemcpy(dst, bitmap.rowBytes(), src, orig.rowBytes(), bitmap.rowBytes(),
107*c8dee2aaSAndroid Build Coastguard Worker                  subset.height());
108*c8dee2aaSAndroid Build Coastguard Worker 
109*c8dee2aaSAndroid Build Coastguard Worker     bitmap.setImmutable();
110*c8dee2aaSAndroid Build Coastguard Worker     return bitmap;
111*c8dee2aaSAndroid Build Coastguard Worker }
112*c8dee2aaSAndroid Build Coastguard Worker 
onMakeSubset(GrDirectContext *,const SkIRect & subset) const113*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> SkImage_Raster::onMakeSubset(GrDirectContext*, const SkIRect& subset) const {
114*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap copy = copy_bitmap_subset(fBitmap, subset);
115*c8dee2aaSAndroid Build Coastguard Worker     if (copy.isNull()) {
116*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
117*c8dee2aaSAndroid Build Coastguard Worker     } else {
118*c8dee2aaSAndroid Build Coastguard Worker         return copy.asImage();
119*c8dee2aaSAndroid Build Coastguard Worker     }
120*c8dee2aaSAndroid Build Coastguard Worker }
121*c8dee2aaSAndroid Build Coastguard Worker 
copy_mipmaps(const SkBitmap & src,SkMipmap * srcMips)122*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkMipmap> copy_mipmaps(const SkBitmap& src, SkMipmap* srcMips) {
123*c8dee2aaSAndroid Build Coastguard Worker     if (!srcMips) {
124*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
125*c8dee2aaSAndroid Build Coastguard Worker     }
126*c8dee2aaSAndroid Build Coastguard Worker 
127*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkMipmap> dst;
128*c8dee2aaSAndroid Build Coastguard Worker     dst.reset(SkMipmap::Build(src.pixmap(),
129*c8dee2aaSAndroid Build Coastguard Worker                               /* factoryProc= */ nullptr,
130*c8dee2aaSAndroid Build Coastguard Worker                               /* computeContents= */ false));
131*c8dee2aaSAndroid Build Coastguard Worker     if (!dst) {
132*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
133*c8dee2aaSAndroid Build Coastguard Worker     }
134*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < dst->countLevels(); ++i) {
135*c8dee2aaSAndroid Build Coastguard Worker         SkMipmap::Level srcLevel, dstLevel;
136*c8dee2aaSAndroid Build Coastguard Worker         srcMips->getLevel(i, &srcLevel);
137*c8dee2aaSAndroid Build Coastguard Worker         dst->getLevel(i, &dstLevel);
138*c8dee2aaSAndroid Build Coastguard Worker         srcLevel.fPixmap.readPixels(dstLevel.fPixmap);
139*c8dee2aaSAndroid Build Coastguard Worker     }
140*c8dee2aaSAndroid Build Coastguard Worker 
141*c8dee2aaSAndroid Build Coastguard Worker     return dst;
142*c8dee2aaSAndroid Build Coastguard Worker }
143*c8dee2aaSAndroid Build Coastguard Worker 
onMakeSubset(skgpu::graphite::Recorder *,const SkIRect & subset,RequiredProperties requiredProperties) const144*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> SkImage_Raster::onMakeSubset(skgpu::graphite::Recorder*,
145*c8dee2aaSAndroid Build Coastguard Worker                                             const SkIRect& subset,
146*c8dee2aaSAndroid Build Coastguard Worker                                             RequiredProperties requiredProperties) const {
147*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkImage> img;
148*c8dee2aaSAndroid Build Coastguard Worker 
149*c8dee2aaSAndroid Build Coastguard Worker     if (requiredProperties.fMipmapped) {
150*c8dee2aaSAndroid Build Coastguard Worker         bool fullCopy = subset == SkIRect::MakeSize(fBitmap.dimensions());
151*c8dee2aaSAndroid Build Coastguard Worker 
152*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<SkMipmap> mips = fullCopy ? copy_mipmaps(fBitmap, fBitmap.fMips.get()) : nullptr;
153*c8dee2aaSAndroid Build Coastguard Worker 
154*c8dee2aaSAndroid Build Coastguard Worker         // SkImage::withMipmaps will always make a copy for us so we can temporarily share
155*c8dee2aaSAndroid Build Coastguard Worker         // the pixel ref with fBitmap
156*c8dee2aaSAndroid Build Coastguard Worker         SkBitmap tmpSubset;
157*c8dee2aaSAndroid Build Coastguard Worker         if (!fBitmap.extractSubset(&tmpSubset, subset)) {
158*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
159*c8dee2aaSAndroid Build Coastguard Worker         }
160*c8dee2aaSAndroid Build Coastguard Worker 
161*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<SkImage> tmp(new SkImage_Raster(tmpSubset, /* bitmapMayBeMutable= */ true));
162*c8dee2aaSAndroid Build Coastguard Worker 
163*c8dee2aaSAndroid Build Coastguard Worker         // withMipmaps will auto generate the mipmaps if a nullptr is passed in
164*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!mips || mips->validForRootLevel(tmp->imageInfo()));
165*c8dee2aaSAndroid Build Coastguard Worker         img = tmp->withMipmaps(std::move(mips));
166*c8dee2aaSAndroid Build Coastguard Worker     } else {
167*c8dee2aaSAndroid Build Coastguard Worker         SkBitmap copy = copy_bitmap_subset(fBitmap, subset);
168*c8dee2aaSAndroid Build Coastguard Worker         if (!copy.isNull()) {
169*c8dee2aaSAndroid Build Coastguard Worker             img = copy.asImage();
170*c8dee2aaSAndroid Build Coastguard Worker         }
171*c8dee2aaSAndroid Build Coastguard Worker     }
172*c8dee2aaSAndroid Build Coastguard Worker 
173*c8dee2aaSAndroid Build Coastguard Worker     return img;
174*c8dee2aaSAndroid Build Coastguard Worker }
175*c8dee2aaSAndroid Build Coastguard Worker 
176*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
177*c8dee2aaSAndroid Build Coastguard Worker 
SkMakeImageFromRasterBitmapPriv(const SkBitmap & bm,SkCopyPixelsMode cpm,uint32_t idForCopy)178*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> SkMakeImageFromRasterBitmapPriv(const SkBitmap& bm, SkCopyPixelsMode cpm,
179*c8dee2aaSAndroid Build Coastguard Worker                                                uint32_t idForCopy) {
180*c8dee2aaSAndroid Build Coastguard Worker     if (kAlways_SkCopyPixelsMode == cpm || (!bm.isImmutable() && kNever_SkCopyPixelsMode != cpm)) {
181*c8dee2aaSAndroid Build Coastguard Worker         SkPixmap pmap;
182*c8dee2aaSAndroid Build Coastguard Worker         if (bm.peekPixels(&pmap)) {
183*c8dee2aaSAndroid Build Coastguard Worker             return MakeRasterCopyPriv(pmap, idForCopy);
184*c8dee2aaSAndroid Build Coastguard Worker         } else {
185*c8dee2aaSAndroid Build Coastguard Worker             return sk_sp<SkImage>();
186*c8dee2aaSAndroid Build Coastguard Worker         }
187*c8dee2aaSAndroid Build Coastguard Worker     }
188*c8dee2aaSAndroid Build Coastguard Worker     return sk_make_sp<SkImage_Raster>(bm, kNever_SkCopyPixelsMode == cpm);
189*c8dee2aaSAndroid Build Coastguard Worker }
190*c8dee2aaSAndroid Build Coastguard Worker 
SkMakeImageFromRasterBitmap(const SkBitmap & bm,SkCopyPixelsMode cpm)191*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> SkMakeImageFromRasterBitmap(const SkBitmap& bm, SkCopyPixelsMode cpm) {
192*c8dee2aaSAndroid Build Coastguard Worker     if (!SkImageInfoIsValid(bm.info()) || bm.rowBytes() < bm.info().minRowBytes()) {
193*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
194*c8dee2aaSAndroid Build Coastguard Worker     }
195*c8dee2aaSAndroid Build Coastguard Worker 
196*c8dee2aaSAndroid Build Coastguard Worker     return SkMakeImageFromRasterBitmapPriv(bm, cpm, kNeedNewImageUniqueID);
197*c8dee2aaSAndroid Build Coastguard Worker }
198*c8dee2aaSAndroid Build Coastguard Worker 
SkBitmapImageGetPixelRef(const SkImage * image)199*c8dee2aaSAndroid Build Coastguard Worker const SkPixelRef* SkBitmapImageGetPixelRef(const SkImage* image) {
200*c8dee2aaSAndroid Build Coastguard Worker     return ((const SkImage_Raster*)image)->getPixelRef();
201*c8dee2aaSAndroid Build Coastguard Worker }
202*c8dee2aaSAndroid Build Coastguard Worker 
onAsLegacyBitmap(GrDirectContext *,SkBitmap * bitmap) const203*c8dee2aaSAndroid Build Coastguard Worker bool SkImage_Raster::onAsLegacyBitmap(GrDirectContext*, SkBitmap* bitmap) const {
204*c8dee2aaSAndroid Build Coastguard Worker     // When we're a snapshot from a surface, our bitmap may not be marked immutable
205*c8dee2aaSAndroid Build Coastguard Worker     // even though logically always we are, but in that case we can't physically share our
206*c8dee2aaSAndroid Build Coastguard Worker     // pixelref since the caller might call setImmutable() themselves
207*c8dee2aaSAndroid Build Coastguard Worker     // (thus changing our state).
208*c8dee2aaSAndroid Build Coastguard Worker     if (fBitmap.isImmutable()) {
209*c8dee2aaSAndroid Build Coastguard Worker         SkIPoint origin = fBitmap.pixelRefOrigin();
210*c8dee2aaSAndroid Build Coastguard Worker         bitmap->setInfo(fBitmap.info(), fBitmap.rowBytes());
211*c8dee2aaSAndroid Build Coastguard Worker         bitmap->setPixelRef(sk_ref_sp(fBitmap.pixelRef()), origin.x(), origin.y());
212*c8dee2aaSAndroid Build Coastguard Worker         return true;
213*c8dee2aaSAndroid Build Coastguard Worker     }
214*c8dee2aaSAndroid Build Coastguard Worker     return this->SkImage_Base::onAsLegacyBitmap(nullptr, bitmap);
215*c8dee2aaSAndroid Build Coastguard Worker }
216*c8dee2aaSAndroid Build Coastguard Worker 
217*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
218*c8dee2aaSAndroid Build Coastguard Worker 
onMakeColorTypeAndColorSpace(SkColorType targetCT,sk_sp<SkColorSpace> targetCS,GrDirectContext *) const219*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> SkImage_Raster::onMakeColorTypeAndColorSpace(SkColorType targetCT,
220*c8dee2aaSAndroid Build Coastguard Worker                                                             sk_sp<SkColorSpace> targetCS,
221*c8dee2aaSAndroid Build Coastguard Worker                                                             GrDirectContext*) const {
222*c8dee2aaSAndroid Build Coastguard Worker     SkPixmap src;
223*c8dee2aaSAndroid Build Coastguard Worker     SkAssertResult(fBitmap.peekPixels(&src));
224*c8dee2aaSAndroid Build Coastguard Worker 
225*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap dst;
226*c8dee2aaSAndroid Build Coastguard Worker     if (!dst.tryAllocPixels(fBitmap.info().makeColorType(targetCT).makeColorSpace(targetCS))) {
227*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
228*c8dee2aaSAndroid Build Coastguard Worker     }
229*c8dee2aaSAndroid Build Coastguard Worker 
230*c8dee2aaSAndroid Build Coastguard Worker     SkAssertResult(dst.writePixels(src));
231*c8dee2aaSAndroid Build Coastguard Worker     dst.setImmutable();
232*c8dee2aaSAndroid Build Coastguard Worker     return dst.asImage();
233*c8dee2aaSAndroid Build Coastguard Worker }
234*c8dee2aaSAndroid Build Coastguard Worker 
onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const235*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> SkImage_Raster::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
236*c8dee2aaSAndroid Build Coastguard Worker     // TODO: If our bitmap is immutable, then we could theoretically create another image sharing
237*c8dee2aaSAndroid Build Coastguard Worker     // our pixelRef. That doesn't work (without more invasive logic), because the image gets its
238*c8dee2aaSAndroid Build Coastguard Worker     // gen ID from the bitmap, which gets it from the pixelRef.
239*c8dee2aaSAndroid Build Coastguard Worker     SkPixmap pixmap = fBitmap.pixmap();
240*c8dee2aaSAndroid Build Coastguard Worker     pixmap.setColorSpace(std::move(newCS));
241*c8dee2aaSAndroid Build Coastguard Worker     return SkImages::RasterFromPixmapCopy(pixmap);
242*c8dee2aaSAndroid Build Coastguard Worker }
243