Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2015 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 #ifndef SkPixmap_DEFINED
      9 #define SkPixmap_DEFINED
     10 
     11 #include "SkColor.h"
     12 #include "SkFilterQuality.h"
     13 #include "SkImageInfo.h"
     14 
     15 class SkColorTable;
     16 class SkData;
     17 struct SkMask;
     18 
     19 /**
     20  *  Pairs SkImageInfo with actual pixels and rowbytes. This class does not try to manage the
     21  *  lifetime of the pixel memory (nor the colortable if provided).
     22  */
     23 class SK_API SkPixmap {
     24 public:
     25     SkPixmap()
     26         : fPixels(NULL), fCTable(NULL), fRowBytes(0), fInfo(SkImageInfo::MakeUnknown(0, 0))
     27     {}
     28 
     29     SkPixmap(const SkImageInfo& info, const void* addr, size_t rowBytes,
     30              SkColorTable* ctable = NULL)
     31         : fPixels(addr), fCTable(ctable), fRowBytes(rowBytes), fInfo(info)
     32     {
     33         if (kIndex_8_SkColorType == info.colorType()) {
     34             SkASSERT(ctable);
     35         } else {
     36             SkASSERT(NULL == ctable);
     37         }
     38     }
     39 
     40     void reset();
     41     void reset(const SkImageInfo& info, const void* addr, size_t rowBytes,
     42                SkColorTable* ctable = NULL);
     43     void reset(const SkImageInfo& info) {
     44         this->reset(info, NULL, 0, NULL);
     45     }
     46 
     47     // overrides the colorspace in the SkImageInfo of the pixmap
     48     void setColorSpace(sk_sp<SkColorSpace>);
     49 
     50     /**
     51      *  If supported, set this pixmap to point to the pixels in the specified mask and return true.
     52      *  On failure, return false and set this pixmap to empty.
     53      */
     54     bool SK_WARN_UNUSED_RESULT reset(const SkMask&);
     55 
     56     /**
     57      *  Computes the intersection of area and this pixmap. If that intersection is non-empty,
     58      *  set subset to that intersection and return true.
     59      *
     60      *  On failure, return false and ignore the subset parameter.
     61      */
     62     bool SK_WARN_UNUSED_RESULT extractSubset(SkPixmap* subset, const SkIRect& area) const;
     63 
     64     const SkImageInfo& info() const { return fInfo; }
     65     size_t rowBytes() const { return fRowBytes; }
     66     const void* addr() const { return fPixels; }
     67     SkColorTable* ctable() const { return fCTable; }
     68 
     69     int width() const { return fInfo.width(); }
     70     int height() const { return fInfo.height(); }
     71     SkColorType colorType() const { return fInfo.colorType(); }
     72     SkAlphaType alphaType() const { return fInfo.alphaType(); }
     73     SkColorSpace* colorSpace() const { return fInfo.colorSpace(); }
     74     bool isOpaque() const { return fInfo.isOpaque(); }
     75 
     76     SkIRect bounds() const { return SkIRect::MakeWH(this->width(), this->height()); }
     77 
     78     /**
     79      *  Return the rowbytes expressed as a number of pixels (like width and height).
     80      */
     81     int rowBytesAsPixels() const { return int(fRowBytes >> this->shiftPerPixel()); }
     82 
     83     /**
     84      *  Return the shift amount per pixel (i.e. 0 for 1-byte per pixel, 1 for 2-bytes per pixel
     85      *  colortypes, 2 for 4-bytes per pixel colortypes). Return 0 for kUnknown_SkColorType.
     86      */
     87     int shiftPerPixel() const { return fInfo.shiftPerPixel(); }
     88 
     89     uint64_t getSize64() const { return sk_64_mul(fInfo.height(), fRowBytes); }
     90     uint64_t getSafeSize64() const { return fInfo.getSafeSize64(fRowBytes); }
     91     size_t getSafeSize() const { return fInfo.getSafeSize(fRowBytes); }
     92 
     93     /**
     94      *  This will brute-force return true if all of the pixels in the pixmap
     95      *  are opaque. If there are no pixels, or encounters an error, returns false.
     96      */
     97     bool computeIsOpaque() const;
     98 
     99     /**
    100      *  Converts the pixel at the specified coordinate to an unpremultiplied
    101      *  SkColor. Note: this ignores any SkColorSpace information, and may return
    102      *  lower precision data than is actually in the pixel. Alpha only
    103      *  colortypes (e.g. kAlpha_8_SkColorType) return black with the appropriate
    104      *  alpha set.  The value is undefined for kUnknown_SkColorType or if x or y
    105      *  are out of bounds, or if the pixtap does not have any pixels.
    106      */
    107     SkColor getColor(int x, int y) const;
    108 
    109     const void* addr(int x, int y) const {
    110         return (const char*)fPixels + fInfo.computeOffset(x, y, fRowBytes);
    111     }
    112     const uint8_t* addr8() const {
    113         SkASSERT(1 == SkColorTypeBytesPerPixel(fInfo.colorType()));
    114         return reinterpret_cast<const uint8_t*>(fPixels);
    115     }
    116     const uint16_t* addr16() const {
    117         SkASSERT(2 == SkColorTypeBytesPerPixel(fInfo.colorType()));
    118         return reinterpret_cast<const uint16_t*>(fPixels);
    119     }
    120     const uint32_t* addr32() const {
    121         SkASSERT(4 == SkColorTypeBytesPerPixel(fInfo.colorType()));
    122         return reinterpret_cast<const uint32_t*>(fPixels);
    123     }
    124     const uint64_t* addr64() const {
    125         SkASSERT(8 == SkColorTypeBytesPerPixel(fInfo.colorType()));
    126         return reinterpret_cast<const uint64_t*>(fPixels);
    127     }
    128     const uint16_t* addrF16() const {
    129         SkASSERT(8 == SkColorTypeBytesPerPixel(fInfo.colorType()));
    130         SkASSERT(kRGBA_F16_SkColorType == fInfo.colorType());
    131         return reinterpret_cast<const uint16_t*>(fPixels);
    132     }
    133 
    134     // Offset by the specified x,y coordinates
    135 
    136     const uint8_t* addr8(int x, int y) const {
    137         SkASSERT((unsigned)x < (unsigned)fInfo.width());
    138         SkASSERT((unsigned)y < (unsigned)fInfo.height());
    139         return (const uint8_t*)((const char*)this->addr8() + y * fRowBytes + (x << 0));
    140     }
    141     const uint16_t* addr16(int x, int y) const {
    142         SkASSERT((unsigned)x < (unsigned)fInfo.width());
    143         SkASSERT((unsigned)y < (unsigned)fInfo.height());
    144         return (const uint16_t*)((const char*)this->addr16() + y * fRowBytes + (x << 1));
    145     }
    146     const uint32_t* addr32(int x, int y) const {
    147         SkASSERT((unsigned)x < (unsigned)fInfo.width());
    148         SkASSERT((unsigned)y < (unsigned)fInfo.height());
    149         return (const uint32_t*)((const char*)this->addr32() + y * fRowBytes + (x << 2));
    150     }
    151     const uint64_t* addr64(int x, int y) const {
    152         SkASSERT((unsigned)x < (unsigned)fInfo.width());
    153         SkASSERT((unsigned)y < (unsigned)fInfo.height());
    154         return (const uint64_t*)((const char*)this->addr64() + y * fRowBytes + (x << 3));
    155     }
    156     const uint16_t* addrF16(int x, int y) const {
    157         SkASSERT(kRGBA_F16_SkColorType == fInfo.colorType());
    158         return reinterpret_cast<const uint16_t*>(this->addr64(x, y));
    159     }
    160 
    161     // Writable versions
    162 
    163     void* writable_addr() const { return const_cast<void*>(fPixels); }
    164     void* writable_addr(int x, int y) const {
    165         return const_cast<void*>(this->addr(x, y));
    166     }
    167     uint8_t* writable_addr8(int x, int y) const {
    168         return const_cast<uint8_t*>(this->addr8(x, y));
    169     }
    170     uint16_t* writable_addr16(int x, int y) const {
    171         return const_cast<uint16_t*>(this->addr16(x, y));
    172     }
    173     uint32_t* writable_addr32(int x, int y) const {
    174         return const_cast<uint32_t*>(this->addr32(x, y));
    175     }
    176     uint64_t* writable_addr64(int x, int y) const {
    177         return const_cast<uint64_t*>(this->addr64(x, y));
    178     }
    179     uint16_t* writable_addrF16(int x, int y) const {
    180         return reinterpret_cast<uint16_t*>(writable_addr64(x, y));
    181     }
    182 
    183     // copy methods
    184 
    185     bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
    186                     int srcX, int srcY) const;
    187     bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes) const {
    188         return this->readPixels(dstInfo, dstPixels, dstRowBytes, 0, 0);
    189     }
    190     bool readPixels(const SkPixmap& dst, int srcX, int srcY) const {
    191         return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), srcX, srcY);
    192     }
    193     bool readPixels(const SkPixmap& dst) const {
    194         return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), 0, 0);
    195     }
    196 
    197     /**
    198      *  Copy the pixels from this pixmap into the dst pixmap, converting as needed into dst's
    199      *  colortype/alphatype. If the conversion cannot be performed, false is returned.
    200      *
    201      *  If dst's dimensions differ from the src dimension, the image will be scaled, applying the
    202      *  specified filter-quality.
    203      */
    204     bool scalePixels(const SkPixmap& dst, SkFilterQuality) const;
    205 
    206     /**
    207      *  Returns true if pixels were written to (e.g. if colorType is kUnknown_SkColorType, this
    208      *  will return false). If subset does not intersect the bounds of this pixmap, returns false.
    209      */
    210     bool erase(SkColor, const SkIRect& subset) const;
    211 
    212     bool erase(SkColor color) const { return this->erase(color, this->bounds()); }
    213     bool erase(const SkColor4f&, const SkIRect* subset = nullptr) const;
    214 
    215 private:
    216     const void*     fPixels;
    217     SkColorTable*   fCTable;
    218     size_t          fRowBytes;
    219     SkImageInfo     fInfo;
    220 };
    221 
    222 /////////////////////////////////////////////////////////////////////////////////////////////
    223 
    224 /////////////////////////////////////////////////////////////////////////////////////////////
    225 
    226 class SK_API SkAutoPixmapUnlock : ::SkNoncopyable {
    227 public:
    228     SkAutoPixmapUnlock() : fUnlockProc(NULL), fIsLocked(false) {}
    229     SkAutoPixmapUnlock(const SkPixmap& pm, void (*unlock)(void*), void* ctx)
    230         : fUnlockProc(unlock), fUnlockContext(ctx), fPixmap(pm), fIsLocked(true)
    231     {}
    232     ~SkAutoPixmapUnlock() { this->unlock(); }
    233 
    234     /**
    235      *  Return the currently locked pixmap. Undefined if it has been unlocked.
    236      */
    237     const SkPixmap& pixmap() const {
    238         SkASSERT(this->isLocked());
    239         return fPixmap;
    240     }
    241 
    242     bool isLocked() const { return fIsLocked; }
    243 
    244     /**
    245      *  Unlocks the pixmap. Can safely be called more than once as it will only call the underlying
    246      *  unlock-proc once.
    247      */
    248     void unlock() {
    249         if (fUnlockProc) {
    250             SkASSERT(fIsLocked);
    251             fUnlockProc(fUnlockContext);
    252             fUnlockProc = NULL;
    253             fIsLocked = false;
    254         }
    255     }
    256 
    257     /**
    258      *  If there is a currently locked pixmap, unlock it, then copy the specified pixmap
    259      *  and (optional) unlock proc/context.
    260      */
    261     void reset(const SkPixmap& pm, void (*unlock)(void*), void* ctx);
    262 
    263 private:
    264     void        (*fUnlockProc)(void*);
    265     void*       fUnlockContext;
    266     SkPixmap    fPixmap;
    267     bool        fIsLocked;
    268 
    269     friend class SkBitmap;
    270 };
    271 
    272 #endif
    273