/src/ghostpdl/base/gxctable.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2023 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* Color table lookup and interpolation */ |
18 | | #include "gx.h" |
19 | | #include "gxfixed.h" |
20 | | #include "gxfrac.h" |
21 | | #include "gxctable.h" |
22 | | |
23 | | /* See gxctable.h for the API and structure definitions. */ |
24 | | |
25 | | /* |
26 | | * Define an implementation that simply picks the nearest value without |
27 | | * any interpolation. |
28 | | */ |
29 | | void |
30 | | gx_color_interpolate_nearest(const fixed * pi, |
31 | | const gx_color_lookup_table * pclt, frac * pv) |
32 | 0 | { |
33 | 0 | const int *pdim = pclt->dims; |
34 | 0 | int m = pclt->m; |
35 | 0 | const gs_const_string *table = pclt->table; |
36 | |
|
37 | 0 | if (pclt->n > 3) { |
38 | 0 | table += fixed2int_var_rounded(pi[0]) * pdim[1]; |
39 | 0 | ++pi, ++pdim; |
40 | 0 | } { |
41 | 0 | int ic = fixed2int_var_rounded(pi[2]); |
42 | 0 | int ib = fixed2int_var_rounded(pi[1]); |
43 | 0 | int ia = fixed2int_var_rounded(pi[0]); |
44 | 0 | const byte *p = pclt->table[ia].data + (ib * pdim[2] + ic) * m; |
45 | 0 | int j; |
46 | |
|
47 | 0 | for (j = 0; j < m; ++j, ++p) |
48 | 0 | pv[j] = byte2frac(*p); |
49 | 0 | } |
50 | 0 | } |
51 | | |
52 | | /* |
53 | | * Define an implementation that uses trilinear interpolation. |
54 | | */ |
55 | | static void |
56 | | interpolate_accum(const fixed * pi, const gx_color_lookup_table * pclt, |
57 | | frac * pv, fixed factor) |
58 | 0 | { |
59 | 0 | const int *pdim = pclt->dims; |
60 | 0 | int m = pclt->m; |
61 | |
|
62 | 0 | if (pclt->n > 3) { |
63 | | /* Do two 3-D interpolations, interpolating between them. */ |
64 | 0 | gx_color_lookup_table clt3; |
65 | 0 | int ix = fixed2int_var(pi[0]); |
66 | 0 | fixed fx = fixed_fraction(pi[0]); |
67 | |
|
68 | 0 | clt3.n = 3; |
69 | 0 | clt3.dims[0] = pdim[1]; /* needed only for range checking */ |
70 | 0 | clt3.dims[1] = pdim[2]; |
71 | 0 | clt3.dims[2] = pdim[3]; |
72 | 0 | clt3.m = m; |
73 | 0 | clt3.table = pclt->table + ix * pdim[1]; |
74 | 0 | interpolate_accum(pi + 1, &clt3, pv, fixed_1); |
75 | 0 | if (ix == pdim[0] - 1) |
76 | 0 | return; |
77 | 0 | clt3.table += pdim[1]; |
78 | 0 | interpolate_accum(pi + 1, &clt3, pv, fx); |
79 | 0 | } else { |
80 | 0 | int ic = fixed2int_var(pi[2]); |
81 | 0 | fixed fc = fixed_fraction(pi[2]); |
82 | 0 | uint dc1 = (ic == pdim[2] - 1 ? 0 : m); |
83 | 0 | int ib = fixed2int_var(pi[1]); |
84 | 0 | fixed fb = fixed_fraction(pi[1]); |
85 | 0 | uint db1 = (ib == pdim[1] - 1 ? 0 : pdim[2] * m); |
86 | 0 | uint dbc = (ib * pdim[2] + ic) * m; |
87 | 0 | uint dbc1 = db1 + dc1; |
88 | 0 | int ia = fixed2int_var(pi[0]); |
89 | 0 | fixed fa = fixed_fraction(pi[0]); |
90 | 0 | const byte *pa0 = pclt->table[ia].data + dbc; |
91 | 0 | const byte *pa1 = |
92 | 0 | (ia == pdim[0] - 1 ? pa0 : pclt->table[ia + 1].data + dbc); |
93 | 0 | int j; |
94 | | |
95 | | /* The values to be interpolated are */ |
96 | | /* pa{0,1}[{0,db1,dc1,dbc1}]. */ |
97 | 0 | for (j = 0; j < m; ++j, ++pa0, ++pa1) { |
98 | 0 | frac v000 = byte2frac(pa0[0]); |
99 | 0 | frac v001 = byte2frac(pa0[dc1]); |
100 | 0 | frac v010 = byte2frac(pa0[db1]); |
101 | 0 | frac v011 = byte2frac(pa0[dbc1]); |
102 | 0 | frac v100 = byte2frac(pa1[0]); |
103 | 0 | frac v101 = byte2frac(pa1[dc1]); |
104 | 0 | frac v110 = byte2frac(pa1[db1]); |
105 | 0 | frac v111 = byte2frac(pa1[dbc1]); |
106 | 0 | frac rv; |
107 | |
|
108 | 0 | frac v00 = v000 + |
109 | 0 | (frac) arith_rshift((long)fc * (v001 - v000), |
110 | 0 | _fixed_shift); |
111 | 0 | frac v01 = v010 + |
112 | 0 | (frac) arith_rshift((long)fc * (v011 - v010), |
113 | 0 | _fixed_shift); |
114 | 0 | frac v10 = v100 + |
115 | 0 | (frac) arith_rshift((long)fc * (v101 - v100), |
116 | 0 | _fixed_shift); |
117 | 0 | frac v11 = v110 + |
118 | 0 | (frac) arith_rshift((long)fc * (v111 - v110), |
119 | 0 | _fixed_shift); |
120 | |
|
121 | 0 | frac v0 = v00 + |
122 | 0 | (frac) arith_rshift((long)fb * (v01 - v00), |
123 | 0 | _fixed_shift); |
124 | 0 | frac v1 = v10 + |
125 | 0 | (frac) arith_rshift((long)fb * (v11 - v10), |
126 | 0 | _fixed_shift); |
127 | |
|
128 | 0 | rv = v0 + |
129 | 0 | (frac) arith_rshift((long)fa * (v1 - v0), |
130 | 0 | _fixed_shift); |
131 | 0 | if (factor == fixed_1) |
132 | 0 | pv[j] = rv; |
133 | 0 | else |
134 | 0 | pv[j] += (frac) arith_rshift((long)factor * (rv - pv[j]), |
135 | 0 | _fixed_shift); |
136 | 0 | } |
137 | 0 | } |
138 | 0 | } |
139 | | void |
140 | | gx_color_interpolate_linear(const fixed * pi, |
141 | | const gx_color_lookup_table * pclt, frac * pv) |
142 | 0 | { |
143 | 0 | interpolate_accum(pi, pclt, pv, fixed_1); |
144 | 0 | } |