]> rtime.felk.cvut.cz Git - hornmich/skoda-qr-demo.git/blob - QRScanner/mobile/jni/fitz/colorspace.c
Add MuPDF native source codes
[hornmich/skoda-qr-demo.git] / QRScanner / mobile / jni / fitz / colorspace.c
1 #include "mupdf/fitz.h"
2
3 #define SLOWCMYK
4
5 void
6 fz_free_colorspace_imp(fz_context *ctx, fz_storable *cs_)
7 {
8         fz_colorspace *cs = (fz_colorspace *)cs_;
9
10         if (cs->free_data && cs->data)
11                 cs->free_data(ctx, cs);
12         fz_free(ctx, cs);
13 }
14
15 fz_colorspace *
16 fz_new_colorspace(fz_context *ctx, char *name, int n)
17 {
18         fz_colorspace *cs = fz_malloc(ctx, sizeof(fz_colorspace));
19         FZ_INIT_STORABLE(cs, 1, fz_free_colorspace_imp);
20         cs->size = sizeof(fz_colorspace);
21         fz_strlcpy(cs->name, name, sizeof cs->name);
22         cs->n = n;
23         cs->to_rgb = NULL;
24         cs->from_rgb = NULL;
25         cs->free_data = NULL;
26         cs->data = NULL;
27         return cs;
28 }
29
30 fz_colorspace *
31 fz_keep_colorspace(fz_context *ctx, fz_colorspace *cs)
32 {
33         return (fz_colorspace *)fz_keep_storable(ctx, &cs->storable);
34 }
35
36 void
37 fz_drop_colorspace(fz_context *ctx, fz_colorspace *cs)
38 {
39         fz_drop_storable(ctx, &cs->storable);
40 }
41
42 /* Device colorspace definitions */
43
44 static void gray_to_rgb(fz_context *ctx, fz_colorspace *cs, const float *gray, float *rgb)
45 {
46         rgb[0] = gray[0];
47         rgb[1] = gray[0];
48         rgb[2] = gray[0];
49 }
50
51 static void rgb_to_gray(fz_context *ctx, fz_colorspace *cs, const float *rgb, float *gray)
52 {
53         float r = rgb[0];
54         float g = rgb[1];
55         float b = rgb[2];
56         gray[0] = r * 0.3f + g * 0.59f + b * 0.11f;
57 }
58
59 static void rgb_to_rgb(fz_context *ctx, fz_colorspace *cs, const float *rgb, float *xyz)
60 {
61         xyz[0] = rgb[0];
62         xyz[1] = rgb[1];
63         xyz[2] = rgb[2];
64 }
65
66 static void bgr_to_rgb(fz_context *ctx, fz_colorspace *cs, const float *bgr, float *rgb)
67 {
68         rgb[0] = bgr[2];
69         rgb[1] = bgr[1];
70         rgb[2] = bgr[0];
71 }
72
73 static void rgb_to_bgr(fz_context *ctx, fz_colorspace *cs, const float *rgb, float *bgr)
74 {
75         bgr[0] = rgb[2];
76         bgr[1] = rgb[1];
77         bgr[2] = rgb[0];
78 }
79
80 static void cmyk_to_rgb(fz_context *ctx, fz_colorspace *cs, const float *cmyk, float *rgb)
81 {
82 #ifdef SLOWCMYK /* from poppler */
83         float c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3];
84         float r, g, b, x;
85         float cm = c * m;
86         float c1m = m - cm;
87         float cm1 = c - cm;
88         float c1m1 = 1 - m - cm1;
89         float c1m1y = c1m1 * y;
90         float c1m1y1 = c1m1 - c1m1y;
91         float c1my = c1m * y;
92         float c1my1 = c1m - c1my;
93         float cm1y = cm1 * y;
94         float cm1y1 = cm1 - cm1y;
95         float cmy = cm * y;
96         float cmy1 = cm - cmy;
97
98         /* this is a matrix multiplication, unrolled for performance */
99         x = c1m1y1 * k;         /* 0 0 0 1 */
100         r = g = b = c1m1y1 - x; /* 0 0 0 0 */
101         r += 0.1373 * x;
102         g += 0.1216 * x;
103         b += 0.1255 * x;
104
105         x = c1m1y * k;          /* 0 0 1 1 */
106         r += 0.1098 * x;
107         g += 0.1020 * x;
108         x = c1m1y - x;          /* 0 0 1 0 */
109         r += x;
110         g += 0.9490 * x;
111
112         x = c1my1 * k;          /* 0 1 0 1 */
113         r += 0.1412 * x;
114         x = c1my1 - x;          /* 0 1 0 0 */
115         r += 0.9255 * x;
116         b += 0.5490 * x;
117
118         x = c1my * k;           /* 0 1 1 1 */
119         r += 0.1333 * x;
120         x = c1my - x;           /* 0 1 1 0 */
121         r += 0.9294 * x;
122         g += 0.1098 * x;
123         b += 0.1412 * x;
124
125         x = cm1y1 * k;          /* 1 0 0 1 */
126         g += 0.0588 * x;
127         b += 0.1412 * x;
128         x = cm1y1 - x;          /* 1 0 0 0 */
129         g += 0.6784 * x;
130         b += 0.9373 * x;
131
132         x = cm1y * k;           /* 1 0 1 1 */
133         g += 0.0745 * x;
134         x = cm1y - x;           /* 1 0 1 0 */
135         g += 0.6510 * x;
136         b += 0.3137 * x;
137
138         x = cmy1 * k;           /* 1 1 0 1 */
139         b += 0.0078 * x;
140         x = cmy1 - x;           /* 1 1 0 0 */
141         r += 0.1804 * x;
142         g += 0.1922 * x;
143         b += 0.5725 * x;
144
145         x = cmy * (1-k);        /* 1 1 1 0 */
146         r += 0.2118 * x;
147         g += 0.2119 * x;
148         b += 0.2235 * x;
149         rgb[0] = fz_clamp(r, 0, 1);
150         rgb[1] = fz_clamp(g, 0, 1);
151         rgb[2] = fz_clamp(b, 0, 1);
152 #else
153         rgb[0] = 1 - fz_min(1, cmyk[0] + cmyk[3]);
154         rgb[1] = 1 - fz_min(1, cmyk[1] + cmyk[3]);
155         rgb[2] = 1 - fz_min(1, cmyk[2] + cmyk[3]);
156 #endif
157 }
158
159 static void rgb_to_cmyk(fz_context *ctx, fz_colorspace *cs, const float *rgb, float *cmyk)
160 {
161         float c, m, y, k;
162         c = 1 - rgb[0];
163         m = 1 - rgb[1];
164         y = 1 - rgb[2];
165         k = fz_min(c, fz_min(m, y));
166         cmyk[0] = c - k;
167         cmyk[1] = m - k;
168         cmyk[2] = y - k;
169         cmyk[3] = k;
170 }
171
172 static fz_colorspace k_default_gray = { {-1, fz_free_colorspace_imp}, 0, "DeviceGray", 1, gray_to_rgb, rgb_to_gray };
173 static fz_colorspace k_default_rgb = { {-1, fz_free_colorspace_imp}, 0, "DeviceRGB", 3, rgb_to_rgb, rgb_to_rgb };
174 static fz_colorspace k_default_bgr = { {-1, fz_free_colorspace_imp}, 0, "DeviceBGR", 3, bgr_to_rgb, rgb_to_bgr };
175 static fz_colorspace k_default_cmyk = { {-1, fz_free_colorspace_imp}, 0, "DeviceCMYK", 4, cmyk_to_rgb, rgb_to_cmyk };
176
177 static fz_colorspace *fz_default_gray = &k_default_gray;
178 static fz_colorspace *fz_default_rgb = &k_default_rgb;
179 static fz_colorspace *fz_default_bgr = &k_default_bgr;
180 static fz_colorspace *fz_default_cmyk = &k_default_cmyk;
181
182 struct fz_colorspace_context_s
183 {
184         int ctx_refs;
185         fz_colorspace *gray, *rgb, *bgr, *cmyk;
186 };
187
188 void fz_new_colorspace_context(fz_context *ctx)
189 {
190         ctx->colorspace = fz_malloc_struct(ctx, fz_colorspace_context);
191         ctx->colorspace->ctx_refs = 1;
192         ctx->colorspace->gray = fz_default_gray;
193         ctx->colorspace->rgb = fz_default_rgb;
194         ctx->colorspace->bgr = fz_default_bgr;
195         ctx->colorspace->cmyk = fz_default_cmyk;
196 }
197
198 fz_colorspace_context *
199 fz_keep_colorspace_context(fz_context *ctx)
200 {
201         if (!ctx || !ctx->colorspace)
202                 return NULL;
203         fz_lock(ctx, FZ_LOCK_ALLOC);
204         ctx->colorspace->ctx_refs++;
205         fz_unlock(ctx, FZ_LOCK_ALLOC);
206         return ctx->colorspace;
207 }
208
209 void fz_drop_colorspace_context(fz_context *ctx)
210 {
211         int drop;
212         if (!ctx || !ctx->colorspace)
213                 return;
214         fz_lock(ctx, FZ_LOCK_ALLOC);
215         drop = --ctx->colorspace->ctx_refs;
216         fz_unlock(ctx, FZ_LOCK_ALLOC);
217         if (drop == 0)
218                 fz_free(ctx, ctx->colorspace);
219 }
220
221 fz_colorspace *
222 fz_device_gray(fz_context *ctx)
223 {
224         return ctx->colorspace->gray;
225 }
226
227 fz_colorspace *
228 fz_device_rgb(fz_context *ctx)
229 {
230         return ctx->colorspace->rgb;
231 }
232
233 fz_colorspace *
234 fz_device_bgr(fz_context *ctx)
235 {
236         return ctx->colorspace->bgr;
237 }
238
239 fz_colorspace *
240 fz_device_cmyk(fz_context *ctx)
241 {
242         return ctx->colorspace->cmyk;
243 }
244
245 fz_colorspace *
246 fz_lookup_device_colorspace(fz_context *ctx, char *name)
247 {
248         if (!strcmp(name, "DeviceGray"))
249                 return fz_device_gray(ctx);
250         if (!strcmp(name, "DeviceRGB"))
251                 return fz_device_rgb(ctx);
252         if (!strcmp(name, "DeviceBGR"))
253                 return fz_device_bgr(ctx);
254         if (!strcmp(name, "DeviceCMYK"))
255                 return fz_device_cmyk(ctx);
256         assert(!"unknown device colorspace");
257         return NULL;
258 }
259
260 void
261 fz_set_device_gray(fz_context *ctx, fz_colorspace *cs)
262 {
263         fz_drop_colorspace(ctx, ctx->colorspace->gray);
264         ctx->colorspace->gray = fz_keep_colorspace(ctx, cs);
265 }
266
267 void
268 fz_set_device_rgb(fz_context *ctx, fz_colorspace *cs)
269 {
270         fz_drop_colorspace(ctx, ctx->colorspace->rgb);
271         ctx->colorspace->rgb = fz_keep_colorspace(ctx, cs);
272 }
273
274 void
275 fz_set_device_bgr(fz_context *ctx, fz_colorspace *cs)
276 {
277         fz_drop_colorspace(ctx, ctx->colorspace->bgr);
278         ctx->colorspace->bgr = fz_keep_colorspace(ctx, cs);
279 }
280
281 void
282 fz_set_device_cmyk(fz_context *ctx, fz_colorspace *cs)
283 {
284         fz_drop_colorspace(ctx, ctx->colorspace->cmyk);
285         ctx->colorspace->cmyk = fz_keep_colorspace(ctx, cs);
286 }
287
288 int
289 fz_colorspace_is_indexed(fz_colorspace *cs)
290 {
291         return (cs && !strcmp(cs->name, "Indexed"));
292 }
293
294 /* Fast pixmap color conversions */
295
296 static void fast_gray_to_rgb(fz_pixmap *dst, fz_pixmap *src)
297 {
298         unsigned char *s = src->samples;
299         unsigned char *d = dst->samples;
300         int n = src->w * src->h;
301         while (n--)
302         {
303                 d[0] = s[0];
304                 d[1] = s[0];
305                 d[2] = s[0];
306                 d[3] = s[1];
307                 s += 2;
308                 d += 4;
309         }
310 }
311
312 static void fast_gray_to_cmyk(fz_pixmap *dst, fz_pixmap *src)
313 {
314         unsigned char *s = src->samples;
315         unsigned char *d = dst->samples;
316         int n = src->w * src->h;
317         while (n--)
318         {
319                 d[0] = 0;
320                 d[1] = 0;
321                 d[2] = 0;
322                 d[3] = 255 - s[0];
323                 d[4] = s[1];
324                 s += 2;
325                 d += 5;
326         }
327 }
328
329 static void fast_rgb_to_gray(fz_pixmap *dst, fz_pixmap *src)
330 {
331         unsigned char *s = src->samples;
332         unsigned char *d = dst->samples;
333         int n = src->w * src->h;
334         while (n--)
335         {
336                 d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
337                 d[1] = s[3];
338                 s += 4;
339                 d += 2;
340         }
341 }
342
343 static void fast_bgr_to_gray(fz_pixmap *dst, fz_pixmap *src)
344 {
345         unsigned char *s = src->samples;
346         unsigned char *d = dst->samples;
347         int n = src->w * src->h;
348         while (n--)
349         {
350                 d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
351                 d[1] = s[3];
352                 s += 4;
353                 d += 2;
354         }
355 }
356
357 static void fast_rgb_to_cmyk(fz_pixmap *dst, fz_pixmap *src)
358 {
359         unsigned char *s = src->samples;
360         unsigned char *d = dst->samples;
361         int n = src->w * src->h;
362         while (n--)
363         {
364                 unsigned char c = 255 - s[0];
365                 unsigned char m = 255 - s[1];
366                 unsigned char y = 255 - s[2];
367                 unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
368                 d[0] = c - k;
369                 d[1] = m - k;
370                 d[2] = y - k;
371                 d[3] = k;
372                 d[4] = s[3];
373                 s += 4;
374                 d += 5;
375         }
376 }
377
378 static void fast_bgr_to_cmyk(fz_pixmap *dst, fz_pixmap *src)
379 {
380         unsigned char *s = src->samples;
381         unsigned char *d = dst->samples;
382         int n = src->w * src->h;
383         while (n--)
384         {
385                 unsigned char c = 255 - s[2];
386                 unsigned char m = 255 - s[1];
387                 unsigned char y = 255 - s[0];
388                 unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
389                 d[0] = c - k;
390                 d[1] = m - k;
391                 d[2] = y - k;
392                 d[3] = k;
393                 d[4] = s[3];
394                 s += 4;
395                 d += 5;
396         }
397 }
398
399 static void fast_cmyk_to_gray(fz_pixmap *dst, fz_pixmap *src)
400 {
401         unsigned char *s = src->samples;
402         unsigned char *d = dst->samples;
403         int n = src->w * src->h;
404         while (n--)
405         {
406                 unsigned char c = fz_mul255(s[0], 77);
407                 unsigned char m = fz_mul255(s[1], 150);
408                 unsigned char y = fz_mul255(s[2], 28);
409                 d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255);
410                 d[1] = s[4];
411                 s += 5;
412                 d += 2;
413         }
414 }
415
416 #ifdef ARCH_ARM
417 static void
418 fast_cmyk_to_rgb_ARM(unsigned char *dst, unsigned char *src, int n)
419 __attribute__((naked));
420
421 static void
422 fast_cmyk_to_rgb_ARM(unsigned char *dst, unsigned char *src, int n)
423 {
424         asm volatile(
425         ENTER_ARM
426         "stmfd  r13!,{r4-r11,r14}                                       \n"
427         "@ r0 = dst                                                     \n"
428         "@ r1 = src                                                     \n"
429         "@ r2 = n                                                       \n"
430         "mov    r12, #0                 @ r12= CMYK = 0                 \n"
431         "b      2f                      @ enter loop                    \n"
432         "1:                             @ White or Black                \n"
433         "@ Cunning trick: On entry r11 = 0 if black, r11 = FF if white  \n"
434         "eor    r12,r11,#0xFF           @ r12= FF if black, 0 if white  \n"
435         "ldrb   r7, [r1],#1             @ r8 = s[4]                     \n"
436         "strb   r11,[r0],#1             @ d[0] = r                      \n"
437         "strb   r11,[r0],#1             @ d[1] = g                      \n"
438         "strb   r11,[r0],#1             @ d[2] = b                      \n"
439         "strb   r7, [r0],#1             @ d[3] = s[4]                   \n"
440         "mov    r12,r12,LSL #24         @ r12 = CMYK                    \n"
441         "subs   r2, r2, #1              @ r2 = n--                      \n"
442         "beq    9f                                                      \n"
443         "2:                             @ Main loop starts here         \n"
444         "ldrb   r3, [r1], #4            @ r3 = c                        \n"
445         "ldrb   r6, [r1, #-1]           @ r6 = k                        \n"
446         "ldrb   r5, [r1, #-2]           @ r5 = y                        \n"
447         "ldrb   r4, [r1, #-3]           @ r4 = m                        \n"
448         "eors   r11,r6, #0xFF           @ if (k == 255)                 \n"
449         "beq    1b                      @   goto black                  \n"
450         "orr    r7, r3, r4, LSL #8                                      \n"
451         "orr    r14,r5, r6, LSL #8                                      \n"
452         "orrs   r7, r7, r14,LSL #16     @ r7 = cmyk                     \n"
453         "beq    1b                      @ if (cmyk == 0) white          \n"
454         "@ At this point, we have to decode a new pixel                 \n"
455         "@ r0 = dst  r1 = src  r2 = n  r7 = cmyk                        \n"
456         "3:                             @ unmatched                     \n"
457         "stmfd  r13!,{r0-r1,r7}         @ stash regs for space          \n"
458         "add    r3, r3, r3, LSR #7      @ r3 = c += c>>7                \n"
459         "add    r4, r4, r4, LSR #7      @ r4 = m += m>>7                \n"
460         "add    r5, r5, r5, LSR #7      @ r5 = y += y>>7                \n"
461         "add    r6, r6, r6, LSR #7      @ r6 = k += k>>7                \n"
462         "mov    r5, r5, LSR #1          @ sacrifice 1 bit of Y          \n"
463         "mul    r8, r3, r4              @ r8 = cm     = c * m           \n"
464         "rsb    r9, r8, r4, LSL #8      @ r9 = c1m    = (m<<8) - cm     \n"
465         "rsb    r3, r8, r3, LSL #8      @ r3 = cm1    = (c<<8) - cm     \n"
466         "rsb    r4, r4, #0x100          @ r4 = 256-m                    \n"
467         "rsb    r4, r3, r4, LSL #8      @ r4 = c1m1   =((256-m)<<8)-cm1 \n"
468         "mul    r7, r4, r5              @ r7 = c1m1y  = c1m1 * y        \n"
469         "rsb    r4, r7, r4, LSL #7      @ r4 = c1m1y1 = (c1m1<<7)-c1m1y \n"
470         "mul    r10,r9, r5              @ r10= c1my   = c1m * y         \n"
471         "rsb    r9, r10,r9, LSL #7      @ r9 = c1my1  = (c1m<<7) - c1my \n"
472         "mul    r11,r3, r5              @ r11= cm1y   = cm1 * y         \n"
473         "rsb    r3, r11,r3, LSL #7      @ r3 = cm1y1  = (cm1<<7) - cm1y \n"
474         "mul    r5, r8, r5              @ r5 = cmy    = cm * y          \n"
475         "rsb    r8, r5, r8, LSL #7      @ r8 = cmy1   = (cm<<7) - cmy   \n"
476         "@ Register recap:                                              \n"
477         "@ r3 = cm1y1                                                   \n"
478         "@ r4 = c1m1y1                                                  \n"
479         "@ r5 = cmy                                                     \n"
480         "@ r6 = k                                                       \n"
481         "@ r7 = c1m1y                                                   \n"
482         "@ r8 = cmy1                                                    \n"
483         "@ r9 = c1my1                                                   \n"
484         "@ r10= c1my                                                    \n"
485         "@ r11= cm1y                                                    \n"
486         "@ The actual matrix multiplication                             \n"
487         "mul    r14,r4, r6              @ r14= x1 = c1m1y1 * k          \n"
488         "rsb    r4, r14,r4, LSL #8      @ r4 = x0 = (c1m1y1<<8) - x1    \n"
489         "add    r4, r4, r14,LSR #8-5    @ r4 = b = x0 + 32*(x1>>8)      \n"
490         "sub    r1, r4, r14,LSR #8      @ r1 = g = x0 + 31*(x1>>8)      \n"
491         "add    r0, r1, r14,LSR #8-2    @ r0 = r = x0 + 35*(x1>>8)      \n"
492         "                                                               \n"
493         "mul    r14,r7, r6              @ r14= x1 = c1m1y * k           \n"
494         "rsb    r7, r14,r7, LSL #8      @ r7 = x0 = (c1m1y<<8) - x1     \n"
495         "add    r0, r0, r7              @ r0 = r += x0                  \n"
496         "add    r1, r1, r7              @ r1 = g += (x0>>8 * 256)       \n"
497         "sub    r1, r1, r7, LSR #8-3    @                    248        \n"
498         "sub    r1, r1, r7, LSR #8-2    @                    244        \n"
499         "sub    r1, r1, r7, LSR #8      @                    243        \n"
500         "sub    r7, r14,r14,LSR #3      @ r7 = 28*(x1>>5)               \n"
501         "add    r0, r0, r7, LSR #8-5    @ r0 = r += 28 * x1             \n"
502         "sub    r7, r7, r14,LSR #4      @ r7 = 26*(x1>>5)               \n"
503         "add    r1, r1, r7, LSR #8-5    @ r1 = g += 26 * x1             \n"
504         "                                                               \n"
505         "mul    r14,r9, r6              @ r14= x1 = c1my1 * k           \n"
506         "sub    r9, r9, r14,LSR #8      @ r9 = x0>>8 = c1my1 - (x1>>8)  \n"
507         "add    r0, r0, r14,LSR #8-5    @ r0 = r += (x1>>8)*32          \n"
508         "add    r0, r0, r14,LSR #8-2    @ r0 = r += (x1>>8)*36          \n"
509         "mov    r14,#237                @ r14= 237                      \n"
510         "mla    r0,r14,r9,r0            @ r14= r += x0*237              \n"
511         "mov    r14,#141                @ r14= 141                      \n"
512         "mla    r4,r14,r9,r4            @ r14= b += x0*141              \n"
513         "                                                               \n"
514         "mul    r14,r10,r6              @ r14= x1 = c1my * k            \n"
515         "sub    r10,r10,r14,LSR #8      @ r10= x0>>8 = c1my - (x1>>8)   \n"
516         "add    r0, r0, r14,LSR #8-5    @ r0 = r += 32 * x1             \n"
517         "add    r0, r0, r14,LSR #8-1    @ r0 = r += 34 * x1             \n"
518         "mov    r14,#238                @ r14= 238                      \n"
519         "mla    r0,r14,r10,r0           @ r0 = r += 238 * x0            \n"
520         "mov    r14,#28                 @ r14= 28                       \n"
521         "mla    r1,r14,r10,r1           @ r1 = g += 28 * x0             \n"
522         "mov    r14,#36                 @ r14= 36                       \n"
523         "mla    r4,r14,r10,r4           @ r4 = b += 36 * x0             \n"
524         "                                                               \n"
525         "mul    r14,r3, r6              @ r14= x1 = cm1y1 * k           \n"
526         "sub    r3, r3, r14,LSR #8      @ r3 = x1>>8 = cm1y1 - (x1>>8)  \n"
527         "add    r1, r1, r14,LSR #8-4    @ r1 = g += 16*x1               \n"
528         "sub    r1, r1, r14,LSR #8      @           15*x1               \n"
529         "add    r4, r4, r14,LSR #8-5    @ r4 = b += 32*x1               \n"
530         "add    r4, r4, r14,LSR #8-2    @           36*x1               \n"
531         "mov    r14,#174                @ r14= 174                      \n"
532         "mla    r1, r14,r3, r1          @ r1 = g += 174 * x0            \n"
533         "mov    r14,#240                @ r14= 240                      \n"
534         "mla    r4, r14,r3, r4          @ r4 = b += 240 * x0            \n"
535         "                                                               \n"
536         "mul    r14,r11,r6              @ r14= x1 = cm1y * k            \n"
537         "sub    r11,r11,r14,LSR #8      @ r11= x0>>8 = cm1y - (x1>>8)   \n"
538         "add    r1, r1, r14,LSR #8-4    @ r1 = g += x1 * 16             \n"
539         "add    r1, r1, r14,LSR #8      @           x1 * 17             \n"
540         "add    r1, r1, r14,LSR #8-1    @           x1 * 19             \n"
541         "mov    r14,#167                @ r14 = 167                     \n"
542         "mla    r1, r14,r11,r1          @ r1 = g += 167 * x0            \n"
543         "mov    r14,#80                 @ r14 = 80                      \n"
544         "mla    r4, r14,r11,r4          @ r4 = b += 80 * x0             \n"
545         "                                                               \n"
546         "mul    r14,r8, r6              @ r14= x1 = cmy1 * k            \n"
547         "sub    r8, r8, r14,LSR #8      @ r8 = x0>>8 = cmy1 - (x1>>8)   \n"
548         "add    r4, r4, r14,LSR #8-1    @ r4 = b += x1 * 2              \n"
549         "mov    r14,#46                 @ r14=46                        \n"
550         "mla    r0, r14,r8, r0          @ r0 = r += 46 * x0             \n"
551         "mov    r14,#49                 @ r14=49                        \n"
552         "mla    r1, r14,r8, r1          @ r1 = g += 49 * x0             \n"
553         "mov    r14,#147                @ r14=147                       \n"
554         "mla    r4, r14,r8, r4          @ r4 = b += 147 * x0            \n"
555         "                                                               \n"
556         "rsb    r6, r6, #256            @ r6 = k = 256-k                \n"
557         "mul    r14,r5, r6              @ r14= x0 = cmy * (256-k)       \n"
558         "mov    r11,#54                 @ r11= 54                       \n"
559         "mov    r14,r14,LSR #8          @ r14= (x0>>8)                  \n"
560         "mov    r8,#57                  @ r8 = 57                       \n"
561         "mla    r0,r14,r11,r0           @ r0 = r += 54*x0               \n"
562         "mla    r1,r14,r11,r1           @ r1 = g += 54*x0               \n"
563         "mla    r4,r14,r8, r4           @ r4 = b += 57*x0               \n"
564         "                                                               \n"
565         "sub    r8, r0, r0, LSR #8      @ r8 = r -= (r>>8)              \n"
566         "sub    r9, r1, r1, LSR #8      @ r9 = g -= (r>>8)              \n"
567         "sub    r10,r4, r4, LSR #8      @ r10= b -= (r>>8)              \n"
568         "ldmfd  r13!,{r0-r1,r12}                                        \n"
569         "mov    r8, r8, LSR #23         @ r8 = r>>23                    \n"
570         "mov    r9, r9, LSR #23         @ r9 = g>>23                    \n"
571         "mov    r10,r10,LSR #23         @ r10= b>>23                    \n"
572         "ldrb   r14,[r1],#1             @ r8 = s[4]                     \n"
573         "strb   r8, [r0],#1             @ d[0] = r                      \n"
574         "strb   r9, [r0],#1             @ d[1] = g                      \n"
575         "strb   r10,[r0],#1             @ d[2] = b                      \n"
576         "strb   r14,[r0],#1             @ d[3] = s[4]                   \n"
577         "subs   r2, r2, #1              @ r2 = n--                      \n"
578         "beq    9f                                                      \n"
579         "@ At this point, we've just decoded a pixel                    \n"
580         "@ r0 = dst  r1 = src  r2 = n  r8 = r  r9 = g  r10= b r12= CMYK \n"
581         "4:                                                             \n"
582         "ldrb   r3, [r1], #4            @ r3 = c                        \n"
583         "ldrb   r6, [r1, #-1]           @ r6 = k                        \n"
584         "ldrb   r5, [r1, #-2]           @ r5 = y                        \n"
585         "ldrb   r4, [r1, #-3]           @ r4 = m                        \n"
586         "eors   r11,r6, #0xFF           @ if (k == 255)                 \n"
587         "beq    1b                      @   goto black                  \n"
588         "orr    r7, r3, r4, LSL #8                                      \n"
589         "orr    r14,r5, r6, LSL #8                                      \n"
590         "orrs   r7, r7, r14,LSL #16     @ r7 = cmyk                     \n"
591         "beq    1b                      @ if (cmyk == 0) white          \n"
592         "cmp    r7, r12                 @ if (cmyk != CMYK)             \n"
593         "bne    3b                      @   not the same, loop          \n"
594         "@ If we get here, we just matched a pixel we have just decoded \n"
595         "ldrb   r3, [r1],#1             @ r8 = s[4]                     \n"
596         "strb   r8, [r0],#1             @ d[0] = r                      \n"
597         "strb   r9, [r0],#1             @ d[1] = g                      \n"
598         "strb   r10,[r0],#1             @ d[2] = b                      \n"
599         "strb   r3, [r0],#1             @ d[3] = s[4]                   \n"
600         "subs   r2, r2, #1              @ r2 = n--                      \n"
601         "bne    4b                                                      \n"
602         "9:                                                             \n"
603         "ldmfd  r13!,{r4-r11,PC}        @ pop, return to thumb          \n"
604         ENTER_THUMB
605         );
606 }
607 #endif
608
609 static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
610 {
611         unsigned char *s = src->samples;
612         unsigned char *d = dst->samples;
613         int n = src->w * src->h;
614 #ifdef ARCH_ARM
615         fast_cmyk_to_rgb_ARM(d, s, n);
616 #else
617         unsigned int C,M,Y,K,r,g,b;
618
619         C = 0;
620         M = 0;
621         Y = 0;
622         K = 0;
623         r = 255;
624         g = 255;
625         b = 255;
626
627         while (n--)
628         {
629 #ifdef SLOWCMYK
630                 unsigned int c = s[0];
631                 unsigned int m = s[1];
632                 unsigned int y = s[2];
633                 unsigned int k = s[3];
634                 unsigned int cm, c1m, cm1, c1m1, c1m1y, c1m1y1, c1my, c1my1, cm1y, cm1y1, cmy, cmy1;
635                 unsigned int x0, x1;
636
637                 if (c == C && m == M && y == Y && k == K)
638                 {
639                         /* Nothing to do */
640                 }
641                 else if (k == 0 && c == 0 && m == 0 && y == 0)
642                 {
643                         r = g = b = 255;
644                         C = 0;
645                         M = 0;
646                         Y = 0;
647                         K = 0;
648                 }
649                 else if (k == 255)
650                 {
651                         r = g = b = 0;
652                         C = 0;
653                         M = 0;
654                         Y = 0;
655                         K = 255;
656                 }
657                 else
658                 {
659                         c += c>>7;
660                         m += m>>7;
661                         y += y>>7;
662                         k += k>>7;
663                         y >>= 1; /* Ditch 1 bit of Y to avoid overflow */
664                         cm = c * m;
665                         c1m = (m<<8) - cm;
666                         cm1 = (c<<8) - cm;
667                         c1m1 = ((256 - m)<<8) - cm1;
668                         c1m1y = c1m1 * y;
669                         c1m1y1 = (c1m1<<7) - c1m1y;
670                         c1my = c1m * y;
671                         c1my1 = (c1m<<7) - c1my;
672                         cm1y = cm1 * y;
673                         cm1y1 = (cm1<<7) - cm1y;
674                         cmy = cm * y;
675                         cmy1 = (cm<<7) - cmy;
676
677                         /* this is a matrix multiplication, unrolled for performance */
678                         x1 = c1m1y1 * k;        /* 0 0 0 1 */
679                         x0 = (c1m1y1<<8) - x1;  /* 0 0 0 0 */
680                         x1 = x1>>8;             /* From 23 fractional bits to 15 */
681                         r = g = b = x0;
682                         r += 35 * x1;   /* 0.1373 */
683                         g += 31 * x1;   /* 0.1216 */
684                         b += 32 * x1;   /* 0.1255 */
685
686                         x1 = c1m1y * k;         /* 0 0 1 1 */
687                         x0 = (c1m1y<<8) - x1;   /* 0 0 1 0 */
688                         x1 >>= 8;               /* From 23 fractional bits to 15 */
689                         r += 28 * x1;   /* 0.1098 */
690                         g += 26 * x1;   /* 0.1020 */
691                         r += x0;
692                         x0 >>= 8;               /* From 23 fractional bits to 15 */
693                         g += 243 * x0;  /* 0.9490 */
694
695                         x1 = c1my1 * k;         /* 0 1 0 1 */
696                         x0 = (c1my1<<8) - x1;   /* 0 1 0 0 */
697                         x1 >>= 8;               /* From 23 fractional bits to 15 */
698                         x0 >>= 8;               /* From 23 fractional bits to 15 */
699                         r += 36 * x1;   /* 0.1412 */
700                         r += 237 * x0;  /* 0.9255 */
701                         b += 141 * x0;  /* 0.5490 */
702
703                         x1 = c1my * k;          /* 0 1 1 1 */
704                         x0 = (c1my<<8) - x1;    /* 0 1 1 0 */
705                         x1 >>= 8;               /* From 23 fractional bits to 15 */
706                         x0 >>= 8;               /* From 23 fractional bits to 15 */
707                         r += 34 * x1;   /* 0.1333 */
708                         r += 238 * x0;  /* 0.9294 */
709                         g += 28 * x0;   /* 0.1098 */
710                         b += 36 * x0;   /* 0.1412 */
711
712                         x1 = cm1y1 * k;         /* 1 0 0 1 */
713                         x0 = (cm1y1<<8) - x1;   /* 1 0 0 0 */
714                         x1 >>= 8;               /* From 23 fractional bits to 15 */
715                         x0 >>= 8;               /* From 23 fractional bits to 15 */
716                         g += 15 * x1;   /* 0.0588 */
717                         b += 36 * x1;   /* 0.1412 */
718                         g += 174 * x0;  /* 0.6784 */
719                         b += 240 * x0;  /* 0.9373 */
720
721                         x1 = cm1y * k;          /* 1 0 1 1 */
722                         x0 = (cm1y<<8) - x1;    /* 1 0 1 0 */
723                         x1 >>= 8;               /* From 23 fractional bits to 15 */
724                         x0 >>= 8;               /* From 23 fractional bits to 15 */
725                         g += 19 * x1;   /* 0.0745 */
726                         g += 167 * x0;  /* 0.6510 */
727                         b += 80 * x0;   /* 0.3137 */
728
729                         x1 = cmy1 * k;          /* 1 1 0 1 */
730                         x0 = (cmy1<<8) - x1;    /* 1 1 0 0 */
731                         x1 >>= 8;               /* From 23 fractional bits to 15 */
732                         x0 >>= 8;               /* From 23 fractional bits to 15 */
733                         b += 2 * x1;    /* 0.0078 */
734                         r += 46 * x0;   /* 0.1804 */
735                         g += 49 * x0;   /* 0.1922 */
736                         b += 147 * x0;  /* 0.5725 */
737
738                         x0 = cmy * (256-k);     /* 1 1 1 0 */
739                         x0 >>= 8;               /* From 23 fractional bits to 15 */
740                         r += 54 * x0;   /* 0.2118 */
741                         g += 54 * x0;   /* 0.2119 */
742                         b += 57 * x0;   /* 0.2235 */
743
744                         r -= (r>>8);
745                         g -= (g>>8);
746                         b -= (b>>8);
747                         r = r>>23;
748                         g = g>>23;
749                         b = b>>23;
750                         C = c;
751                         M = m;
752                         Y = y;
753                         K = k;
754                 }
755                 d[0] = r;
756                 d[1] = g;
757                 d[2] = b;
758 #else
759                 d[0] = 255 - (unsigned char)fz_mini(s[0] + s[3], 255);
760                 d[1] = 255 - (unsigned char)fz_mini(s[1] + s[3], 255);
761                 d[2] = 255 - (unsigned char)fz_mini(s[2] + s[3], 255);
762 #endif
763                 d[3] = s[4];
764                 s += 5;
765                 d += 4;
766         }
767 #endif
768 }
769
770 static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
771 {
772         unsigned char *s = src->samples;
773         unsigned char *d = dst->samples;
774         int n = src->w * src->h;
775         while (n--)
776         {
777 #ifdef SLOWCMYK
778                 float cmyk[4], rgb[3];
779                 cmyk[0] = s[0] / 255.0f;
780                 cmyk[1] = s[1] / 255.0f;
781                 cmyk[2] = s[2] / 255.0f;
782                 cmyk[3] = s[3] / 255.0f;
783                 cmyk_to_rgb(ctx, NULL, cmyk, rgb);
784                 d[0] = rgb[2] * 255;
785                 d[1] = rgb[1] * 255;
786                 d[2] = rgb[0] * 255;
787 #else
788                 d[0] = 255 - (unsigned char)fz_mini(s[2] + s[3], 255);
789                 d[1] = 255 - (unsigned char)fz_mini(s[1] + s[3], 255);
790                 d[2] = 255 - (unsigned char)fz_mini(s[0] + s[3], 255);
791 #endif
792                 d[3] = s[4];
793                 s += 5;
794                 d += 4;
795         }
796 }
797
798 static void fast_rgb_to_bgr(fz_pixmap *dst, fz_pixmap *src)
799 {
800         unsigned char *s = src->samples;
801         unsigned char *d = dst->samples;
802         int n = src->w * src->h;
803         while (n--)
804         {
805                 d[0] = s[2];
806                 d[1] = s[1];
807                 d[2] = s[0];
808                 d[3] = s[3];
809                 s += 4;
810                 d += 4;
811         }
812 }
813
814 static void
815 fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
816 {
817         float srcv[FZ_MAX_COLORS];
818         float dstv[FZ_MAX_COLORS];
819         int srcn, dstn;
820         int k, i;
821         unsigned int xy;
822
823         fz_colorspace *ss = src->colorspace;
824         fz_colorspace *ds = dst->colorspace;
825
826         unsigned char *s = src->samples;
827         unsigned char *d = dst->samples;
828
829         assert(src->w == dst->w && src->h == dst->h);
830         assert(src->n == ss->n + 1);
831         assert(dst->n == ds->n + 1);
832
833         srcn = ss->n;
834         dstn = ds->n;
835
836         xy = (unsigned int)(src->w * src->h);
837
838         /* Special case for Lab colorspace (scaling of components to float) */
839         if (!strcmp(ss->name, "Lab") && srcn == 3)
840         {
841                 fz_color_converter cc;
842
843                 fz_lookup_color_converter(&cc, ctx, ds, ss);
844                 for (; xy > 0; xy--)
845                 {
846                         srcv[0] = *s++ / 255.0f * 100;
847                         srcv[1] = *s++ - 128;
848                         srcv[2] = *s++ - 128;
849
850                         cc.convert(&cc, dstv, srcv);
851
852                         for (k = 0; k < dstn; k++)
853                                 *d++ = dstv[k] * 255;
854
855                         *d++ = *s++;
856                 }
857         }
858
859         /* Brute-force for small images */
860         else if (xy < 256)
861         {
862                 fz_color_converter cc;
863
864                 fz_lookup_color_converter(&cc, ctx, ds, ss);
865                 for (; xy > 0; xy--)
866                 {
867                         for (k = 0; k < srcn; k++)
868                                 srcv[k] = *s++ / 255.0f;
869
870                         cc.convert(&cc, dstv, srcv);
871
872                         for (k = 0; k < dstn; k++)
873                                 *d++ = dstv[k] * 255;
874
875                         *d++ = *s++;
876                 }
877         }
878
879         /* 1-d lookup table for separation and similar colorspaces */
880         else if (srcn == 1)
881         {
882                 unsigned char lookup[FZ_MAX_COLORS * 256];
883                 fz_color_converter cc;
884
885                 fz_lookup_color_converter(&cc, ctx, ds, ss);
886                 for (i = 0; i < 256; i++)
887                 {
888                         srcv[0] = i / 255.0f;
889                         cc.convert(&cc, dstv, srcv);
890                         for (k = 0; k < dstn; k++)
891                                 lookup[i * dstn + k] = dstv[k] * 255;
892                 }
893
894                 for (; xy > 0; xy--)
895                 {
896                         i = *s++;
897                         for (k = 0; k < dstn; k++)
898                                 *d++ = lookup[i * dstn + k];
899                         *d++ = *s++;
900                 }
901         }
902
903         /* Memoize colors using a hash table for the general case */
904         else
905         {
906                 fz_hash_table *lookup;
907                 unsigned char *color;
908                 unsigned char dummy = s[0] ^ 255;
909                 unsigned char *sold = &dummy;
910                 fz_color_converter cc;
911
912                 fz_lookup_color_converter(&cc, ctx, ds, ss);
913                 lookup = fz_new_hash_table(ctx, 509, srcn, -1);
914
915                 for (; xy > 0; xy--)
916                 {
917                         if (*s == *sold && memcmp(sold,s,srcn) == 0)
918                         {
919                                 sold = s;
920                                 memcpy(d, d-dstn-1, dstn);
921                                 d += dstn;
922                                 s += srcn;
923                                 *d++ = *s++;
924                         }
925                         else
926                         {
927                                 sold = s;
928                                 color = fz_hash_find(ctx, lookup, s);
929                                 if (color)
930                                 {
931                                         memcpy(d, color, dstn);
932                                         s += srcn;
933                                         d += dstn;
934                                         *d++ = *s++;
935                                 }
936                                 else
937                                 {
938                                         for (k = 0; k < srcn; k++)
939                                                 srcv[k] = *s++ / 255.0f;
940                                         cc.convert(&cc, dstv, srcv);
941                                         for (k = 0; k < dstn; k++)
942                                                 *d++ = dstv[k] * 255;
943
944                                         fz_hash_insert(ctx, lookup, s - srcn, d - dstn);
945
946                                         *d++ = *s++;
947                                 }
948                         }
949                 }
950
951                 fz_free_hash(ctx, lookup);
952         }
953 }
954
955 void
956 fz_convert_pixmap(fz_context *ctx, fz_pixmap *dp, fz_pixmap *sp)
957 {
958         fz_colorspace *ss = sp->colorspace;
959         fz_colorspace *ds = dp->colorspace;
960
961         assert(ss && ds);
962
963         dp->interpolate = sp->interpolate;
964
965         if (ss == fz_default_gray)
966         {
967                 if (ds == fz_default_rgb) fast_gray_to_rgb(dp, sp);
968                 else if (ds == fz_default_bgr) fast_gray_to_rgb(dp, sp); /* bgr == rgb here */
969                 else if (ds == fz_default_cmyk) fast_gray_to_cmyk(dp, sp);
970                 else fz_std_conv_pixmap(ctx, dp, sp);
971         }
972
973         else if (ss == fz_default_rgb)
974         {
975                 if (ds == fz_default_gray) fast_rgb_to_gray(dp, sp);
976                 else if (ds == fz_default_bgr) fast_rgb_to_bgr(dp, sp);
977                 else if (ds == fz_default_cmyk) fast_rgb_to_cmyk(dp, sp);
978                 else fz_std_conv_pixmap(ctx, dp, sp);
979         }
980
981         else if (ss == fz_default_bgr)
982         {
983                 if (ds == fz_default_gray) fast_bgr_to_gray(dp, sp);
984                 else if (ds == fz_default_rgb) fast_rgb_to_bgr(dp, sp); /* bgr = rgb here */
985                 else if (ds == fz_default_cmyk) fast_bgr_to_cmyk(sp, dp);
986                 else fz_std_conv_pixmap(ctx, dp, sp);
987         }
988
989         else if (ss == fz_default_cmyk)
990         {
991                 if (ds == fz_default_gray) fast_cmyk_to_gray(dp, sp);
992                 else if (ds == fz_default_bgr) fast_cmyk_to_bgr(ctx, dp, sp);
993                 else if (ds == fz_default_rgb) fast_cmyk_to_rgb(ctx, dp, sp);
994                 else fz_std_conv_pixmap(ctx, dp, sp);
995         }
996
997         else fz_std_conv_pixmap(ctx, dp, sp);
998 }
999
1000 /* Convert a single color */
1001
1002 static void
1003 std_conv_color(fz_color_converter *cc, float *dstv, const float *srcv)
1004 {
1005         float rgb[3];
1006         int i;
1007         fz_colorspace *srcs = cc->ss;
1008         fz_colorspace *dsts = cc->ds;
1009         fz_context *ctx = cc->ctx;
1010
1011         if (srcs != dsts)
1012         {
1013                 assert(srcs->to_rgb && dsts->from_rgb);
1014                 srcs->to_rgb(ctx, srcs, srcv, rgb);
1015                 dsts->from_rgb(ctx, dsts, rgb, dstv);
1016                 for (i = 0; i < dsts->n; i++)
1017                         dstv[i] = fz_clamp(dstv[i], 0, 1);
1018         }
1019         else
1020         {
1021                 for (i = 0; i < srcs->n; i++)
1022                         dstv[i] = srcv[i];
1023         }
1024 }
1025
1026 static void
1027 g2rgb(fz_color_converter *cc, float *dv, const float *sv)
1028 {
1029         dv[0] = sv[0];
1030         dv[1] = sv[0];
1031         dv[2] = sv[0];
1032 }
1033
1034 static void
1035 g2cmyk(fz_color_converter *cc, float *dv, const float *sv)
1036 {
1037         dv[0] = 0;
1038         dv[1] = 0;
1039         dv[2] = 0;
1040         dv[3] = 1 - sv[0];
1041 }
1042
1043 static void
1044 rgb2g(fz_color_converter *cc, float *dv, const float *sv)
1045 {
1046         dv[0] = sv[0] * 0.3f + sv[1] * 0.59f + sv[2] * 0.11f;
1047 }
1048
1049 static void
1050 rgb2bgr(fz_color_converter *cc, float *dv, const float *sv)
1051 {
1052         dv[0] = sv[2];
1053         dv[1] = sv[1];
1054         dv[2] = sv[0];
1055 }
1056
1057 static void
1058 rgb2cmyk(fz_color_converter *cc, float *dv, const float *sv)
1059 {
1060         float c = 1 - sv[0];
1061         float m = 1 - sv[1];
1062         float y = 1 - sv[2];
1063         float k = fz_min(c, fz_min(m, y));
1064         dv[0] = c - k;
1065         dv[1] = m - k;
1066         dv[2] = y - k;
1067         dv[3] = k;
1068 }
1069
1070 static void
1071 bgr2g(fz_color_converter *cc, float *dv, const float *sv)
1072 {
1073         dv[0] = sv[0] * 0.11f + sv[1] * 0.59f + sv[2] * 0.3f;
1074 }
1075
1076 static void
1077 bgr2cmyk(fz_color_converter *cc, float *dv, const float *sv)
1078 {
1079         float c = 1 - sv[2];
1080         float m = 1 - sv[1];
1081         float y = 1 - sv[0];
1082         float k = fz_min(c, fz_min(m, y));
1083         dv[0] = c - k;
1084         dv[1] = m - k;
1085         dv[2] = y - k;
1086         dv[3] = k;
1087 }
1088
1089 static void
1090 cmyk2g(fz_color_converter *cc, float *dv, const float *sv)
1091 {
1092         float c = sv[0] * 0.3f;
1093         float m = sv[1] * 0.59f;
1094         float y = sv[2] * 0.11f;
1095         dv[0] = 1 - fz_min(c + m + y + sv[3], 1);
1096 }
1097
1098 static void
1099 cmyk2rgb(fz_color_converter *cc, float *dv, const float *sv)
1100 {
1101 #ifdef SLOWCMYK
1102         cmyk_to_rgb(cc->ctx, NULL, sv, dv);
1103 #else
1104         dv[0] = 1 - fz_min(sv[0] + sv[3], 1);
1105         dv[1] = 1 - fz_min(sv[1] + sv[3], 1);
1106         dv[2] = 1 - fz_min(sv[2] + sv[3], 1);
1107 #endif
1108 }
1109
1110 static void
1111 cmyk2bgr(fz_color_converter *cc, float *dv, const float *sv)
1112 {
1113 #ifdef SLOWCMYK
1114         float rgb[3];
1115         cmyk_to_rgb(cc->ctx, NULL, sv, rgb);
1116         dv[0] = rgb[2];
1117         dv[1] = rgb[1];
1118         dv[2] = rgb[0];
1119 #else
1120         dv[0] = 1 - fz_min(sv[2] + sv[3], 1);
1121         dv[1] = 1 - fz_min(sv[1] + sv[3], 1);
1122         dv[2] = 1 - fz_min(sv[0] + sv[3], 1);
1123 #endif
1124 }
1125
1126 void fz_lookup_color_converter(fz_color_converter *cc, fz_context *ctx, fz_colorspace *ds, fz_colorspace *ss)
1127 {
1128         cc->ctx = ctx;
1129         cc->ds = ds;
1130         cc->ss = ss;
1131         if (ss == fz_default_gray)
1132         {
1133                 if ((ds == fz_default_rgb) || (ds == fz_default_bgr))
1134                         cc->convert = g2rgb;
1135                 else if (ds == fz_default_cmyk)
1136                         cc->convert = g2cmyk;
1137                 else
1138                         cc->convert = std_conv_color;
1139         }
1140
1141         else if (ss == fz_default_rgb)
1142         {
1143                 if (ds == fz_default_gray)
1144                         cc->convert = rgb2g;
1145                 else if (ds == fz_default_bgr)
1146                         cc->convert = rgb2bgr;
1147                 else if (ds == fz_default_cmyk)
1148                         cc->convert = rgb2cmyk;
1149                 else
1150                         cc->convert = std_conv_color;
1151         }
1152
1153         else if (ss == fz_default_bgr)
1154         {
1155                 if (ds == fz_default_gray)
1156                         cc->convert = bgr2g;
1157                 else if (ds == fz_default_rgb)
1158                         cc->convert = rgb2bgr;
1159                 else if (ds == fz_default_cmyk)
1160                         cc->convert = bgr2cmyk;
1161                 else
1162                         cc->convert = std_conv_color;
1163         }
1164
1165         else if (ss == fz_default_cmyk)
1166         {
1167                 if (ds == fz_default_gray)
1168                         cc->convert = cmyk2g;
1169                 else if (ds == fz_default_rgb)
1170                         cc->convert = cmyk2rgb;
1171                 else if (ds == fz_default_bgr)
1172                         cc->convert = cmyk2bgr;
1173                 else
1174                         cc->convert = std_conv_color;
1175         }
1176
1177         else
1178                 cc->convert = std_conv_color;
1179 }
1180
1181 void
1182 fz_convert_color(fz_context *ctx, fz_colorspace *ds, float *dv, fz_colorspace *ss, const float *sv)
1183 {
1184         fz_color_converter cc;
1185         fz_lookup_color_converter(&cc, ctx, ds, ss);
1186         cc.convert(&cc, dv, sv);
1187 }
1188
1189 /* Indexed */
1190
1191 struct indexed
1192 {
1193         fz_colorspace *base;
1194         int high;
1195         unsigned char *lookup;
1196 };
1197
1198 static void
1199 indexed_to_rgb(fz_context *ctx, fz_colorspace *cs, const float *color, float *rgb)
1200 {
1201         struct indexed *idx = cs->data;
1202         float alt[FZ_MAX_COLORS];
1203         int i, k;
1204         i = color[0] * 255;
1205         i = fz_clampi(i, 0, idx->high);
1206         for (k = 0; k < idx->base->n; k++)
1207                 alt[k] = idx->lookup[i * idx->base->n + k] / 255.0f;
1208         idx->base->to_rgb(ctx, idx->base, alt, rgb);
1209 }
1210
1211 static void
1212 free_indexed(fz_context *ctx, fz_colorspace *cs)
1213 {
1214         struct indexed *idx = cs->data;
1215         if (idx->base)
1216                 fz_drop_colorspace(ctx, idx->base);
1217         fz_free(ctx, idx->lookup);
1218         fz_free(ctx, idx);
1219 }
1220
1221 fz_colorspace *
1222 fz_new_indexed_colorspace(fz_context *ctx, fz_colorspace *base, int high, unsigned char *lookup)
1223 {
1224         fz_colorspace *cs;
1225         struct indexed *idx;
1226
1227         idx = fz_malloc_struct(ctx, struct indexed);
1228         idx->lookup = lookup;
1229         idx->base = base;
1230         idx->high = high;
1231
1232         fz_try(ctx)
1233         {
1234                 cs = fz_new_colorspace(ctx, "Indexed", 1);
1235                 cs->to_rgb = indexed_to_rgb;
1236                 cs->free_data = free_indexed;
1237                 cs->data = idx;
1238                 cs->size += sizeof(*idx) + (base->n * (idx->high + 1)) + base->size;
1239         }
1240         fz_catch(ctx)
1241         {
1242                 fz_free(ctx, idx);
1243                 fz_rethrow_message(ctx, "failed to create indexed colorspace");
1244         }
1245         return cs;
1246 }
1247
1248 fz_pixmap *
1249 fz_expand_indexed_pixmap(fz_context *ctx, fz_pixmap *src)
1250 {
1251         struct indexed *idx;
1252         fz_pixmap *dst;
1253         unsigned char *s, *d;
1254         int y, x, k, n, high;
1255         unsigned char *lookup;
1256         fz_irect bbox;
1257
1258         assert(src->colorspace->to_rgb == indexed_to_rgb);
1259         assert(src->n == 2);
1260
1261         idx = src->colorspace->data;
1262         high = idx->high;
1263         lookup = idx->lookup;
1264         n = idx->base->n;
1265
1266         dst = fz_new_pixmap_with_bbox(ctx, idx->base, fz_pixmap_bbox(ctx, src, &bbox));
1267         s = src->samples;
1268         d = dst->samples;
1269
1270         for (y = 0; y < src->h; y++)
1271         {
1272                 for (x = 0; x < src->w; x++)
1273                 {
1274                         int v = *s++;
1275                         int a = *s++;
1276                         v = fz_mini(v, high);
1277                         for (k = 0; k < n; k++)
1278                                 *d++ = fz_mul255(lookup[v * n + k], a);
1279                         *d++ = a;
1280                 }
1281         }
1282
1283         dst->interpolate = src->interpolate;
1284
1285         return dst;
1286 }
1287
1288 typedef struct fz_cached_color_converter
1289 {
1290         fz_color_converter base;
1291         fz_hash_table *hash;
1292
1293 }
1294 fz_cached_color_converter;
1295
1296 static void fz_cached_color_convert(fz_color_converter *cc_, float *ds, const float *ss)
1297 {
1298         fz_cached_color_converter *cc = cc_->opaque;
1299         fz_context *ctx = cc->base.ctx;
1300         void *val = fz_hash_find(ctx, cc->hash, ss);
1301         int n = cc->base.ds->n * sizeof(float);
1302         fz_color_converter *base_cc = &cc->base;
1303
1304         if (val)
1305         {
1306                 memcpy(ds, val, n);
1307                 return;
1308         }
1309
1310         base_cc->convert(base_cc, ds, ss);
1311         val = fz_malloc(ctx, n);
1312         memcpy(val, ds, n);
1313         fz_try(ctx)
1314         {
1315                 fz_hash_insert(ctx, cc->hash, ss, val);
1316         }
1317         fz_catch(ctx)
1318         {
1319                 fz_free(ctx, val);
1320         }
1321 }
1322
1323 void fz_init_cached_color_converter(fz_context *ctx, fz_color_converter *cc, fz_colorspace *ds, fz_colorspace *ss)
1324 {
1325         int n = ss->n;
1326         fz_cached_color_converter *cached = fz_malloc_struct(ctx, fz_cached_color_converter);
1327
1328         fz_try(ctx)
1329         {
1330                 fz_lookup_color_converter(&cached->base, ctx, ds, ss);
1331                 cached->hash = fz_new_hash_table(ctx, 256, n * sizeof(float), -1);
1332                 cc->convert = fz_cached_color_convert;
1333                 cc->ctx = ctx;
1334                 cc->ds = ds;
1335                 cc->ss = ss;
1336                 cc->opaque = cached;
1337         }
1338         fz_catch(ctx)
1339         {
1340                 fz_free_hash(ctx, cached->hash);
1341                 fz_rethrow(ctx);
1342         }
1343 }
1344
1345 void fz_fin_cached_color_converter(fz_color_converter *cc_)
1346 {
1347         fz_cached_color_converter *cc;
1348         fz_context *ctx;
1349         int i, n;
1350
1351         if (cc_ == NULL)
1352                 return;
1353         cc = cc_->opaque;
1354         if (cc == NULL)
1355                 return;
1356         cc_->opaque = NULL;
1357         ctx = cc_->ctx;
1358
1359         n = fz_hash_len(ctx, cc->hash);
1360         for (i = 0; i < n; i++)
1361         {
1362                 void *v = fz_hash_get_val(ctx, cc->hash, i);
1363                 if (v)
1364                         fz_free(ctx, v);
1365         }
1366         fz_free_hash(ctx, cc->hash);
1367         fz_free(ctx, cc);
1368 }