blob: 494e21004acde43ac7e370da07765831d8d4910b [file] [log] [blame]
reed@google.com6997ebb2012-07-30 19:50:31 +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
reed@google.comf6627b72012-07-27 18:02:50 +00008#include "SkBitmap.h"
mike@reedtribe.org70e35902012-07-29 20:38:16 +00009#include "SkCanvas.h"
reed5965c8a2015-01-07 18:04:45 -080010#include "SkImageGenerator.h"
scroggo@google.com7def5e12013-05-31 14:00:10 +000011#include "SkImagePriv.h"
12#include "SkImage_Base.h"
reed96472de2014-12-10 09:53:42 -080013#include "SkReadPixelsRec.h"
reedf8d18742015-01-02 20:45:37 -080014#include "SkString.h"
reed4af267b2014-11-21 08:46:37 -080015#include "SkSurface.h"
scroggo@google.com7def5e12013-05-31 14:00:10 +000016
reed@google.comf6627b72012-07-27 18:02:50 +000017uint32_t SkImage::NextUniqueID() {
18 static int32_t gUniqueID;
19
20 // never return 0;
21 uint32_t id;
22 do {
23 id = sk_atomic_inc(&gUniqueID) + 1;
24 } while (0 == id);
25 return id;
26}
27
reed@google.com4f7c6152014-02-06 14:11:56 +000028const void* SkImage::peekPixels(SkImageInfo* info, size_t* rowBytes) const {
29 SkImageInfo infoStorage;
30 size_t rowBytesStorage;
31 if (NULL == info) {
32 info = &infoStorage;
33 }
34 if (NULL == rowBytes) {
35 rowBytes = &rowBytesStorage;
36 }
37 return as_IB(this)->onPeekPixels(info, rowBytes);
38}
39
reed96472de2014-12-10 09:53:42 -080040bool SkImage::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
41 int srcX, int srcY) const {
42 SkReadPixelsRec rec(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
43 if (!rec.trim(this->width(), this->height())) {
reed@google.com4f7c6152014-02-06 14:11:56 +000044 return false;
45 }
reed96472de2014-12-10 09:53:42 -080046 return as_IB(this)->onReadPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY);
reed@google.com4f7c6152014-02-06 14:11:56 +000047}
48
kkinnunencd6ca9e2015-02-18 10:50:52 -080049GrTexture* SkImage::getTexture() const {
scroggo@google.com7def5e12013-05-31 14:00:10 +000050 return as_IB(this)->onGetTexture();
51}
52
piotaixr76d5b472014-07-22 15:02:05 -070053SkShader* SkImage::newShader(SkShader::TileMode tileX,
54 SkShader::TileMode tileY,
55 const SkMatrix* localMatrix) const {
56 return as_IB(this)->onNewShader(tileX, tileY, localMatrix);
piotaixrcef04f82014-07-14 07:48:04 -070057}
58
scroggo@google.com7def5e12013-05-31 14:00:10 +000059SkData* SkImage::encode(SkImageEncoder::Type type, int quality) const {
60 SkBitmap bm;
61 if (as_IB(this)->getROPixels(&bm)) {
62 return SkImageEncoder::EncodeData(bm, type, quality);
63 }
64 return NULL;
junov@chromium.orgda904742013-05-01 22:38:16 +000065}
reed@google.com4f7c6152014-02-06 14:11:56 +000066
reed5965c8a2015-01-07 18:04:45 -080067SkImage* SkImage::NewFromData(SkData* data) {
68 if (NULL == data) {
69 return NULL;
70 }
71 SkImageGenerator* generator = SkImageGenerator::NewFromData(data);
72 return generator ? SkImage::NewFromGenerator(generator) : NULL;
73}
74
reed4af267b2014-11-21 08:46:37 -080075SkSurface* SkImage::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) const {
76 if (NULL == props) {
77 props = &as_IB(this)->props();
78 }
79 return as_IB(this)->onNewSurface(info, *props);
80}
81
reedf8d18742015-01-02 20:45:37 -080082const char* SkImage::toString(SkString* str) const {
83 str->appendf("image: (id:%d (%d, %d) %s)", this->uniqueID(), this->width(), this->height(),
84 this->isOpaque() ? "opaque" : "");
85 return str->c_str();
86}
87
reedf803da12015-01-23 05:58:07 -080088SkImage* SkImage::newImage(int newWidth, int newHeight, const SkIRect* subset,
89 SkFilterQuality quality) const {
90 if (newWidth <= 0 || newHeight <= 0) {
91 return NULL;
92 }
93
94 const SkIRect bounds = SkIRect::MakeWH(this->width(), this->height());
95
96 if (subset) {
97 if (!bounds.contains(*subset)) {
98 return NULL;
99 }
100 if (bounds == *subset) {
101 subset = NULL; // and fall through to check below
102 }
103 }
104
105 if (NULL == subset && this->width() == newWidth && this->height() == newHeight) {
106 return SkRef(const_cast<SkImage*>(this));
107 }
108
109 return as_IB(this)->onNewImage(newWidth, newHeight, subset, quality);
110}
111
reed@google.com4f7c6152014-02-06 14:11:56 +0000112///////////////////////////////////////////////////////////////////////////////
113
114static bool raster_canvas_supports(const SkImageInfo& info) {
reede5ea5002014-09-03 11:54:58 -0700115 switch (info.colorType()) {
commit-bot@chromium.org28fcae22014-04-11 17:15:40 +0000116 case kN32_SkColorType:
reede5ea5002014-09-03 11:54:58 -0700117 return kUnpremul_SkAlphaType != info.alphaType();
reed@google.com4f7c6152014-02-06 14:11:56 +0000118 case kRGB_565_SkColorType:
119 return true;
120 case kAlpha_8_SkColorType:
121 return true;
122 default:
123 break;
124 }
125 return false;
126}
127
reed96472de2014-12-10 09:53:42 -0800128bool SkImage_Base::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
129 int srcX, int srcY) const {
130 if (!raster_canvas_supports(dstInfo)) {
131 return false;
reed@google.com4f7c6152014-02-06 14:11:56 +0000132 }
133
reed96472de2014-12-10 09:53:42 -0800134 SkBitmap bm;
135 bm.installPixels(dstInfo, dstPixels, dstRowBytes);
136 SkCanvas canvas(bm);
reed@google.com4f7c6152014-02-06 14:11:56 +0000137
138 SkPaint paint;
reed96472de2014-12-10 09:53:42 -0800139 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
140 canvas.drawImage(this, -SkIntToScalar(srcX), -SkIntToScalar(srcY), &paint);
reed@google.com4f7c6152014-02-06 14:11:56 +0000141
reed@google.com4f7c6152014-02-06 14:11:56 +0000142 return true;
143}
reedf803da12015-01-23 05:58:07 -0800144
145SkImage* SkImage_Base::onNewImage(int newWidth, int newHeight, const SkIRect* subset,
146 SkFilterQuality quality) const {
147 const bool opaque = this->isOpaque();
148 const SkImageInfo info = SkImageInfo::Make(newWidth, newHeight, kN32_SkColorType,
149 opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
150 SkAutoTUnref<SkSurface> surface(this->newSurface(info, NULL));
151 if (!surface.get()) {
152 return NULL;
153 }
154
155 SkRect src;
156 if (subset) {
157 src.set(*subset);
158 } else {
159 src = SkRect::MakeIWH(this->width(), this->height());
160 }
161
162 surface->getCanvas()->scale(newWidth / src.width(), newHeight / src.height());
163 surface->getCanvas()->translate(-src.x(), -src.y());
164
165 SkPaint paint;
166 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
167 paint.setFilterQuality(quality);
168 surface->getCanvas()->drawImage(this, 0, 0, &paint);
169 return surface->newImageSnapshot();
170}
171
172