blob: 948575482362410f65fc3eef09be8e7927921b7b [file] [log] [blame]
reed@google.comf309dbc2013-12-09 22:09:41 +00001/*
2 * Copyright 2010 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#include "SkImageInfo.h"
halcanary484b3d02016-04-25 10:32:23 -07009#include "SkImageInfoPriv.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000010#include "SkReadBuffer.h"
11#include "SkWriteBuffer.h"
reed@google.comf309dbc2013-12-09 22:09:41 +000012
reed960b2d62016-06-17 09:26:41 -070013/*
14 * We store this as a byte in the ImageInfo flatten buffer.
15 */
16enum class SkFlattenColorSpaceEnum {
17 kUnspecified,
18 kSRGB,
19 kAdobe1998,
20 // ... add more here
21 kLastEnum = kAdobe1998,
22 // final value means the actual profile data follows the info
23 kICCProfile = 0xFF,
24};
25
26static sk_sp<SkColorSpace> make_from_enum(SkFlattenColorSpaceEnum value) {
27 switch (value) {
28 case SkFlattenColorSpaceEnum::kSRGB:
29 return SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
30 case SkFlattenColorSpaceEnum::kAdobe1998:
31 return SkColorSpace::NewNamed(SkColorSpace::kAdobeRGB_Named);
32 default:
33 return nullptr;
34 }
35}
36
37SkColorSpace::Named sk_deduce_named_from_colorspace(SkColorSpace* cs) {
38 return cs->fNamed;
39}
40
41static SkFlattenColorSpaceEnum deduce_from_colorspace(SkColorSpace* cs) {
42 if (!cs) {
43 return SkFlattenColorSpaceEnum::kUnspecified;
44 }
45 switch (sk_deduce_named_from_colorspace(cs)) {
46 case SkColorSpace::kSRGB_Named:
47 return SkFlattenColorSpaceEnum::kSRGB;
48 case SkColorSpace::kAdobeRGB_Named:
49 return SkFlattenColorSpaceEnum::kAdobe1998;
50 default:
51 return SkFlattenColorSpaceEnum::kICCProfile;
52 }
53}
54
55///////////////////////////////////////////////////////////////////////////////////////////////////
56
57#ifdef SK_SUPPORT_LEGACY_COLORPROFILETYPE
58SkColorProfileType SkImageInfo::profileType() const {
59 return fColorSpace && fColorSpace->gammaCloseToSRGB()
60 ? kSRGB_SkColorProfileType : kLinear_SkColorProfileType;
61}
62#endif
63
halcanary484b3d02016-04-25 10:32:23 -070064// Indicate how images and gradients should interpret colors by default.
herb835acc72016-05-17 06:50:15 -070065bool gDefaultProfileIsSRGB;
halcanary484b3d02016-04-25 10:32:23 -070066
67SkColorProfileType SkDefaultColorProfile() {
68 return gDefaultProfileIsSRGB ? kSRGB_SkColorProfileType
69 : kLinear_SkColorProfileType;
70}
herb9bc22352016-04-20 15:07:32 -070071
reed2bdf1f52014-09-03 05:48:56 -070072static bool alpha_type_is_valid(SkAlphaType alphaType) {
73 return (alphaType >= 0) && (alphaType <= kLastEnum_SkAlphaType);
commit-bot@chromium.orgef74fa12013-12-17 20:49:46 +000074}
75
reed2bdf1f52014-09-03 05:48:56 -070076static bool color_type_is_valid(SkColorType colorType) {
77 return (colorType >= 0) && (colorType <= kLastEnum_SkColorType);
commit-bot@chromium.orgef74fa12013-12-17 20:49:46 +000078}
79
reedfbce71f2016-06-02 12:40:22 -070080SkImageInfo SkImageInfo::MakeS32(int width, int height, SkAlphaType at) {
reed960b2d62016-06-17 09:26:41 -070081 return SkImageInfo(width, height, kN32_SkColorType, at,
reedfbce71f2016-06-02 12:40:22 -070082 SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named));
83}
84
reed2bdf1f52014-09-03 05:48:56 -070085void SkImageInfo::unflatten(SkReadBuffer& buffer) {
86 fWidth = buffer.read32();
87 fHeight = buffer.read32();
88
89 uint32_t packed = buffer.read32();
reed7c748852014-11-10 08:57:21 -080090 SkASSERT(0 == (packed >> 24));
reed2bdf1f52014-09-03 05:48:56 -070091 fColorType = (SkColorType)((packed >> 0) & 0xFF);
reed960b2d62016-06-17 09:26:41 -070092 fAlphaType = (SkAlphaType)((packed >> 8) & 0xFF);
93 SkFlattenColorSpaceEnum csenum = (SkFlattenColorSpaceEnum)((packed >> 16) & 0xFF);
94 buffer.validate(alpha_type_is_valid(fAlphaType) && color_type_is_valid(fColorType));
95
96 if (SkFlattenColorSpaceEnum::kICCProfile == csenum) {
97 SkASSERT(false); // we shouldn't hit this yet, as we don't write these yet
98 fColorSpace.reset();
99 } else {
100 if (csenum > SkFlattenColorSpaceEnum::kLastEnum) {
101 csenum = SkFlattenColorSpaceEnum::kUnspecified;
102 }
103 fColorSpace = make_from_enum(csenum);
104 }
reed@google.comf309dbc2013-12-09 22:09:41 +0000105}
106
reed2bdf1f52014-09-03 05:48:56 -0700107void SkImageInfo::flatten(SkWriteBuffer& buffer) const {
108 buffer.write32(fWidth);
109 buffer.write32(fHeight);
reed@google.comf309dbc2013-12-09 22:09:41 +0000110
reed960b2d62016-06-17 09:26:41 -0700111 SkFlattenColorSpaceEnum csenum = deduce_from_colorspace(fColorSpace.get());
112
113 // TODO: when we actually support flattening the colorspace to a profile blob, remove this
114 // hack (and write the blob after we write packed.
115 if (SkFlattenColorSpaceEnum::kICCProfile == csenum) {
116 csenum = SkFlattenColorSpaceEnum::kUnspecified;
117 }
118
119 SkASSERT(0 == ((int)csenum & ~0xFF));
reed2bdf1f52014-09-03 05:48:56 -0700120 SkASSERT(0 == (fAlphaType & ~0xFF));
121 SkASSERT(0 == (fColorType & ~0xFF));
reed960b2d62016-06-17 09:26:41 -0700122 uint32_t packed = ((int)csenum << 16) | (fAlphaType << 8) | fColorType;
reed2bdf1f52014-09-03 05:48:56 -0700123 buffer.write32(packed);
reed960b2d62016-06-17 09:26:41 -0700124
125 if (SkFlattenColorSpaceEnum::kICCProfile == csenum) {
126 // TODO: write the ICCProfile blob
127 }
reed@google.comf309dbc2013-12-09 22:09:41 +0000128}
scroggo2fd0d142014-07-01 07:08:19 -0700129
130bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType,
131 SkAlphaType* canonical) {
132 switch (colorType) {
133 case kUnknown_SkColorType:
reed44977482015-02-27 10:23:00 -0800134 alphaType = kUnknown_SkAlphaType;
scroggo2fd0d142014-07-01 07:08:19 -0700135 break;
136 case kAlpha_8_SkColorType:
137 if (kUnpremul_SkAlphaType == alphaType) {
138 alphaType = kPremul_SkAlphaType;
139 }
140 // fall-through
141 case kIndex_8_SkColorType:
142 case kARGB_4444_SkColorType:
143 case kRGBA_8888_SkColorType:
144 case kBGRA_8888_SkColorType:
reed9e01ac72016-02-06 20:38:45 -0800145 case kRGBA_F16_SkColorType:
reed44977482015-02-27 10:23:00 -0800146 if (kUnknown_SkAlphaType == alphaType) {
scroggo2fd0d142014-07-01 07:08:19 -0700147 return false;
148 }
149 break;
150 case kRGB_565_SkColorType:
reed0c9b1a82015-03-17 17:44:06 -0700151 case kGray_8_SkColorType:
scroggo2fd0d142014-07-01 07:08:19 -0700152 alphaType = kOpaque_SkAlphaType;
153 break;
154 default:
155 return false;
156 }
157 if (canonical) {
158 *canonical = alphaType;
159 }
160 return true;
161}
reed96472de2014-12-10 09:53:42 -0800162
163///////////////////////////////////////////////////////////////////////////////////////////////////
164
165#include "SkReadPixelsRec.h"
166
167bool SkReadPixelsRec::trim(int srcWidth, int srcHeight) {
168 switch (fInfo.colorType()) {
169 case kUnknown_SkColorType:
170 case kIndex_8_SkColorType:
171 return false;
172 default:
173 break;
174 }
halcanary96fcdcc2015-08-27 07:41:13 -0700175 if (nullptr == fPixels || fRowBytes < fInfo.minRowBytes()) {
reed96472de2014-12-10 09:53:42 -0800176 return false;
177 }
178 if (0 == fInfo.width() || 0 == fInfo.height()) {
179 return false;
180 }
181
182 int x = fX;
183 int y = fY;
184 SkIRect srcR = SkIRect::MakeXYWH(x, y, fInfo.width(), fInfo.height());
185 if (!srcR.intersect(0, 0, srcWidth, srcHeight)) {
186 return false;
187 }
188
189 // if x or y are negative, then we have to adjust pixels
190 if (x > 0) {
191 x = 0;
192 }
193 if (y > 0) {
194 y = 0;
195 }
196 // here x,y are either 0 or negative
197 fPixels = ((char*)fPixels - y * fRowBytes - x * fInfo.bytesPerPixel());
198 // the intersect may have shrunk info's logical size
199 fInfo = fInfo.makeWH(srcR.width(), srcR.height());
200 fX = srcR.x();
201 fY = srcR.y();
202
203 return true;
204}