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