/src/ghostpdl/base/gximdecode.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2014-2021 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., 1305 Grant Avenue - Suite 200, Novato, |
13 | | CA 94945, U.S.A., +1(415)492-9861, for further information. |
14 | | */ |
15 | | |
16 | | /* Methods for decoding and unpacking image data. Used for color |
17 | | monitoring in clist and for creating TIFF files for xpswrite device */ |
18 | | |
19 | | #include "gximdecode.h" |
20 | | #include "string_.h" |
21 | | |
22 | | /* We need to have the unpacking proc so that we can monitor the data for color |
23 | | or decode during xpswrite */ |
24 | | void |
25 | | get_unpack_proc(gx_image_enum_common_t *pie, image_decode_t *imd, |
26 | 1.27k | gs_image_format_t format, const float *decode) { |
27 | | |
28 | 1.27k | static sample_unpack_proc_t procs[2][6] = { |
29 | 1.27k | { sample_unpack_1, sample_unpack_2, |
30 | 1.27k | sample_unpack_4, sample_unpack_8, |
31 | 1.27k | sample_unpack_12, sample_unpackicc_16 |
32 | 1.27k | }, |
33 | 1.27k | { sample_unpack_1_interleaved, sample_unpack_2_interleaved, |
34 | 1.27k | sample_unpack_4_interleaved, sample_unpack_8_interleaved, |
35 | 1.27k | sample_unpack_12, sample_unpackicc_16 |
36 | 1.27k | } }; |
37 | 1.27k | int num_planes = pie->num_planes; |
38 | 1.27k | bool interleaved = (num_planes == 1 && pie->plane_depths[0] != imd->bps); |
39 | 1.27k | int i; |
40 | 1.27k | int index_bps = (imd->bps < 8 ? imd->bps >> 1 : (imd->bps >> 2) + 1); |
41 | 1.27k | int log2_xbytes = (imd->bps <= 8 ? 0 : arch_log2_sizeof_frac); |
42 | | |
43 | 1.27k | switch (format) { |
44 | 1.27k | case gs_image_format_chunky: |
45 | 1.27k | imd->spread = 1 << log2_xbytes; |
46 | 1.27k | break; |
47 | 0 | case gs_image_format_component_planar: |
48 | 0 | imd->spread = (imd->spp) << log2_xbytes; |
49 | 0 | break; |
50 | 0 | case gs_image_format_bit_planar: |
51 | 0 | imd->spread = (imd->spp) << log2_xbytes; |
52 | 0 | break; |
53 | 0 | default: |
54 | 0 | imd->spread = 0; |
55 | 1.27k | } |
56 | | |
57 | 1.27k | if (interleaved) { |
58 | 882 | int num_components = pie->plane_depths[0] / imd->bps; |
59 | | |
60 | 2.76k | for (i = 1; i < num_components; i++) { |
61 | 1.88k | if (decode[0] != decode[i * 2 + 0] || |
62 | 1.88k | decode[1] != decode[i * 2 + 1]) |
63 | 0 | break; |
64 | 1.88k | } |
65 | 882 | if (i == num_components) |
66 | 882 | interleaved = false; /* Use single table. */ |
67 | 882 | } |
68 | 1.27k | imd->unpack = procs[interleaved][index_bps]; |
69 | 1.27k | } |
70 | | |
71 | | /* We also need the mapping method for the unpacking proc */ |
72 | | void |
73 | | get_map(image_decode_t *imd, gs_image_format_t format, const float *decode) |
74 | 1.27k | { |
75 | 1.27k | int ci = 0; |
76 | 1.27k | int decode_type; |
77 | 1.27k | int bps = imd->bps; |
78 | 1.27k | int spp = imd->spp; |
79 | 1.27k | static const float default_decode[] = { |
80 | 1.27k | 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0 |
81 | 1.27k | }; |
82 | 1.27k | const float *this_decode = &decode[ci * 2]; |
83 | 1.27k | const float *map_decode; /* decoding used to */ |
84 | | /* construct the expansion map */ |
85 | 1.27k | const float *real_decode; /* decoding for expanded samples */ |
86 | | |
87 | 1.27k | decode_type = 3; /* 0=custom, 1=identity, 2=inverted, 3=impossible */ |
88 | 3.43k | for (ci = 0; ci < spp; ci += 2) { |
89 | 2.15k | decode_type &= (decode[ci] == 0. && decode[ci + 1] == 1.) | |
90 | 2.15k | (decode[ci] == 1. && decode[ci + 1] == 0.) << 1; |
91 | 2.15k | } |
92 | | |
93 | | /* Initialize the maps from samples to intensities. */ |
94 | 4.43k | for (ci = 0; ci < spp; ci++) { |
95 | 3.16k | sample_map *pmap = &imd->map[ci]; |
96 | | |
97 | 3.16k | if (bps > 8) |
98 | 0 | imd->applymap = applymap16; |
99 | 3.16k | else |
100 | 3.16k | imd->applymap = applymap8; |
101 | | |
102 | | /* If the decoding is [0 1] or [1 0], we can fold it */ |
103 | | /* into the expansion of the sample values; */ |
104 | | /* otherwise, we have to use the floating point method. */ |
105 | | |
106 | 3.16k | this_decode = &decode[ci * 2]; |
107 | | |
108 | 3.16k | map_decode = real_decode = this_decode; |
109 | 3.16k | if (!(decode_type & 1)) { |
110 | 10 | if ((decode_type & 2) && bps <= 8) { |
111 | 8 | real_decode = default_decode; |
112 | 8 | } |
113 | 2 | else { |
114 | 2 | map_decode = default_decode; |
115 | 2 | } |
116 | 10 | } |
117 | 3.16k | if (bps > 2 || format != gs_image_format_chunky) { |
118 | 3.09k | if (bps <= 8) |
119 | 3.09k | image_init_map(&pmap->table.lookup8[0], 1 << bps, |
120 | 3.09k | map_decode); |
121 | 3.09k | } |
122 | 66 | else { /* The map index encompasses more than one pixel. */ |
123 | 66 | byte map[4]; |
124 | 66 | register int i; |
125 | | |
126 | 66 | image_init_map(&map[0], 1 << bps, map_decode); |
127 | 66 | switch (bps) { |
128 | 65 | case 1: |
129 | 65 | { |
130 | 65 | register bits32 *p = &pmap->table.lookup4x1to32[0]; |
131 | | |
132 | 65 | if (map[0] == 0 && map[1] == 0xff) |
133 | 63 | memcpy((byte *)p, lookup4x1to32_identity, 16 * 4); |
134 | 2 | else if (map[0] == 0xff && map[1] == 0) |
135 | 2 | memcpy((byte *)p, lookup4x1to32_inverted, 16 * 4); |
136 | 0 | else |
137 | 0 | for (i = 0; i < 16; i++, p++) |
138 | 0 | ((byte *)p)[0] = map[i >> 3], |
139 | 0 | ((byte *)p)[1] = map[(i >> 2) & 1], |
140 | 0 | ((byte *)p)[2] = map[(i >> 1) & 1], |
141 | 0 | ((byte *)p)[3] = map[i & 1]; |
142 | 65 | } |
143 | 65 | break; |
144 | 1 | case 2: |
145 | 1 | { |
146 | 1 | register bits16 *p = &pmap->table.lookup2x2to16[0]; |
147 | | |
148 | 17 | for (i = 0; i < 16; i++, p++) |
149 | 16 | ((byte *)p)[0] = map[i >> 2], |
150 | 16 | ((byte *)p)[1] = map[i & 3]; |
151 | 1 | } |
152 | 1 | break; |
153 | 66 | } |
154 | 66 | } |
155 | 3.16k | pmap->decode_base /* = decode_lookup[0] */ = real_decode[0]; |
156 | 3.16k | pmap->decode_factor = |
157 | 3.16k | (real_decode[1] - real_decode[0]) / |
158 | 3.16k | (bps <= 8 ? 255.0 : (float)frac_1); |
159 | 3.16k | pmap->decode_max /* = decode_lookup[15] */ = real_decode[1]; |
160 | 3.16k | if (decode_type) { |
161 | 3.15k | pmap->decoding = sd_none; |
162 | 3.15k | pmap->inverted = map_decode[0] != 0; |
163 | 3.15k | } |
164 | 2 | else if (bps <= 4) { |
165 | 0 | int step = 15 / ((1 << bps) - 1); |
166 | 0 | int i; |
167 | |
|
168 | 0 | pmap->decoding = sd_lookup; |
169 | 0 | for (i = 15 - step; i > 0; i -= step) |
170 | 0 | pmap->decode_lookup[i] = pmap->decode_base + |
171 | 0 | i * (255.0 / 15) * pmap->decode_factor; |
172 | 0 | } |
173 | 2 | else |
174 | 2 | pmap->decoding = sd_compute; |
175 | 3.16k | } |
176 | 1.27k | } |
177 | | |
178 | | /* We only provide 8 or 16 bit output with the application of the mapping */ |
179 | | void applymap8(sample_map map[], const void *psrc_in, int spp, void *pdes, |
180 | | void *bufend) |
181 | 877k | { |
182 | 877k | byte* psrc = (byte*)psrc_in; |
183 | 877k | byte *curr_pos = (byte*) pdes; |
184 | 877k | int k; |
185 | 877k | float temp; |
186 | | |
187 | 1.33G | while (curr_pos < (byte*) bufend) { |
188 | 5.21G | for (k = 0; k < spp; k++) { |
189 | 3.88G | switch (map[k].decoding) { |
190 | 3.88G | case sd_none: |
191 | 3.88G | *curr_pos = *psrc; |
192 | 3.88G | break; |
193 | 0 | case sd_lookup: |
194 | 0 | temp = map[k].decode_lookup[(*psrc) >> 4] * 255; |
195 | 0 | if (temp > 255) temp = 255; |
196 | 0 | if (temp < 0) temp = 0; |
197 | 0 | *curr_pos = (byte)temp; |
198 | 0 | break; |
199 | 3.12k | case sd_compute: |
200 | 3.12k | temp = map[k].decode_base + |
201 | 3.12k | *(psrc) * map[k].decode_factor; |
202 | 3.12k | temp *= 255; |
203 | 3.12k | if (temp > 255) temp = 255; |
204 | 3.12k | if (temp < 0) temp = 0; |
205 | 3.12k | *curr_pos = (byte)temp; |
206 | 3.12k | default: |
207 | 3.12k | break; |
208 | 3.88G | } |
209 | 3.88G | curr_pos++; |
210 | 3.88G | psrc++; |
211 | 3.88G | } |
212 | 1.33G | } |
213 | 877k | } |
214 | | |
215 | | void applymap16(sample_map map[], const void *psrc_in, int spp, void *pdes, |
216 | | void *bufend) |
217 | 0 | { |
218 | 0 | unsigned short *curr_pos = (unsigned short*)pdes; |
219 | 0 | unsigned short *psrc = (unsigned short*)psrc_in; |
220 | 0 | int k; |
221 | 0 | float temp; |
222 | |
|
223 | 0 | while (curr_pos < (unsigned short*) bufend) { |
224 | 0 | for (k = 0; k < spp; k++) { |
225 | 0 | switch (map[k].decoding) { |
226 | 0 | case sd_none: |
227 | 0 | *curr_pos = *psrc; |
228 | 0 | break; |
229 | 0 | case sd_lookup: |
230 | 0 | temp = map[k].decode_lookup[*(psrc) >> 4] * 65535.0; |
231 | 0 | if (temp > 65535) temp = 65535; |
232 | 0 | if (temp < 0) temp = 0; |
233 | 0 | *curr_pos = (unsigned short)temp; |
234 | 0 | break; |
235 | 0 | case sd_compute: |
236 | 0 | temp = map[k].decode_base + |
237 | 0 | *psrc * map[k].decode_factor; |
238 | 0 | temp *= 65535; |
239 | 0 | if (temp > 65535) temp = 65535; |
240 | 0 | if (temp < 0) temp = 0; |
241 | 0 | *curr_pos = (unsigned short)temp; |
242 | 0 | default: |
243 | 0 | break; |
244 | 0 | } |
245 | 0 | curr_pos++; |
246 | 0 | psrc++; |
247 | 0 | } |
248 | 0 | } |
249 | 0 | } |