Index: src/core/SkColorSpace_ICC.cpp |
diff --git a/src/core/SkColorSpace_ICC.cpp b/src/core/SkColorSpace_ICC.cpp |
index 710558286cd8e7bba2f841df979e47a7e8c1f41a..cbb974f1f11a80a84905c0c5ca31dacfe60e5baf 100644 |
--- a/src/core/SkColorSpace_ICC.cpp |
+++ b/src/core/SkColorSpace_ICC.cpp |
@@ -26,16 +26,16 @@ |
return nullptr; \ |
} while (0) |
-static uint16_t read_big_endian_short(const uint8_t* ptr) { |
+static uint16_t read_big_endian_u16(const uint8_t* ptr) { |
return ptr[0] << 8 | ptr[1]; |
} |
-static uint32_t read_big_endian_uint(const uint8_t* ptr) { |
+static uint32_t read_big_endian_u32(const uint8_t* ptr) { |
return ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3]; |
} |
-static int32_t read_big_endian_int(const uint8_t* ptr) { |
- return (int32_t) read_big_endian_uint(ptr); |
+static int32_t read_big_endian_i32(const uint8_t* ptr) { |
+ return (int32_t) read_big_endian_u32(ptr); |
} |
// This is equal to the header size according to the ICC specification (128) |
@@ -105,7 +105,7 @@ struct ICCProfileHeader { |
uint32_t* dst = (uint32_t*) this; |
for (uint32_t i = 0; i < kICCHeaderSize / 4; i++, src+=4) { |
- dst[i] = read_big_endian_uint(src); |
+ dst[i] = read_big_endian_u32(src); |
} |
} |
@@ -186,9 +186,9 @@ struct ICCTag { |
uint32_t fLength; |
const uint8_t* init(const uint8_t* src) { |
- fSignature = read_big_endian_uint(src); |
- fOffset = read_big_endian_uint(src + 4); |
- fLength = read_big_endian_uint(src + 8); |
+ fSignature = read_big_endian_u32(src); |
+ fOffset = read_big_endian_u32(src + 4); |
+ fLength = read_big_endian_u32(src + 8); |
return src + 12; |
} |
@@ -228,9 +228,9 @@ static bool load_xyz(float dst[3], const uint8_t* src, size_t len) { |
return false; |
} |
- dst[0] = SkFixedToFloat(read_big_endian_int(src + 8)); |
- dst[1] = SkFixedToFloat(read_big_endian_int(src + 12)); |
- dst[2] = SkFixedToFloat(read_big_endian_int(src + 16)); |
+ dst[0] = SkFixedToFloat(read_big_endian_i32(src + 8)); |
+ dst[1] = SkFixedToFloat(read_big_endian_i32(src + 12)); |
+ dst[2] = SkFixedToFloat(read_big_endian_i32(src + 16)); |
SkColorSpacePrintf("XYZ %g %g %g\n", dst[0], dst[1], dst[2]); |
return true; |
} |
@@ -259,7 +259,7 @@ static SkGammas::Type set_gamma_value(SkGammas::Data* data, float value) { |
static float read_big_endian_16_dot_16(const uint8_t buf[4]) { |
// It just so happens that SkFixed is also 16.16! |
- return SkFixedToFloat(read_big_endian_int(buf)); |
+ return SkFixedToFloat(read_big_endian_i32(buf)); |
} |
/** |
@@ -285,11 +285,11 @@ static SkGammas::Type parse_gamma(SkGammas::Data* outData, SkGammas::Params* out |
// tag, so that we can move on to the next tag. |
size_t tagBytes; |
- uint32_t type = read_big_endian_uint(src); |
+ uint32_t type = read_big_endian_u32(src); |
// Bytes 4-7 are reserved and should be set to zero. |
switch (type) { |
case kTAG_CurveType: { |
- uint32_t count = read_big_endian_uint(src + 8); |
+ uint32_t count = read_big_endian_u32(src + 8); |
// tagBytes = 12 + 2 * count |
// We need to do safe addition here to avoid integer overflow. |
@@ -317,7 +317,7 @@ static SkGammas::Type parse_gamma(SkGammas::Data* outData, SkGammas::Params* out |
const uint16_t* table = (const uint16_t*) (src + 12); |
if (1 == count) { |
// The table entry is the gamma (with a bias of 256). |
- float value = (read_big_endian_short((const uint8_t*) table)) / 256.0f; |
+ float value = (read_big_endian_u16((const uint8_t*) table)) / 256.0f; |
SkColorSpacePrintf("gamma %g\n", value); |
return set_gamma_value(outData, value); |
@@ -334,11 +334,11 @@ static SkGammas::Type parse_gamma(SkGammas::Data* outData, SkGammas::Params* out |
// The magic values were chosen because they match both the very common |
// HP sRGB gamma table and the less common Canon sRGB gamma table (which use |
// different rounding rules). |
- if (0 == read_big_endian_short((const uint8_t*) &table[0]) && |
- 3366 == read_big_endian_short((const uint8_t*) &table[257]) && |
- 14116 == read_big_endian_short((const uint8_t*) &table[513]) && |
- 34318 == read_big_endian_short((const uint8_t*) &table[768]) && |
- 65535 == read_big_endian_short((const uint8_t*) &table[1023])) { |
+ if (0 == read_big_endian_u16((const uint8_t*) &table[0]) && |
+ 3366 == read_big_endian_u16((const uint8_t*) &table[257]) && |
+ 14116 == read_big_endian_u16((const uint8_t*) &table[513]) && |
+ 34318 == read_big_endian_u16((const uint8_t*) &table[768]) && |
+ 65535 == read_big_endian_u16((const uint8_t*) &table[1023])) { |
outData->fNamed = SkColorSpace::kSRGB_GammaNamed; |
return SkGammas::Type::kNamed_Type; |
} |
@@ -347,11 +347,11 @@ static SkGammas::Type parse_gamma(SkGammas::Data* outData, SkGammas::Params* out |
if (26 == count) { |
// The magic values were chosen because they match a very common LCMS sRGB |
// gamma table. |
- if (0 == read_big_endian_short((const uint8_t*) &table[0]) && |
- 3062 == read_big_endian_short((const uint8_t*) &table[6]) && |
- 12824 == read_big_endian_short((const uint8_t*) &table[12]) && |
- 31237 == read_big_endian_short((const uint8_t*) &table[18]) && |
- 65535 == read_big_endian_short((const uint8_t*) &table[25])) { |
+ if (0 == read_big_endian_u16((const uint8_t*) &table[0]) && |
+ 3062 == read_big_endian_u16((const uint8_t*) &table[6]) && |
+ 12824 == read_big_endian_u16((const uint8_t*) &table[12]) && |
+ 31237 == read_big_endian_u16((const uint8_t*) &table[18]) && |
+ 65535 == read_big_endian_u16((const uint8_t*) &table[25])) { |
outData->fNamed = SkColorSpace::kSRGB_GammaNamed; |
return SkGammas::Type::kNamed_Type; |
} |
@@ -360,11 +360,11 @@ static SkGammas::Type parse_gamma(SkGammas::Data* outData, SkGammas::Params* out |
if (4096 == count) { |
// The magic values were chosen because they match Nikon, Epson, and |
// LCMS sRGB gamma tables (all of which use different rounding rules). |
- if (0 == read_big_endian_short((const uint8_t*) &table[0]) && |
- 950 == read_big_endian_short((const uint8_t*) &table[515]) && |
- 3342 == read_big_endian_short((const uint8_t*) &table[1025]) && |
- 14079 == read_big_endian_short((const uint8_t*) &table[2051]) && |
- 65535 == read_big_endian_short((const uint8_t*) &table[4095])) { |
+ if (0 == read_big_endian_u16((const uint8_t*) &table[0]) && |
+ 950 == read_big_endian_u16((const uint8_t*) &table[515]) && |
+ 3342 == read_big_endian_u16((const uint8_t*) &table[1025]) && |
+ 14079 == read_big_endian_u16((const uint8_t*) &table[2051]) && |
+ 65535 == read_big_endian_u16((const uint8_t*) &table[4095])) { |
outData->fNamed = SkColorSpace::kSRGB_GammaNamed; |
return SkGammas::Type::kNamed_Type; |
} |
@@ -384,7 +384,7 @@ static SkGammas::Type parse_gamma(SkGammas::Data* outData, SkGammas::Params* out |
}; |
// Determine the format of the parametric curve tag. |
- uint16_t format = read_big_endian_short(src + 8); |
+ uint16_t format = read_big_endian_u16(src + 8); |
if (format > kGABCDEF_ParaCurveType) { |
SkColorSpacePrintf("Unsupported gamma tag type %d\n", type); |
return SkGammas::Type::kNone_Type; |
@@ -597,7 +597,7 @@ static size_t load_gammas(void* memory, size_t offset, SkGammas::Type type, |
float* outTable = (float*) storage; |
const uint16_t* inTable = (const uint16_t*) (src + 12); |
for (int i = 0; i < data->fTable.fSize; i++) { |
- outTable[i] = (read_big_endian_short((const uint8_t*) &inTable[i])) / 65535.0f; |
+ outTable[i] = (read_big_endian_u16((const uint8_t*) &inTable[i])) / 65535.0f; |
} |
return sizeof(float) * data->fTable.fSize; |
@@ -614,8 +614,8 @@ static size_t load_gammas(void* memory, size_t offset, SkGammas::Type type, |
static constexpr uint32_t kTAG_AtoBType = SkSetFourByteTag('m', 'A', 'B', ' '); |
-static bool load_color_lut(SkColorLookUpTable* colorLUT, uint32_t inputChannels, |
- uint32_t outputChannels, const uint8_t* src, size_t len) { |
+static bool load_color_lut(sk_sp<SkColorLookUpTable>* colorLUT, uint32_t inputChannels, |
+ const uint8_t* src, size_t len) { |
// 16 bytes reserved for grid points, 2 for precision, 2 for padding. |
// The color LUT data follows after this header. |
static constexpr uint32_t kColorLUTHeaderSize = 20; |
@@ -625,12 +625,11 @@ static bool load_color_lut(SkColorLookUpTable* colorLUT, uint32_t inputChannels, |
} |
size_t dataLen = len - kColorLUTHeaderSize; |
- SkASSERT(3 == inputChannels && 3 == outputChannels); |
- colorLUT->fInputChannels = inputChannels; |
- colorLUT->fOutputChannels = outputChannels; |
+ SkASSERT(3 == inputChannels); |
+ uint8_t gridPoints[3]; |
uint32_t numEntries = 1; |
for (uint32_t i = 0; i < inputChannels; i++) { |
- colorLUT->fGridPoints[i] = src[i]; |
+ gridPoints[i] = src[i]; |
if (0 == src[i]) { |
SkColorSpacePrintf("Each input channel must have at least one grid point."); |
return false; |
@@ -642,7 +641,7 @@ static bool load_color_lut(SkColorLookUpTable* colorLUT, uint32_t inputChannels, |
} |
} |
- if (!safe_mul(numEntries, outputChannels, &numEntries)) { |
+ if (!safe_mul(numEntries, SkColorLookUpTable::kOutputChannels, &numEntries)) { |
SkColorSpacePrintf("Too many entries in Color LUT."); |
return false; |
} |
@@ -671,13 +670,17 @@ static bool load_color_lut(SkColorLookUpTable* colorLUT, uint32_t inputChannels, |
} |
// Movable struct colorLUT has ownership of fTable. |
- colorLUT->fTable = std::unique_ptr<float[]>(new float[numEntries]); |
+ void* memory = sk_malloc_throw(sizeof(SkColorLookUpTable) + sizeof(float) * numEntries); |
+ *colorLUT = sk_sp<SkColorLookUpTable>(new (memory) SkColorLookUpTable(inputChannels, |
+ gridPoints)); |
+ |
+ float* table = SkTAddOffset<float>(memory, sizeof(SkColorLookUpTable)); |
const uint8_t* ptr = src + kColorLUTHeaderSize; |
for (uint32_t i = 0; i < numEntries; i++, ptr += precision) { |
if (1 == precision) { |
- colorLUT->fTable[i] = ((float) ptr[i]) / 255.0f; |
+ table[i] = ((float) ptr[i]) / 255.0f; |
} else { |
- colorLUT->fTable[i] = ((float) read_big_endian_short(ptr)) / 65535.0f; |
+ table[i] = ((float) read_big_endian_u16(ptr)) / 65535.0f; |
} |
} |
@@ -693,18 +696,18 @@ static bool load_matrix(SkMatrix44* toXYZ, const uint8_t* src, size_t len) { |
// For this matrix to behave like our "to XYZ D50" matrices, it needs to be scaled. |
constexpr float scale = 65535.0 / 32768.0; |
float array[16]; |
- array[ 0] = scale * SkFixedToFloat(read_big_endian_int(src)); |
- array[ 1] = scale * SkFixedToFloat(read_big_endian_int(src + 4)); |
- array[ 2] = scale * SkFixedToFloat(read_big_endian_int(src + 8)); |
- array[ 3] = scale * SkFixedToFloat(read_big_endian_int(src + 36)); // translate R |
- array[ 4] = scale * SkFixedToFloat(read_big_endian_int(src + 12)); |
- array[ 5] = scale * SkFixedToFloat(read_big_endian_int(src + 16)); |
- array[ 6] = scale * SkFixedToFloat(read_big_endian_int(src + 20)); |
- array[ 7] = scale * SkFixedToFloat(read_big_endian_int(src + 40)); // translate G |
- array[ 8] = scale * SkFixedToFloat(read_big_endian_int(src + 24)); |
- array[ 9] = scale * SkFixedToFloat(read_big_endian_int(src + 28)); |
- array[10] = scale * SkFixedToFloat(read_big_endian_int(src + 32)); |
- array[11] = scale * SkFixedToFloat(read_big_endian_int(src + 44)); // translate B |
+ array[ 0] = scale * SkFixedToFloat(read_big_endian_i32(src)); |
+ array[ 1] = scale * SkFixedToFloat(read_big_endian_i32(src + 4)); |
+ array[ 2] = scale * SkFixedToFloat(read_big_endian_i32(src + 8)); |
+ array[ 3] = scale * SkFixedToFloat(read_big_endian_i32(src + 36)); // translate R |
+ array[ 4] = scale * SkFixedToFloat(read_big_endian_i32(src + 12)); |
+ array[ 5] = scale * SkFixedToFloat(read_big_endian_i32(src + 16)); |
+ array[ 6] = scale * SkFixedToFloat(read_big_endian_i32(src + 20)); |
+ array[ 7] = scale * SkFixedToFloat(read_big_endian_i32(src + 40)); // translate G |
+ array[ 8] = scale * SkFixedToFloat(read_big_endian_i32(src + 24)); |
+ array[ 9] = scale * SkFixedToFloat(read_big_endian_i32(src + 28)); |
+ array[10] = scale * SkFixedToFloat(read_big_endian_i32(src + 32)); |
+ array[11] = scale * SkFixedToFloat(read_big_endian_i32(src + 44)); // translate B |
array[12] = 0.0f; |
array[13] = 0.0f; |
array[14] = 0.0f; |
@@ -713,14 +716,14 @@ static bool load_matrix(SkMatrix44* toXYZ, const uint8_t* src, size_t len) { |
return true; |
} |
-static bool load_a2b0(SkColorLookUpTable* colorLUT, SkColorSpace::GammaNamed* gammaNamed, |
+static bool load_a2b0(sk_sp<SkColorLookUpTable>* colorLUT, SkColorSpace::GammaNamed* gammaNamed, |
sk_sp<SkGammas>* gammas, SkMatrix44* toXYZ, const uint8_t* src, size_t len) { |
if (len < 32) { |
SkColorSpacePrintf("A to B tag is too small (%d bytes).", len); |
return false; |
} |
- uint32_t type = read_big_endian_uint(src); |
+ uint32_t type = read_big_endian_u32(src); |
if (kTAG_AtoBType != type) { |
// FIXME (msarett): Need to support lut8Type and lut16Type. |
SkColorSpacePrintf("Unsupported A to B tag type.\n"); |
@@ -731,9 +734,11 @@ static bool load_a2b0(SkColorLookUpTable* colorLUT, SkColorSpace::GammaNamed* ga |
// must be zero. |
uint8_t inputChannels = src[8]; |
uint8_t outputChannels = src[9]; |
- if (3 != inputChannels || 3 != outputChannels) { |
+ if (3 != inputChannels || SkColorLookUpTable::kOutputChannels != outputChannels) { |
// We only handle (supposedly) RGB inputs and RGB outputs. The numbers of input |
// channels and output channels both must be 3. |
+ // TODO (msarett): |
+ // Support different numbers of input channels. Ex: CMYK (4). |
SkColorSpacePrintf("Input and output channels must equal 3 in A to B tag.\n"); |
return false; |
} |
@@ -742,8 +747,8 @@ static bool load_a2b0(SkColorLookUpTable* colorLUT, SkColorSpace::GammaNamed* ga |
// B curves (which we do not yet support), we will handle these elements in the order in |
// which they should be applied (rather than the order in which they occur in the tag). |
// If the offset is non-zero it indicates that the element is present. |
- uint32_t offsetToACurves = read_big_endian_int(src + 28); |
- uint32_t offsetToBCurves = read_big_endian_int(src + 12); |
+ uint32_t offsetToACurves = read_big_endian_i32(src + 28); |
+ uint32_t offsetToBCurves = read_big_endian_i32(src + 12); |
if ((0 != offsetToACurves) || (0 != offsetToBCurves)) { |
// FIXME (msarett): Handle A and B curves. |
// Note that the A curve is technically required in order to have a color LUT. |
@@ -752,15 +757,15 @@ static bool load_a2b0(SkColorLookUpTable* colorLUT, SkColorSpace::GammaNamed* ga |
SkColorSpacePrintf("Ignoring A and/or B curve. Output may be wrong.\n"); |
} |
- uint32_t offsetToColorLUT = read_big_endian_int(src + 24); |
+ uint32_t offsetToColorLUT = read_big_endian_i32(src + 24); |
if (0 != offsetToColorLUT && offsetToColorLUT < len) { |
- if (!load_color_lut(colorLUT, inputChannels, outputChannels, src + offsetToColorLUT, |
+ if (!load_color_lut(colorLUT, inputChannels, src + offsetToColorLUT, |
len - offsetToColorLUT)) { |
SkColorSpacePrintf("Failed to read color LUT from A to B tag.\n"); |
} |
} |
- uint32_t offsetToMCurves = read_big_endian_int(src + 20); |
+ uint32_t offsetToMCurves = read_big_endian_i32(src + 20); |
if (0 != offsetToMCurves && offsetToMCurves < len) { |
const uint8_t* rTagPtr = src + offsetToMCurves; |
size_t tagLen = len - offsetToMCurves; |
@@ -836,7 +841,7 @@ static bool load_a2b0(SkColorLookUpTable* colorLUT, SkColorSpace::GammaNamed* ga |
} |
} |
- uint32_t offsetToMatrix = read_big_endian_int(src + 16); |
+ uint32_t offsetToMatrix = read_big_endian_i32(src + 16); |
if (0 != offsetToMatrix && offsetToMatrix < len) { |
if (!load_matrix(toXYZ, src + offsetToMatrix, len - offsetToMatrix)) { |
SkColorSpacePrintf("Failed to read matrix from A to B tag.\n"); |
@@ -1035,14 +1040,13 @@ sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) { |
if (a2b0) { |
GammaNamed gammaNamed = kNonStandard_GammaNamed; |
sk_sp<SkGammas> gammas = nullptr; |
- sk_sp<SkColorLookUpTable> colorLUT = sk_make_sp<SkColorLookUpTable>(); |
+ sk_sp<SkColorLookUpTable> colorLUT = nullptr; |
SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor); |
- if (!load_a2b0(colorLUT.get(), &gammaNamed, &gammas, &toXYZ, a2b0->addr(base), |
+ if (!load_a2b0(&colorLUT, &gammaNamed, &gammas, &toXYZ, a2b0->addr(base), |
a2b0->fLength)) { |
return_null("Failed to parse A2B0 tag"); |
} |
- colorLUT = colorLUT->fTable ? colorLUT : nullptr; |
if (colorLUT || kNonStandard_GammaNamed == gammaNamed) { |
return sk_sp<SkColorSpace>(new SkColorSpace_Base(std::move(colorLUT), |
gammaNamed, std::move(gammas), |