SkEncodedInfo.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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 "SkData.h"
  10. #include "SkImageInfo.h"
  11. #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(kOpaque_Alpha != alpha);
  113. SkASSERT(bitsPerComponent >= 8);
  114. break;
  115. case kBGRA_Color:
  116. case kYUVA_Color:
  117. SkASSERT(kOpaque_Alpha != alpha);
  118. SkASSERT(8 == bitsPerComponent);
  119. break;
  120. case kXAlpha_Color:
  121. SkASSERT(kUnpremul_Alpha == alpha);
  122. SkASSERT(8 == bitsPerComponent);
  123. break;
  124. case k565_Color:
  125. SkASSERT(kOpaque_Alpha == alpha);
  126. SkASSERT(8 == bitsPerComponent);
  127. break;
  128. default:
  129. SkASSERT(false);
  130. break;
  131. }
  132. return SkEncodedInfo(width, height, color, alpha, bitsPerComponent, std::move(profile));
  133. }
  134. /*
  135. * Returns a recommended SkImageInfo.
  136. *
  137. * TODO: Leave this up to the client.
  138. */
  139. SkImageInfo makeImageInfo() const {
  140. auto ct = kGray_Color == fColor ? kGray_8_SkColorType :
  141. kXAlpha_Color == fColor ? kAlpha_8_SkColorType :
  142. k565_Color == fColor ? kRGB_565_SkColorType :
  143. kN32_SkColorType ;
  144. auto alpha = kOpaque_Alpha == fAlpha ? kOpaque_SkAlphaType
  145. : kUnpremul_SkAlphaType;
  146. sk_sp<SkColorSpace> cs = fProfile ? SkColorSpace::Make(*fProfile->profile())
  147. : nullptr;
  148. if (!cs) {
  149. cs = SkColorSpace::MakeSRGB();
  150. }
  151. return SkImageInfo::Make(fWidth, fHeight, ct, alpha, std::move(cs));
  152. }
  153. int width() const { return fWidth; }
  154. int height() const { return fHeight; }
  155. Color color() const { return fColor; }
  156. Alpha alpha() const { return fAlpha; }
  157. bool opaque() const { return fAlpha == kOpaque_Alpha; }
  158. const skcms_ICCProfile* profile() const {
  159. if (!fProfile) return nullptr;
  160. return fProfile->profile();
  161. }
  162. uint8_t bitsPerComponent() const { return fBitsPerComponent; }
  163. uint8_t bitsPerPixel() const {
  164. switch (fColor) {
  165. case kGray_Color:
  166. return fBitsPerComponent;
  167. case kXAlpha_Color:
  168. case kGrayAlpha_Color:
  169. return 2 * fBitsPerComponent;
  170. case kPalette_Color:
  171. return fBitsPerComponent;
  172. case kRGB_Color:
  173. case kBGR_Color:
  174. case kYUV_Color:
  175. case k565_Color:
  176. return 3 * fBitsPerComponent;
  177. case kRGBA_Color:
  178. case kBGRA_Color:
  179. case kBGRX_Color:
  180. case kYUVA_Color:
  181. case kInvertedCMYK_Color:
  182. case kYCCK_Color:
  183. return 4 * fBitsPerComponent;
  184. default:
  185. SkASSERT(false);
  186. return 0;
  187. }
  188. }
  189. SkEncodedInfo(const SkEncodedInfo& orig) = delete;
  190. SkEncodedInfo& operator=(const SkEncodedInfo&) = delete;
  191. SkEncodedInfo(SkEncodedInfo&& orig) = default;
  192. SkEncodedInfo& operator=(SkEncodedInfo&&) = default;
  193. // Explicit copy method, to avoid accidental copying.
  194. SkEncodedInfo copy() const {
  195. auto copy = SkEncodedInfo::Make(fWidth, fHeight, fColor, fAlpha, fBitsPerComponent);
  196. if (fProfile) {
  197. copy.fProfile.reset(new ICCProfile(*fProfile.get()));
  198. }
  199. return copy;
  200. }
  201. private:
  202. SkEncodedInfo(int width, int height, Color color, Alpha alpha,
  203. uint8_t bitsPerComponent, std::unique_ptr<ICCProfile> profile)
  204. : fWidth(width)
  205. , fHeight(height)
  206. , fColor(color)
  207. , fAlpha(alpha)
  208. , fBitsPerComponent(bitsPerComponent)
  209. , fProfile(std::move(profile))
  210. {}
  211. int fWidth;
  212. int fHeight;
  213. Color fColor;
  214. Alpha fAlpha;
  215. uint8_t fBitsPerComponent;
  216. std::unique_ptr<ICCProfile> fProfile;
  217. };
  218. #endif