OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
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 #include "SkBitmap.h" | 8 #include "SkBitmap.h" |
9 #include "SkCodecPriv.h" | 9 #include "SkCodecPriv.h" |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
11 #include "SkColorSpace.h" | 11 #include "SkColorSpace_Base.h" |
12 #include "SkColorTable.h" | 12 #include "SkColorTable.h" |
13 #include "SkMath.h" | 13 #include "SkMath.h" |
14 #include "SkOpts.h" | 14 #include "SkOpts.h" |
15 #include "SkPngCodec.h" | 15 #include "SkPngCodec.h" |
16 #include "SkSize.h" | 16 #include "SkSize.h" |
17 #include "SkStream.h" | 17 #include "SkStream.h" |
18 #include "SkSwizzler.h" | 18 #include "SkSwizzler.h" |
19 #include "SkTemplates.h" | 19 #include "SkTemplates.h" |
20 #include "SkUtils.h" | 20 #include "SkUtils.h" |
21 | 21 |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 // do the conversion ourselves rather than convert | 165 // do the conversion ourselves rather than convert |
166 // fixed point -> double -> float. | 166 // fixed point -> double -> float. |
167 return ((float) x) * 0.00001f; | 167 return ((float) x) * 0.00001f; |
168 } | 168 } |
169 | 169 |
170 static float png_inverted_fixed_point_to_float(png_fixed_point x) { | 170 static float png_inverted_fixed_point_to_float(png_fixed_point x) { |
171 // This is necessary because the gAMA chunk actually stores 1/gamma. | 171 // This is necessary because the gAMA chunk actually stores 1/gamma. |
172 return 1.0f / png_fixed_point_to_float(x); | 172 return 1.0f / png_fixed_point_to_float(x); |
173 } | 173 } |
174 | 174 |
| 175 static constexpr float gSRGB_toXYZD50[] { |
| 176 0.4358f, 0.2224f, 0.0139f, // * R |
| 177 0.3853f, 0.7170f, 0.0971f, // * G |
| 178 0.1430f, 0.0606f, 0.7139f, // * B |
| 179 }; |
| 180 |
175 // Returns a colorSpace object that represents any color space information in | 181 // Returns a colorSpace object that represents any color space information in |
176 // the encoded data. If the encoded data contains no color space, this will | 182 // the encoded data. If the encoded data contains no color space, this will |
177 // return NULL. | 183 // return NULL. |
178 sk_sp<SkColorSpace> read_color_space(png_structp png_ptr, png_infop info_ptr) { | 184 sk_sp<SkColorSpace> read_color_space(png_structp png_ptr, png_infop info_ptr) { |
179 | 185 |
180 #if (PNG_LIBPNG_VER_MAJOR > 1) || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_M
INOR >= 6) | 186 #if (PNG_LIBPNG_VER_MAJOR > 1) || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_M
INOR >= 6) |
181 | 187 |
182 // First check for an ICC profile | 188 // First check for an ICC profile |
183 png_bytep profile; | 189 png_bytep profile; |
184 png_uint_32 length; | 190 png_uint_32 length; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 | 222 |
217 // FIXME (msarett): Here we are treating XYZ values as D50 even though t
he color | 223 // FIXME (msarett): Here we are treating XYZ values as D50 even though t
he color |
218 // temperature is unspecified. I suspect that this ass
umption | 224 // temperature is unspecified. I suspect that this ass
umption |
219 // is most often ok, but we could also calculate the co
lor | 225 // is most often ok, but we could also calculate the co
lor |
220 // temperature (D value) and then convert the XYZ to D5
0. Maybe | 226 // temperature (D value) and then convert the XYZ to D5
0. Maybe |
221 // we should add a new constructor to SkColorSpace that
accepts | 227 // we should add a new constructor to SkColorSpace that
accepts |
222 // XYZ with D-Unkown? | 228 // XYZ with D-Unkown? |
223 for (int i = 0; i < 9; i++) { | 229 for (int i = 0; i < 9; i++) { |
224 toXYZD50[i] = png_fixed_point_to_float(XYZ[i]); | 230 toXYZD50[i] = png_fixed_point_to_float(XYZ[i]); |
225 } | 231 } |
| 232 SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor); |
| 233 mat.set3x3ColMajorf(toXYZD50); |
226 | 234 |
227 if (PNG_INFO_gAMA == png_get_gAMA_fixed(png_ptr, info_ptr, &gamma)) { | 235 if (PNG_INFO_gAMA == png_get_gAMA_fixed(png_ptr, info_ptr, &gamma)) { |
228 float value = png_inverted_fixed_point_to_float(gamma); | 236 float value = png_inverted_fixed_point_to_float(gamma); |
229 gammas[0] = value; | 237 gammas[0] = value; |
230 gammas[1] = value; | 238 gammas[1] = value; |
231 gammas[2] = value; | 239 gammas[2] = value; |
232 | 240 |
233 } else { | 241 return SkColorSpace_Base::NewRGB(gammas, mat); |
234 // Default to sRGB (gamma = 2.2f) if the image has color space infor
mation, | |
235 // but does not specify gamma. | |
236 gammas[0] = 2.2f; | |
237 gammas[1] = 2.2f; | |
238 gammas[2] = 2.2f; | |
239 } | 242 } |
240 | 243 |
241 SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor); | 244 // Default to sRGB gamma if the image has color space information, |
242 mat.set3x3ColMajorf(toXYZD50); | 245 // but does not specify gamma. |
243 return SkColorSpace::NewRGB(gammas, mat); | 246 return SkColorSpace::NewRGB(SkColorSpace::kSRGB_GammaNamed, mat); |
244 } | 247 } |
245 | 248 |
246 // Last, check for gamma. | 249 // Last, check for gamma. |
247 if (PNG_INFO_gAMA == png_get_gAMA_fixed(png_ptr, info_ptr, &gamma)) { | 250 if (PNG_INFO_gAMA == png_get_gAMA_fixed(png_ptr, info_ptr, &gamma)) { |
248 | 251 |
249 // Guess a default value for cHRM? Or should we just give up? | |
250 // Here we use the identity matrix as a default. | |
251 | |
252 // Set the gammas. | 252 // Set the gammas. |
253 float value = png_inverted_fixed_point_to_float(gamma); | 253 float value = png_inverted_fixed_point_to_float(gamma); |
254 gammas[0] = value; | 254 gammas[0] = value; |
255 gammas[1] = value; | 255 gammas[1] = value; |
256 gammas[2] = value; | 256 gammas[2] = value; |
257 | 257 |
258 return SkColorSpace::NewRGB(gammas, SkMatrix44::I()); | 258 // Since there is no cHRM, we will guess sRGB gamut. |
| 259 SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor); |
| 260 mat.set3x3ColMajorf(gSRGB_toXYZD50); |
| 261 |
| 262 return SkColorSpace_Base::NewRGB(gammas, mat); |
259 } | 263 } |
260 | 264 |
261 #endif // LIBPNG >= 1.6 | 265 #endif // LIBPNG >= 1.6 |
262 | 266 |
263 // Finally, what should we do if there is no color space information in the
PNG? | 267 // Report that there is no color space information in the PNG. SkPngCodec i
s currently |
264 // The specification says that this indicates "gamma is unknown" and that th
e | 268 // implemented to guess sRGB in this case. |
265 // "color is device dependent". I'm assuming we can represent this with NUL
L. | |
266 // But should we guess sRGB? Most images are sRGB, even if they don't speci
fy. | |
267 return nullptr; | 269 return nullptr; |
268 } | 270 } |
269 | 271 |
270 static int bytes_per_pixel(int bitsPerPixel) { | 272 static int bytes_per_pixel(int bitsPerPixel) { |
271 // Note that we will have to change this implementation if we start | 273 // Note that we will have to change this implementation if we start |
272 // supporting outputs from libpng that are less than 8-bits per component. | 274 // supporting outputs from libpng that are less than 8-bits per component. |
273 return bitsPerPixel / 8; | 275 return bitsPerPixel / 8; |
274 } | 276 } |
275 | 277 |
276 // Subclass of SkPngCodec which supports scanline decoding | 278 // Subclass of SkPngCodec which supports scanline decoding |
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
807 SkCodec* outCodec; | 809 SkCodec* outCodec; |
808 if (read_header(stream, chunkReader, &outCodec, nullptr, nullptr)) { | 810 if (read_header(stream, chunkReader, &outCodec, nullptr, nullptr)) { |
809 // Codec has taken ownership of the stream. | 811 // Codec has taken ownership of the stream. |
810 SkASSERT(outCodec); | 812 SkASSERT(outCodec); |
811 streamDeleter.release(); | 813 streamDeleter.release(); |
812 return outCodec; | 814 return outCodec; |
813 } | 815 } |
814 | 816 |
815 return nullptr; | 817 return nullptr; |
816 } | 818 } |
OLD | NEW |