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 "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:
     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 
     65     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 
     73     SkImage_Raster(const SkBitmap& bm, const SkSurfaceProps* props)
     74         : INHERITED(bm.width(), bm.height(), props)
     75         , fBitmap(bm) {}
     76 
     77 private:
     78     SkImage_Raster() : INHERITED(0, 0, NULL) {}
     79 
     80     SkBitmap    fBitmap;
     81 
     82     typedef SkImage_Base INHERITED;
     83 };
     84 
     85 ///////////////////////////////////////////////////////////////////////////////
     86 
     87 static void release_data(void* addr, void* context) {
     88     SkData* data = static_cast<SkData*>(context);
     89     data->unref();
     90 }
     91 
     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 
    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 
    114 SkImage_Raster::~SkImage_Raster() {}
    115 
    116 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 
    121 SkSurface* SkImage_Raster::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) const {
    122     return SkSurface::NewRaster(info, &props);
    123 }
    124 
    125 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 
    131 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 
    141 bool SkImage_Raster::getROPixels(SkBitmap* dst) const {
    142     *dst = fBitmap;
    143     return true;
    144 }
    145 
    146 ///////////////////////////////////////////////////////////////////////////////
    147 
    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 
    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 
    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 
    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 
    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 
    218 const SkPixelRef* SkBitmapImageGetPixelRef(const SkImage* image) {
    219     return ((const SkImage_Raster*)image)->getPixelRef();
    220 }
    221 
    222 bool SkImage_Raster::isOpaque() const {
    223     return fBitmap.isOpaque();
    224 }
    225 
    226