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