1 /*
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"
9 #include "SkSafeMath.h"
10 #include "SkReadBuffer.h"
11 #include "SkWriteBuffer.h"
12
13 // These values must be constant over revisions, though they can be renamed to reflect if/when
14 // they are deprecated.
15 enum Stored_SkColorType {
16 kUnknown_Stored_SkColorType = 0,
17 kAlpha_8_Stored_SkColorType = 1,
18 kRGB_565_Stored_SkColorType = 2,
19 kARGB_4444_Stored_SkColorType = 3,
20 kRGBA_8888_Stored_SkColorType = 4,
21 kBGRA_8888_Stored_SkColorType = 5,
22 kIndex_8_Stored_SkColorType_DEPRECATED = 6,
23 kGray_8_Stored_SkColorType = 7,
24 kRGBA_F16_Stored_SkColorType = 8,
25 kRGB_888x_Stored_SkColorType = 9,
26 kRGBA_1010102_Stored_SkColorType = 10,
27 kRGB_101010x_Stored_SkColorType = 11,
28 };
29
live_to_stored(unsigned ct)30 static uint8_t live_to_stored(unsigned ct) {
31 switch (ct) {
32 case kUnknown_SkColorType: return kUnknown_Stored_SkColorType;
33 case kAlpha_8_SkColorType: return kAlpha_8_Stored_SkColorType;
34 case kRGB_565_SkColorType: return kRGB_565_Stored_SkColorType;
35 case kARGB_4444_SkColorType: return kARGB_4444_Stored_SkColorType;
36 case kRGBA_8888_SkColorType: return kRGBA_8888_Stored_SkColorType;
37 case kRGB_888x_SkColorType: return kRGB_888x_Stored_SkColorType;
38 case kBGRA_8888_SkColorType: return kBGRA_8888_Stored_SkColorType;
39 case kRGBA_1010102_SkColorType: return kRGBA_1010102_Stored_SkColorType;
40 case kRGB_101010x_SkColorType: return kRGB_101010x_Stored_SkColorType;
41 case kGray_8_SkColorType: return kGray_8_Stored_SkColorType;
42 case kRGBA_F16_SkColorType: return kRGBA_F16_Stored_SkColorType;
43 }
44 return kUnknown_Stored_SkColorType;
45 }
46
stored_to_live(unsigned stored)47 static SkColorType stored_to_live(unsigned stored) {
48 switch (stored) {
49 case kUnknown_Stored_SkColorType: return kUnknown_SkColorType;
50 case kAlpha_8_Stored_SkColorType: return kAlpha_8_SkColorType;
51 case kRGB_565_Stored_SkColorType: return kRGB_565_SkColorType;
52 case kARGB_4444_Stored_SkColorType: return kARGB_4444_SkColorType;
53 case kRGBA_8888_Stored_SkColorType: return kRGBA_8888_SkColorType;
54 case kRGB_888x_Stored_SkColorType: return kRGB_888x_SkColorType;
55 case kBGRA_8888_Stored_SkColorType: return kBGRA_8888_SkColorType;
56 case kRGBA_1010102_Stored_SkColorType: return kRGBA_1010102_SkColorType;
57 case kRGB_101010x_Stored_SkColorType: return kRGB_101010x_SkColorType;
58 case kIndex_8_Stored_SkColorType_DEPRECATED: return kUnknown_SkColorType;
59 case kGray_8_Stored_SkColorType: return kGray_8_SkColorType;
60 case kRGBA_F16_Stored_SkColorType: return kRGBA_F16_SkColorType;
61 }
62 return kUnknown_SkColorType;
63 }
64
65 ///////////////////////////////////////////////////////////////////////////////////////////////////
66
computeByteSize(size_t rowBytes) const67 size_t SkImageInfo::computeByteSize(size_t rowBytes) const {
68 if (0 == fHeight) {
69 return 0;
70 }
71 SkSafeMath safe;
72 size_t bytes = safe.add(safe.mul(fHeight - 1, rowBytes),
73 safe.mul(fWidth, this->bytesPerPixel()));
74 return safe ? bytes : SK_MaxSizeT;
75 }
76
alpha_type_is_valid(SkAlphaType alphaType)77 static bool alpha_type_is_valid(SkAlphaType alphaType) {
78 return (alphaType >= kUnknown_SkAlphaType) && (alphaType <= kLastEnum_SkAlphaType);
79 }
80
color_type_is_valid(SkColorType colorType)81 static bool color_type_is_valid(SkColorType colorType) {
82 return (colorType >= kUnknown_SkColorType) && (colorType <= kLastEnum_SkColorType);
83 }
84
MakeS32(int width,int height,SkAlphaType at)85 SkImageInfo SkImageInfo::MakeS32(int width, int height, SkAlphaType at) {
86 return SkImageInfo(width, height, kN32_SkColorType, at,
87 SkColorSpace::MakeSRGB());
88 }
89
90 static const int kColorTypeMask = 0x0F;
91 static const int kAlphaTypeMask = 0x03;
92
unflatten(SkReadBuffer & buffer)93 void SkImageInfo::unflatten(SkReadBuffer& buffer) {
94 fWidth = buffer.read32();
95 fHeight = buffer.read32();
96
97 uint32_t packed = buffer.read32();
98 fColorType = stored_to_live((packed >> 0) & kColorTypeMask);
99 fAlphaType = (SkAlphaType)((packed >> 8) & kAlphaTypeMask);
100 buffer.validate(alpha_type_is_valid(fAlphaType) && color_type_is_valid(fColorType));
101
102 sk_sp<SkData> data = buffer.readByteArrayAsData();
103 fColorSpace = SkColorSpace::Deserialize(data->data(), data->size());
104 }
105
flatten(SkWriteBuffer & buffer) const106 void SkImageInfo::flatten(SkWriteBuffer& buffer) const {
107 buffer.write32(fWidth);
108 buffer.write32(fHeight);
109
110 SkASSERT(0 == (fAlphaType & ~kAlphaTypeMask));
111 SkASSERT(0 == (fColorType & ~kColorTypeMask));
112 uint32_t packed = (fAlphaType << 8) | live_to_stored(fColorType);
113 buffer.write32(packed);
114
115 if (fColorSpace) {
116 sk_sp<SkData> data = fColorSpace->serialize();
117 if (data) {
118 buffer.writeDataAsByteArray(data.get());
119 } else {
120 buffer.writeByteArray(nullptr, 0);
121 }
122 } else {
123 sk_sp<SkData> data = SkData::MakeEmpty();
124 buffer.writeDataAsByteArray(data.get());
125 }
126 }
127
SkColorTypeValidateAlphaType(SkColorType colorType,SkAlphaType alphaType,SkAlphaType * canonical)128 bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType,
129 SkAlphaType* canonical) {
130 switch (colorType) {
131 case kUnknown_SkColorType:
132 alphaType = kUnknown_SkAlphaType;
133 break;
134 case kAlpha_8_SkColorType:
135 if (kUnpremul_SkAlphaType == alphaType) {
136 alphaType = kPremul_SkAlphaType;
137 }
138 // fall-through
139 case kARGB_4444_SkColorType:
140 case kRGBA_8888_SkColorType:
141 case kBGRA_8888_SkColorType:
142 case kRGBA_1010102_SkColorType:
143 case kRGBA_F16_SkColorType:
144 if (kUnknown_SkAlphaType == alphaType) {
145 return false;
146 }
147 break;
148 case kGray_8_SkColorType:
149 case kRGB_565_SkColorType:
150 case kRGB_888x_SkColorType:
151 case kRGB_101010x_SkColorType:
152 alphaType = kOpaque_SkAlphaType;
153 break;
154 default:
155 return false;
156 }
157 if (canonical) {
158 *canonical = alphaType;
159 }
160 return true;
161 }
162
163 ///////////////////////////////////////////////////////////////////////////////////////////////////
164
165 #include "SkReadPixelsRec.h"
166
trim(int srcWidth,int srcHeight)167 bool SkReadPixelsRec::trim(int srcWidth, int srcHeight) {
168 if (nullptr == fPixels || fRowBytes < fInfo.minRowBytes()) {
169 return false;
170 }
171 if (0 >= fInfo.width() || 0 >= fInfo.height()) {
172 return false;
173 }
174
175 int x = fX;
176 int y = fY;
177 SkIRect srcR = SkIRect::MakeXYWH(x, y, fInfo.width(), fInfo.height());
178 if (!srcR.intersect(0, 0, srcWidth, srcHeight)) {
179 return false;
180 }
181
182 // if x or y are negative, then we have to adjust pixels
183 if (x > 0) {
184 x = 0;
185 }
186 if (y > 0) {
187 y = 0;
188 }
189 // here x,y are either 0 or negative
190 fPixels = ((char*)fPixels - y * fRowBytes - x * fInfo.bytesPerPixel());
191 // the intersect may have shrunk info's logical size
192 fInfo = fInfo.makeWH(srcR.width(), srcR.height());
193 fX = srcR.x();
194 fY = srcR.y();
195
196 return true;
197 }
198
199 ///////////////////////////////////////////////////////////////////////////////////////////////////
200
201 #include "SkWritePixelsRec.h"
202
trim(int dstWidth,int dstHeight)203 bool SkWritePixelsRec::trim(int dstWidth, int dstHeight) {
204 if (nullptr == fPixels || fRowBytes < fInfo.minRowBytes()) {
205 return false;
206 }
207 if (0 >= fInfo.width() || 0 >= fInfo.height()) {
208 return false;
209 }
210
211 int x = fX;
212 int y = fY;
213 SkIRect dstR = SkIRect::MakeXYWH(x, y, fInfo.width(), fInfo.height());
214 if (!dstR.intersect(0, 0, dstWidth, dstHeight)) {
215 return false;
216 }
217
218 // if x or y are negative, then we have to adjust pixels
219 if (x > 0) {
220 x = 0;
221 }
222 if (y > 0) {
223 y = 0;
224 }
225 // here x,y are either 0 or negative
226 fPixels = ((const char*)fPixels - y * fRowBytes - x * fInfo.bytesPerPixel());
227 // the intersect may have shrunk info's logical size
228 fInfo = fInfo.makeWH(dstR.width(), dstR.height());
229 fX = dstR.x();
230 fY = dstR.y();
231
232 return true;
233 }
234