1 /*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #ifndef SkColorSpaceXformPriv_DEFINED
9 #define SkColorSpaceXformPriv_DEFINED
10
11 #include "SkColorSpaceXform.h"
12 #include "SkHalf.h"
13 #include "SkSRGB.h"
14
15 #define SkCSXformPrintfDefined 0
16 #define SkCSXformPrintf(...)
17
18 // Interpolating lookup in a variably sized table.
interp_lut(float input,const float * table,int tableSize)19 static inline float interp_lut(float input, const float* table, int tableSize) {
20 float index = input * (tableSize - 1);
21 float diff = index - sk_float_floor2int(index);
22 return table[(int) sk_float_floor2int(index)] * (1.0f - diff) +
23 table[(int) sk_float_ceil2int(index)] * diff;
24 }
25
26 // Expand range from 0-1 to 0-255, then convert.
clamp_normalized_float_to_byte(float v)27 static inline uint8_t clamp_normalized_float_to_byte(float v) {
28 // The ordering of the logic is a little strange here in order
29 // to make sure we convert NaNs to 0.
30 v = v * 255.0f;
31 if (v >= 254.5f) {
32 return 255;
33 } else if (v >= 0.5f) {
34 return (uint8_t) (v + 0.5f);
35 } else {
36 return 0;
37 }
38 }
39
clamp_0_1(float v)40 static inline float clamp_0_1(float v) {
41 // The ordering of the logic is a little strange here in order
42 // to make sure we convert NaNs to 0.
43 if (v >= 1.0f) {
44 return 1.0f;
45 } else if (v >= 0.0f) {
46 return v;
47 } else {
48 return 0.0f;
49 }
50 }
51
52 /**
53 * Invert table lookup. Ex: what indices corresponds to the input values?
54 * This will have strange results when the table is not increasing.
55 * But any sane gamma function will be increasing.
56 * @param outTableFloat Destination table for float (0-1) results. Can be nullptr if not wanted.
57 * @param outTableByte Destination table for byte (0-255) results. Can be nullptr if not wanted.
58 * @param outTableSize Number of elements in |outTableFloat| or |outTableBytes|
59 * @param inTable The source table to invert
60 * @param inTableSize The number of elements in |inTable|
61 */
invert_table_gamma(float * outTableFloat,uint8_t * outTableByte,int outTableSize,const float * inTable,int inTableSize)62 static inline void invert_table_gamma(float* outTableFloat, uint8_t* outTableByte,
63 int outTableSize, const float* inTable, int inTableSize) {
64 // should never have a gamma table this small anyway, 0/1 are either not allowed
65 // or imply a non-table gamma such as linear/exponential
66 SkASSERT(inTableSize >= 2);
67 int inIndex = 1;
68 for (int outIndex = 0; outIndex < outTableSize; ++outIndex) {
69 const float input = outIndex / (outTableSize - 1.0f);
70 while (inIndex < inTableSize - 1 && inTable[inIndex] < input) {
71 ++inIndex;
72 }
73 const float diff = input - inTable[inIndex - 1];
74 const float distance = inTable[inIndex] - inTable[inIndex - 1];
75 const float normalizedIndex = (inIndex - 1) + diff / distance;
76 const float index = normalizedIndex / (inTableSize - 1);
77 if (outTableByte) {
78 outTableByte[outIndex] = clamp_normalized_float_to_byte(index);
79 }
80 if (outTableFloat) {
81 outTableFloat[outIndex] = clamp_0_1(index);
82 }
83 }
84 }
85
select_xform_format(SkColorType colorType)86 static inline SkColorSpaceXform::ColorFormat select_xform_format(SkColorType colorType) {
87 switch (colorType) {
88 case kRGBA_8888_SkColorType:
89 return SkColorSpaceXform::kRGBA_8888_ColorFormat;
90 case kBGRA_8888_SkColorType:
91 return SkColorSpaceXform::kBGRA_8888_ColorFormat;
92 case kRGBA_F16_SkColorType:
93 return SkColorSpaceXform::kRGBA_F16_ColorFormat;
94 case kRGB_565_SkColorType:
95 return SkColorSpaceXform::kBGR_565_ColorFormat;
96 default:
97 SkASSERT(false);
98 return SkColorSpaceXform::kRGBA_8888_ColorFormat;
99 }
100 }
101
102 #endif
103