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: SkPixmap()27 SkPixmap() 28 : fPixels(NULL), fRowBytes(0), fInfo(SkImageInfo::MakeUnknown(0, 0)) 29 {} 30 SkPixmap(const SkImageInfo & info,const void * addr,size_t rowBytes)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); reset(const SkImageInfo & info)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 info()58 const SkImageInfo& info() const { return fInfo; } rowBytes()59 size_t rowBytes() const { return fRowBytes; } addr()60 const void* addr() const { return fPixels; } 61 width()62 int width() const { return fInfo.width(); } height()63 int height() const { return fInfo.height(); } colorType()64 SkColorType colorType() const { return fInfo.colorType(); } alphaType()65 SkAlphaType alphaType() const { return fInfo.alphaType(); } colorSpace()66 SkColorSpace* colorSpace() const { return fInfo.colorSpace(); } isOpaque()67 bool isOpaque() const { return fInfo.isOpaque(); } 68 bounds()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 */ rowBytesAsPixels()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 */ shiftPerPixel()80 int shiftPerPixel() const { return fInfo.shiftPerPixel(); } 81 getSize64()82 uint64_t getSize64() const { return sk_64_mul(fInfo.height(), fRowBytes); } getSafeSize64()83 uint64_t getSafeSize64() const { return fInfo.getSafeSize64(fRowBytes); } getSafeSize()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 addr(int x,int y)102 const void* addr(int x, int y) const { 103 return (const char*)fPixels + fInfo.computeOffset(x, y, fRowBytes); 104 } addr8()105 const uint8_t* addr8() const { 106 SkASSERT(1 == SkColorTypeBytesPerPixel(fInfo.colorType())); 107 return reinterpret_cast<const uint8_t*>(fPixels); 108 } addr16()109 const uint16_t* addr16() const { 110 SkASSERT(2 == SkColorTypeBytesPerPixel(fInfo.colorType())); 111 return reinterpret_cast<const uint16_t*>(fPixels); 112 } addr32()113 const uint32_t* addr32() const { 114 SkASSERT(4 == SkColorTypeBytesPerPixel(fInfo.colorType())); 115 return reinterpret_cast<const uint32_t*>(fPixels); 116 } addr64()117 const uint64_t* addr64() const { 118 SkASSERT(8 == SkColorTypeBytesPerPixel(fInfo.colorType())); 119 return reinterpret_cast<const uint64_t*>(fPixels); 120 } addrF16()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 addr8(int x,int y)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 } addr16(int x,int y)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 } addr32(int x,int y)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 } addr64(int x,int y)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 } addrF16(int x,int y)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 writable_addr()156 void* writable_addr() const { return const_cast<void*>(fPixels); } writable_addr(int x,int y)157 void* writable_addr(int x, int y) const { 158 return const_cast<void*>(this->addr(x, y)); 159 } writable_addr8(int x,int y)160 uint8_t* writable_addr8(int x, int y) const { 161 return const_cast<uint8_t*>(this->addr8(x, y)); 162 } writable_addr16(int x,int y)163 uint16_t* writable_addr16(int x, int y) const { 164 return const_cast<uint16_t*>(this->addr16(x, y)); 165 } writable_addr32(int x,int y)166 uint32_t* writable_addr32(int x, int y) const { 167 return const_cast<uint32_t*>(this->addr32(x, y)); 168 } writable_addr64(int x,int y)169 uint64_t* writable_addr64(int x, int y) const { 170 return const_cast<uint64_t*>(this->addr64(x, y)); 171 } writable_addrF16(int x,int y)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; readPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes)180 bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes) const { 181 return this->readPixels(dstInfo, dstPixels, dstRowBytes, 0, 0); 182 } readPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int srcX,int srcY)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 } readPixels(const SkPixmap & dst,int srcX,int srcY)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 } readPixels(const SkPixmap & dst)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 erase(SkColor color)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 SkPixmap(const SkImageInfo & info,const void * addr,size_t rowBytes,SkColorTable *)214 SkPixmap(const SkImageInfo& info, const void* addr, size_t rowBytes, SkColorTable*) 215 : fPixels(addr), fRowBytes(rowBytes), fInfo(info) 216 {} reset(const SkImageInfo & info,const void * addr,size_t rowBytes,SkColorTable *)217 void reset(const SkImageInfo& info, const void* addr, size_t rowBytes, 218 SkColorTable*) { 219 this->reset(info, addr, rowBytes); 220 } ctable()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