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 "SkData.h"
12 #include "SkImageGenerator.h"
13 #include "SkImagePriv.h"
14 #include "SkPixelRef.h"
15 #include "SkSurface.h"
16
17 class SkImage_Raster : public SkImage_Base {
18 public:
ValidArgs(const Info & info,size_t rowBytes)19 static bool ValidArgs(const Info& info, size_t rowBytes) {
20 const int maxDimension = SK_MaxS32 >> 2;
21 const size_t kMaxPixelByteSize = SK_MaxS32;
22
23 if (info.width() <= 0 || info.height() <= 0) {
24 return false;
25 }
26 if (info.width() > maxDimension || info.height() > maxDimension) {
27 return false;
28 }
29 if ((unsigned)info.colorType() > (unsigned)kLastEnum_SkColorType) {
30 return false;
31 }
32 if ((unsigned)info.alphaType() > (unsigned)kLastEnum_SkAlphaType) {
33 return false;
34 }
35
36 if (kUnknown_SkColorType == info.colorType()) {
37 return false;
38 }
39
40 // TODO: check colorspace
41
42 if (rowBytes < SkImageMinRowBytes(info)) {
43 return false;
44 }
45
46 int64_t size = (int64_t)info.height() * rowBytes;
47 if (size > (int64_t)kMaxPixelByteSize) {
48 return false;
49 }
50 return true;
51 }
52
53 SkImage_Raster(const SkImageInfo&, SkData*, size_t rb, const SkSurfaceProps*);
54 virtual ~SkImage_Raster();
55
56 SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) const override;
57 bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY) const override;
58 const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const override;
59 bool getROPixels(SkBitmap*) const override;
60
61 // exposed for SkSurface_Raster via SkNewImageFromPixelRef
62 SkImage_Raster(const SkImageInfo&, SkPixelRef*, const SkIPoint& pixelRefOrigin, size_t rowBytes,
63 const SkSurfaceProps*);
64
getPixelRef() const65 SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }
66
67 SkShader* onNewShader(SkShader::TileMode,
68 SkShader::TileMode,
69 const SkMatrix* localMatrix) const override;
70
71 bool isOpaque() const override;
72
SkImage_Raster(const SkBitmap & bm,const SkSurfaceProps * props)73 SkImage_Raster(const SkBitmap& bm, const SkSurfaceProps* props)
74 : INHERITED(bm.width(), bm.height(), props)
75 , fBitmap(bm) {}
76
77 private:
SkImage_Raster()78 SkImage_Raster() : INHERITED(0, 0, NULL) {}
79
80 SkBitmap fBitmap;
81
82 typedef SkImage_Base INHERITED;
83 };
84
85 ///////////////////////////////////////////////////////////////////////////////
86
release_data(void * addr,void * context)87 static void release_data(void* addr, void* context) {
88 SkData* data = static_cast<SkData*>(context);
89 data->unref();
90 }
91
SkImage_Raster(const Info & info,SkData * data,size_t rowBytes,const SkSurfaceProps * props)92 SkImage_Raster::SkImage_Raster(const Info& info, SkData* data, size_t rowBytes,
93 const SkSurfaceProps* props)
94 : INHERITED(info.width(), info.height(), props)
95 {
96 data->ref();
97 void* addr = const_cast<void*>(data->data());
98 SkColorTable* ctable = NULL;
99
100 fBitmap.installPixels(info, addr, rowBytes, ctable, release_data, data);
101 fBitmap.setImmutable();
102 fBitmap.lockPixels();
103 }
104
SkImage_Raster(const Info & info,SkPixelRef * pr,const SkIPoint & pixelRefOrigin,size_t rowBytes,const SkSurfaceProps * props)105 SkImage_Raster::SkImage_Raster(const Info& info, SkPixelRef* pr, const SkIPoint& pixelRefOrigin,
106 size_t rowBytes, const SkSurfaceProps* props)
107 : INHERITED(info.width(), info.height(), props)
108 {
109 fBitmap.setInfo(info, rowBytes);
110 fBitmap.setPixelRef(pr, pixelRefOrigin);
111 fBitmap.lockPixels();
112 }
113
~SkImage_Raster()114 SkImage_Raster::~SkImage_Raster() {}
115
onNewShader(SkShader::TileMode tileX,SkShader::TileMode tileY,const SkMatrix * localMatrix) const116 SkShader* SkImage_Raster::onNewShader(SkShader::TileMode tileX, SkShader::TileMode tileY,
117 const SkMatrix* localMatrix) const {
118 return SkShader::CreateBitmapShader(fBitmap, tileX, tileY, localMatrix);
119 }
120
onNewSurface(const SkImageInfo & info,const SkSurfaceProps & props) const121 SkSurface* SkImage_Raster::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) const {
122 return SkSurface::NewRaster(info, &props);
123 }
124
onReadPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int srcX,int srcY) const125 bool SkImage_Raster::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
126 int srcX, int srcY) const {
127 SkBitmap shallowCopy(fBitmap);
128 return shallowCopy.readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
129 }
130
onPeekPixels(SkImageInfo * infoPtr,size_t * rowBytesPtr) const131 const void* SkImage_Raster::onPeekPixels(SkImageInfo* infoPtr, size_t* rowBytesPtr) const {
132 const SkImageInfo info = fBitmap.info();
133 if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) {
134 return NULL;
135 }
136 *infoPtr = info;
137 *rowBytesPtr = fBitmap.rowBytes();
138 return fBitmap.getPixels();
139 }
140
getROPixels(SkBitmap * dst) const141 bool SkImage_Raster::getROPixels(SkBitmap* dst) const {
142 *dst = fBitmap;
143 return true;
144 }
145
146 ///////////////////////////////////////////////////////////////////////////////
147
NewRasterCopy(const SkImageInfo & info,const void * pixels,size_t rowBytes)148 SkImage* SkImage::NewRasterCopy(const SkImageInfo& info, const void* pixels, size_t rowBytes) {
149 if (!SkImage_Raster::ValidArgs(info, rowBytes) || !pixels) {
150 return NULL;
151 }
152
153 // Here we actually make a copy of the caller's pixel data
154 SkAutoDataUnref data(SkData::NewWithCopy(pixels, info.height() * rowBytes));
155 return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes, NULL));
156 }
157
158
NewRasterData(const SkImageInfo & info,SkData * data,size_t rowBytes)159 SkImage* SkImage::NewRasterData(const SkImageInfo& info, SkData* data, size_t rowBytes) {
160 if (!SkImage_Raster::ValidArgs(info, rowBytes) || !data) {
161 return NULL;
162 }
163
164 // did they give us enough data?
165 size_t size = info.height() * rowBytes;
166 if (data->size() < size) {
167 return NULL;
168 }
169
170 return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes, NULL));
171 }
172
NewFromGenerator(SkImageGenerator * generator)173 SkImage* SkImage::NewFromGenerator(SkImageGenerator* generator) {
174 SkBitmap bitmap;
175 if (!SkInstallDiscardablePixelRef(generator, &bitmap)) {
176 return NULL;
177 }
178 if (0 == bitmap.width() || 0 == bitmap.height()) {
179 return NULL;
180 }
181
182 return SkNEW_ARGS(SkImage_Raster, (bitmap, NULL));
183 }
184
SkNewImageFromPixelRef(const SkImageInfo & info,SkPixelRef * pr,const SkIPoint & pixelRefOrigin,size_t rowBytes,const SkSurfaceProps * props)185 SkImage* SkNewImageFromPixelRef(const SkImageInfo& info, SkPixelRef* pr,
186 const SkIPoint& pixelRefOrigin, size_t rowBytes,
187 const SkSurfaceProps* props) {
188 if (!SkImage_Raster::ValidArgs(info, rowBytes)) {
189 return NULL;
190 }
191 return SkNEW_ARGS(SkImage_Raster, (info, pr, pixelRefOrigin, rowBytes, props));
192 }
193
SkNewImageFromBitmap(const SkBitmap & bm,bool canSharePixelRef,const SkSurfaceProps * props)194 SkImage* SkNewImageFromBitmap(const SkBitmap& bm, bool canSharePixelRef,
195 const SkSurfaceProps* props) {
196 if (!SkImage_Raster::ValidArgs(bm.info(), bm.rowBytes())) {
197 return NULL;
198 }
199
200 SkImage* image = NULL;
201 if (canSharePixelRef || bm.isImmutable()) {
202 image = SkNEW_ARGS(SkImage_Raster, (bm, props));
203 } else {
204 bm.lockPixels();
205 if (bm.getPixels()) {
206 image = SkImage::NewRasterCopy(bm.info(), bm.getPixels(), bm.rowBytes());
207 }
208 bm.unlockPixels();
209
210 // we don't expose props to NewRasterCopy (need a private vers) so post-init it here
211 if (image && props) {
212 as_IB(image)->initWithProps(*props);
213 }
214 }
215 return image;
216 }
217
SkBitmapImageGetPixelRef(const SkImage * image)218 const SkPixelRef* SkBitmapImageGetPixelRef(const SkImage* image) {
219 return ((const SkImage_Raster*)image)->getPixelRef();
220 }
221
isOpaque() const222 bool SkImage_Raster::isOpaque() const {
223 return fBitmap.isOpaque();
224 }
225
226