Line data Source code
1 : /* vim: set ts=8 sw=8 noexpandtab: */
2 : #include "qcms.h"
3 : #include "qcmstypes.h"
4 :
5 : /* used as a lookup table for the output transformation.
6 : * we refcount them so we only need to have one around per output
7 : * profile, instead of duplicating them per transform */
8 : struct precache_output
9 : {
10 : int ref_count;
11 : /* We previously used a count of 65536 here but that seems like more
12 : * precision than we actually need. By reducing the size we can
13 : * improve startup performance and reduce memory usage. ColorSync on
14 : * 10.5 uses 4097 which is perhaps because they use a fixed point
15 : * representation where 1. is represented by 0x1000. */
16 : #define PRECACHE_OUTPUT_SIZE 8192
17 : #define PRECACHE_OUTPUT_MAX (PRECACHE_OUTPUT_SIZE-1)
18 : uint8_t data[PRECACHE_OUTPUT_SIZE];
19 : };
20 :
21 : #ifdef _MSC_VER
22 : #define ALIGN __declspec(align(16))
23 : #else
24 : #define ALIGN __attribute__(( aligned (16) ))
25 : #endif
26 :
27 : struct _qcms_transform {
28 : float ALIGN matrix[3][4];
29 : float *input_gamma_table_r;
30 : float *input_gamma_table_g;
31 : float *input_gamma_table_b;
32 :
33 : float *input_clut_table_r;
34 : float *input_clut_table_g;
35 : float *input_clut_table_b;
36 : uint16_t input_clut_table_length;
37 : float *r_clut;
38 : float *g_clut;
39 : float *b_clut;
40 : uint16_t grid_size;
41 : float *output_clut_table_r;
42 : float *output_clut_table_g;
43 : float *output_clut_table_b;
44 : uint16_t output_clut_table_length;
45 :
46 : float *input_gamma_table_gray;
47 :
48 : float out_gamma_r;
49 : float out_gamma_g;
50 : float out_gamma_b;
51 :
52 : float out_gamma_gray;
53 :
54 : uint16_t *output_gamma_lut_r;
55 : uint16_t *output_gamma_lut_g;
56 : uint16_t *output_gamma_lut_b;
57 :
58 : uint16_t *output_gamma_lut_gray;
59 :
60 : size_t output_gamma_lut_r_length;
61 : size_t output_gamma_lut_g_length;
62 : size_t output_gamma_lut_b_length;
63 :
64 : size_t output_gamma_lut_gray_length;
65 :
66 : struct precache_output *output_table_r;
67 : struct precache_output *output_table_g;
68 : struct precache_output *output_table_b;
69 :
70 : void (*transform_fn)(struct _qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length);
71 : };
72 :
73 : struct matrix {
74 : float m[3][3];
75 : bool invalid;
76 : };
77 :
78 : struct qcms_modular_transform;
79 :
80 : typedef void (*transform_module_fn_t)(struct qcms_modular_transform *transform, float *src, float *dest, size_t length);
81 :
82 : struct qcms_modular_transform {
83 : struct matrix matrix;
84 : float tx, ty, tz;
85 :
86 : float *input_clut_table_r;
87 : float *input_clut_table_g;
88 : float *input_clut_table_b;
89 : uint16_t input_clut_table_length;
90 : float *r_clut;
91 : float *g_clut;
92 : float *b_clut;
93 : uint16_t grid_size;
94 : float *output_clut_table_r;
95 : float *output_clut_table_g;
96 : float *output_clut_table_b;
97 : uint16_t output_clut_table_length;
98 :
99 : uint16_t *output_gamma_lut_r;
100 : uint16_t *output_gamma_lut_g;
101 : uint16_t *output_gamma_lut_b;
102 :
103 : size_t output_gamma_lut_r_length;
104 : size_t output_gamma_lut_g_length;
105 : size_t output_gamma_lut_b_length;
106 :
107 : transform_module_fn_t transform_module_fn;
108 : struct qcms_modular_transform *next_transform;
109 : };
110 :
111 : typedef int32_t s15Fixed16Number;
112 : typedef uint16_t uInt16Number;
113 : typedef uint8_t uInt8Number;
114 :
115 : struct XYZNumber {
116 : s15Fixed16Number X;
117 : s15Fixed16Number Y;
118 : s15Fixed16Number Z;
119 : };
120 :
121 : struct curveType {
122 : uint32_t type;
123 : uint32_t count;
124 : float parameter[7];
125 : uInt16Number data[];
126 : };
127 :
128 : struct lutmABType {
129 : uint8_t num_in_channels;
130 : uint8_t num_out_channels;
131 : // 16 is the upperbound, actual is 0..num_in_channels.
132 : uint8_t num_grid_points[16];
133 :
134 : s15Fixed16Number e00;
135 : s15Fixed16Number e01;
136 : s15Fixed16Number e02;
137 : s15Fixed16Number e03;
138 : s15Fixed16Number e10;
139 : s15Fixed16Number e11;
140 : s15Fixed16Number e12;
141 : s15Fixed16Number e13;
142 : s15Fixed16Number e20;
143 : s15Fixed16Number e21;
144 : s15Fixed16Number e22;
145 : s15Fixed16Number e23;
146 :
147 : // reversed elements (for mBA)
148 : bool reversed;
149 :
150 : float *clut_table;
151 : struct curveType *a_curves[10];
152 : struct curveType *b_curves[10];
153 : struct curveType *m_curves[10];
154 : float clut_table_data[];
155 : };
156 :
157 : /* should lut8Type and lut16Type be different types? */
158 : struct lutType { // used by lut8Type/lut16Type (mft2) only
159 : uint8_t num_input_channels;
160 : uint8_t num_output_channels;
161 : uint8_t num_clut_grid_points;
162 :
163 : s15Fixed16Number e00;
164 : s15Fixed16Number e01;
165 : s15Fixed16Number e02;
166 : s15Fixed16Number e10;
167 : s15Fixed16Number e11;
168 : s15Fixed16Number e12;
169 : s15Fixed16Number e20;
170 : s15Fixed16Number e21;
171 : s15Fixed16Number e22;
172 :
173 : uint16_t num_input_table_entries;
174 : uint16_t num_output_table_entries;
175 :
176 : float *input_table;
177 : float *clut_table;
178 : float *output_table;
179 :
180 : float table_data[];
181 : };
182 : #if 0
183 : /* this is from an intial idea of having the struct correspond to the data in
184 : * the file. I decided that it wasn't a good idea.
185 : */
186 : struct tag_value {
187 : uint32_t type;
188 : union {
189 : struct {
190 : uint32_t reserved;
191 : struct {
192 : s15Fixed16Number X;
193 : s15Fixed16Number Y;
194 : s15Fixed16Number Z;
195 : } XYZNumber;
196 : } XYZType;
197 : };
198 : }; // I guess we need to pack this?
199 : #endif
200 :
201 : #define RGB_SIGNATURE 0x52474220
202 : #define GRAY_SIGNATURE 0x47524159
203 : #define XYZ_SIGNATURE 0x58595A20
204 : #define LAB_SIGNATURE 0x4C616220
205 :
206 : struct _qcms_profile {
207 : uint32_t class;
208 : uint32_t color_space;
209 : uint32_t pcs;
210 : qcms_intent rendering_intent;
211 : struct XYZNumber redColorant;
212 : struct XYZNumber blueColorant;
213 : struct XYZNumber greenColorant;
214 : struct curveType *redTRC;
215 : struct curveType *blueTRC;
216 : struct curveType *greenTRC;
217 : struct curveType *grayTRC;
218 : struct lutType *A2B0;
219 : struct lutType *B2A0;
220 : struct lutmABType *mAB;
221 : struct lutmABType *mBA;
222 : struct matrix chromaticAdaption;
223 :
224 : struct precache_output *output_table_r;
225 : struct precache_output *output_table_g;
226 : struct precache_output *output_table_b;
227 : };
228 :
229 : #ifdef _MSC_VER
230 : #define inline _inline
231 : #endif
232 :
233 : /* produces the nearest float to 'a' with a maximum error
234 : * of 1/1024 which happens for large values like 0x40000040 */
235 144 : static inline float s15Fixed16Number_to_float(s15Fixed16Number a)
236 : {
237 144 : return ((int32_t)a)/65536.f;
238 : }
239 :
240 99 : static inline s15Fixed16Number double_to_s15Fixed16Number(double v)
241 : {
242 99 : return (int32_t)(v*65536);
243 : }
244 :
245 0 : static inline float uInt8Number_to_float(uInt8Number a)
246 : {
247 0 : return ((int32_t)a)/255.f;
248 : }
249 :
250 0 : static inline float uInt16Number_to_float(uInt16Number a)
251 : {
252 0 : return ((int32_t)a)/65535.f;
253 : }
254 :
255 :
256 : void precache_release(struct precache_output *p);
257 : qcms_bool set_rgb_colorants(qcms_profile *profile, qcms_CIE_xyY white_point, qcms_CIE_xyYTRIPLE primaries);
258 : qcms_bool get_rgb_colorants(struct matrix *colorants, qcms_CIE_xyY white_point, qcms_CIE_xyYTRIPLE primaries);
259 :
260 : void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform,
261 : unsigned char *src,
262 : unsigned char *dest,
263 : size_t length);
264 : void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform,
265 : unsigned char *src,
266 : unsigned char *dest,
267 : size_t length);
268 : void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform,
269 : unsigned char *src,
270 : unsigned char *dest,
271 : size_t length);
272 : void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform,
273 : unsigned char *src,
274 : unsigned char *dest,
275 : size_t length);
276 :
277 : void qcms_transform_data_rgb_out_lut_altivec(qcms_transform *transform,
278 : unsigned char *src,
279 : unsigned char *dest,
280 : size_t length);
281 : void qcms_transform_data_rgba_out_lut_altivec(qcms_transform *transform,
282 : unsigned char *src,
283 : unsigned char *dest,
284 : size_t length);
285 :
286 : extern qcms_bool qcms_supports_iccv4;
287 :
288 : #ifdef _MSC_VER
289 :
290 : long __cdecl _InterlockedIncrement(long volatile *);
291 : long __cdecl _InterlockedDecrement(long volatile *);
292 : #pragma intrinsic(_InterlockedIncrement)
293 : #pragma intrinsic(_InterlockedDecrement)
294 :
295 : #define qcms_atomic_increment(x) _InterlockedIncrement((long volatile *)&x)
296 : #define qcms_atomic_decrement(x) _InterlockedDecrement((long volatile*)&x)
297 :
298 : #else
299 :
300 : #define qcms_atomic_increment(x) __sync_add_and_fetch(&x, 1)
301 : #define qcms_atomic_decrement(x) __sync_sub_and_fetch(&x, 1)
302 :
303 : #endif
304 :
305 :
306 : #ifdef NATIVE_OUTPUT
307 : # define RGB_OUTPUT_COMPONENTS 4
308 : # define RGBA_OUTPUT_COMPONENTS 4
309 : # ifdef IS_LITTLE_ENDIAN
310 : # define OUTPUT_A_INDEX 3
311 : # define OUTPUT_R_INDEX 2
312 : # define OUTPUT_G_INDEX 1
313 : # define OUTPUT_B_INDEX 0
314 : # else
315 : # define OUTPUT_A_INDEX 0
316 : # define OUTPUT_R_INDEX 1
317 : # define OUTPUT_G_INDEX 2
318 : # define OUTPUT_B_INDEX 3
319 : # endif
320 : #else
321 : # define RGB_OUTPUT_COMPONENTS 3
322 : # define RGBA_OUTPUT_COMPONENTS 4
323 : # define OUTPUT_R_INDEX 0
324 : # define OUTPUT_G_INDEX 1
325 : # define OUTPUT_B_INDEX 2
326 : # define OUTPUT_A_INDEX 3
327 : #endif
|