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 "SkBitmap.h" 9#include "SkCanvas.h" 10#include "SkImageGenerator.h" 11#include "SkImagePriv.h" 12#include "SkImage_Base.h" 13#include "SkReadPixelsRec.h" 14#include "SkString.h" 15#include "SkSurface.h" 16 17uint32_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 28const 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 40bool 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())) { 44 return false; 45 } 46 return as_IB(this)->onReadPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY); 47} 48 49GrTexture* SkImage::getTexture() const { 50 return as_IB(this)->onGetTexture(); 51} 52 53SkShader* SkImage::newShader(SkShader::TileMode tileX, 54 SkShader::TileMode tileY, 55 const SkMatrix* localMatrix) const { 56 return as_IB(this)->onNewShader(tileX, tileY, localMatrix); 57} 58 59SkData* 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; 65} 66 67SkImage* 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 75SkSurface* 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 82const 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 88SkImage* 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 112/////////////////////////////////////////////////////////////////////////////// 113 114static bool raster_canvas_supports(const SkImageInfo& info) { 115 switch (info.colorType()) { 116 case kN32_SkColorType: 117 return kUnpremul_SkAlphaType != info.alphaType(); 118 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 128bool 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; 132 } 133 134 SkBitmap bm; 135 bm.installPixels(dstInfo, dstPixels, dstRowBytes); 136 SkCanvas canvas(bm); 137 138 SkPaint paint; 139 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 140 canvas.drawImage(this, -SkIntToScalar(srcX), -SkIntToScalar(srcY), &paint); 141 142 return true; 143} 144 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////////////////////////////////////////////////////////////////////////////////////// 173 174#if !SK_SUPPORT_GPU 175 176SkImage* SkImage::NewFromTexture(GrContext*, const GrBackendTextureDesc&, SkAlphaType) { 177 return NULL; 178} 179 180SkImage* SkImage::NewFromTextureCopy(GrContext*, const GrBackendTextureDesc&, SkAlphaType) { 181 return NULL; 182} 183 184#endif 185