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