SkEncodedInfo.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. * Copyright 2016 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. #ifndef SkEncodedInfo_DEFINED
  8. #define SkEncodedInfo_DEFINED
  9. #include "include/core/SkData.h"
  10. #include "include/core/SkImageInfo.h"
  11. #include "include/third_party/skcms/skcms.h"
  12. struct SkEncodedInfo {
  13. public:
  14. class ICCProfile {
  15. public:
  16. static std::unique_ptr<ICCProfile> Make(sk_sp<SkData>);
  17. static std::unique_ptr<ICCProfile> Make(const skcms_ICCProfile&);
  18. const skcms_ICCProfile* profile() const { return &fProfile; }
  19. private:
  20. ICCProfile(const skcms_ICCProfile&, sk_sp<SkData> = nullptr);
  21. skcms_ICCProfile fProfile;
  22. sk_sp<SkData> fData;
  23. };
  24. enum Alpha {
  25. kOpaque_Alpha,
  26. kUnpremul_Alpha,
  27. // Each pixel is either fully opaque or fully transparent.
  28. // There is no difference between requesting kPremul or kUnpremul.
  29. kBinary_Alpha,
  30. };
  31. /*
  32. * We strive to make the number of components per pixel obvious through
  33. * our naming conventions.
  34. * Ex: kRGB has 3 components. kRGBA has 4 components.
  35. *
  36. * This sometimes results in redundant Alpha and Color information.
  37. * Ex: kRGB images must also be kOpaque.
  38. */
  39. enum Color {
  40. // PNG, WBMP
  41. kGray_Color,
  42. // PNG
  43. kGrayAlpha_Color,
  44. // PNG with Skia-specific sBIT
  45. // Like kGrayAlpha, except this expects to be treated as
  46. // kAlpha_8_SkColorType, which ignores the gray component. If
  47. // decoded to full color (e.g. kN32), the gray component is respected
  48. // (so it can share code with kGrayAlpha).
  49. kXAlpha_Color,
  50. // PNG
  51. // 565 images may be encoded to PNG by specifying the number of
  52. // significant bits for each channel. This is a strange 565
  53. // representation because the image is still encoded with 8 bits per
  54. // component.
  55. k565_Color,
  56. // PNG, GIF, BMP
  57. kPalette_Color,
  58. // PNG, RAW
  59. kRGB_Color,
  60. kRGBA_Color,
  61. // BMP
  62. kBGR_Color,
  63. kBGRX_Color,
  64. kBGRA_Color,
  65. // JPEG, WEBP
  66. kYUV_Color,
  67. // WEBP
  68. kYUVA_Color,
  69. // JPEG
  70. // Photoshop actually writes inverted CMYK data into JPEGs, where zero
  71. // represents 100% ink coverage. For this reason, we treat CMYK JPEGs
  72. // as having inverted CMYK. libjpeg-turbo warns that this may break
  73. // other applications, but the CMYK JPEGs we see on the web expect to
  74. // be treated as inverted CMYK.
  75. kInvertedCMYK_Color,
  76. kYCCK_Color,
  77. };
  78. static SkEncodedInfo Make(int width, int height, Color color, Alpha alpha,
  79. int bitsPerComponent) {
  80. return Make(width, height, color, alpha, bitsPerComponent, nullptr);
  81. }
  82. static SkEncodedInfo Make(int width, int height, Color color, Alpha alpha,
  83. int bitsPerComponent, std::unique_ptr<ICCProfile> profile) {
  84. SkASSERT(1 == bitsPerComponent ||
  85. 2 == bitsPerComponent ||
  86. 4 == bitsPerComponent ||
  87. 8 == bitsPerComponent ||
  88. 16 == bitsPerComponent);
  89. switch (color) {
  90. case kGray_Color:
  91. SkASSERT(kOpaque_Alpha == alpha);
  92. break;
  93. case kGrayAlpha_Color:
  94. SkASSERT(kOpaque_Alpha != alpha);
  95. break;
  96. case kPalette_Color:
  97. SkASSERT(16 != bitsPerComponent);
  98. break;
  99. case kRGB_Color:
  100. case kBGR_Color:
  101. case kBGRX_Color:
  102. SkASSERT(kOpaque_Alpha == alpha);
  103. SkASSERT(bitsPerComponent >= 8);
  104. break;
  105. case kYUV_Color:
  106. case kInvertedCMYK_Color:
  107. case kYCCK_Color:
  108. SkASSERT(kOpaque_Alpha == alpha);
  109. SkASSERT(8 == bitsPerComponent);
  110. break;
  111. case kRGBA_Color:
  112. SkASSERT(bitsPerComponent >= 8);
  113. break;
  114. case kBGRA_Color:
  115. case kYUVA_Color:
  116. SkASSERT(8 == bitsPerComponent);
  117. break;
  118. case kXAlpha_Color:
  119. SkASSERT(kUnpremul_Alpha == alpha);
  120. SkASSERT(8 == bitsPerComponent);
  121. break;
  122. case k565_Color:
  123. SkASSERT(kOpaque_Alpha == alpha);
  124. SkASSERT(8 == bitsPerComponent);
  125. break;
  126. default:
  127. SkASSERT(false);
  128. break;
  129. }
  130. return SkEncodedInfo(width, height, color, alpha, bitsPerComponent, std::move(profile));
  131. }
  132. /*
  133. * Returns a recommended SkImageInfo.
  134. *
  135. * TODO: Leave this up to the client.
  136. */
  137. SkImageInfo makeImageInfo() const {
  138. auto ct = kGray_Color == fColor ? kGray_8_SkColorType :
  139. kXAlpha_Color == fColor ? kAlpha_8_SkColorType :
  140. k565_Color == fColor ? kRGB_565_SkColorType :
  141. kN32_SkColorType ;
  142. auto alpha = kOpaque_Alpha == fAlpha ? kOpaque_SkAlphaType
  143. : kUnpremul_SkAlphaType;
  144. sk_sp<SkColorSpace> cs = fProfile ? SkColorSpace::Make(*fProfile->profile())
  145. : nullptr;
  146. if (!cs) {
  147. cs = SkColorSpace::MakeSRGB();
  148. }
  149. return SkImageInfo::Make(fWidth, fHeight, ct, alpha, std::move(cs));
  150. }
  151. int width() const { return fWidth; }
  152. int height() const { return fHeight; }
  153. Color color() const { return fColor; }
  154. Alpha alpha() const { return fAlpha; }
  155. bool opaque() const { return fAlpha == kOpaque_Alpha; }
  156. const skcms_ICCProfile* profile() const {
  157. if (!fProfile) return nullptr;
  158. return fProfile->profile();
  159. }
  160. uint8_t bitsPerComponent() const { return fBitsPerComponent; }
  161. uint8_t bitsPerPixel() const {
  162. switch (fColor) {
  163. case kGray_Color:
  164. return fBitsPerComponent;
  165. case kXAlpha_Color:
  166. case kGrayAlpha_Color:
  167. return 2 * fBitsPerComponent;
  168. case kPalette_Color:
  169. return fBitsPerComponent;
  170. case kRGB_Color:
  171. case kBGR_Color:
  172. case kYUV_Color:
  173. case k565_Color:
  174. return 3 * fBitsPerComponent;
  175. case kRGBA_Color:
  176. case kBGRA_Color:
  177. case kBGRX_Color:
  178. case kYUVA_Color:
  179. case kInvertedCMYK_Color:
  180. case kYCCK_Color:
  181. return 4 * fBitsPerComponent;
  182. default:
  183. SkASSERT(false);
  184. return 0;
  185. }
  186. }
  187. SkEncodedInfo(const SkEncodedInfo& orig) = delete;
  188. SkEncodedInfo& operator=(const SkEncodedInfo&) = delete;
  189. SkEncodedInfo(SkEncodedInfo&& orig) = default;
  190. SkEncodedInfo& operator=(SkEncodedInfo&&) = default;
  191. // Explicit copy method, to avoid accidental copying.
  192. SkEncodedInfo copy() const {
  193. auto copy = SkEncodedInfo::Make(fWidth, fHeight, fColor, fAlpha, fBitsPerComponent);
  194. if (fProfile) {
  195. copy.fProfile.reset(new ICCProfile(*fProfile.get()));
  196. }
  197. return copy;
  198. }
  199. private:
  200. SkEncodedInfo(int width, int height, Color color, Alpha alpha,
  201. uint8_t bitsPerComponent, std::unique_ptr<ICCProfile> profile)
  202. : fWidth(width)
  203. , fHeight(height)
  204. , fColor(color)
  205. , fAlpha(alpha)
  206. , fBitsPerComponent(bitsPerComponent)
  207. , fProfile(std::move(profile))
  208. {}
  209. int fWidth;
  210. int fHeight;
  211. Color fColor;
  212. Alpha fAlpha;
  213. uint8_t fBitsPerComponent;
  214. std::unique_ptr<ICCProfile> fProfile;
  215. };
  216. #endif