aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/skcms/skcms_internal.h
blob: 97fc8dea8dc92376749d0c9351d357a22b4b4b51 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#pragma once

// skcms_internal.h contains APIs shared by skcms' internals and its test tools.
// Please don't use this header from outside the skcms repo.

#include "skcms.h"
#include <stdbool.h>
#include <stdint.h>

#if defined(__cpluscplus)
extern "C" {
#endif

// ~~~~ General Helper Macros ~~~~

    // sizeof(x) will return size_t, which is 32-bit on some machines and 64-bit on others.
    // We have better testing on 64-bit machines, so force 32-bit machines to behave like 64-bit.
    #define SAFE_SIZEOF(x) ((uint64_t)sizeof(x))

    // Please do not use sizeof() directly, and size_t only when required.
    // (We have no way of enforcing these requests...)

    #define ARRAY_COUNT(arr) (int)(SAFE_SIZEOF((arr)) / SAFE_SIZEOF(*(arr)))


// ~~~~ skcms_Curve ~~~~

    // Evaluate an skcms_Curve at x.
    float skcms_eval_curve(const skcms_Curve*, float x);
    float skcms_MaxRoundtripError(const skcms_Curve*, const skcms_TransferFunction*);


// ~~~~ skcms_TransferFunction ~~~~
    bool skcms_TransferFunction_isValid(const skcms_TransferFunction*);

    float skcms_TransferFunction_eval(const skcms_TransferFunction*, float);

    bool skcms_TransferFunction_invert(const skcms_TransferFunction*, skcms_TransferFunction*);

    // Fit c,d,f parameters of an skcms_TransferFunction to the first 2 ≤ L ≤ N
    // evenly-spaced points on an skcms_Curve within a given tolerance, returning L.
    int skcms_fit_linear(const skcms_Curve*, int N, float tol, float* c, float* d, float* f);


// ~~~~ skcms_ICCProfile ~~~~

    bool skcms_GetCHAD(const skcms_ICCProfile* profile, skcms_Matrix3x3* m);

    // 252 of a random shuffle of all possible bytes.
    // 252 is evenly divisible by 3 and 4.  Only 192, 10, 241, and 43 are missing.
    // Used for ICC profile equivalence testing.
    extern const uint8_t skcms_252_random_bytes[252];


// ~~~~ Linear Algebra ~~~~

    typedef struct { float vals[3]; } skcms_Vector3;

    // It is _not_ safe to alias the pointers to invert in-place.
    bool skcms_Matrix3x3_invert(const skcms_Matrix3x3*, skcms_Matrix3x3*);
    skcms_Matrix3x3 skcms_Matrix3x3_concat(const skcms_Matrix3x3* A, const skcms_Matrix3x3* B);

    skcms_Vector3 skcms_MV_mul(const skcms_Matrix3x3*, const skcms_Vector3*);


// ~~~~ Portable Math ~~~~

    static const union {
        uint32_t bits;
        float    f;
    } inf_ = { 0x7f800000 };

    #define INFINITY_ inf_.f

    static inline float floorf_(float x) {
        float roundtrip = (float)((int)x);
        return roundtrip > x ? roundtrip - 1 : roundtrip;
    }

    static inline float fmaxf_(float x, float y) { return x > y ? x : y; }
    static inline float fminf_(float x, float y) { return x < y ? x : y; }
    static inline float fabsf_(float x) { return x < 0 ? -x : x; }

    float log2f_(float);
    float exp2f_(float);
    float powf_(float, float);

    static inline bool isfinitef_(float x) { return 0 == x*0; }


// ~~~~ Transform ~~~~

    #define FOREACH_Op(M) \
        M(noop)           \
        M(load_a8)        \
        M(load_g8)        \
        M(load_4444)      \
        M(load_565)       \
        M(load_888)       \
        M(load_8888)      \
        M(load_1010102)   \
        M(load_161616)    \
        M(load_16161616)  \
        M(load_hhh)       \
        M(load_hhhh)      \
        M(load_fff)       \
        M(load_ffff)      \
        M(swap_rb)        \
        M(clamp)          \
        M(invert)         \
        M(force_opaque)   \
        M(premul)         \
        M(unpremul)       \
        M(matrix_3x3)     \
        M(matrix_3x4)     \
        M(lab_to_xyz)     \
        M(tf_r)           \
        M(tf_g)           \
        M(tf_b)           \
        M(tf_a)           \
        M(table_8_r)      \
        M(table_8_g)      \
        M(table_8_b)      \
        M(table_8_a)      \
        M(table_16_r)     \
        M(table_16_g)     \
        M(table_16_b)     \
        M(table_16_a)     \
        M(clut_3D_8)      \
        M(clut_3D_16)     \
        M(clut_4D_8)      \
        M(clut_4D_16)     \
        M(store_a8)       \
        M(store_g8)       \
        M(store_4444)     \
        M(store_565)      \
        M(store_888)      \
        M(store_8888)     \
        M(store_1010102)  \
        M(store_161616)   \
        M(store_16161616) \
        M(store_hhh)      \
        M(store_hhhh)     \
        M(store_fff)      \
        M(store_ffff)

    typedef enum {
        #define M(op) Op_##op,
        FOREACH_Op(M)
        #undef M
    } Op;

#if defined(__cpluscplus)
}  // extern "C"
#endif