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