michael@0: /* michael@0: * Copyright 2013 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef SkImageInfo_DEFINED michael@0: #define SkImageInfo_DEFINED michael@0: michael@0: #include "SkMath.h" michael@0: #include "SkSize.h" michael@0: michael@0: class SkWriteBuffer; michael@0: class SkReadBuffer; michael@0: michael@0: /** michael@0: * Describes how to interpret the alpha compoent of a pixel. michael@0: */ michael@0: enum SkAlphaType { michael@0: /** michael@0: * All pixels should be treated as opaque, regardless of the value stored michael@0: * in their alpha field. Used for legacy images that wrote 0 or garbarge michael@0: * in their alpha field, but intended the RGB to be treated as opaque. michael@0: */ michael@0: kIgnore_SkAlphaType, michael@0: michael@0: /** michael@0: * All pixels are stored as opaque. This differs slightly from kIgnore in michael@0: * that kOpaque has correct "opaque" values stored in the pixels, while michael@0: * kIgnore may not, but in both cases the caller should treat the pixels michael@0: * as opaque. michael@0: */ michael@0: kOpaque_SkAlphaType, michael@0: michael@0: /** michael@0: * All pixels have their alpha premultiplied in their color components. michael@0: * This is the natural format for the rendering target pixels. michael@0: */ michael@0: kPremul_SkAlphaType, michael@0: michael@0: /** michael@0: * All pixels have their color components stored without any regard to the michael@0: * alpha. e.g. this is the default configuration for PNG images. michael@0: * michael@0: * This alpha-type is ONLY supported for input images. Rendering cannot michael@0: * generate this on output. michael@0: */ michael@0: kUnpremul_SkAlphaType, michael@0: michael@0: kLastEnum_SkAlphaType = kUnpremul_SkAlphaType michael@0: }; michael@0: michael@0: static inline bool SkAlphaTypeIsOpaque(SkAlphaType at) { michael@0: SK_COMPILE_ASSERT(kIgnore_SkAlphaType < kOpaque_SkAlphaType, bad_alphatype_order); michael@0: SK_COMPILE_ASSERT(kPremul_SkAlphaType > kOpaque_SkAlphaType, bad_alphatype_order); michael@0: SK_COMPILE_ASSERT(kUnpremul_SkAlphaType > kOpaque_SkAlphaType, bad_alphatype_order); michael@0: michael@0: return (unsigned)at <= kOpaque_SkAlphaType; michael@0: } michael@0: michael@0: static inline bool SkAlphaTypeIsValid(unsigned value) { michael@0: return value <= kLastEnum_SkAlphaType; michael@0: } michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: /** michael@0: * Describes how to interpret the components of a pixel. michael@0: */ michael@0: enum SkColorType { michael@0: kUnknown_SkColorType, michael@0: kAlpha_8_SkColorType, michael@0: kRGB_565_SkColorType, michael@0: kARGB_4444_SkColorType, michael@0: kRGBA_8888_SkColorType, michael@0: kBGRA_8888_SkColorType, michael@0: kIndex_8_SkColorType, michael@0: michael@0: kLastEnum_SkColorType = kIndex_8_SkColorType, michael@0: michael@0: #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A) michael@0: kPMColor_SkColorType = kBGRA_8888_SkColorType michael@0: #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A) michael@0: kPMColor_SkColorType = kRGBA_8888_SkColorType michael@0: #else michael@0: #error "SK_*32_SHFIT values must correspond to BGRA or RGBA byte order" michael@0: #endif michael@0: }; michael@0: michael@0: static int SkColorTypeBytesPerPixel(SkColorType ct) { michael@0: static const uint8_t gSize[] = { michael@0: 0, // Unknown michael@0: 1, // Alpha_8 michael@0: 2, // RGB_565 michael@0: 2, // ARGB_4444 michael@0: 4, // RGBA_8888 michael@0: 4, // BGRA_8888 michael@0: 1, // kIndex_8 michael@0: }; michael@0: SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gSize) == (size_t)(kLastEnum_SkColorType + 1), michael@0: size_mismatch_with_SkColorType_enum); michael@0: michael@0: SkASSERT((size_t)ct < SK_ARRAY_COUNT(gSize)); michael@0: return gSize[ct]; michael@0: } michael@0: michael@0: static inline size_t SkColorTypeMinRowBytes(SkColorType ct, int width) { michael@0: return width * SkColorTypeBytesPerPixel(ct); michael@0: } michael@0: michael@0: static inline bool SkColorTypeIsValid(unsigned value) { michael@0: return value <= kLastEnum_SkColorType; michael@0: } michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: /** michael@0: * Describe an image's dimensions and pixel type. michael@0: */ michael@0: struct SkImageInfo { michael@0: int fWidth; michael@0: int fHeight; michael@0: SkColorType fColorType; michael@0: SkAlphaType fAlphaType; michael@0: michael@0: static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at) { michael@0: SkImageInfo info = { michael@0: width, height, ct, at michael@0: }; michael@0: return info; michael@0: } michael@0: michael@0: /** michael@0: * Sets colortype to the native ARGB32 type. michael@0: */ michael@0: static SkImageInfo MakeN32(int width, int height, SkAlphaType at) { michael@0: SkImageInfo info = { michael@0: width, height, kPMColor_SkColorType, at michael@0: }; michael@0: return info; michael@0: } michael@0: michael@0: /** michael@0: * Sets colortype to the native ARGB32 type, and the alphatype to premul. michael@0: */ michael@0: static SkImageInfo MakeN32Premul(int width, int height) { michael@0: SkImageInfo info = { michael@0: width, height, kPMColor_SkColorType, kPremul_SkAlphaType michael@0: }; michael@0: return info; michael@0: } michael@0: michael@0: /** michael@0: * Sets colortype to the native ARGB32 type, and the alphatype to premul. michael@0: */ michael@0: static SkImageInfo MakeN32Premul(const SkISize& size) { michael@0: return MakeN32Premul(size.width(), size.height()); michael@0: } michael@0: michael@0: static SkImageInfo MakeA8(int width, int height) { michael@0: SkImageInfo info = { michael@0: width, height, kAlpha_8_SkColorType, kPremul_SkAlphaType michael@0: }; michael@0: return info; michael@0: } michael@0: michael@0: static SkImageInfo MakeUnknown(int width, int height) { michael@0: SkImageInfo info = { michael@0: width, height, kUnknown_SkColorType, kIgnore_SkAlphaType michael@0: }; michael@0: return info; michael@0: } michael@0: michael@0: int width() const { return fWidth; } michael@0: int height() const { return fHeight; } michael@0: SkColorType colorType() const { return fColorType; } michael@0: SkAlphaType alphaType() const { return fAlphaType; } michael@0: michael@0: bool isEmpty() const { return fWidth <= 0 || fHeight <= 0; } michael@0: michael@0: bool isOpaque() const { michael@0: return SkAlphaTypeIsOpaque(fAlphaType); michael@0: } michael@0: michael@0: SkISize dimensions() const { return SkISize::Make(fWidth, fHeight); } michael@0: michael@0: int bytesPerPixel() const { michael@0: return SkColorTypeBytesPerPixel(fColorType); michael@0: } michael@0: michael@0: uint64_t minRowBytes64() const { michael@0: return sk_64_mul(fWidth, this->bytesPerPixel()); michael@0: } michael@0: michael@0: size_t minRowBytes() const { michael@0: return (size_t)this->minRowBytes64(); michael@0: } michael@0: michael@0: bool operator==(const SkImageInfo& other) const { michael@0: return 0 == memcmp(this, &other, sizeof(other)); michael@0: } michael@0: bool operator!=(const SkImageInfo& other) const { michael@0: return 0 != memcmp(this, &other, sizeof(other)); michael@0: } michael@0: michael@0: void unflatten(SkReadBuffer&); michael@0: void flatten(SkWriteBuffer&) const; michael@0: michael@0: int64_t getSafeSize64(size_t rowBytes) const { michael@0: if (0 == fHeight) { michael@0: return 0; michael@0: } michael@0: return sk_64_mul(fHeight - 1, rowBytes) + fWidth * this->bytesPerPixel(); michael@0: } michael@0: michael@0: size_t getSafeSize(size_t rowBytes) const { michael@0: return (size_t)this->getSafeSize64(rowBytes); michael@0: } michael@0: michael@0: bool validRowBytes(size_t rowBytes) const { michael@0: uint64_t rb = sk_64_mul(fWidth, this->bytesPerPixel()); michael@0: return rowBytes >= rb; michael@0: } michael@0: michael@0: SkDEBUGCODE(void validate() const;) michael@0: }; michael@0: michael@0: #endif