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 (ColorSpaceHeader::kFloatGamma_Flag != header.fFlags || length < 15 * sizeof(float)) | |
Brian Osman
2016/08/22 14:00:02
The first condition on the 'if' is strange - we're
msarett
2016/08/22 14:10:24
Yeah thanks... Removing that condition.
| |
348 { | |
349 return nullptr; | |
350 } | |
351 | |
352 float gammas[3]; | |
353 gammas[0] = *(((const float*) data) + 0); | |
354 gammas[1] = *(((const float*) data) + 1); | |
355 gammas[2] = *(((const float*) data) + 2); | |
356 data = SkTAddOffset<const void>(data, 3 * sizeof(float)); | |
357 | |
358 SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor); | |
359 toXYZ.set4x3ColMajorf((const float*) data); | |
360 return SkColorSpace_Base::NewRGB(gammas, toXYZ); | |
361 } | |
362 default: | |
363 return nullptr; | |
307 } | 364 } |
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 } | 365 } |
318 | 366 |
319 bool SkColorSpace::Equals(const SkColorSpace* src, const SkColorSpace* dst) { | 367 bool SkColorSpace::Equals(const SkColorSpace* src, const SkColorSpace* dst) { |
320 if (src == dst) { | 368 if (src == dst) { |
321 return true; | 369 return true; |
322 } | 370 } |
323 | 371 |
324 if (!src || !dst) { | 372 if (!src || !dst) { |
325 return false; | 373 return false; |
326 } | 374 } |
(...skipping 21 matching lines...) Expand all Loading... | |
348 } | 396 } |
349 | 397 |
350 // It's important to check fProfileData before named gammas. Some profiles may have named | 398 // 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. | 399 // gammas, but also include other wacky features that cause us to save the d ata. |
352 switch (src->fGammaNamed) { | 400 switch (src->fGammaNamed) { |
353 case kSRGB_GammaNamed: | 401 case kSRGB_GammaNamed: |
354 case k2Dot2Curve_GammaNamed: | 402 case k2Dot2Curve_GammaNamed: |
355 case kLinear_GammaNamed: | 403 case kLinear_GammaNamed: |
356 return (src->fGammaNamed == dst->fGammaNamed) && (src->fToXYZD50 == dst->fToXYZD50); | 404 return (src->fGammaNamed == dst->fGammaNamed) && (src->fToXYZD50 == dst->fToXYZD50); |
357 default: | 405 default: |
358 // If |src| does not have a named gamma, fProfileData should be non- null. | 406 if (src->fGammaNamed != dst->fGammaNamed) { |
359 // FIXME (msarett): We may hit this case on pngs that specify float gammas. | 407 return false; |
360 // Gamma can be non-standard, but we don't have a p rofile | 408 } |
361 // to fall back on. What do we do? | 409 |
362 return false; | 410 // It is unlikely that we will reach this case. |
411 sk_sp<SkData> srcData = src->serialize(); | |
412 sk_sp<SkData> dstData = dst->serialize(); | |
413 return srcData->size() == dstData->size() && | |
414 0 == memcmp(srcData->data(), dstData->data(), srcData->size() ); | |
363 } | 415 } |
364 } | 416 } |
365 | 417 |
366 bool SkColorSpace::gammasAreMatching() const { | 418 bool SkColorSpace::gammasAreMatching() const { |
367 const SkGammas* gammas = as_CSB(this)->gammas(); | 419 const SkGammas* gammas = as_CSB(this)->gammas(); |
368 SkASSERT(gammas); | 420 SkASSERT(gammas); |
369 return gammas->fRedType == gammas->fGreenType && gammas->fGreenType == gamma s->fBlueType && | 421 return gammas->fRedType == gammas->fGreenType && gammas->fGreenType == gamma s->fBlueType && |
370 gammas->fRedData == gammas->fGreenData && gammas->fGreenData == gamma s->fBlueData; | 422 gammas->fRedData == gammas->fGreenData && gammas->fGreenData == gamma s->fBlueData; |
371 } | 423 } |
372 | 424 |
(...skipping 21 matching lines...) Expand all Loading... | |
394 gammas->fBlueType == SkGammas::Type::kTable_Type; | 446 gammas->fBlueType == SkGammas::Type::kTable_Type; |
395 } | 447 } |
396 | 448 |
397 bool SkColorSpace::gammasAreParams() const { | 449 bool SkColorSpace::gammasAreParams() const { |
398 const SkGammas* gammas = as_CSB(this)->gammas(); | 450 const SkGammas* gammas = as_CSB(this)->gammas(); |
399 SkASSERT(gammas); | 451 SkASSERT(gammas); |
400 return gammas->fRedType == SkGammas::Type::kParam_Type && | 452 return gammas->fRedType == SkGammas::Type::kParam_Type && |
401 gammas->fGreenType == SkGammas::Type::kParam_Type && | 453 gammas->fGreenType == SkGammas::Type::kParam_Type && |
402 gammas->fBlueType == SkGammas::Type::kParam_Type; | 454 gammas->fBlueType == SkGammas::Type::kParam_Type; |
403 } | 455 } |
OLD | NEW |