OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 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 "SkColorSpace.h" | 8 #include "SkColorSpace.h" |
9 #include "SkColorSpace_Base.h" | 9 #include "SkColorSpace_Base.h" |
10 #include "SkColorSpacePriv.h" | 10 #include "SkColorSpacePriv.h" |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 color_space_almost_equal(toXYZD50.getFloat(2, 2), standard[8]) && | 61 color_space_almost_equal(toXYZD50.getFloat(2, 2), standard[8]) && |
62 color_space_almost_equal(toXYZD50.getFloat(0, 3), 0.0f) && | 62 color_space_almost_equal(toXYZD50.getFloat(0, 3), 0.0f) && |
63 color_space_almost_equal(toXYZD50.getFloat(1, 3), 0.0f) && | 63 color_space_almost_equal(toXYZD50.getFloat(1, 3), 0.0f) && |
64 color_space_almost_equal(toXYZD50.getFloat(2, 3), 0.0f) && | 64 color_space_almost_equal(toXYZD50.getFloat(2, 3), 0.0f) && |
65 color_space_almost_equal(toXYZD50.getFloat(3, 0), 0.0f) && | 65 color_space_almost_equal(toXYZD50.getFloat(3, 0), 0.0f) && |
66 color_space_almost_equal(toXYZD50.getFloat(3, 1), 0.0f) && | 66 color_space_almost_equal(toXYZD50.getFloat(3, 1), 0.0f) && |
67 color_space_almost_equal(toXYZD50.getFloat(3, 2), 0.0f) && | 67 color_space_almost_equal(toXYZD50.getFloat(3, 2), 0.0f) && |
68 color_space_almost_equal(toXYZD50.getFloat(3, 3), 1.0f); | 68 color_space_almost_equal(toXYZD50.getFloat(3, 3), 1.0f); |
69 } | 69 } |
70 | 70 |
71 sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(float values[3], const SkMatrix44&
toXYZD50) { | 71 sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(const float values[3], const SkMat
rix44& toXYZD50) { |
72 if (0.0f > values[0] || 0.0f > values[1] || 0.0f > values[2]) { | 72 if (0.0f > values[0] || 0.0f > values[1] || 0.0f > values[2]) { |
73 return nullptr; | 73 return nullptr; |
74 } | 74 } |
75 | 75 |
76 GammaNamed gammaNamed = kNonStandard_GammaNamed; | 76 GammaNamed gammaNamed = kNonStandard_GammaNamed; |
77 if (color_space_almost_equal(2.2f, values[0]) && | 77 if (color_space_almost_equal(2.2f, values[0]) && |
78 color_space_almost_equal(2.2f, values[1]) && | 78 color_space_almost_equal(2.2f, values[1]) && |
79 color_space_almost_equal(2.2f, values[2])) { | 79 color_space_almost_equal(2.2f, values[2])) { |
80 gammaNamed = k2Dot2Curve_GammaNamed; | 80 gammaNamed = k2Dot2Curve_GammaNamed; |
81 } else if (color_space_almost_equal(1.0f, values[0]) && | 81 } else if (color_space_almost_equal(1.0f, values[0]) && |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 | 157 |
158 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 158 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
159 | 159 |
160 enum Version { | 160 enum Version { |
161 k0_Version, // Initial version, header + flags for matrix and profile | 161 k0_Version, // Initial version, header + flags for matrix and profile |
162 }; | 162 }; |
163 | 163 |
164 struct ColorSpaceHeader { | 164 struct ColorSpaceHeader { |
165 /** | 165 /** |
166 * If kMatrix_Flag is set, we will write 12 floats after the header. | 166 * If kMatrix_Flag is set, we will write 12 floats after the header. |
167 * Should not be set at the same time as the kICC_Flag. | 167 * Should not be set at the same time as the kICC_Flag or kFloatGamma_Flag. |
168 */ | 168 */ |
169 static constexpr uint8_t kMatrix_Flag = 1 << 0; | 169 static constexpr uint8_t kMatrix_Flag = 1 << 0; |
170 | 170 |
171 /** | 171 /** |
172 * If kICC_Flag is set, we will write an ICC profile after the header. | 172 * If kICC_Flag is set, we will write an ICC profile after the header. |
173 * The ICC profile will be written as a uint32 size, followed immediately | 173 * The ICC profile will be written as a uint32 size, followed immediately |
174 * by the data (padded to 4 bytes). | 174 * by the data (padded to 4 bytes). |
175 * Should not be set at the same time as the kMatrix_Flag. | 175 * Should not be set at the same time as the kMatrix_Flag or kFloatGamma_Fl
ag. |
176 */ | 176 */ |
177 static constexpr uint8_t kICC_Flag = 1 << 1; | 177 static constexpr uint8_t kICC_Flag = 1 << 1; |
| 178 |
| 179 /** |
| 180 * If kFloatGamma_Flag is set, we will write 15 floats after the header. |
| 181 * The first three are the gamma values, and the next twelve are the |
| 182 * matrix. |
| 183 * Should not be set at the same time as the kICC_Flag or kMatrix_Flag. |
| 184 */ |
| 185 static constexpr uint8_t kFloatGamma_Flag = 1 << 2; |
178 | 186 |
179 static ColorSpaceHeader Pack(Version version, SkColorSpace::Named named, | 187 static ColorSpaceHeader Pack(Version version, SkColorSpace::Named named, |
180 SkColorSpace::GammaNamed gammaNamed, uint8_t fl
ags) { | 188 SkColorSpace::GammaNamed gammaNamed, uint8_t fl
ags) { |
181 ColorSpaceHeader header; | 189 ColorSpaceHeader header; |
182 | 190 |
183 SkASSERT(k0_Version == version); | 191 SkASSERT(k0_Version == version); |
184 header.fVersion = (uint8_t) version; | 192 header.fVersion = (uint8_t) version; |
185 | 193 |
186 SkASSERT(named <= SkColorSpace::kAdobeRGB_Named); | 194 SkASSERT(named <= SkColorSpace::kAdobeRGB_Named); |
187 header.fNamed = (uint8_t) named; | 195 header.fNamed = (uint8_t) named; |
188 | 196 |
189 SkASSERT(gammaNamed <= SkColorSpace::kNonStandard_GammaNamed); | 197 SkASSERT(gammaNamed <= SkColorSpace::kNonStandard_GammaNamed); |
190 header.fGammaNamed = (uint8_t) gammaNamed; | 198 header.fGammaNamed = (uint8_t) gammaNamed; |
191 | 199 |
192 SkASSERT(flags <= kICC_Flag); | 200 SkASSERT(flags <= kFloatGamma_Flag); |
193 header.fFlags = flags; | 201 header.fFlags = flags; |
194 return header; | 202 return header; |
195 } | 203 } |
196 | 204 |
197 uint8_t fVersion; // Always zero | 205 uint8_t fVersion; // Always zero |
198 uint8_t fNamed; // Must be a SkColorSpace::Named | 206 uint8_t fNamed; // Must be a SkColorSpace::Named |
199 uint8_t fGammaNamed; // Must be a SkColorSpace::GammaNamed | 207 uint8_t fGammaNamed; // Must be a SkColorSpace::GammaNamed |
200 uint8_t fFlags; // Some combination of the flags listed above | 208 uint8_t fFlags; // Some combination of the flags listed above |
201 }; | 209 }; |
202 | 210 |
(...skipping 23 matching lines...) Expand all Loading... |
226 if (memory) { | 234 if (memory) { |
227 *((ColorSpaceHeader*) memory) = | 235 *((ColorSpaceHeader*) memory) = |
228 ColorSpaceHeader::Pack(k0_Version, fNamed, fGammaNam
ed, | 236 ColorSpaceHeader::Pack(k0_Version, fNamed, fGammaNam
ed, |
229 ColorSpaceHeader::kMatrix_Fla
g); | 237 ColorSpaceHeader::kMatrix_Fla
g); |
230 memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader)
); | 238 memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader)
); |
231 fToXYZD50.as4x3ColMajorf((float*) memory); | 239 fToXYZD50.as4x3ColMajorf((float*) memory); |
232 } | 240 } |
233 return sizeof(ColorSpaceHeader) + 12 * sizeof(float); | 241 return sizeof(ColorSpaceHeader) + 12 * sizeof(float); |
234 } | 242 } |
235 default: | 243 default: |
236 SkASSERT(false); | 244 // Otherwise, write the gamma values and the matrix. |
237 return 0; | 245 if (memory) { |
| 246 *((ColorSpaceHeader*) memory) = |
| 247 ColorSpaceHeader::Pack(k0_Version, fNamed, fGammaNam
ed, |
| 248 ColorSpaceHeader::kFloatGamma
_Flag); |
| 249 memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader)
); |
| 250 |
| 251 const SkGammas* gammas = as_CSB(this)->gammas(); |
| 252 SkASSERT(gammas); |
| 253 SkASSERT(SkGammas::Type::kValue_Type == gammas->fRedType && |
| 254 SkGammas::Type::kValue_Type == gammas->fGreenType &
& |
| 255 SkGammas::Type::kValue_Type == gammas->fBlueType); |
| 256 *(((float*) memory) + 0) = gammas->fRedData.fValue; |
| 257 *(((float*) memory) + 1) = gammas->fGreenData.fValue; |
| 258 *(((float*) memory) + 2) = gammas->fBlueData.fValue; |
| 259 memory = SkTAddOffset<void>(memory, 3 * sizeof(float)); |
| 260 |
| 261 fToXYZD50.as4x3ColMajorf((float*) memory); |
| 262 } |
| 263 return sizeof(ColorSpaceHeader) + 15 * sizeof(float); |
238 } | 264 } |
239 } | 265 } |
240 | 266 |
241 // Otherwise, serialize the ICC data. | 267 // Otherwise, serialize the ICC data. |
242 size_t profileSize = as_CSB(this)->fProfileData->size(); | 268 size_t profileSize = as_CSB(this)->fProfileData->size(); |
243 if (SkAlign4(profileSize) != (uint32_t) SkAlign4(profileSize)) { | 269 if (SkAlign4(profileSize) != (uint32_t) SkAlign4(profileSize)) { |
244 return 0; | 270 return 0; |
245 } | 271 } |
246 | 272 |
247 if (memory) { | 273 if (memory) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 } | 321 } |
296 | 322 |
297 SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor); | 323 SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor); |
298 toXYZ.set4x3ColMajorf((const float*) data); | 324 toXYZ.set4x3ColMajorf((const float*) data); |
299 return NewRGB((GammaNamed) header.fGammaNamed, toXYZ); | 325 return NewRGB((GammaNamed) header.fGammaNamed, toXYZ); |
300 } | 326 } |
301 default: | 327 default: |
302 break; | 328 break; |
303 } | 329 } |
304 | 330 |
305 if (ColorSpaceHeader::kICC_Flag != header.fFlags || length < sizeof(uint32_t
)) { | 331 switch (header.fFlags) { |
306 return nullptr; | 332 case ColorSpaceHeader::kICC_Flag: { |
| 333 if (length < sizeof(uint32_t)) { |
| 334 return nullptr; |
| 335 } |
| 336 |
| 337 uint32_t profileSize = *((uint32_t*) data); |
| 338 data = SkTAddOffset<const void>(data, sizeof(uint32_t)); |
| 339 length -= sizeof(uint32_t); |
| 340 if (length < profileSize) { |
| 341 return nullptr; |
| 342 } |
| 343 |
| 344 return NewICC(data, profileSize); |
| 345 } |
| 346 case ColorSpaceHeader::kFloatGamma_Flag: { |
| 347 if (length < 15 * sizeof(float)) { |
| 348 return nullptr; |
| 349 } |
| 350 |
| 351 float gammas[3]; |
| 352 gammas[0] = *(((const float*) data) + 0); |
| 353 gammas[1] = *(((const float*) data) + 1); |
| 354 gammas[2] = *(((const float*) data) + 2); |
| 355 data = SkTAddOffset<const void>(data, 3 * sizeof(float)); |
| 356 |
| 357 SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor); |
| 358 toXYZ.set4x3ColMajorf((const float*) data); |
| 359 return SkColorSpace_Base::NewRGB(gammas, toXYZ); |
| 360 } |
| 361 default: |
| 362 return nullptr; |
307 } | 363 } |
308 | |
309 uint32_t profileSize = *((uint32_t*) data); | |
310 data = SkTAddOffset<const void>(data, sizeof(uint32_t)); | |
311 length -= sizeof(uint32_t); | |
312 if (length < profileSize) { | |
313 return nullptr; | |
314 } | |
315 | |
316 return NewICC(data, profileSize); | |
317 } | 364 } |
318 | 365 |
319 bool SkColorSpace::Equals(const SkColorSpace* src, const SkColorSpace* dst) { | 366 bool SkColorSpace::Equals(const SkColorSpace* src, const SkColorSpace* dst) { |
320 if (src == dst) { | 367 if (src == dst) { |
321 return true; | 368 return true; |
322 } | 369 } |
323 | 370 |
324 if (!src || !dst) { | 371 if (!src || !dst) { |
325 return false; | 372 return false; |
326 } | 373 } |
(...skipping 21 matching lines...) Expand all Loading... |
348 } | 395 } |
349 | 396 |
350 // It's important to check fProfileData before named gammas. Some profiles
may have named | 397 // It's important to check fProfileData before named gammas. Some profiles
may have named |
351 // gammas, but also include other wacky features that cause us to save the d
ata. | 398 // gammas, but also include other wacky features that cause us to save the d
ata. |
352 switch (src->fGammaNamed) { | 399 switch (src->fGammaNamed) { |
353 case kSRGB_GammaNamed: | 400 case kSRGB_GammaNamed: |
354 case k2Dot2Curve_GammaNamed: | 401 case k2Dot2Curve_GammaNamed: |
355 case kLinear_GammaNamed: | 402 case kLinear_GammaNamed: |
356 return (src->fGammaNamed == dst->fGammaNamed) && (src->fToXYZD50 ==
dst->fToXYZD50); | 403 return (src->fGammaNamed == dst->fGammaNamed) && (src->fToXYZD50 ==
dst->fToXYZD50); |
357 default: | 404 default: |
358 // If |src| does not have a named gamma, fProfileData should be non-
null. | 405 if (src->fGammaNamed != dst->fGammaNamed) { |
359 // FIXME (msarett): We may hit this case on pngs that specify float
gammas. | 406 return false; |
360 // Gamma can be non-standard, but we don't have a p
rofile | 407 } |
361 // to fall back on. What do we do? | 408 |
362 return false; | 409 // It is unlikely that we will reach this case. |
| 410 sk_sp<SkData> srcData = src->serialize(); |
| 411 sk_sp<SkData> dstData = dst->serialize(); |
| 412 return srcData->size() == dstData->size() && |
| 413 0 == memcmp(srcData->data(), dstData->data(), srcData->size()
); |
363 } | 414 } |
364 } | 415 } |
365 | 416 |
366 bool SkColorSpace::gammasAreMatching() const { | 417 bool SkColorSpace::gammasAreMatching() const { |
367 const SkGammas* gammas = as_CSB(this)->gammas(); | 418 const SkGammas* gammas = as_CSB(this)->gammas(); |
368 SkASSERT(gammas); | 419 SkASSERT(gammas); |
369 return gammas->fRedType == gammas->fGreenType && gammas->fGreenType == gamma
s->fBlueType && | 420 return gammas->fRedType == gammas->fGreenType && gammas->fGreenType == gamma
s->fBlueType && |
370 gammas->fRedData == gammas->fGreenData && gammas->fGreenData == gamma
s->fBlueData; | 421 gammas->fRedData == gammas->fGreenData && gammas->fGreenData == gamma
s->fBlueData; |
371 } | 422 } |
372 | 423 |
(...skipping 21 matching lines...) Expand all Loading... |
394 gammas->fBlueType == SkGammas::Type::kTable_Type; | 445 gammas->fBlueType == SkGammas::Type::kTable_Type; |
395 } | 446 } |
396 | 447 |
397 bool SkColorSpace::gammasAreParams() const { | 448 bool SkColorSpace::gammasAreParams() const { |
398 const SkGammas* gammas = as_CSB(this)->gammas(); | 449 const SkGammas* gammas = as_CSB(this)->gammas(); |
399 SkASSERT(gammas); | 450 SkASSERT(gammas); |
400 return gammas->fRedType == SkGammas::Type::kParam_Type && | 451 return gammas->fRedType == SkGammas::Type::kParam_Type && |
401 gammas->fGreenType == SkGammas::Type::kParam_Type && | 452 gammas->fGreenType == SkGammas::Type::kParam_Type && |
402 gammas->fBlueType == SkGammas::Type::kParam_Type; | 453 gammas->fBlueType == SkGammas::Type::kParam_Type; |
403 } | 454 } |
OLD | NEW |