comparison mupdf-source/source/fitz/color-fast.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 // Copyright (C) 2004-2024 Artifex Software, Inc.
2 //
3 // This file is part of MuPDF.
4 //
5 // MuPDF is free software: you can redistribute it and/or modify it under the
6 // terms of the GNU Affero General Public License as published by the Free
7 // Software Foundation, either version 3 of the License, or (at your option)
8 // any later version.
9 //
10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13 // details.
14 //
15 // You should have received a copy of the GNU Affero General Public License
16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17 //
18 // Alternative licensing terms are available from the licensor.
19 // For commercial licensing, see <https://www.artifex.com/> or contact
20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21 // CA 94129, USA, for further information.
22
23 #include "mupdf/fitz.h"
24
25 #include "color-imp.h"
26
27 #include <math.h>
28
29 /* Fast color transforms */
30
31 static void gray_to_gray(fz_context *ctx, fz_color_converter *cc, const float *gray, float *xyz)
32 {
33 xyz[0] = gray[0];
34 }
35
36 static void gray_to_rgb(fz_context *ctx, fz_color_converter *cc, const float *gray, float *rgb)
37 {
38 rgb[0] = gray[0];
39 rgb[1] = gray[0];
40 rgb[2] = gray[0];
41 }
42
43 static void rgb_to_gray(fz_context *ctx, fz_color_converter *cc, const float *rgb, float *gray)
44 {
45 gray[0] = rgb[0] * 0.3f + rgb[1] * 0.59f + rgb[2] * 0.11f;
46 }
47
48 static void bgr_to_gray(fz_context *ctx, fz_color_converter *cc, const float *bgr, float *gray)
49 {
50 gray[0] = bgr[0] * 0.11f + bgr[1] * 0.59f + bgr[2] * 0.3f;
51 }
52
53 static void rgb_to_rgb(fz_context *ctx, fz_color_converter *cc, const float *rgb, float *xyz)
54 {
55 xyz[0] = rgb[0];
56 xyz[1] = rgb[1];
57 xyz[2] = rgb[2];
58 }
59
60 static void rgb_to_bgr(fz_context *ctx, fz_color_converter *cc, const float *rgb, float *bgr)
61 {
62 bgr[0] = rgb[2];
63 bgr[1] = rgb[1];
64 bgr[2] = rgb[0];
65 }
66
67 static void cmyk_to_cmyk(fz_context *ctx, fz_color_converter *cc, const float *cmyk, float *xyz)
68 {
69 xyz[0] = cmyk[0];
70 xyz[1] = cmyk[1];
71 xyz[2] = cmyk[2];
72 xyz[3] = cmyk[3];
73 }
74
75 static void gray_to_cmyk(fz_context *ctx, fz_color_converter *cc, const float *gray, float *cmyk)
76 {
77 cmyk[0] = 0;
78 cmyk[1] = 0;
79 cmyk[2] = 0;
80 cmyk[3] = 1 - gray[0];
81 }
82
83 static void cmyk_to_gray(fz_context *ctx, fz_color_converter *cc, const float *cmyk, float *gray)
84 {
85 float c = cmyk[0] * 0.3f;
86 float m = cmyk[1] * 0.59f;
87 float y = cmyk[2] * 0.11f;
88 gray[0] = 1 - fz_min(c + m + y + cmyk[3], 1);
89 }
90
91 static void rgb_to_cmyk(fz_context *ctx, fz_color_converter *cc, const float *rgb, float *cmyk)
92 {
93 float c, m, y, k;
94 c = 1 - rgb[0];
95 m = 1 - rgb[1];
96 y = 1 - rgb[2];
97 k = fz_min(c, fz_min(m, y));
98 cmyk[0] = c - k;
99 cmyk[1] = m - k;
100 cmyk[2] = y - k;
101 cmyk[3] = k;
102 }
103
104 static void bgr_to_cmyk(fz_context *ctx, fz_color_converter *cc, const float *bgr, float *cmyk)
105 {
106 float c, m, y, k;
107 c = 1 - bgr[2];
108 m = 1 - bgr[1];
109 y = 1 - bgr[0];
110 k = fz_min(c, fz_min(m, y));
111 cmyk[0] = c - k;
112 cmyk[1] = m - k;
113 cmyk[2] = y - k;
114 cmyk[3] = k;
115 }
116
117 static void cmyk_to_rgb(fz_context *ctx, fz_color_converter *cc, const float *cmyk, float *rgb)
118 {
119 rgb[0] = 1 - fz_min(1, cmyk[0] + cmyk[3]);
120 rgb[1] = 1 - fz_min(1, cmyk[1] + cmyk[3]);
121 rgb[2] = 1 - fz_min(1, cmyk[2] + cmyk[3]);
122 }
123
124 static void cmyk_to_bgr(fz_context *ctx, fz_color_converter *cc, const float *cmyk, float *bgr)
125 {
126 bgr[0] = 1 - fz_min(cmyk[2] + cmyk[3], 1);
127 bgr[1] = 1 - fz_min(cmyk[1] + cmyk[3], 1);
128 bgr[2] = 1 - fz_min(cmyk[0] + cmyk[3], 1);
129 }
130
131 static inline float fung(float x)
132 {
133 if (x >= 6.0f / 29.0f)
134 return x * x * x;
135 return (108.0f / 841.0f) * (x - (4.0f / 29.0f));
136 }
137
138 static void lab_to_rgb(fz_context *ctx, fz_color_converter *cc, const float *lab, float *rgb)
139 {
140 /* input is in range (0..100, -128..127, -128..127) not (0..1, 0..1, 0..1) */
141 float lstar, astar, bstar, l, m, n, x, y, z, r, g, b;
142 lstar = lab[0];
143 astar = lab[1];
144 bstar = lab[2];
145 m = (lstar + 16) / 116;
146 l = m + astar / 500;
147 n = m - bstar / 200;
148 x = fung(l);
149 y = fung(m);
150 z = fung(n);
151 r = (3.240449f * x + -1.537136f * y + -0.498531f * z) * 0.830026f;
152 g = (-0.969265f * x + 1.876011f * y + 0.041556f * z) * 1.05452f;
153 b = (0.055643f * x + -0.204026f * y + 1.057229f * z) * 1.1003f;
154 rgb[0] = sqrtf(fz_clamp(r, 0, 1));
155 rgb[1] = sqrtf(fz_clamp(g, 0, 1));
156 rgb[2] = sqrtf(fz_clamp(b, 0, 1));
157 }
158
159 static void lab_to_gray(fz_context *ctx, fz_color_converter *cc, const float *lab, float *gray)
160 {
161 gray[0] = lab[0] / 100;
162 }
163
164 static void lab_to_bgr(fz_context *ctx, fz_color_converter *cc, const float *lab, float *bgr)
165 {
166 float rgb[3];
167 lab_to_rgb(ctx, cc, lab, rgb);
168 rgb_to_bgr(ctx, cc, rgb, bgr);
169 }
170
171 static void lab_to_cmyk(fz_context *ctx, fz_color_converter *cc, const float *lab, float *cmyk)
172 {
173 float rgb[3];
174 lab_to_rgb(ctx, cc, lab, rgb);
175 rgb_to_cmyk(ctx, cc, rgb, cmyk);
176 }
177
178 fz_color_convert_fn *
179 fz_lookup_fast_color_converter(fz_context *ctx, fz_colorspace *ss, fz_colorspace *ds)
180 {
181 int stype = ss->type;
182 int dtype = ds->type;
183
184 if (stype == FZ_COLORSPACE_GRAY)
185 {
186 if (dtype == FZ_COLORSPACE_GRAY) return gray_to_gray;
187 if (dtype == FZ_COLORSPACE_RGB) return gray_to_rgb;
188 if (dtype == FZ_COLORSPACE_BGR) return gray_to_rgb;
189 if (dtype == FZ_COLORSPACE_CMYK) return gray_to_cmyk;
190 }
191
192 else if (stype == FZ_COLORSPACE_RGB)
193 {
194 if (dtype == FZ_COLORSPACE_GRAY) return rgb_to_gray;
195 if (dtype == FZ_COLORSPACE_RGB) return rgb_to_rgb;
196 if (dtype == FZ_COLORSPACE_BGR) return rgb_to_bgr;
197 if (dtype == FZ_COLORSPACE_CMYK) return rgb_to_cmyk;
198 }
199
200 else if (stype == FZ_COLORSPACE_BGR)
201 {
202 if (dtype == FZ_COLORSPACE_GRAY) return bgr_to_gray;
203 if (dtype == FZ_COLORSPACE_RGB) return rgb_to_bgr;
204 if (dtype == FZ_COLORSPACE_BGR) return rgb_to_rgb;
205 if (dtype == FZ_COLORSPACE_CMYK) return bgr_to_cmyk;
206 }
207
208 else if (stype == FZ_COLORSPACE_CMYK)
209 {
210 if (dtype == FZ_COLORSPACE_GRAY) return cmyk_to_gray;
211 if (dtype == FZ_COLORSPACE_RGB) return cmyk_to_rgb;
212 if (dtype == FZ_COLORSPACE_BGR) return cmyk_to_bgr;
213 if (dtype == FZ_COLORSPACE_CMYK) return cmyk_to_cmyk;
214 }
215
216 else if (stype == FZ_COLORSPACE_LAB)
217 {
218 if (dtype == FZ_COLORSPACE_GRAY) return lab_to_gray;
219 if (dtype == FZ_COLORSPACE_RGB) return lab_to_rgb;
220 if (dtype == FZ_COLORSPACE_BGR) return lab_to_bgr;
221 if (dtype == FZ_COLORSPACE_CMYK) return lab_to_cmyk;
222 }
223
224 fz_throw(ctx, FZ_ERROR_ARGUMENT, "cannot find color converter");
225 }
226
227 /* Fast pixmap color conversions */
228
229 static void fast_gray_to_rgb(fz_context *ctx, const fz_pixmap *src, fz_pixmap *dst, int copy_spots)
230 {
231 unsigned char *s = src->samples;
232 unsigned char *d = dst->samples;
233 size_t w = src->w;
234 int h = src->h;
235 int sn = src->n;
236 int ss = src->s;
237 int sa = src->alpha;
238 int dn = dst->n;
239 int ds = dst->s;
240 int da = dst->alpha;
241 ptrdiff_t d_line_inc = dst->stride - w * dn;
242 ptrdiff_t s_line_inc = src->stride - w * sn;
243
244 /* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
245 if (copy_spots && ss != ds)
246 fz_throw(ctx, FZ_ERROR_ARGUMENT, "incompatible number of spots when converting pixmap");
247 if (!da && sa)
248 fz_throw(ctx, FZ_ERROR_ARGUMENT, "cannot drop alpha when converting pixmap");
249
250 if ((int)w < 0 || h < 0)
251 return;
252
253 if (d_line_inc == 0 && s_line_inc == 0)
254 {
255 w *= h;
256 h = 1;
257 }
258
259 if (ss == 0 && ds == 0)
260 {
261 /* Common, no spots case */
262 if (da)
263 {
264 if (sa)
265 {
266 while (h--)
267 {
268 size_t ww = w;
269 while (ww--)
270 {
271 d[0] = s[0];
272 d[1] = s[0];
273 d[2] = s[0];
274 d[3] = s[1];
275 s += 2;
276 d += 4;
277 }
278 d += d_line_inc;
279 s += s_line_inc;
280 }
281 }
282 else
283 {
284 while (h--)
285 {
286 size_t ww = w;
287 while (ww--)
288 {
289 d[0] = s[0];
290 d[1] = s[0];
291 d[2] = s[0];
292 d[3] = 255;
293 s++;
294 d += 4;
295 }
296 d += d_line_inc;
297 s += s_line_inc;
298 }
299 }
300 }
301 else
302 {
303 while (h--)
304 {
305 size_t ww = w;
306 while (ww--)
307 {
308 d[0] = s[0];
309 d[1] = s[0];
310 d[2] = s[0];
311 s++;
312 d += 3;
313 }
314 d += d_line_inc;
315 s += s_line_inc;
316 }
317 }
318 }
319 else if (copy_spots)
320 {
321 /* Slower, spots capable version */
322 int i;
323 while (h--)
324 {
325 size_t ww = w;
326 while (ww--)
327 {
328 d[0] = s[0];
329 d[1] = s[0];
330 d[2] = s[0];
331 s += 1;
332 d += 3;
333 for (i=ss; i > 0; i--)
334 *d++ = *s++;
335 if (da)
336 *d++ = sa ? *s++ : 255;
337 }
338 d += d_line_inc;
339 s += s_line_inc;
340 }
341 }
342 else
343 {
344 while (h--)
345 {
346 size_t ww = w;
347 while (ww--)
348 {
349 d[0] = s[0];
350 d[1] = s[0];
351 d[2] = s[0];
352 s += sn;
353 d += dn;
354 if (da)
355 d[-1] = sa ? s[-1] : 255;
356 }
357 d += d_line_inc;
358 s += s_line_inc;
359 }
360 }
361 }
362
363 static void fast_gray_to_cmyk(fz_context *ctx, const fz_pixmap *src, fz_pixmap *dst, int copy_spots)
364 {
365 unsigned char *s = src->samples;
366 unsigned char *d = dst->samples;
367 size_t w = src->w;
368 int h = src->h;
369 int sn = src->n;
370 int ss = src->s;
371 int sa = src->alpha;
372 int dn = dst->n;
373 int ds = dst->s;
374 int da = dst->alpha;
375 ptrdiff_t d_line_inc = dst->stride - w * dn;
376 ptrdiff_t s_line_inc = src->stride - w * sn;
377 int k, g;
378 int a = 255;
379 int i;
380
381 if (copy_spots && ss != ds)
382 fz_throw(ctx, FZ_ERROR_ARGUMENT, "incompatible number of spots when converting pixmap");
383
384 if ((int)w < 0 || h < 0)
385 fz_throw(ctx, FZ_ERROR_LIMIT, "integer overflow");
386
387 while (h--)
388 {
389 size_t ww = w;
390 while (ww--)
391 {
392 g = s[0];
393
394 if (sa)
395 {
396 a = s[1+ss];
397 g = fz_div255(g, a);
398 }
399
400 k = 255 - g;
401
402 if (da)
403 {
404 *d++ = 0;
405 *d++ = 0;
406 *d++ = 0;
407 *d++ = fz_mul255(k, a);
408 }
409 else
410 {
411 *d++ = 0;
412 *d++ = 0;
413 *d++ = 0;
414 *d++ = k;
415 }
416
417 if (copy_spots)
418 {
419 s += 1;
420 for (i=ss; i > 0; --i)
421 *d++ = *s++;
422 s += sa;
423 }
424 else
425 {
426 s += 1 + ss + sa;
427 d += ds;
428 }
429
430 if (da)
431 {
432 *d++ = a;
433 }
434 }
435 d += d_line_inc;
436 s += s_line_inc;
437 }
438 }
439
440 static void fast_rgb_to_gray(fz_context *ctx, const fz_pixmap *src, fz_pixmap *dst, int copy_spots)
441 {
442 unsigned char *s = src->samples;
443 unsigned char *d = dst->samples;
444 size_t w = src->w;
445 int h = src->h;
446 int sn = src->n;
447 int ss = src->s;
448 int sa = src->alpha;
449 int dn = dst->n;
450 int ds = dst->s;
451 int da = dst->alpha;
452 ptrdiff_t d_line_inc = dst->stride - w * dn;
453 ptrdiff_t s_line_inc = src->stride - w * sn;
454
455 /* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
456 if (copy_spots && ss != ds)
457 fz_throw(ctx, FZ_ERROR_ARGUMENT, "incompatible number of spots when converting pixmap");
458 if (!da && sa)
459 fz_throw(ctx, FZ_ERROR_ARGUMENT, "cannot drop alpha when converting pixmap");
460
461 if ((int)w < 0 || h < 0)
462 return;
463
464 if (d_line_inc == 0 && s_line_inc == 0)
465 {
466 w *= h;
467 h = 1;
468 }
469
470 if (ss == 0 && ds == 0)
471 {
472 /* Common, no spots case */
473 if (da)
474 {
475 if (sa)
476 {
477 while (h--)
478 {
479 size_t ww = w;
480 while (ww--)
481 {
482 d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
483 d[1] = s[3];
484 s += 4;
485 d += 2;
486 }
487 d += d_line_inc;
488 s += s_line_inc;
489 }
490 }
491 else
492 {
493 while (h--)
494 {
495 size_t ww = w;
496 while (ww--)
497 {
498 d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
499 d[1] = 255;
500 s += 3;
501 d += 2;
502 }
503 d += d_line_inc;
504 s += s_line_inc;
505 }
506 }
507 }
508 else
509 {
510 while (h--)
511 {
512 size_t ww = w;
513 while (ww--)
514 {
515 d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
516 s += 3;
517 d++;
518 }
519 d += d_line_inc;
520 s += s_line_inc;
521 }
522 }
523 }
524 else if (copy_spots)
525 {
526 /* Slower, spots capable version */
527 int i;
528 while (h--)
529 {
530 size_t ww = w;
531 while (ww--)
532 {
533 d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
534 s += 3;
535 d++;
536 for (i=ss; i > 0; i--)
537 *d++ = *s++;
538 if (da)
539 *d++ = sa ? *s++ : 255;
540 }
541 d += d_line_inc;
542 s += s_line_inc;
543 }
544 }
545 else
546 {
547 while (h--)
548 {
549 size_t ww = w;
550 while (ww--)
551 {
552 d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
553 s += sn;
554 d += dn;
555 if (da)
556 d[-1] = sa ? s[-1] : 255;
557 }
558 d += d_line_inc;
559 s += s_line_inc;
560 }
561 }
562 }
563
564 static void fast_bgr_to_gray(fz_context *ctx, const fz_pixmap *src, fz_pixmap *dst, int copy_spots)
565 {
566 unsigned char *s = src->samples;
567 unsigned char *d = dst->samples;
568 size_t w = src->w;
569 int h = src->h;
570 int sn = src->n;
571 int ss = src->s;
572 int sa = src->alpha;
573 int dn = dst->n;
574 int ds = dst->s;
575 int da = dst->alpha;
576 ptrdiff_t d_line_inc = dst->stride - w * dn;
577 ptrdiff_t s_line_inc = src->stride - w * sn;
578
579 /* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
580 if (copy_spots && ss != ds)
581 fz_throw(ctx, FZ_ERROR_ARGUMENT, "incompatible number of spots when converting pixmap");
582 if (!da && sa)
583 fz_throw(ctx, FZ_ERROR_ARGUMENT, "cannot drop alpha when converting pixmap");
584
585 if ((int)w < 0 || h < 0)
586 return;
587
588 if (d_line_inc == 0 && s_line_inc == 0)
589 {
590 w *= h;
591 h = 1;
592 }
593
594 if (ss == 0 && ds == 0)
595 {
596 /* Common, no spots case */
597 if (da)
598 {
599 if (sa)
600 {
601 while (h--)
602 {
603 size_t ww = w;
604 while (ww--)
605 {
606 d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
607 d[1] = s[3];
608 s += 4;
609 d += 2;
610 }
611 d += d_line_inc;
612 s += s_line_inc;
613 }
614 }
615 else
616 {
617 while (h--)
618 {
619 size_t ww = w;
620 while (ww--)
621 {
622 d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
623 d[1] = 255;
624 s += 3;
625 d += 2;
626 }
627 d += d_line_inc;
628 s += s_line_inc;
629 }
630 }
631 }
632 else
633 {
634 int si = 3 + src->alpha;
635
636 while (h--)
637 {
638 size_t ww = w;
639 while (ww--)
640 {
641 d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
642 s += si;
643 d++;
644 }
645 d += d_line_inc;
646 s += s_line_inc;
647 }
648 }
649 }
650 else if (copy_spots)
651 {
652 /* Slower, spots capable version */
653 while (h--)
654 {
655 int i;
656 size_t ww = w;
657 while (ww--)
658 {
659 d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
660 s += 3;
661 d++;
662 for (i=ss; i > 0; i--)
663 *d++ = *s++;
664 if (da)
665 *d++ = sa ? *s++ : 255;
666 }
667 d += d_line_inc;
668 s += s_line_inc;
669 }
670 }
671 else
672 {
673 /* Slower, spots capable version */
674 while (h--)
675 {
676 size_t ww = w;
677 while (ww--)
678 {
679 d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
680 s += sn;
681 d += dn;
682 if (da)
683 d[-1] = sa ? s[-1] : 255;
684 }
685 d += d_line_inc;
686 s += s_line_inc;
687 }
688 }
689 }
690
691 static void fast_rgb_to_cmyk(fz_context *ctx, const fz_pixmap *src, fz_pixmap *dst, int copy_spots)
692 {
693 unsigned char *s = src->samples;
694 unsigned char *d = dst->samples;
695 size_t w = src->w;
696 int h = src->h;
697 int sn = src->n;
698 int ss = src->s;
699 int sa = src->alpha;
700 int dn = dst->n;
701 int ds = dst->s;
702 int da = dst->alpha;
703 ptrdiff_t d_line_inc = dst->stride - w * dn;
704 ptrdiff_t s_line_inc = src->stride - w * sn;
705 int c, m, y, k, r, g, b;
706 int a = 255;
707 int i;
708
709 if (copy_spots && ss != ds)
710 fz_throw(ctx, FZ_ERROR_ARGUMENT, "incompatible number of spots when converting pixmap");
711
712 if ((int)w < 0 || h < 0)
713 fz_throw(ctx, FZ_ERROR_LIMIT, "integer overflow");
714
715 while (h--)
716 {
717 size_t ww = w;
718 while (ww--)
719 {
720 r = s[0];
721 g = s[1];
722 b = s[2];
723
724 if (sa)
725 {
726 a = s[3+ss];
727 r = fz_div255(r, a);
728 g = fz_div255(g, a);
729 b = fz_div255(b, a);
730 }
731
732 c = 255 - r;
733 m = 255 - g;
734 y = 255 - b;
735 k = fz_mini(c, fz_mini(m, y));
736 c = c - k;
737 m = m - k;
738 y = y - k;
739
740 if (da)
741 {
742 *d++ = fz_mul255(c, a);
743 *d++ = fz_mul255(m, a);
744 *d++ = fz_mul255(y, a);
745 *d++ = fz_mul255(k, a);
746 }
747 else
748 {
749 *d++ = c;
750 *d++ = m;
751 *d++ = y;
752 *d++ = k;
753 }
754
755 if (copy_spots)
756 {
757 s += 3;
758 for (i=ss; i > 0; --i)
759 *d++ = *s++;
760 s += sa;
761 }
762 else
763 {
764 s += 3 + ss + sa;
765 d += ds;
766 }
767
768 if (da)
769 {
770 *d++ = a;
771 }
772 }
773 d += d_line_inc;
774 s += s_line_inc;
775 }
776 }
777
778 static void fast_bgr_to_cmyk(fz_context *ctx, const fz_pixmap *src, fz_pixmap *dst, int copy_spots)
779 {
780 unsigned char *s = src->samples;
781 unsigned char *d = dst->samples;
782 size_t w = src->w;
783 int h = src->h;
784 int sn = src->n;
785 int ss = src->s;
786 int sa = src->alpha;
787 int dn = dst->n;
788 int ds = dst->s;
789 int da = dst->alpha;
790 ptrdiff_t d_line_inc = dst->stride - w * dn;
791 ptrdiff_t s_line_inc = src->stride - w * sn;
792 int c, m, y, k, r, g, b;
793 int a = 255;
794 int i;
795
796 if (copy_spots && ss != ds)
797 fz_throw(ctx, FZ_ERROR_ARGUMENT, "incompatible number of spots when converting pixmap");
798
799 if ((int)w < 0 || h < 0)
800 fz_throw(ctx, FZ_ERROR_LIMIT, "integer overflow");
801
802 while (h--)
803 {
804 size_t ww = w;
805 while (ww--)
806 {
807 b = s[0];
808 g = s[1];
809 r = s[2];
810
811 if (sa)
812 {
813 a = s[3+ss];
814 r = fz_div255(r, a);
815 g = fz_div255(g, a);
816 b = fz_div255(b, a);
817 }
818
819 c = 255 - r;
820 m = 255 - g;
821 y = 255 - b;
822 k = fz_mini(c, fz_mini(m, y));
823 c = c - k;
824 m = m - k;
825 y = y - k;
826
827 if (da)
828 {
829 *d++ = fz_mul255(c, a);
830 *d++ = fz_mul255(m, a);
831 *d++ = fz_mul255(y, a);
832 *d++ = fz_mul255(k, a);
833 }
834 else
835 {
836 *d++ = c;
837 *d++ = m;
838 *d++ = y;
839 *d++ = k;
840 }
841
842 if (copy_spots)
843 {
844 s += 3;
845 for (i=ss; i > 0; --i)
846 *d++ = *s++;
847 s += sa;
848 }
849 else
850 {
851 s += 3 + ss + sa;
852 d += ds;
853 }
854
855 if (da)
856 {
857 *d++ = a;
858 }
859 }
860 d += d_line_inc;
861 s += s_line_inc;
862 }
863 }
864
865 static void fast_cmyk_to_gray(fz_context *ctx, const fz_pixmap *src, fz_pixmap *dst, int copy_spots)
866 {
867 unsigned char *s = src->samples;
868 unsigned char *d = dst->samples;
869 size_t w = src->w;
870 int h = src->h;
871 int sn = src->n;
872 int ss = src->s;
873 int sa = src->alpha;
874 int dn = dst->n;
875 int ds = dst->s;
876 int da = dst->alpha;
877 ptrdiff_t d_line_inc = dst->stride - w * dn;
878 ptrdiff_t s_line_inc = src->stride - w * sn;
879 int c, m, y, k, g;
880 int a = 255;
881 int i;
882
883 if (copy_spots && ss != ds)
884 fz_throw(ctx, FZ_ERROR_ARGUMENT, "incompatible number of spots when converting pixmap");
885
886 if ((int)w < 0 || h < 0)
887 fz_throw(ctx, FZ_ERROR_LIMIT, "integer overflow");
888
889 while (h--)
890 {
891 size_t ww = w;
892 while (ww--)
893 {
894 c = s[0];
895 m = s[1];
896 y = s[2];
897 k = s[3];
898
899 if (sa)
900 {
901 a = s[4+ss];
902 c = fz_div255(c, a);
903 m = fz_div255(m, a);
904 y = fz_div255(y, a);
905 k = fz_div255(k, a);
906 }
907
908 g = 255 - fz_mini(c + m + y + k, 255);
909
910 if (da)
911 {
912 *d++ = fz_mul255(g, a);
913 }
914 else
915 {
916 *d++ = g;
917 }
918
919 if (copy_spots)
920 {
921 s += 4;
922 for (i=ss; i > 0; --i)
923 *d++ = *s++;
924 s += sa;
925 }
926 else
927 {
928 s += 4 + ss + sa;
929 d += ds;
930 }
931
932 if (da)
933 {
934 *d++ = a;
935 }
936 }
937 d += d_line_inc;
938 s += s_line_inc;
939 }
940 }
941
942 static void fast_cmyk_to_rgb(fz_context *ctx, const fz_pixmap *src, fz_pixmap *dst, int copy_spots)
943 {
944 unsigned char *s = src->samples;
945 unsigned char *d = dst->samples;
946 size_t w = src->w;
947 int h = src->h;
948 int sn = src->n;
949 int ss = src->s;
950 int sa = src->alpha;
951 int dn = dst->n;
952 int ds = dst->s;
953 int da = dst->alpha;
954 ptrdiff_t d_line_inc = dst->stride - w * dn;
955 ptrdiff_t s_line_inc = src->stride - w * sn;
956 int c, m, y, k, r, g, b;
957 int a = 255;
958 int i;
959
960 if (copy_spots && ss != ds)
961 fz_throw(ctx, FZ_ERROR_ARGUMENT, "incompatible number of spots when converting pixmap");
962
963 if ((int)w < 0 || h < 0)
964 fz_throw(ctx, FZ_ERROR_LIMIT, "integer overflow");
965
966 while (h--)
967 {
968 size_t ww = w;
969 while (ww--)
970 {
971 c = s[0];
972 m = s[1];
973 y = s[2];
974 k = s[3];
975
976 if (sa)
977 {
978 a = s[4+ss];
979 c = fz_div255(c, a);
980 m = fz_div255(m, a);
981 y = fz_div255(y, a);
982 k = fz_div255(k, a);
983 }
984
985 r = 255 - fz_mini(c + k, 255);
986 g = 255 - fz_mini(m + k, 255);
987 b = 255 - fz_mini(y + k, 255);
988
989 if (da)
990 {
991 *d++ = fz_mul255(r, a);
992 *d++ = fz_mul255(g, a);
993 *d++ = fz_mul255(b, a);
994 }
995 else
996 {
997 *d++ = r;
998 *d++ = g;
999 *d++ = b;
1000 }
1001
1002 if (copy_spots)
1003 {
1004 s += 4;
1005 for (i=ss; i > 0; --i)
1006 *d++ = *s++;
1007 s += sa;
1008 }
1009 else
1010 {
1011 s += 4 + ss + sa;
1012 d += ds;
1013 }
1014
1015 if (da)
1016 {
1017 *d++ = a;
1018 }
1019 }
1020 d += d_line_inc;
1021 s += s_line_inc;
1022 }
1023 }
1024
1025 static void fast_cmyk_to_bgr(fz_context *ctx, const fz_pixmap *src, fz_pixmap *dst, int copy_spots)
1026 {
1027 unsigned char *s = src->samples;
1028 unsigned char *d = dst->samples;
1029 size_t w = src->w;
1030 int h = src->h;
1031 int sn = src->n;
1032 int ss = src->s;
1033 int sa = src->alpha;
1034 int dn = dst->n;
1035 int ds = dst->s;
1036 int da = dst->alpha;
1037 ptrdiff_t d_line_inc = dst->stride - w * dn;
1038 ptrdiff_t s_line_inc = src->stride - w * sn;
1039 int c, m, y, k, r, g, b;
1040 int a = 255;
1041 int i;
1042
1043 if (copy_spots && ss != ds)
1044 fz_throw(ctx, FZ_ERROR_ARGUMENT, "incompatible number of spots when converting pixmap");
1045
1046 if ((int)w < 0 || h < 0)
1047 fz_throw(ctx, FZ_ERROR_LIMIT, "integer overflow");
1048
1049 while (h--)
1050 {
1051 size_t ww = w;
1052 while (ww--)
1053 {
1054 c = s[0];
1055 m = s[1];
1056 y = s[2];
1057 k = s[3];
1058
1059 if (sa)
1060 {
1061 a = s[4+ss];
1062 c = fz_div255(c, a);
1063 m = fz_div255(m, a);
1064 y = fz_div255(y, a);
1065 k = fz_div255(k, a);
1066 }
1067
1068 r = 255 - fz_mini(c + k, 255);
1069 g = 255 - fz_mini(m + k, 255);
1070 b = 255 - fz_mini(y + k, 255);
1071
1072 if (da)
1073 {
1074 *d++ = fz_mul255(b, a);
1075 *d++ = fz_mul255(g, a);
1076 *d++ = fz_mul255(r, a);
1077 }
1078 else
1079 {
1080 *d++ = b;
1081 *d++ = g;
1082 *d++ = r;
1083 }
1084
1085 if (copy_spots)
1086 {
1087 s += 4;
1088 for (i=ss; i > 0; --i)
1089 *d++ = *s++;
1090 s += sa;
1091 }
1092 else
1093 {
1094 s += 4 + ss + sa;
1095 d += ds;
1096 }
1097
1098 if (da)
1099 {
1100 *d++ = a;
1101 }
1102 }
1103 d += d_line_inc;
1104 s += s_line_inc;
1105 }
1106 }
1107
1108 static void fast_rgb_to_bgr(fz_context *ctx, const fz_pixmap *src, fz_pixmap *dst, int copy_spots)
1109 {
1110 unsigned char *s = src->samples;
1111 unsigned char *d = dst->samples;
1112 size_t w = src->w;
1113 int h = src->h;
1114 int sn = src->n;
1115 int ss = src->s;
1116 int sa = src->alpha;
1117 int dn = dst->n;
1118 int ds = dst->s;
1119 int da = dst->alpha;
1120 ptrdiff_t d_line_inc = dst->stride - w * dn;
1121 ptrdiff_t s_line_inc = src->stride - w * sn;
1122
1123 /* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
1124 if (copy_spots && ss != ds)
1125 fz_throw(ctx, FZ_ERROR_ARGUMENT, "incompatible number of spots when converting pixmap");
1126 if (!da && sa)
1127 fz_throw(ctx, FZ_ERROR_ARGUMENT, "cannot drop alpha when converting pixmap");
1128
1129 if ((int)w < 0 || h < 0)
1130 return;
1131
1132 if (d_line_inc == 0 && s_line_inc == 0)
1133 {
1134 w *= h;
1135 h = 1;
1136 }
1137
1138 if (ss == 0 && ds == 0)
1139 {
1140 /* Common, no spots case */
1141 if (da)
1142 {
1143 if (sa)
1144 {
1145 while (h--)
1146 {
1147 size_t ww = w;
1148 while (ww--)
1149 {
1150 d[0] = s[2];
1151 d[1] = s[1];
1152 d[2] = s[0];
1153 d[3] = s[3];
1154 s += 4;
1155 d += 4;
1156 }
1157 }
1158 }
1159 else
1160 {
1161 while (h--)
1162 {
1163 size_t ww = w;
1164 while (ww--)
1165 {
1166 d[0] = s[2];
1167 d[1] = s[1];
1168 d[2] = s[0];
1169 d[3] = 255;
1170 s += 3;
1171 d += 4;
1172 }
1173 }
1174 }
1175 }
1176 else
1177 {
1178 while (h--)
1179 {
1180 size_t ww = w;
1181 while (ww--)
1182 {
1183 d[0] = s[2];
1184 d[1] = s[1];
1185 d[2] = s[0];
1186 s += 3;
1187 d += 3;
1188 }
1189 }
1190 }
1191 }
1192 else if (copy_spots)
1193 {
1194 /* Slower, spots capable version */
1195 while (h--)
1196 {
1197 int i;
1198 size_t ww = w;
1199 while (ww--)
1200 {
1201 d[0] = s[2];
1202 d[1] = s[1];
1203 d[2] = s[0];
1204 s += 3;
1205 d += 3;
1206 for (i=ss; i > 0; i--)
1207 *d++ = *s++;
1208 if (da)
1209 *d++ = sa ? *s++ : 255;
1210 }
1211 d += d_line_inc;
1212 s += s_line_inc;
1213 }
1214 }
1215 else
1216 {
1217 while (h--)
1218 {
1219 size_t ww = w;
1220 while (ww--)
1221 {
1222 d[0] = s[2];
1223 d[1] = s[1];
1224 d[2] = s[0];
1225 s += sn;
1226 d += dn;
1227 if (da)
1228 d[-1] = sa ? s[-1] : 255;
1229 }
1230 d += d_line_inc;
1231 s += s_line_inc;
1232 }
1233 }
1234 }
1235
1236 static void fast_gray_to_gray(fz_context *ctx, const fz_pixmap *src, fz_pixmap *dst, int copy_spots)
1237 {
1238 unsigned char *s = src->samples;
1239 unsigned char *d = dst->samples;
1240 size_t w = src->w;
1241 int h = src->h;
1242 int sn = src->n;
1243 int ss = src->s;
1244 int sa = src->alpha;
1245 int dn = dst->n;
1246 int ds = dst->s;
1247 int da = dst->alpha;
1248 ptrdiff_t d_line_inc = dst->stride - w * dn;
1249 ptrdiff_t s_line_inc = src->stride - w * sn;
1250
1251 if ((int)w < 0 || h < 0)
1252 return;
1253
1254 /* Alpha-only pixmaps count as device_gray with no alpha. */
1255 if (sn == 1 && sa)
1256 sa = 0;
1257 if (dn == 1 && da)
1258 da = 0;
1259
1260 /* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
1261 if (copy_spots && ss != ds)
1262 fz_throw(ctx, FZ_ERROR_ARGUMENT, "incompatible number of spots when converting pixmap");
1263 if (!da && sa)
1264 fz_throw(ctx, FZ_ERROR_ARGUMENT, "cannot drop alpha when converting pixmap");
1265
1266 if (d_line_inc == 0 && s_line_inc == 0)
1267 {
1268 w *= h;
1269 h = 1;
1270 }
1271
1272 if (ss == 0 && ds == 0)
1273 {
1274 /* Common, no spots case */
1275 if (da)
1276 {
1277 if (sa)
1278 {
1279 while (h--)
1280 {
1281 size_t ww = w;
1282 while (ww--)
1283 {
1284 d[0] = s[0];
1285 d[1] = s[1];
1286 s += 2;
1287 d += 2;
1288 }
1289 }
1290 }
1291 else
1292 {
1293 while (h--)
1294 {
1295 size_t ww = w;
1296 while (ww--)
1297 {
1298 d[0] = s[0];
1299 d[1] = 255;
1300 s += 1;
1301 d += 2;
1302 }
1303 }
1304 }
1305 }
1306 else
1307 {
1308 while (h--)
1309 {
1310 size_t ww = w;
1311 while (ww--)
1312 {
1313 d[0] = s[0];
1314 s += 1;
1315 d += 1;
1316 }
1317 }
1318 }
1319 }
1320 else if (copy_spots)
1321 {
1322 /* Slower, spots capable version */
1323 while (h--)
1324 {
1325 int i;
1326 size_t ww = w;
1327 while (ww--)
1328 {
1329 d[0] = s[0];
1330 s += 1;
1331 d += 1;
1332 for (i=ss; i > 0; i--)
1333 *d++ = *s++;
1334 if (da)
1335 *d++ = sa ? *s++ : 255;
1336 }
1337 d += d_line_inc;
1338 s += s_line_inc;
1339 }
1340 }
1341 else
1342 {
1343 while (h--)
1344 {
1345 size_t ww = w;
1346 while (ww--)
1347 {
1348 d[0] = s[0];
1349 s += sn;
1350 d += dn;
1351 if (da)
1352 d[-1] = sa ? s[-1] : 255;
1353 }
1354 d += d_line_inc;
1355 s += s_line_inc;
1356 }
1357 }
1358 }
1359
1360 static void fast_rgb_to_rgb(fz_context *ctx, const fz_pixmap *src, fz_pixmap *dst, int copy_spots)
1361 {
1362 unsigned char *s = src->samples;
1363 unsigned char *d = dst->samples;
1364 size_t w = src->w;
1365 int h = src->h;
1366 int sn = src->n;
1367 int ss = src->s;
1368 int sa = src->alpha;
1369 int dn = dst->n;
1370 int ds = dst->s;
1371 int da = dst->alpha;
1372 ptrdiff_t d_line_inc = dst->stride - w * dn;
1373 ptrdiff_t s_line_inc = src->stride - w * sn;
1374
1375 /* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
1376 if (copy_spots && ss != ds)
1377 fz_throw(ctx, FZ_ERROR_ARGUMENT, "incompatible number of spots when converting pixmap");
1378 if (!da && sa)
1379 fz_throw(ctx, FZ_ERROR_ARGUMENT, "cannot drop alpha when converting pixmap");
1380
1381 if ((int)w < 0 || h < 0)
1382 return;
1383
1384 if (d_line_inc == 0 && s_line_inc == 0)
1385 {
1386 w *= h;
1387 h = 1;
1388 }
1389
1390 if (ss == 0 && ds == 0)
1391 {
1392 /* Common, no spots case */
1393 if (da)
1394 {
1395 if (sa)
1396 {
1397 while (h--)
1398 {
1399 size_t ww = w;
1400 while (ww--)
1401 {
1402 d[0] = s[0];
1403 d[1] = s[1];
1404 d[2] = s[2];
1405 d[3] = s[3];
1406 s += 4;
1407 d += 4;
1408 }
1409 }
1410 }
1411 else
1412 {
1413 while (h--)
1414 {
1415 size_t ww = w;
1416 while (ww--)
1417 {
1418 d[0] = s[0];
1419 d[1] = s[1];
1420 d[2] = s[2];
1421 d[3] = 255;
1422 s += 3;
1423 d += 4;
1424 }
1425 }
1426 }
1427 }
1428 else
1429 {
1430 while (h--)
1431 {
1432 size_t ww = w;
1433 while (ww--)
1434 {
1435 d[0] = s[0];
1436 d[1] = s[1];
1437 d[2] = s[2];
1438 s += 3;
1439 d += 3;
1440 }
1441 }
1442 }
1443 }
1444 else if (copy_spots)
1445 {
1446 /* Slower, spots capable version */
1447 while (h--)
1448 {
1449 int i;
1450 size_t ww = w;
1451 while (ww--)
1452 {
1453 d[0] = s[0];
1454 d[1] = s[1];
1455 d[2] = s[2];
1456 s += 3;
1457 d += 3;
1458 for (i=ss; i > 0; i--)
1459 *d++ = *s++;
1460 if (da)
1461 *d++ = sa ? *s++ : 255;
1462 }
1463 d += d_line_inc;
1464 s += s_line_inc;
1465 }
1466 }
1467 else
1468 {
1469 while (h--)
1470 {
1471 size_t ww = w;
1472 while (ww--)
1473 {
1474 d[0] = s[0];
1475 d[1] = s[1];
1476 d[2] = s[2];
1477 s += sn;
1478 d += dn;
1479 if (da)
1480 d[-1] = sa ? s[-1] : 255;
1481 }
1482 d += d_line_inc;
1483 s += s_line_inc;
1484 }
1485 }
1486 }
1487
1488 static void fast_cmyk_to_cmyk(fz_context *ctx, const fz_pixmap *src, fz_pixmap *dst, int copy_spots)
1489 {
1490 unsigned char *s = src->samples;
1491 unsigned char *d = dst->samples;
1492 size_t w = src->w;
1493 int h = src->h;
1494 int sn = src->n;
1495 int ss = src->s;
1496 int sa = src->alpha;
1497 int dn = dst->n;
1498 int ds = dst->s;
1499 int da = dst->alpha;
1500 ptrdiff_t d_line_inc = dst->stride - w * dn;
1501 ptrdiff_t s_line_inc = src->stride - w * sn;
1502
1503 /* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
1504 if (copy_spots && ss != ds)
1505 fz_throw(ctx, FZ_ERROR_ARGUMENT, "incompatible number of spots when converting pixmap");
1506 if (!da && sa)
1507 fz_throw(ctx, FZ_ERROR_ARGUMENT, "cannot drop alpha when converting pixmap");
1508
1509 if ((int)w < 0 || h < 0)
1510 return;
1511
1512 if (d_line_inc == 0 && s_line_inc == 0)
1513 {
1514 w *= h;
1515 h = 1;
1516 }
1517
1518 if (ss == 0 && ds == 0)
1519 {
1520 /* Common, no spots case */
1521 if (da)
1522 {
1523 if (sa)
1524 {
1525 while (h--)
1526 {
1527 size_t ww = w;
1528 while (ww--)
1529 {
1530 d[0] = s[0];
1531 d[1] = s[1];
1532 d[2] = s[2];
1533 d[3] = s[3];
1534 d[4] = s[4];
1535 s += 5;
1536 d += 5;
1537 }
1538 }
1539 }
1540 else
1541 {
1542 while (h--)
1543 {
1544 size_t ww = w;
1545 while (ww--)
1546 {
1547 d[0] = s[0];
1548 d[1] = s[1];
1549 d[2] = s[2];
1550 d[3] = s[3];
1551 d[4] = 255;
1552 s += 4;
1553 d += 5;
1554 }
1555 }
1556 }
1557 }
1558 else
1559 {
1560 while (h--)
1561 {
1562 size_t ww = w;
1563 while (ww--)
1564 {
1565 d[0] = s[0];
1566 d[1] = s[1];
1567 d[2] = s[2];
1568 d[3] = s[3];
1569 s += 4;
1570 d += 4;
1571 }
1572 }
1573 }
1574 }
1575 else if (copy_spots)
1576 {
1577 /* Slower, spots capable version */
1578 while (h--)
1579 {
1580 int i;
1581 size_t ww = w;
1582 while (ww--)
1583 {
1584 d[0] = s[0];
1585 d[1] = s[1];
1586 d[2] = s[2];
1587 d[3] = s[3];
1588 s += 4;
1589 d += 4;
1590 for (i=ss; i > 0; i--)
1591 *d++ = *s++;
1592 if (da)
1593 *d++ = sa ? *s++ : 255;
1594 }
1595 d += d_line_inc;
1596 s += s_line_inc;
1597 }
1598 }
1599 else
1600 {
1601 while (h--)
1602 {
1603 size_t ww = w;
1604 while (ww--)
1605 {
1606 d[0] = s[0];
1607 d[1] = s[1];
1608 d[2] = s[2];
1609 d[3] = s[3];
1610 s += sn;
1611 d += dn;
1612 if (da)
1613 d[-1] = sa ? s[-1] : 255;
1614 }
1615 d += d_line_inc;
1616 s += s_line_inc;
1617 }
1618 }
1619 }
1620
1621 void
1622 fz_fast_any_to_alpha(fz_context *ctx, const fz_pixmap *src, fz_pixmap *dst, int copy_spots)
1623 {
1624 if (!src->alpha)
1625 fz_clear_pixmap_with_value(ctx, dst, 255);
1626 else
1627 {
1628 unsigned char *s = src->samples;
1629 unsigned char *d = dst->samples;
1630 size_t w = src->w;
1631 int h = src->h;
1632 int n = src->n;
1633 ptrdiff_t d_line_inc = dst->stride - w * dst->n;
1634 ptrdiff_t s_line_inc = src->stride - w * src->n;
1635
1636 if ((int)w < 0 || h < 0)
1637 return;
1638
1639 if (d_line_inc == 0 && s_line_inc == 0)
1640 {
1641 w *= h;
1642 h = 1;
1643 }
1644
1645 s += n-1;
1646 while (h--)
1647 {
1648 size_t ww = w;
1649 while (ww--)
1650 {
1651 *d++ = *s;
1652 s += n;
1653 }
1654 d += d_line_inc;
1655 s += s_line_inc;
1656 }
1657 }
1658 }
1659
1660 void
1661 fz_convert_fast_pixmap_samples(fz_context *ctx, const fz_pixmap *src, fz_pixmap *dst, int copy_spots)
1662 {
1663 fz_colorspace *ss = src->colorspace;
1664 fz_colorspace *ds = dst->colorspace;
1665 int dtype = ds ? ds->type : FZ_COLORSPACE_GRAY;
1666 int stype = ss ? ss->type : FZ_COLORSPACE_GRAY;
1667
1668 if (!ds)
1669 {
1670 fz_fast_any_to_alpha(ctx, src, dst, copy_spots);
1671 }
1672
1673 else if (stype == FZ_COLORSPACE_GRAY)
1674 {
1675 if (dtype == FZ_COLORSPACE_GRAY)
1676 fast_gray_to_gray(ctx, src, dst, copy_spots);
1677 else if (dtype == FZ_COLORSPACE_RGB)
1678 fast_gray_to_rgb(ctx, src, dst, copy_spots);
1679 else if (dtype == FZ_COLORSPACE_BGR)
1680 fast_gray_to_rgb(ctx, src, dst, copy_spots);
1681 else if (dtype == FZ_COLORSPACE_CMYK)
1682 fast_gray_to_cmyk(ctx, src, dst, copy_spots);
1683 else
1684 goto slow;
1685 }
1686
1687 else if (stype == FZ_COLORSPACE_RGB)
1688 {
1689 if (dtype == FZ_COLORSPACE_GRAY)
1690 fast_rgb_to_gray(ctx, src, dst, copy_spots);
1691 else if (dtype == FZ_COLORSPACE_RGB)
1692 fast_rgb_to_rgb(ctx, src, dst, copy_spots);
1693 else if (dtype == FZ_COLORSPACE_BGR)
1694 fast_rgb_to_bgr(ctx, src, dst, copy_spots);
1695 else if (dtype == FZ_COLORSPACE_CMYK)
1696 fast_rgb_to_cmyk(ctx, src, dst, copy_spots);
1697 else
1698 goto slow;
1699 }
1700
1701 else if (stype == FZ_COLORSPACE_BGR)
1702 {
1703 if (dtype == FZ_COLORSPACE_GRAY)
1704 fast_bgr_to_gray(ctx, src, dst, copy_spots);
1705 else if (dtype == FZ_COLORSPACE_RGB)
1706 fast_rgb_to_bgr(ctx, src, dst, copy_spots);
1707 else if (dtype == FZ_COLORSPACE_BGR)
1708 fast_rgb_to_rgb(ctx, src, dst, copy_spots);
1709 else if (dtype == FZ_COLORSPACE_CMYK)
1710 fast_bgr_to_cmyk(ctx, src, dst, copy_spots);
1711 else
1712 goto slow;
1713 }
1714
1715 else if (stype == FZ_COLORSPACE_CMYK)
1716 {
1717 if (dtype == FZ_COLORSPACE_GRAY)
1718 fast_cmyk_to_gray(ctx, src, dst, copy_spots);
1719 else if (dtype == FZ_COLORSPACE_RGB)
1720 fast_cmyk_to_rgb(ctx, src, dst, copy_spots);
1721 else if (dtype == FZ_COLORSPACE_BGR)
1722 fast_cmyk_to_bgr(ctx, src, dst, copy_spots);
1723 else if (dtype == FZ_COLORSPACE_CMYK)
1724 fast_cmyk_to_cmyk(ctx, src, dst, copy_spots);
1725 else
1726 goto slow;
1727 }
1728 else
1729 {
1730 goto slow;
1731 }
1732 return;
1733
1734 slow:
1735 fz_convert_slow_pixmap_samples(ctx, src, dst, NULL, fz_default_color_params, copy_spots);
1736 }