Home | History | Annotate | Download | only in image
      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 
     17 uint32_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 
     28 const 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 
     40 bool 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 
     49 GrTexture* SkImage::getTexture() const {
     50     return as_IB(this)->onGetTexture();
     51 }
     52 
     53 SkShader* 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 
     59 SkData* 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 
     67 SkImage* 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 
     75 SkSurface* 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 
     82 const 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 
     88 SkImage* 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 
    114 static 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 
    128 bool 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 
    145 SkImage* 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 
    176 SkImage* SkImage::NewFromTexture(GrContext*, const GrBackendTextureDesc&, SkAlphaType) {
    177     return NULL;
    178 }
    179 
    180 SkImage* SkImage::NewFromTextureCopy(GrContext*, const GrBackendTextureDesc&, SkAlphaType) {
    181     return NULL;
    182 }
    183 
    184 #endif
    185