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 "SkImageInfoPriv.h"
9 #include "SkSafeMath.h"
10 #include "SkReadBuffer.h"
11 #include "SkWriteBuffer.h"
12
SkColorTypeBytesPerPixel(SkColorType ct)13 int 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 case kRGBA_F32_SkColorType: return 16;
27 }
28 return 0;
29 }
30
SkColorTypeIsAlwaysOpaque(SkColorType ct)31 bool SkColorTypeIsAlwaysOpaque(SkColorType ct) {
32 return !(kAlpha_SkColorTypeComponentFlag & SkColorTypeComponentFlags(ct));
33 }
34
35 ///////////////////////////////////////////////////////////////////////////////////////////////////
36
bytesPerPixel() const37 int SkImageInfo::bytesPerPixel() const { return SkColorTypeBytesPerPixel(fColorType); }
38
shiftPerPixel() const39 int SkImageInfo::shiftPerPixel() const { return SkColorTypeShiftPerPixel(fColorType); }
40
computeOffset(int x,int y,size_t rowBytes) const41 size_t SkImageInfo::computeOffset(int x, int y, size_t rowBytes) const {
42 SkASSERT((unsigned)x < (unsigned)this->width());
43 SkASSERT((unsigned)y < (unsigned)this->height());
44 return SkColorTypeComputeOffset(this->colorType(), x, y, rowBytes);
45 }
46
computeByteSize(size_t rowBytes) const47 size_t SkImageInfo::computeByteSize(size_t rowBytes) const {
48 if (0 == this->height()) {
49 return 0;
50 }
51 SkSafeMath safe;
52 size_t bytes = safe.add(safe.mul(safe.addInt(this->height(), -1), rowBytes),
53 safe.mul(this->width(), this->bytesPerPixel()));
54 return safe ? bytes : SIZE_MAX;
55 }
56
MakeS32(int width,int height,SkAlphaType at)57 SkImageInfo SkImageInfo::MakeS32(int width, int height, SkAlphaType at) {
58 return SkImageInfo(width, height, kN32_SkColorType, at,
59 SkColorSpace::MakeSRGB());
60 }
61
SkColorTypeValidateAlphaType(SkColorType colorType,SkAlphaType alphaType,SkAlphaType * canonical)62 bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType,
63 SkAlphaType* canonical) {
64 switch (colorType) {
65 case kUnknown_SkColorType:
66 alphaType = kUnknown_SkAlphaType;
67 break;
68 case kAlpha_8_SkColorType:
69 if (kUnpremul_SkAlphaType == alphaType) {
70 alphaType = kPremul_SkAlphaType;
71 }
72 // fall-through
73 case kARGB_4444_SkColorType:
74 case kRGBA_8888_SkColorType:
75 case kBGRA_8888_SkColorType:
76 case kRGBA_1010102_SkColorType:
77 case kRGBA_F16_SkColorType:
78 case kRGBA_F32_SkColorType:
79 if (kUnknown_SkAlphaType == alphaType) {
80 return false;
81 }
82 break;
83 case kGray_8_SkColorType:
84 case kRGB_565_SkColorType:
85 case kRGB_888x_SkColorType:
86 case kRGB_101010x_SkColorType:
87 alphaType = kOpaque_SkAlphaType;
88 break;
89 default:
90 return false;
91 }
92 if (canonical) {
93 *canonical = alphaType;
94 }
95 return true;
96 }
97
98 ///////////////////////////////////////////////////////////////////////////////////////////////////
99
100 #include "SkReadPixelsRec.h"
101
trim(int srcWidth,int srcHeight)102 bool SkReadPixelsRec::trim(int srcWidth, int srcHeight) {
103 if (nullptr == fPixels || fRowBytes < fInfo.minRowBytes()) {
104 return false;
105 }
106 if (0 >= fInfo.width() || 0 >= fInfo.height()) {
107 return false;
108 }
109
110 int x = fX;
111 int y = fY;
112 SkIRect srcR = SkIRect::MakeXYWH(x, y, fInfo.width(), fInfo.height());
113 if (!srcR.intersect(0, 0, srcWidth, srcHeight)) {
114 return false;
115 }
116
117 // if x or y are negative, then we have to adjust pixels
118 if (x > 0) {
119 x = 0;
120 }
121 if (y > 0) {
122 y = 0;
123 }
124 // here x,y are either 0 or negative
125 // we negate and add them so UBSAN (pointer-overflow) doesn't get confused.
126 fPixels = ((char*)fPixels + -y*fRowBytes + -x*fInfo.bytesPerPixel());
127 // the intersect may have shrunk info's logical size
128 fInfo = fInfo.makeWH(srcR.width(), srcR.height());
129 fX = srcR.x();
130 fY = srcR.y();
131
132 return true;
133 }
134
135 ///////////////////////////////////////////////////////////////////////////////////////////////////
136
137 #include "SkWritePixelsRec.h"
138
trim(int dstWidth,int dstHeight)139 bool SkWritePixelsRec::trim(int dstWidth, int dstHeight) {
140 if (nullptr == fPixels || fRowBytes < fInfo.minRowBytes()) {
141 return false;
142 }
143 if (0 >= fInfo.width() || 0 >= fInfo.height()) {
144 return false;
145 }
146
147 int x = fX;
148 int y = fY;
149 SkIRect dstR = SkIRect::MakeXYWH(x, y, fInfo.width(), fInfo.height());
150 if (!dstR.intersect(0, 0, dstWidth, dstHeight)) {
151 return false;
152 }
153
154 // if x or y are negative, then we have to adjust pixels
155 if (x > 0) {
156 x = 0;
157 }
158 if (y > 0) {
159 y = 0;
160 }
161 // here x,y are either 0 or negative
162 // we negate and add them so UBSAN (pointer-overflow) doesn't get confused.
163 fPixels = ((const char*)fPixels + -y*fRowBytes + -x*fInfo.bytesPerPixel());
164 // the intersect may have shrunk info's logical size
165 fInfo = fInfo.makeWH(dstR.width(), dstR.height());
166 fX = dstR.x();
167 fY = dstR.y();
168
169 return true;
170 }
171