| /* |
| * Copyright 2016 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SkColorSpaceXformPriv_DEFINED |
| #define SkColorSpaceXformPriv_DEFINED |
| |
| #include "SkColorSpaceXform.h" |
| #include "SkHalf.h" |
| #include "SkSRGB.h" |
| |
| #define SkCSXformPrintfDefined 0 |
| #define SkCSXformPrintf(...) |
| |
| // Interpolating lookup in a variably sized table. |
| static inline float interp_lut(float input, const float* table, int tableSize) { |
| float index = input * (tableSize - 1); |
| float diff = index - sk_float_floor2int(index); |
| return table[(int) sk_float_floor2int(index)] * (1.0f - diff) + |
| table[(int) sk_float_ceil2int(index)] * diff; |
| } |
| |
| // Expand range from 0-1 to 0-255, then convert. |
| static inline uint8_t clamp_normalized_float_to_byte(float v) { |
| // The ordering of the logic is a little strange here in order |
| // to make sure we convert NaNs to 0. |
| v = v * 255.0f; |
| if (v >= 254.5f) { |
| return 255; |
| } else if (v >= 0.5f) { |
| return (uint8_t) (v + 0.5f); |
| } else { |
| return 0; |
| } |
| } |
| |
| static inline float clamp_0_1(float v) { |
| // The ordering of the logic is a little strange here in order |
| // to make sure we convert NaNs to 0. |
| if (v >= 1.0f) { |
| return 1.0f; |
| } else if (v >= 0.0f) { |
| return v; |
| } else { |
| return 0.0f; |
| } |
| } |
| |
| /** |
| * Invert table lookup. Ex: what indices corresponds to the input values? |
| * This will have strange results when the table is not increasing. |
| * But any sane gamma function will be increasing. |
| * @param outTableFloat Destination table for float (0-1) results. Can be nullptr if not wanted. |
| * @param outTableByte Destination table for byte (0-255) results. Can be nullptr if not wanted. |
| * @param outTableSize Number of elements in |outTableFloat| or |outTableBytes| |
| * @param inTable The source table to invert |
| * @param inTableSize The number of elements in |inTable| |
| */ |
| static inline void invert_table_gamma(float* outTableFloat, uint8_t* outTableByte, |
| int outTableSize, const float* inTable, int inTableSize) { |
| // should never have a gamma table this small anyway, 0/1 are either not allowed |
| // or imply a non-table gamma such as linear/exponential |
| SkASSERT(inTableSize >= 2); |
| int inIndex = 1; |
| for (int outIndex = 0; outIndex < outTableSize; ++outIndex) { |
| const float input = outIndex / (outTableSize - 1.0f); |
| while (inIndex < inTableSize - 1 && inTable[inIndex] < input) { |
| ++inIndex; |
| } |
| const float diff = input - inTable[inIndex - 1]; |
| const float distance = inTable[inIndex] - inTable[inIndex - 1]; |
| const float normalizedIndex = (inIndex - 1) + diff / distance; |
| const float index = normalizedIndex / (inTableSize - 1); |
| if (outTableByte) { |
| outTableByte[outIndex] = clamp_normalized_float_to_byte(index); |
| } |
| if (outTableFloat) { |
| outTableFloat[outIndex] = clamp_0_1(index); |
| } |
| } |
| } |
| |
| static inline SkColorSpaceXform::ColorFormat select_xform_format(SkColorType colorType) { |
| switch (colorType) { |
| case kRGBA_8888_SkColorType: |
| return SkColorSpaceXform::kRGBA_8888_ColorFormat; |
| case kBGRA_8888_SkColorType: |
| return SkColorSpaceXform::kBGRA_8888_ColorFormat; |
| case kRGBA_F16_SkColorType: |
| return SkColorSpaceXform::kRGBA_F16_ColorFormat; |
| case kRGB_565_SkColorType: |
| return SkColorSpaceXform::kBGR_565_ColorFormat; |
| default: |
| SkASSERT(false); |
| return SkColorSpaceXform::kRGBA_8888_ColorFormat; |
| } |
| } |
| |
| #endif |