blob: b684cdfcf426677d73f2376ba80b101803b5696e [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
Mike Reed7fcfb622018-02-09 13:26:46 -05008#include "SkImageInfoPriv.h"
Mike Reede74dafc2017-09-29 13:41:58 -04009#include "SkSafeMath.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
Mike Reed7fcfb622018-02-09 13:26:46 -050013int SkColorTypeBytesPerPixel(SkColorType ct) {
14 switch (ct) {
15 case kUnknown_SkColorType: return 0;
16 case kAlpha_8_SkColorType: return 1;
17 case kRGB_565_SkColorType: return 2;
18 case kARGB_4444_SkColorType: return 2;
19 case kRGBA_8888_SkColorType: return 4;
20 case kBGRA_8888_SkColorType: return 4;
21 case kRGB_888x_SkColorType: return 4;
22 case kRGBA_1010102_SkColorType: return 4;
23 case kRGB_101010x_SkColorType: return 4;
24 case kGray_8_SkColorType: return 1;
25 case kRGBA_F16_SkColorType: return 8;
26 }
27 return 0;
28}
29
Mike Reed58050132017-07-12 22:10:29 -040030// These values must be constant over revisions, though they can be renamed to reflect if/when
31// they are deprecated.
32enum Stored_SkColorType {
33 kUnknown_Stored_SkColorType = 0,
34 kAlpha_8_Stored_SkColorType = 1,
35 kRGB_565_Stored_SkColorType = 2,
36 kARGB_4444_Stored_SkColorType = 3,
37 kRGBA_8888_Stored_SkColorType = 4,
38 kBGRA_8888_Stored_SkColorType = 5,
39 kIndex_8_Stored_SkColorType_DEPRECATED = 6,
40 kGray_8_Stored_SkColorType = 7,
41 kRGBA_F16_Stored_SkColorType = 8,
Brian Salomone41e1762018-01-25 14:07:47 -050042 kRGB_888x_Stored_SkColorType = 9,
43 kRGBA_1010102_Stored_SkColorType = 10,
44 kRGB_101010x_Stored_SkColorType = 11,
Mike Reed58050132017-07-12 22:10:29 -040045};
46
47static uint8_t live_to_stored(unsigned ct) {
Brian Salomone41e1762018-01-25 14:07:47 -050048 switch (ct) {
49 case kUnknown_SkColorType: return kUnknown_Stored_SkColorType;
50 case kAlpha_8_SkColorType: return kAlpha_8_Stored_SkColorType;
51 case kRGB_565_SkColorType: return kRGB_565_Stored_SkColorType;
52 case kARGB_4444_SkColorType: return kARGB_4444_Stored_SkColorType;
53 case kRGBA_8888_SkColorType: return kRGBA_8888_Stored_SkColorType;
54 case kRGB_888x_SkColorType: return kRGB_888x_Stored_SkColorType;
55 case kBGRA_8888_SkColorType: return kBGRA_8888_Stored_SkColorType;
56 case kRGBA_1010102_SkColorType: return kRGBA_1010102_Stored_SkColorType;
57 case kRGB_101010x_SkColorType: return kRGB_101010x_Stored_SkColorType;
58 case kGray_8_SkColorType: return kGray_8_Stored_SkColorType;
59 case kRGBA_F16_SkColorType: return kRGBA_F16_Stored_SkColorType;
Mike Reedb3d1d902017-07-17 10:36:33 -040060 }
Brian Salomone41e1762018-01-25 14:07:47 -050061 return kUnknown_Stored_SkColorType;
Mike Reed58050132017-07-12 22:10:29 -040062}
63
64static SkColorType stored_to_live(unsigned stored) {
Brian Salomone41e1762018-01-25 14:07:47 -050065 switch (stored) {
66 case kUnknown_Stored_SkColorType: return kUnknown_SkColorType;
67 case kAlpha_8_Stored_SkColorType: return kAlpha_8_SkColorType;
68 case kRGB_565_Stored_SkColorType: return kRGB_565_SkColorType;
69 case kARGB_4444_Stored_SkColorType: return kARGB_4444_SkColorType;
70 case kRGBA_8888_Stored_SkColorType: return kRGBA_8888_SkColorType;
71 case kRGB_888x_Stored_SkColorType: return kRGB_888x_SkColorType;
72 case kBGRA_8888_Stored_SkColorType: return kBGRA_8888_SkColorType;
73 case kRGBA_1010102_Stored_SkColorType: return kRGBA_1010102_SkColorType;
74 case kRGB_101010x_Stored_SkColorType: return kRGB_101010x_SkColorType;
75 case kIndex_8_Stored_SkColorType_DEPRECATED: return kUnknown_SkColorType;
76 case kGray_8_Stored_SkColorType: return kGray_8_SkColorType;
77 case kRGBA_F16_Stored_SkColorType: return kRGBA_F16_SkColorType;
Mike Reedb3d1d902017-07-17 10:36:33 -040078 }
Brian Salomone41e1762018-01-25 14:07:47 -050079 return kUnknown_SkColorType;
Mike Reed58050132017-07-12 22:10:29 -040080}
81
82///////////////////////////////////////////////////////////////////////////////////////////////////
83
Mike Reed7fcfb622018-02-09 13:26:46 -050084int SkImageInfo::bytesPerPixel() const { return SkColorTypeBytesPerPixel(fColorType); }
85
86int SkImageInfo::shiftPerPixel() const { return SkColorTypeShiftPerPixel(fColorType); }
87
88size_t SkImageInfo::computeOffset(int x, int y, size_t rowBytes) const {
89 SkASSERT((unsigned)x < (unsigned)fWidth);
90 SkASSERT((unsigned)y < (unsigned)fHeight);
91 return SkColorTypeComputeOffset(fColorType, x, y, rowBytes);
92}
93
Mike Reede74dafc2017-09-29 13:41:58 -040094size_t SkImageInfo::computeByteSize(size_t rowBytes) const {
95 if (0 == fHeight) {
96 return 0;
97 }
98 SkSafeMath safe;
99 size_t bytes = safe.add(safe.mul(fHeight - 1, rowBytes),
100 safe.mul(fWidth, this->bytesPerPixel()));
Mike Reed72818012017-10-09 11:37:44 -0400101 return safe ? bytes : SK_MaxSizeT;
Mike Reede74dafc2017-09-29 13:41:58 -0400102}
103
reed2bdf1f52014-09-03 05:48:56 -0700104static bool alpha_type_is_valid(SkAlphaType alphaType) {
Petr Hosek8bc69172017-09-09 01:54:43 -0700105 return (alphaType >= kUnknown_SkAlphaType) && (alphaType <= kLastEnum_SkAlphaType);
commit-bot@chromium.orgef74fa12013-12-17 20:49:46 +0000106}
107
reed2bdf1f52014-09-03 05:48:56 -0700108static bool color_type_is_valid(SkColorType colorType) {
Petr Hosek8bc69172017-09-09 01:54:43 -0700109 return (colorType >= kUnknown_SkColorType) && (colorType <= kLastEnum_SkColorType);
commit-bot@chromium.orgef74fa12013-12-17 20:49:46 +0000110}
111
reedfbce71f2016-06-02 12:40:22 -0700112SkImageInfo SkImageInfo::MakeS32(int width, int height, SkAlphaType at) {
reed960b2d62016-06-17 09:26:41 -0700113 return SkImageInfo(width, height, kN32_SkColorType, at,
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500114 SkColorSpace::MakeSRGB());
reedfbce71f2016-06-02 12:40:22 -0700115}
116
robertphillipsc31bb872016-06-28 11:02:30 -0700117static const int kColorTypeMask = 0x0F;
118static const int kAlphaTypeMask = 0x03;
119
reed2bdf1f52014-09-03 05:48:56 -0700120void SkImageInfo::unflatten(SkReadBuffer& buffer) {
121 fWidth = buffer.read32();
122 fHeight = buffer.read32();
123
124 uint32_t packed = buffer.read32();
Mike Reedb3d1d902017-07-17 10:36:33 -0400125 fColorType = stored_to_live((packed >> 0) & kColorTypeMask);
robertphillipsc31bb872016-06-28 11:02:30 -0700126 fAlphaType = (SkAlphaType)((packed >> 8) & kAlphaTypeMask);
reed960b2d62016-06-17 09:26:41 -0700127 buffer.validate(alpha_type_is_valid(fAlphaType) && color_type_is_valid(fColorType));
128
msarett111a42d2016-06-22 08:18:54 -0700129 sk_sp<SkData> data = buffer.readByteArrayAsData();
130 fColorSpace = SkColorSpace::Deserialize(data->data(), data->size());
reed@google.comf309dbc2013-12-09 22:09:41 +0000131}
132
reed2bdf1f52014-09-03 05:48:56 -0700133void SkImageInfo::flatten(SkWriteBuffer& buffer) const {
134 buffer.write32(fWidth);
135 buffer.write32(fHeight);
reed@google.comf309dbc2013-12-09 22:09:41 +0000136
robertphillipsc31bb872016-06-28 11:02:30 -0700137 SkASSERT(0 == (fAlphaType & ~kAlphaTypeMask));
138 SkASSERT(0 == (fColorType & ~kColorTypeMask));
Mike Reed58050132017-07-12 22:10:29 -0400139 uint32_t packed = (fAlphaType << 8) | live_to_stored(fColorType);
reed2bdf1f52014-09-03 05:48:56 -0700140 buffer.write32(packed);
reed960b2d62016-06-17 09:26:41 -0700141
msarett111a42d2016-06-22 08:18:54 -0700142 if (fColorSpace) {
143 sk_sp<SkData> data = fColorSpace->serialize();
144 if (data) {
145 buffer.writeDataAsByteArray(data.get());
146 } else {
147 buffer.writeByteArray(nullptr, 0);
148 }
149 } else {
150 sk_sp<SkData> data = SkData::MakeEmpty();
151 buffer.writeDataAsByteArray(data.get());
reed960b2d62016-06-17 09:26:41 -0700152 }
reed@google.comf309dbc2013-12-09 22:09:41 +0000153}
scroggo2fd0d142014-07-01 07:08:19 -0700154
155bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType,
156 SkAlphaType* canonical) {
157 switch (colorType) {
158 case kUnknown_SkColorType:
reed44977482015-02-27 10:23:00 -0800159 alphaType = kUnknown_SkAlphaType;
scroggo2fd0d142014-07-01 07:08:19 -0700160 break;
161 case kAlpha_8_SkColorType:
162 if (kUnpremul_SkAlphaType == alphaType) {
163 alphaType = kPremul_SkAlphaType;
164 }
165 // fall-through
scroggo2fd0d142014-07-01 07:08:19 -0700166 case kARGB_4444_SkColorType:
167 case kRGBA_8888_SkColorType:
168 case kBGRA_8888_SkColorType:
Mike Kleinac568a92018-01-25 09:09:32 -0500169 case kRGBA_1010102_SkColorType:
reed9e01ac72016-02-06 20:38:45 -0800170 case kRGBA_F16_SkColorType:
reed44977482015-02-27 10:23:00 -0800171 if (kUnknown_SkAlphaType == alphaType) {
scroggo2fd0d142014-07-01 07:08:19 -0700172 return false;
173 }
174 break;
reed0c9b1a82015-03-17 17:44:06 -0700175 case kGray_8_SkColorType:
Mike Kleinac568a92018-01-25 09:09:32 -0500176 case kRGB_565_SkColorType:
177 case kRGB_888x_SkColorType:
178 case kRGB_101010x_SkColorType:
scroggo2fd0d142014-07-01 07:08:19 -0700179 alphaType = kOpaque_SkAlphaType;
180 break;
181 default:
182 return false;
183 }
184 if (canonical) {
185 *canonical = alphaType;
186 }
187 return true;
188}
reed96472de2014-12-10 09:53:42 -0800189
190///////////////////////////////////////////////////////////////////////////////////////////////////
191
192#include "SkReadPixelsRec.h"
193
194bool SkReadPixelsRec::trim(int srcWidth, int srcHeight) {
halcanary96fcdcc2015-08-27 07:41:13 -0700195 if (nullptr == fPixels || fRowBytes < fInfo.minRowBytes()) {
reed96472de2014-12-10 09:53:42 -0800196 return false;
197 }
Matt Sarettcb6266b2017-01-17 10:48:53 -0500198 if (0 >= fInfo.width() || 0 >= fInfo.height()) {
reed96472de2014-12-10 09:53:42 -0800199 return false;
200 }
201
202 int x = fX;
203 int y = fY;
204 SkIRect srcR = SkIRect::MakeXYWH(x, y, fInfo.width(), fInfo.height());
205 if (!srcR.intersect(0, 0, srcWidth, srcHeight)) {
206 return false;
207 }
208
209 // if x or y are negative, then we have to adjust pixels
210 if (x > 0) {
211 x = 0;
212 }
213 if (y > 0) {
214 y = 0;
215 }
216 // here x,y are either 0 or negative
217 fPixels = ((char*)fPixels - y * fRowBytes - x * fInfo.bytesPerPixel());
218 // the intersect may have shrunk info's logical size
219 fInfo = fInfo.makeWH(srcR.width(), srcR.height());
220 fX = srcR.x();
221 fY = srcR.y();
222
223 return true;
224}
Matt Sarett03dd6d52017-01-23 12:15:09 -0500225
226///////////////////////////////////////////////////////////////////////////////////////////////////
227
228#include "SkWritePixelsRec.h"
229
230bool SkWritePixelsRec::trim(int dstWidth, int dstHeight) {
231 if (nullptr == fPixels || fRowBytes < fInfo.minRowBytes()) {
232 return false;
233 }
234 if (0 >= fInfo.width() || 0 >= fInfo.height()) {
235 return false;
236 }
237
238 int x = fX;
239 int y = fY;
240 SkIRect dstR = SkIRect::MakeXYWH(x, y, fInfo.width(), fInfo.height());
241 if (!dstR.intersect(0, 0, dstWidth, dstHeight)) {
242 return false;
243 }
244
245 // if x or y are negative, then we have to adjust pixels
246 if (x > 0) {
247 x = 0;
248 }
249 if (y > 0) {
250 y = 0;
251 }
252 // here x,y are either 0 or negative
253 fPixels = ((const char*)fPixels - y * fRowBytes - x * fInfo.bytesPerPixel());
254 // the intersect may have shrunk info's logical size
255 fInfo = fInfo.makeWH(dstR.width(), dstR.height());
256 fX = dstR.x();
257 fY = dstR.y();
258
259 return true;
260}