/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkEncodedInfo_DEFINED #define SkEncodedInfo_DEFINED #include "include/core/SkAlphaType.h" #include "include/core/SkColorSpace.h" #include "include/core/SkColorType.h" #include "include/core/SkData.h" #include "include/core/SkImageInfo.h" #include "include/core/SkRefCnt.h" #include "include/core/SkTypes.h" #include "include/private/SkHdrMetadata.h" #include "include/private/base/SkAPI.h" #include "include/private/base/SkTo.h" #include "modules/skcms/skcms.h" #include #include #include #include namespace SkCodecs { class ColorProfile; } struct SK_API SkEncodedInfo { public: enum Alpha { kOpaque_Alpha, kUnpremul_Alpha, // Each pixel is either fully opaque or fully transparent. // There is no difference between requesting kPremul or kUnpremul. kBinary_Alpha, }; /* * We strive to make the number of components per pixel obvious through * our naming conventions. * Ex: kRGB has 3 components. kRGBA has 4 components. * * This sometimes results in redundant Alpha and Color information. * Ex: kRGB images must also be kOpaque. */ enum Color { // PNG, WBMP kGray_Color, // PNG kGrayAlpha_Color, // PNG with Skia-specific sBIT // Like kGrayAlpha, except this expects to be treated as // kAlpha_8_SkColorType, which ignores the gray component. If // decoded to full color (e.g. kN32), the gray component is respected // (so it can share code with kGrayAlpha). kXAlpha_Color, // PNG // 565 images may be encoded to PNG by specifying the number of // significant bits for each channel. This is a strange 565 // representation because the image is still encoded with 8 bits per // component. k565_Color, // PNG, GIF, BMP kPalette_Color, // PNG, RAW kRGB_Color, kRGBA_Color, // BMP kBGR_Color, kBGRX_Color, kBGRA_Color, // JPEG, WEBP kYUV_Color, // WEBP kYUVA_Color, // JPEG // Photoshop actually writes inverted CMYK data into JPEGs, where zero // represents 100% ink coverage. For this reason, we treat CMYK JPEGs // as having inverted CMYK. libjpeg-turbo warns that this may break // other applications, but the CMYK JPEGs we see on the web expect to // be treated as inverted CMYK. kInvertedCMYK_Color, kYCCK_Color, }; static SkEncodedInfo Make( int width, int height, Color color, Alpha alpha, int bitsPerComponent); static SkEncodedInfo Make( int width, int height, Color color, Alpha alpha, int bitsPerComponent, std::unique_ptr profile); static SkEncodedInfo Make( int width, int height, Color color, Alpha alpha, int bitsPerComponent, std::unique_ptr profile, int colorDepth); static SkEncodedInfo Make( int width, int height, Color color, Alpha alpha, int bitsPerComponent, int colorDepth, std::unique_ptr profile, const skhdr::Metadata& hdrMetadata); /* * Returns a recommended SkImageInfo. * * TODO: Leave this up to the client. */ SkImageInfo makeImageInfo() const; int width() const { return fWidth; } int height() const { return fHeight; } Color color() const { return fColor; } Alpha alpha() const { return fAlpha; } bool opaque() const { return fAlpha == kOpaque_Alpha; } // TODO(https://issues.skia.org/issues/464217864): Remove direct access to the // skcms_ICCProfile and change profileData() to serialize a new profile. const skcms_ICCProfile* profile() const; sk_sp profileData() const; const SkCodecs::ColorProfile* colorProfile() const { return fColorProfile.get(); } uint8_t bitsPerComponent() const { return fBitsPerComponent; } uint8_t bitsPerPixel() const { switch (fColor) { case kGray_Color: return fBitsPerComponent; case kXAlpha_Color: case kGrayAlpha_Color: return 2 * fBitsPerComponent; case kPalette_Color: return fBitsPerComponent; case kRGB_Color: case kBGR_Color: case kYUV_Color: case k565_Color: return 3 * fBitsPerComponent; case kRGBA_Color: case kBGRA_Color: case kBGRX_Color: case kYUVA_Color: case kInvertedCMYK_Color: case kYCCK_Color: return 4 * fBitsPerComponent; } SkASSERT(false); return 0; } SkEncodedInfo(const SkEncodedInfo& orig) = delete; SkEncodedInfo& operator=(const SkEncodedInfo&) = delete; SkEncodedInfo(SkEncodedInfo&& orig); SkEncodedInfo& operator=(SkEncodedInfo&&); // Explicit copy method, to avoid accidental copying. SkEncodedInfo copy() const; // Return number of bits of R/G/B channel uint8_t getColorDepth() const { return fColorDepth; } // Return the HDR metadata associated with this image. Note that even SDR images can include // HDR metadata (e.g, indicating how to inverse tone map when displayed on an HDR display). const skhdr::Metadata& getHdrMetadata() const { return fHdrMetadata; } ~SkEncodedInfo(); private: SkEncodedInfo( int width, int height, Color color, Alpha alpha, uint8_t bitsPerComponent, uint8_t colorDepth, std::unique_ptr profile, const skhdr::Metadata& hdrMetadata); static void VerifyColor(Color color, Alpha alpha, int bitsPerComponent) { // Avoid `-Wunused-parameter` warnings on non-debug builds. std::ignore = alpha; std::ignore = bitsPerComponent; switch (color) { case kGray_Color: SkASSERT(kOpaque_Alpha == alpha); return; case kGrayAlpha_Color: SkASSERT(kOpaque_Alpha != alpha); return; case kPalette_Color: SkASSERT(16 != bitsPerComponent); return; case kRGB_Color: case kBGR_Color: case kBGRX_Color: SkASSERT(kOpaque_Alpha == alpha); SkASSERT(bitsPerComponent >= 8); return; case kYUV_Color: case kInvertedCMYK_Color: case kYCCK_Color: SkASSERT(kOpaque_Alpha == alpha); SkASSERT(8 == bitsPerComponent); return; case kRGBA_Color: SkASSERT(bitsPerComponent >= 8); return; case kBGRA_Color: case kYUVA_Color: SkASSERT(8 == bitsPerComponent); return; case kXAlpha_Color: SkASSERT(kUnpremul_Alpha == alpha); SkASSERT(8 == bitsPerComponent); return; case k565_Color: SkASSERT(kOpaque_Alpha == alpha); SkASSERT(8 == bitsPerComponent); return; } SkASSERT(false); // Unrecognized `color` enum value. } int fWidth; int fHeight; Color fColor; Alpha fAlpha; uint8_t fBitsPerComponent; uint8_t fColorDepth; std::unique_ptr fColorProfile; skhdr::Metadata fHdrMetadata; }; #endif