| 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 |