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 bool valid_alpha(SkAlphaType dstAlpha, SkAlphaType srcAlpha) { |
84 // Check for supported alpha types | 85 // Check for supported alpha types |
85 if (srcAlpha != dstAlpha) { | 86 if (srcAlpha != dstAlpha) { |
86 if (kOpaque_SkAlphaType == srcAlpha) { | 87 if (kOpaque_SkAlphaType == srcAlpha) { |
87 // If the source is opaque, we must decode to opaque | 88 // If the source is opaque, we must decode to opaque |
88 return false; | 89 return false; |
89 } | 90 } |
90 | 91 |
91 // The source is not opaque | 92 // The source is not opaque |
92 switch (dstAlpha) { | 93 switch (dstAlpha) { |
93 case kPremul_SkAlphaType: | 94 case kPremul_SkAlphaType: |
94 case kUnpremul_SkAlphaType: | 95 case kUnpremul_SkAlphaType: |
95 // The source is not opaque, so either of these is okay | 96 // The source is not opaque, so either of these is okay |
96 break; | 97 break; |
97 default: | 98 default: |
98 // We cannot decode a non-opaque image to opaque (or unknown) | 99 // We cannot decode a non-opaque image to opaque (or unknown) |
99 return false; | 100 return false; |
100 } | 101 } |
101 } | 102 } |
102 return true; | 103 return true; |
103 } | 104 } |
104 | 105 |
105 /* | 106 /* |
106 * Most of our codecs support the same conversions: | 107 * Most of our codecs support the same conversions: |
107 * - profileType must be the same | 108 * - profileType must be the same |
108 * - opaque only to opaque (and 565 only if opaque) | 109 * - opaque only to opaque (and 565 only if opaque) |
109 * - premul to unpremul and vice versa | 110 * - premul to unpremul and vice versa |
110 * - always support N32 | 111 * - always support N32 |
111 * - otherwise match the src color type | 112 * - otherwise match the src color type |
112 */ | 113 */ |
113 static bool conversion_possible(const SkImageInfo& dst, const SkImageInfo& src)
{ | 114 inline bool conversion_possible(const SkImageInfo& dst, const SkImageInfo& src)
{ |
114 if (dst.profileType() != src.profileType()) { | 115 if (dst.profileType() != src.profileType()) { |
115 return false; | 116 return false; |
116 } | 117 } |
117 | 118 |
118 // Ensure the alpha type is valid | 119 // Ensure the alpha type is valid |
119 if (!valid_alpha(dst.alphaType(), src.alphaType())) { | 120 if (!valid_alpha(dst.alphaType(), src.alphaType())) { |
120 return false; | 121 return false; |
121 } | 122 } |
122 | 123 |
123 // Check for supported color types | 124 // Check for supported color types |
124 switch (dst.colorType()) { | 125 switch (dst.colorType()) { |
125 case kN32_SkColorType: | 126 case kN32_SkColorType: |
126 return true; | 127 return true; |
127 case kRGB_565_SkColorType: | 128 case kRGB_565_SkColorType: |
128 return src.alphaType() == kOpaque_SkAlphaType; | 129 return src.alphaType() == kOpaque_SkAlphaType; |
129 default: | 130 default: |
130 return dst.colorType() == src.colorType(); | 131 return dst.colorType() == src.colorType(); |
131 } | 132 } |
132 } | 133 } |
133 | 134 |
134 /* | 135 /* |
135 * If there is a color table, get a pointer to the colors, otherwise return null
ptr | 136 * If there is a color table, get a pointer to the colors, otherwise return null
ptr |
136 */ | 137 */ |
137 static const SkPMColor* get_color_ptr(SkColorTable* colorTable) { | 138 inline const SkPMColor* get_color_ptr(SkColorTable* colorTable) { |
138 return nullptr != colorTable ? colorTable->readColors() : nullptr; | 139 return nullptr != colorTable ? colorTable->readColors() : nullptr; |
139 } | 140 } |
140 | 141 |
141 /* | 142 /* |
| 143 * Given that the encoded image uses a color table, return the fill value |
| 144 */ |
| 145 inline uint32_t get_color_table_fill_value(SkColorType colorType, const SkPMColo
r* colorPtr, |
| 146 uint8_t fillIndex) { |
| 147 SkASSERT(nullptr != colorPtr); |
| 148 switch (colorType) { |
| 149 case kN32_SkColorType: |
| 150 return colorPtr[fillIndex]; |
| 151 case kRGB_565_SkColorType: |
| 152 return SkPixel32ToPixel16(colorPtr[fillIndex]); |
| 153 case kIndex_8_SkColorType: |
| 154 return fillIndex; |
| 155 default: |
| 156 SkASSERT(false); |
| 157 return 0; |
| 158 } |
| 159 } |
| 160 |
| 161 /* |
142 * | 162 * |
143 * Copy the codec color table back to the client when kIndex8 color type is requ
ested | 163 * Copy the codec color table back to the client when kIndex8 color type is requ
ested |
144 */ | 164 */ |
145 static inline void copy_color_table(const SkImageInfo& dstInfo, SkColorTable* co
lorTable, | 165 inline void copy_color_table(const SkImageInfo& dstInfo, SkColorTable* colorTabl
e, |
146 SkPMColor* inputColorPtr, int* inputColorCount) { | 166 SkPMColor* inputColorPtr, int* inputColorCount) { |
147 if (kIndex_8_SkColorType == dstInfo.colorType()) { | 167 if (kIndex_8_SkColorType == dstInfo.colorType()) { |
148 SkASSERT(nullptr != inputColorPtr); | 168 SkASSERT(nullptr != inputColorPtr); |
149 SkASSERT(nullptr != inputColorCount); | 169 SkASSERT(nullptr != inputColorCount); |
150 SkASSERT(nullptr != colorTable); | 170 SkASSERT(nullptr != colorTable); |
151 memcpy(inputColorPtr, colorTable->readColors(), *inputColorCount * sizeo
f(SkPMColor)); | 171 memcpy(inputColorPtr, colorTable->readColors(), *inputColorCount * sizeo
f(SkPMColor)); |
152 } | 172 } |
153 } | 173 } |
154 | 174 |
155 /* | 175 /* |
156 * Compute row bytes for an image using pixels per byte | 176 * Compute row bytes for an image using pixels per byte |
157 */ | 177 */ |
158 static inline size_t compute_row_bytes_ppb(int width, uint32_t pixelsPerByte) { | 178 inline size_t compute_row_bytes_ppb(int width, uint32_t pixelsPerByte) { |
159 return (width + pixelsPerByte - 1) / pixelsPerByte; | 179 return (width + pixelsPerByte - 1) / pixelsPerByte; |
160 } | 180 } |
161 | 181 |
162 /* | 182 /* |
163 * Compute row bytes for an image using bytes per pixel | 183 * Compute row bytes for an image using bytes per pixel |
164 */ | 184 */ |
165 static inline size_t compute_row_bytes_bpp(int width, uint32_t bytesPerPixel) { | 185 inline size_t compute_row_bytes_bpp(int width, uint32_t bytesPerPixel) { |
166 return width * bytesPerPixel; | 186 return width * bytesPerPixel; |
167 } | 187 } |
168 | 188 |
169 /* | 189 /* |
170 * Compute row bytes for an image | 190 * Compute row bytes for an image |
171 */ | 191 */ |
172 static inline size_t compute_row_bytes(int width, uint32_t bitsPerPixel) { | 192 inline size_t compute_row_bytes(int width, uint32_t bitsPerPixel) { |
173 if (bitsPerPixel < 16) { | 193 if (bitsPerPixel < 16) { |
174 SkASSERT(0 == 8 % bitsPerPixel); | 194 SkASSERT(0 == 8 % bitsPerPixel); |
175 const uint32_t pixelsPerByte = 8 / bitsPerPixel; | 195 const uint32_t pixelsPerByte = 8 / bitsPerPixel; |
176 return compute_row_bytes_ppb(width, pixelsPerByte); | 196 return compute_row_bytes_ppb(width, pixelsPerByte); |
177 } else { | 197 } else { |
178 SkASSERT(0 == bitsPerPixel % 8); | 198 SkASSERT(0 == bitsPerPixel % 8); |
179 const uint32_t bytesPerPixel = bitsPerPixel / 8; | 199 const uint32_t bytesPerPixel = bitsPerPixel / 8; |
180 return compute_row_bytes_bpp(width, bytesPerPixel); | 200 return compute_row_bytes_bpp(width, bytesPerPixel); |
181 } | 201 } |
182 } | 202 } |
183 | 203 |
184 /* | 204 /* |
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 | 205 * Get a byte from a buffer |
203 * This method is unsafe, the caller is responsible for performing a check | 206 * This method is unsafe, the caller is responsible for performing a check |
204 */ | 207 */ |
205 static inline uint8_t get_byte(uint8_t* buffer, uint32_t i) { | 208 inline uint8_t get_byte(uint8_t* buffer, uint32_t i) { |
206 return buffer[i]; | 209 return buffer[i]; |
207 } | 210 } |
208 | 211 |
209 /* | 212 /* |
210 * Get a short from a buffer | 213 * Get a short from a buffer |
211 * This method is unsafe, the caller is responsible for performing a check | 214 * This method is unsafe, the caller is responsible for performing a check |
212 */ | 215 */ |
213 static inline uint16_t get_short(uint8_t* buffer, uint32_t i) { | 216 inline uint16_t get_short(uint8_t* buffer, uint32_t i) { |
214 uint16_t result; | 217 uint16_t result; |
215 memcpy(&result, &(buffer[i]), 2); | 218 memcpy(&result, &(buffer[i]), 2); |
216 #ifdef SK_CPU_BENDIAN | 219 #ifdef SK_CPU_BENDIAN |
217 return SkEndianSwap16(result); | 220 return SkEndianSwap16(result); |
218 #else | 221 #else |
219 return result; | 222 return result; |
220 #endif | 223 #endif |
221 } | 224 } |
222 | 225 |
223 /* | 226 /* |
224 * Get an int from a buffer | 227 * Get an int from a buffer |
225 * This method is unsafe, the caller is responsible for performing a check | 228 * This method is unsafe, the caller is responsible for performing a check |
226 */ | 229 */ |
227 static inline uint32_t get_int(uint8_t* buffer, uint32_t i) { | 230 inline uint32_t get_int(uint8_t* buffer, uint32_t i) { |
228 uint32_t result; | 231 uint32_t result; |
229 memcpy(&result, &(buffer[i]), 4); | 232 memcpy(&result, &(buffer[i]), 4); |
230 #ifdef SK_CPU_BENDIAN | 233 #ifdef SK_CPU_BENDIAN |
231 return SkEndianSwap32(result); | 234 return SkEndianSwap32(result); |
232 #else | 235 #else |
233 return result; | 236 return result; |
234 #endif | 237 #endif |
235 } | 238 } |
236 | 239 |
237 #ifdef SK_PRINT_CODEC_MESSAGES | 240 #ifdef SK_PRINT_CODEC_MESSAGES |
238 #define SkCodecPrintf SkDebugf | 241 #define SkCodecPrintf SkDebugf |
239 #else | 242 #else |
240 #define SkCodecPrintf(...) | 243 #define SkCodecPrintf(...) |
241 #endif | 244 #endif |
242 | 245 |
243 #endif // SkCodecPriv_DEFINED | 246 #endif // SkCodecPriv_DEFINED |
OLD | NEW |