OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 The Android Open Source Project | 2 * Copyright 2015 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #ifndef SkCodecPriv_DEFINED | 8 #ifndef SkCodecPriv_DEFINED |
9 #define SkCodecPriv_DEFINED | 9 #define SkCodecPriv_DEFINED |
10 | 10 |
| 11 #include "SkColorPriv.h" |
11 #include "SkColorTable.h" | 12 #include "SkColorTable.h" |
12 #include "SkImageInfo.h" | 13 #include "SkImageInfo.h" |
13 #include "SkSwizzler.h" | 14 #include "SkSwizzler.h" |
14 #include "SkTypes.h" | 15 #include "SkTypes.h" |
15 #include "SkUtils.h" | 16 #include "SkUtils.h" |
16 | 17 |
17 /* | 18 /* |
18 * | 19 * |
19 * Helper routine for alpha result codes | 20 * Helper routine for alpha result codes |
20 * | 21 * |
21 */ | 22 */ |
22 #define INIT_RESULT_ALPHA \ | 23 #define INIT_RESULT_ALPHA \ |
23 uint8_t zeroAlpha = 0; \ | 24 uint8_t zeroAlpha = 0; \ |
24 uint8_t maxAlpha = 0xFF; | 25 uint8_t maxAlpha = 0xFF; |
25 | 26 |
26 #define UPDATE_RESULT_ALPHA(alpha) \ | 27 #define UPDATE_RESULT_ALPHA(alpha) \ |
27 zeroAlpha |= (alpha); \ | 28 zeroAlpha |= (alpha); \ |
28 maxAlpha &= (alpha); | 29 maxAlpha &= (alpha); |
29 | 30 |
30 #define COMPUTE_RESULT_ALPHA \ | 31 #define COMPUTE_RESULT_ALPHA \ |
31 SkSwizzler::GetResult(zeroAlpha, maxAlpha); | 32 SkSwizzler::GetResult(zeroAlpha, maxAlpha); |
32 | 33 |
33 /* | 34 /* |
34 * returns a scaled dimension based on the original dimension and the sampleSize | 35 * returns a scaled dimension based on the original dimension and the sampleSize |
35 * NOTE: we round down here for scaled dimension to match the behavior of SkImag
eDecoder | 36 * NOTE: we round down here for scaled dimension to match the behavior of SkImag
eDecoder |
36 */ | 37 */ |
37 static int get_scaled_dimension(int srcDimension, int sampleSize) { | 38 inline int get_scaled_dimension(int srcDimension, int sampleSize) { |
38 if (sampleSize > srcDimension) { | 39 if (sampleSize > srcDimension) { |
39 return 1; | 40 return 1; |
40 } | 41 } |
41 return srcDimension / sampleSize; | 42 return srcDimension / sampleSize; |
42 } | 43 } |
43 | 44 |
44 /* | 45 /* |
45 * Returns the first coordinate that we will keep during a scaled decode. | 46 * Returns the first coordinate that we will keep during a scaled decode. |
46 * The output can be interpreted as an x-coordinate or a y-coordinate. | 47 * The output can be interpreted as an x-coordinate or a y-coordinate. |
47 * | 48 * |
48 * This does not need to be called and is not called when sampleFactor == 1. | 49 * This does not need to be called and is not called when sampleFactor == 1. |
49 */ | 50 */ |
50 static int get_start_coord(int sampleFactor) { return sampleFactor / 2; }; | 51 inline int get_start_coord(int sampleFactor) { return sampleFactor / 2; }; |
51 | 52 |
52 /* | 53 /* |
53 * Given a coordinate in the original image, this returns the corresponding | 54 * Given a coordinate in the original image, this returns the corresponding |
54 * coordinate in the scaled image. This function is meaningless if | 55 * coordinate in the scaled image. This function is meaningless if |
55 * IsCoordNecessary returns false. | 56 * IsCoordNecessary returns false. |
56 * The output can be interpreted as an x-coordinate or a y-coordinate. | 57 * The output can be interpreted as an x-coordinate or a y-coordinate. |
57 * | 58 * |
58 * This does not need to be called and is not called when sampleFactor == 1. | 59 * This does not need to be called and is not called when sampleFactor == 1. |
59 */ | 60 */ |
60 static int get_dst_coord(int srcCoord, int sampleFactor) { return srcCoord / sam
pleFactor; }; | 61 inline int get_dst_coord(int srcCoord, int sampleFactor) { return srcCoord / sam
pleFactor; }; |
61 | 62 |
62 /* | 63 /* |
63 * When scaling, we will discard certain y-coordinates (rows) and | 64 * When scaling, we will discard certain y-coordinates (rows) and |
64 * x-coordinates (columns). This function returns true if we should keep the | 65 * x-coordinates (columns). This function returns true if we should keep the |
65 * coordinate and false otherwise. | 66 * coordinate and false otherwise. |
66 * The inputs may be x-coordinates or y-coordinates. | 67 * The inputs may be x-coordinates or y-coordinates. |
67 * | 68 * |
68 * This does not need to be called and is not called when sampleFactor == 1. | 69 * This does not need to be called and is not called when sampleFactor == 1. |
69 */ | 70 */ |
70 static bool is_coord_necessary(int srcCoord, int sampleFactor, int scaledDim) { | 71 inline bool is_coord_necessary(int srcCoord, int sampleFactor, int scaledDim) { |
71 // Get the first coordinate that we want to keep | 72 // Get the first coordinate that we want to keep |
72 int startCoord = get_start_coord(sampleFactor); | 73 int startCoord = get_start_coord(sampleFactor); |
73 | 74 |
74 // Return false on edge cases | 75 // Return false on edge cases |
75 if (srcCoord < startCoord || get_dst_coord(srcCoord, sampleFactor) >= scaled
Dim) { | 76 if (srcCoord < startCoord || get_dst_coord(srcCoord, sampleFactor) >= scaled
Dim) { |
76 return false; | 77 return false; |
77 } | 78 } |
78 | 79 |
79 // Every sampleFactor rows are necessary | 80 // Every sampleFactor rows are necessary |
80 return ((srcCoord - startCoord) % sampleFactor) == 0; | 81 return ((srcCoord - startCoord) % sampleFactor) == 0; |
81 } | 82 } |
82 | 83 |
83 static inline bool valid_alpha(SkAlphaType dstAlpha, SkAlphaType srcAlpha) { | 84 inline uint32_t ceil_div(uint32_t a, uint32_t b) { |
| 85 return (a + b - 1) / b; |
| 86 } |
| 87 |
| 88 /* |
| 89 * Gets the output row corresponding to the encoded row for interlaced gifs |
| 90 */ |
| 91 inline uint32_t get_output_row_interlaced(uint32_t encodedRow, uint32_t height)
{ |
| 92 SkASSERT(encodedRow < height); |
| 93 // First pass |
| 94 if (encodedRow * 8 < height) { |
| 95 return encodedRow * 8; |
| 96 } |
| 97 // Second pass |
| 98 if (encodedRow * 4 < height) { |
| 99 return 4 + 8 * (encodedRow - ceil_div(height, 8)); |
| 100 } |
| 101 // Third pass |
| 102 if (encodedRow * 2 < height) { |
| 103 return 2 + 4 * (encodedRow - ceil_div(height, 4)); |
| 104 } |
| 105 // Fourth pass |
| 106 return 1 + 2 * (encodedRow - ceil_div(height, 2)); |
| 107 } |
| 108 |
| 109 inline bool valid_alpha(SkAlphaType dstAlpha, SkAlphaType srcAlpha) { |
84 // Check for supported alpha types | 110 // Check for supported alpha types |
85 if (srcAlpha != dstAlpha) { | 111 if (srcAlpha != dstAlpha) { |
86 if (kOpaque_SkAlphaType == srcAlpha) { | 112 if (kOpaque_SkAlphaType == srcAlpha) { |
87 // If the source is opaque, we must decode to opaque | 113 // If the source is opaque, we must decode to opaque |
88 return false; | 114 return false; |
89 } | 115 } |
90 | 116 |
91 // The source is not opaque | 117 // The source is not opaque |
92 switch (dstAlpha) { | 118 switch (dstAlpha) { |
93 case kPremul_SkAlphaType: | 119 case kPremul_SkAlphaType: |
94 case kUnpremul_SkAlphaType: | 120 case kUnpremul_SkAlphaType: |
95 // The source is not opaque, so either of these is okay | 121 // The source is not opaque, so either of these is okay |
96 break; | 122 break; |
97 default: | 123 default: |
98 // We cannot decode a non-opaque image to opaque (or unknown) | 124 // We cannot decode a non-opaque image to opaque (or unknown) |
99 return false; | 125 return false; |
100 } | 126 } |
101 } | 127 } |
102 return true; | 128 return true; |
103 } | 129 } |
104 | 130 |
105 /* | 131 /* |
106 * Most of our codecs support the same conversions: | 132 * Most of our codecs support the same conversions: |
107 * - profileType must be the same | 133 * - profileType must be the same |
108 * - opaque only to opaque (and 565 only if opaque) | 134 * - opaque only to opaque (and 565 only if opaque) |
109 * - premul to unpremul and vice versa | 135 * - premul to unpremul and vice versa |
110 * - always support N32 | 136 * - always support N32 |
111 * - otherwise match the src color type | 137 * - otherwise match the src color type |
112 */ | 138 */ |
113 static bool conversion_possible(const SkImageInfo& dst, const SkImageInfo& src)
{ | 139 inline bool conversion_possible(const SkImageInfo& dst, const SkImageInfo& src)
{ |
114 if (dst.profileType() != src.profileType()) { | 140 if (dst.profileType() != src.profileType()) { |
115 return false; | 141 return false; |
116 } | 142 } |
117 | 143 |
118 // Ensure the alpha type is valid | 144 // Ensure the alpha type is valid |
119 if (!valid_alpha(dst.alphaType(), src.alphaType())) { | 145 if (!valid_alpha(dst.alphaType(), src.alphaType())) { |
120 return false; | 146 return false; |
121 } | 147 } |
122 | 148 |
123 // Check for supported color types | 149 // Check for supported color types |
124 switch (dst.colorType()) { | 150 switch (dst.colorType()) { |
125 case kN32_SkColorType: | 151 case kN32_SkColorType: |
126 return true; | 152 return true; |
127 case kRGB_565_SkColorType: | 153 case kRGB_565_SkColorType: |
128 return src.alphaType() == kOpaque_SkAlphaType; | 154 return src.alphaType() == kOpaque_SkAlphaType; |
129 default: | 155 default: |
130 return dst.colorType() == src.colorType(); | 156 return dst.colorType() == src.colorType(); |
131 } | 157 } |
132 } | 158 } |
133 | 159 |
134 /* | 160 /* |
135 * If there is a color table, get a pointer to the colors, otherwise return null
ptr | 161 * If there is a color table, get a pointer to the colors, otherwise return null
ptr |
136 */ | 162 */ |
137 static const SkPMColor* get_color_ptr(SkColorTable* colorTable) { | 163 inline const SkPMColor* get_color_ptr(SkColorTable* colorTable) { |
138 return nullptr != colorTable ? colorTable->readColors() : nullptr; | 164 return nullptr != colorTable ? colorTable->readColors() : nullptr; |
139 } | 165 } |
140 | 166 |
141 /* | 167 /* |
| 168 * Given that the encoded image uses a color table, return the fill value |
| 169 */ |
| 170 inline uint32_t get_color_table_fill_value(SkColorType colorType, const SkPMColo
r* colorPtr, |
| 171 uint8_t fillIndex) { |
| 172 SkASSERT(nullptr != colorPtr); |
| 173 switch (colorType) { |
| 174 case kN32_SkColorType: |
| 175 return colorPtr[fillIndex]; |
| 176 case kRGB_565_SkColorType: |
| 177 return SkPixel32ToPixel16(colorPtr[fillIndex]); |
| 178 case kIndex_8_SkColorType: |
| 179 return fillIndex; |
| 180 default: |
| 181 SkASSERT(false); |
| 182 return 0; |
| 183 } |
| 184 } |
| 185 |
| 186 /* |
142 * | 187 * |
143 * Copy the codec color table back to the client when kIndex8 color type is requ
ested | 188 * Copy the codec color table back to the client when kIndex8 color type is requ
ested |
144 */ | 189 */ |
145 static inline void copy_color_table(const SkImageInfo& dstInfo, SkColorTable* co
lorTable, | 190 inline void copy_color_table(const SkImageInfo& dstInfo, SkColorTable* colorTabl
e, |
146 SkPMColor* inputColorPtr, int* inputColorCount) { | 191 SkPMColor* inputColorPtr, int* inputColorCount) { |
147 if (kIndex_8_SkColorType == dstInfo.colorType()) { | 192 if (kIndex_8_SkColorType == dstInfo.colorType()) { |
148 SkASSERT(nullptr != inputColorPtr); | 193 SkASSERT(nullptr != inputColorPtr); |
149 SkASSERT(nullptr != inputColorCount); | 194 SkASSERT(nullptr != inputColorCount); |
150 SkASSERT(nullptr != colorTable); | 195 SkASSERT(nullptr != colorTable); |
151 memcpy(inputColorPtr, colorTable->readColors(), *inputColorCount * sizeo
f(SkPMColor)); | 196 memcpy(inputColorPtr, colorTable->readColors(), *inputColorCount * sizeo
f(SkPMColor)); |
152 } | 197 } |
153 } | 198 } |
154 | 199 |
155 /* | 200 /* |
156 * Compute row bytes for an image using pixels per byte | 201 * Compute row bytes for an image using pixels per byte |
157 */ | 202 */ |
158 static inline size_t compute_row_bytes_ppb(int width, uint32_t pixelsPerByte) { | 203 inline size_t compute_row_bytes_ppb(int width, uint32_t pixelsPerByte) { |
159 return (width + pixelsPerByte - 1) / pixelsPerByte; | 204 return (width + pixelsPerByte - 1) / pixelsPerByte; |
160 } | 205 } |
161 | 206 |
162 /* | 207 /* |
163 * Compute row bytes for an image using bytes per pixel | 208 * Compute row bytes for an image using bytes per pixel |
164 */ | 209 */ |
165 static inline size_t compute_row_bytes_bpp(int width, uint32_t bytesPerPixel) { | 210 inline size_t compute_row_bytes_bpp(int width, uint32_t bytesPerPixel) { |
166 return width * bytesPerPixel; | 211 return width * bytesPerPixel; |
167 } | 212 } |
168 | 213 |
169 /* | 214 /* |
170 * Compute row bytes for an image | 215 * Compute row bytes for an image |
171 */ | 216 */ |
172 static inline size_t compute_row_bytes(int width, uint32_t bitsPerPixel) { | 217 inline size_t compute_row_bytes(int width, uint32_t bitsPerPixel) { |
173 if (bitsPerPixel < 16) { | 218 if (bitsPerPixel < 16) { |
174 SkASSERT(0 == 8 % bitsPerPixel); | 219 SkASSERT(0 == 8 % bitsPerPixel); |
175 const uint32_t pixelsPerByte = 8 / bitsPerPixel; | 220 const uint32_t pixelsPerByte = 8 / bitsPerPixel; |
176 return compute_row_bytes_ppb(width, pixelsPerByte); | 221 return compute_row_bytes_ppb(width, pixelsPerByte); |
177 } else { | 222 } else { |
178 SkASSERT(0 == bitsPerPixel % 8); | 223 SkASSERT(0 == bitsPerPixel % 8); |
179 const uint32_t bytesPerPixel = bitsPerPixel / 8; | 224 const uint32_t bytesPerPixel = bitsPerPixel / 8; |
180 return compute_row_bytes_bpp(width, bytesPerPixel); | 225 return compute_row_bytes_bpp(width, bytesPerPixel); |
181 } | 226 } |
182 } | 227 } |
183 | 228 |
184 /* | 229 /* |
185 * On incomplete images, get the color to fill with | |
186 */ | |
187 static inline SkPMColor get_fill_color_or_index(SkAlphaType alphaType) { | |
188 // This condition works properly for all supported output color types. | |
189 // kIndex8: The low 8-bits of both possible return values is 0, which is | |
190 // our desired default index. | |
191 // kGray8: The low 8-bits of both possible return values is 0, which is | |
192 // black, our desired fill value. | |
193 // kRGB565: The low 16-bits of both possible return values is 0, which is | |
194 // black, our desired fill value. | |
195 // kN32: Return black for opaque images and transparent for non-opaque | |
196 // images. | |
197 return kOpaque_SkAlphaType == alphaType ? | |
198 SK_ColorBLACK : SK_ColorTRANSPARENT; | |
199 } | |
200 | |
201 /* | |
202 * Get a byte from a buffer | 230 * Get a byte from a buffer |
203 * This method is unsafe, the caller is responsible for performing a check | 231 * This method is unsafe, the caller is responsible for performing a check |
204 */ | 232 */ |
205 static inline uint8_t get_byte(uint8_t* buffer, uint32_t i) { | 233 inline uint8_t get_byte(uint8_t* buffer, uint32_t i) { |
206 return buffer[i]; | 234 return buffer[i]; |
207 } | 235 } |
208 | 236 |
209 /* | 237 /* |
210 * Get a short from a buffer | 238 * Get a short from a buffer |
211 * This method is unsafe, the caller is responsible for performing a check | 239 * This method is unsafe, the caller is responsible for performing a check |
212 */ | 240 */ |
213 static inline uint16_t get_short(uint8_t* buffer, uint32_t i) { | 241 inline uint16_t get_short(uint8_t* buffer, uint32_t i) { |
214 uint16_t result; | 242 uint16_t result; |
215 memcpy(&result, &(buffer[i]), 2); | 243 memcpy(&result, &(buffer[i]), 2); |
216 #ifdef SK_CPU_BENDIAN | 244 #ifdef SK_CPU_BENDIAN |
217 return SkEndianSwap16(result); | 245 return SkEndianSwap16(result); |
218 #else | 246 #else |
219 return result; | 247 return result; |
220 #endif | 248 #endif |
221 } | 249 } |
222 | 250 |
223 /* | 251 /* |
224 * Get an int from a buffer | 252 * Get an int from a buffer |
225 * This method is unsafe, the caller is responsible for performing a check | 253 * This method is unsafe, the caller is responsible for performing a check |
226 */ | 254 */ |
227 static inline uint32_t get_int(uint8_t* buffer, uint32_t i) { | 255 inline uint32_t get_int(uint8_t* buffer, uint32_t i) { |
228 uint32_t result; | 256 uint32_t result; |
229 memcpy(&result, &(buffer[i]), 4); | 257 memcpy(&result, &(buffer[i]), 4); |
230 #ifdef SK_CPU_BENDIAN | 258 #ifdef SK_CPU_BENDIAN |
231 return SkEndianSwap32(result); | 259 return SkEndianSwap32(result); |
232 #else | 260 #else |
233 return result; | 261 return result; |
234 #endif | 262 #endif |
235 } | 263 } |
236 | 264 |
237 #ifdef SK_PRINT_CODEC_MESSAGES | 265 #ifdef SK_PRINT_CODEC_MESSAGES |
238 #define SkCodecPrintf SkDebugf | 266 #define SkCodecPrintf SkDebugf |
239 #else | 267 #else |
240 #define SkCodecPrintf(...) | 268 #define SkCodecPrintf(...) |
241 #endif | 269 #endif |
242 | 270 |
243 #endif // SkCodecPriv_DEFINED | 271 #endif // SkCodecPriv_DEFINED |
OLD | NEW |