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