]> git.ipfire.org Git - thirdparty/cups.git/blob - filter/image-colorspace.c
Copyright update...
[thirdparty/cups.git] / filter / image-colorspace.c
1 /*
2 * "$Id: image-colorspace.c,v 1.24 2002/01/02 17:58:58 mike Exp $"
3 *
4 * Colorspace conversions for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1993-2002 by Easy Software Products.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
19 *
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
26 * ImageSetProfile() - Set the device color profile.
27 * ImageWhiteToWhite() - Convert luminance colors to device-dependent
28 * ImageWhiteToRGB() - Convert luminance data to RGB.
29 * ImageWhiteToBlack() - Convert luminance colors to black.
30 * ImageWhiteToCMY() - Convert luminance colors to CMY.
31 * ImageWhiteToCMYK() - Convert luminance colors to CMYK.
32 * ImageRGBToBlack() - Convert RGB data to black.
33 * ImageRGBToCMY() - Convert RGB colors to CMY.
34 * ImageRGBToCMYK() - Convert RGB colors to CMYK.
35 * ImageRGBToWhite() - Convert RGB colors to luminance.
36 * ImageRGBToRGB() - Convert RGB colors to device-dependent RGB.
37 * ImageLut() - Adjust all pixel values with the given LUT.
38 * ImageRGBAdjust() - Adjust the hue and saturation of the given RGB
39 * colors.
40 * huerotate() - Rotate the hue, maintaining luminance.
41 * ident() - Make an identity matrix.
42 * mult() - Multiply two matrices.
43 * saturate() - Make a saturation matrix.
44 * xform() - Transform a 3D point using a matrix...
45 * xrotate() - Rotate about the x (red) axis...
46 * yrotate() - Rotate about the y (green) axis...
47 * zrotate() - Rotate about the z (blue) axis...
48 * zshear() - Shear z using x and y...
49 */
50
51 /*
52 * Include necessary headers...
53 */
54
55 #include "image.h"
56 #include <math.h>
57
58
59 /*
60 * Local globals...
61 */
62
63 static int ImageHaveProfile = 0; /* Do we have a color profile? */
64 static int ImageDensity[256]; /* Ink/marker density LUT */
65 static int ImageMatrix[3][3][256]; /* Color transform matrix LUT */
66
67
68 /*
69 * Local functions...
70 */
71
72 static void huerotate(float [3][3], float);
73 static void ident(float [3][3]);
74 static void mult(float [3][3], float [3][3], float [3][3]);
75 static void saturate(float [3][3], float);
76 static void xform(float [3][3], float, float, float, float *, float *, float *);
77 static void xrotate(float [3][3], float, float);
78 static void yrotate(float [3][3], float, float);
79 static void zrotate(float [3][3], float, float);
80 static void zshear(float [3][3], float, float);
81
82
83 /*
84 * 'ImageSetProfile()' - Set the device color profile.
85 */
86
87 void
88 ImageSetProfile(float d, /* I - Ink/marker density */
89 float g, /* I - Ink/marker gamma */
90 float matrix[3][3]) /* I - Color transform matrix */
91 {
92 int i, j, k; /* Looping vars */
93 float m; /* Current matrix value */
94 int *im; /* Pointer into ImageMatrix */
95
96 ImageHaveProfile = 1;
97
98 for (i = 0, im = ImageMatrix[0][0]; i < 3; i ++)
99 for (j = 0; j < 3; j ++)
100 for (k = 0, m = matrix[i][j]; k < 256; k ++)
101 *im++ = (int)(k * m + 0.5);
102
103 for (k = 0, im = ImageDensity; k < 256; k ++)
104 *im++ = 255.0 * d * pow((float)k / 255.0, g) + 0.5;
105 }
106
107
108 /*
109 * 'ImageWhiteToWhite()' - Convert luminance colors to device-dependent
110 * luminance.
111 */
112
113 void
114 ImageWhiteToWhite(const ib_t *in, /* I - Input pixels */
115 ib_t *out, /* I - Output pixels */
116 int count) /* I - Number of pixels */
117 {
118 if (ImageHaveProfile)
119 while (count > 0)
120 {
121 *out++ = 255 - ImageDensity[255 - *in++];
122 count --;
123 }
124 else if (in != out)
125 memcpy(out, in, count);
126 }
127
128
129 /*
130 * 'ImageWhiteToRGB()' - Convert luminance data to RGB.
131 */
132
133 void
134 ImageWhiteToRGB(const ib_t *in, /* I - Input pixels */
135 ib_t *out, /* I - Output pixels */
136 int count) /* I - Number of pixels */
137 {
138 if (ImageHaveProfile)
139 while (count > 0)
140 {
141 out[0] = 255 - ImageDensity[255 - *in++];
142 out[1] = out[0];
143 out[2] = out[0];
144 out += 3;
145 count --;
146 }
147 else
148 while (count > 0)
149 {
150 *out++ = *in;
151 *out++ = *in;
152 *out++ = *in++;
153 count --;
154 }
155 }
156
157
158 /*
159 * 'ImageWhiteToBlack()' - Convert luminance colors to black.
160 */
161
162 void
163 ImageWhiteToBlack(const ib_t *in, /* I - Input pixels */
164 ib_t *out, /* I - Output pixels */
165 int count) /* I - Number of pixels */
166 {
167 if (ImageHaveProfile)
168 while (count > 0)
169 {
170 *out++ = ImageDensity[255 - *in++];
171 count --;
172 }
173 else
174 while (count > 0)
175 {
176 *out++ = 255 - *in++;
177 count --;
178 }
179 }
180
181
182 /*
183 * 'ImageWhiteToCMY()' - Convert luminance colors to CMY.
184 */
185
186 void
187 ImageWhiteToCMY(const ib_t *in, /* I - Input pixels */
188 ib_t *out, /* I - Output pixels */
189 int count) /* I - Number of pixels */
190 {
191 if (ImageHaveProfile)
192 while (count > 0)
193 {
194 out[0] = ImageDensity[255 - *in++];
195 out[1] = out[0];
196 out[2] = out[0];
197 out += 3;
198 count --;
199 }
200 else
201 while (count > 0)
202 {
203 *out++ = 255 - *in;
204 *out++ = 255 - *in;
205 *out++ = 255 - *in++;
206 count --;
207 }
208 }
209
210
211 /*
212 * 'ImageWhiteToCMYK()' - Convert luminance colors to CMYK.
213 */
214
215 void
216 ImageWhiteToCMYK(const ib_t *in, /* I - Input pixels */
217 ib_t *out, /* I - Output pixels */
218 int count) /* I - Number of pixels */
219 {
220 if (ImageHaveProfile)
221 while (count > 0)
222 {
223 *out++ = 0;
224 *out++ = 0;
225 *out++ = 0;
226 *out++ = ImageDensity[255 - *in++];
227 count --;
228 }
229 else
230 while (count > 0)
231 {
232 *out++ = 0;
233 *out++ = 0;
234 *out++ = 0;
235 *out++ = 255 - *in++;
236 count --;
237 }
238 }
239
240
241 /*
242 * 'ImageRGBToBlack()' - Convert RGB data to black.
243 */
244
245 void
246 ImageRGBToBlack(const ib_t *in, /* I - Input pixels */
247 ib_t *out, /* I - Output pixels */
248 int count) /* I - Number of pixels */
249 {
250 if (ImageHaveProfile)
251 while (count > 0)
252 {
253 *out++ = ImageDensity[255 - (31 * in[0] + 61 * in[1] + 8 * in[2]) / 100];
254 in += 3;
255 count --;
256 }
257 else
258 while (count > 0)
259 {
260 *out++ = 255 - (31 * in[0] + 61 * in[1] + 8 * in[2]) / 100;
261 in += 3;
262 count --;
263 }
264 }
265
266
267 /*
268 * 'ImageRGBToCMY()' - Convert RGB colors to CMY.
269 */
270
271 void
272 ImageRGBToCMY(const ib_t *in, /* I - Input pixels */
273 ib_t *out, /* I - Output pixels */
274 int count) /* I - Number of pixels */
275 {
276 int c, m, y, k; /* CMYK values */
277 int cc, cm, cy; /* Calibrated CMY values */
278
279
280 if (ImageHaveProfile)
281 while (count > 0)
282 {
283 c = 255 - *in++;
284 m = 255 - *in++;
285 y = 255 - *in++;
286 k = min(c, min(m, y));
287 c -= k;
288 m -= k;
289 y -= k;
290
291 cc = ImageMatrix[0][0][c] +
292 ImageMatrix[0][1][m] +
293 ImageMatrix[0][2][y] + k;
294 cm = ImageMatrix[1][0][c] +
295 ImageMatrix[1][1][m] +
296 ImageMatrix[1][2][y] + k;
297 cy = ImageMatrix[2][0][c] +
298 ImageMatrix[2][1][m] +
299 ImageMatrix[2][2][y] + k;
300
301 if (cc < 0)
302 *out++ = 0;
303 else if (cc > 255)
304 *out++ = ImageDensity[255];
305 else
306 *out++ = ImageDensity[cc];
307
308 if (cm < 0)
309 *out++ = 0;
310 else if (cm > 255)
311 *out++ = ImageDensity[255];
312 else
313 *out++ = ImageDensity[cm];
314
315 if (cy < 0)
316 *out++ = 0;
317 else if (cy > 255)
318 *out++ = ImageDensity[255];
319 else
320 *out++ = ImageDensity[cy];
321
322 count --;
323 }
324 else
325 while (count > 0)
326 {
327 c = 255 - in[0];
328 m = 255 - in[1];
329 y = 255 - in[2];
330 k = min(c, min(m, y));
331
332 *out++ = (255 - in[1] / 4) * (c - k) / 255 + k;
333 *out++ = (255 - in[2] / 4) * (m - k) / 255 + k;
334 *out++ = (255 - in[0] / 4) * (y - k) / 255 + k;
335 in += 3;
336 count --;
337 }
338 }
339
340
341 /*
342 * 'ImageRGBToCMYK()' - Convert RGB colors to CMYK.
343 */
344
345 void
346 ImageRGBToCMYK(const ib_t *in, /* I - Input pixels */
347 ib_t *out, /* I - Output pixels */
348 int count)/* I - Number of pixels */
349 {
350 int c, m, y, k, /* CMYK values */
351 km; /* Maximum K value */
352 int cc, cm, cy; /* Calibrated CMY values */
353
354
355 if (ImageHaveProfile)
356 while (count > 0)
357 {
358 c = 255 - *in++;
359 m = 255 - *in++;
360 y = 255 - *in++;
361 k = min(c, min(m, y));
362
363 if ((km = max(c, max(m, y))) > k)
364 k = k * k * k / (km * km);
365
366 c -= k;
367 m -= k;
368 y -= k;
369
370 cc = (ImageMatrix[0][0][c] +
371 ImageMatrix[0][1][m] +
372 ImageMatrix[0][2][y]);
373 cm = (ImageMatrix[1][0][c] +
374 ImageMatrix[1][1][m] +
375 ImageMatrix[1][2][y]);
376 cy = (ImageMatrix[2][0][c] +
377 ImageMatrix[2][1][m] +
378 ImageMatrix[2][2][y]);
379
380 if (cc < 0)
381 *out++ = 0;
382 else if (cc > 255)
383 *out++ = ImageDensity[255];
384 else
385 *out++ = ImageDensity[cc];
386
387 if (cm < 0)
388 *out++ = 0;
389 else if (cm > 255)
390 *out++ = ImageDensity[255];
391 else
392 *out++ = ImageDensity[cm];
393
394 if (cy < 0)
395 *out++ = 0;
396 else if (cy > 255)
397 *out++ = ImageDensity[255];
398 else
399 *out++ = ImageDensity[cy];
400
401 *out++ = ImageDensity[k];
402
403 count --;
404 }
405 else
406 while (count > 0)
407 {
408 c = 255 - *in++;
409 m = 255 - *in++;
410 y = 255 - *in++;
411 k = min(c, min(m, y));
412
413 if ((km = max(c, max(m, y))) > k)
414 k = k * k * k / (km * km);
415
416 c -= k;
417 m -= k;
418 y -= k;
419
420 *out++ = c;
421 *out++ = m;
422 *out++ = y;
423 *out++ = k;
424
425 count --;
426 }
427 }
428
429
430 /*
431 * 'ImageRGBToWhite()' - Convert RGB colors to luminance.
432 */
433
434 void
435 ImageRGBToWhite(const ib_t *in, /* I - Input pixels */
436 ib_t *out, /* I - Output pixels */
437 int count) /* I - Number of pixels */
438 {
439 if (ImageHaveProfile)
440 while (count > 0)
441 {
442 *out++ = 255 - ImageDensity[255 - (31 * in[0] + 61 * in[1] + 8 * in[2]) / 100];
443 in += 3;
444 count --;
445 }
446 else
447 while (count > 0)
448 {
449 *out++ = (31 * in[0] + 61 * in[1] + 8 * in[2]) / 100;
450 in += 3;
451 count --;
452 }
453 }
454
455
456 /*
457 * 'ImageRGBToRGB()' - Convert RGB colors to device-dependent RGB.
458 */
459
460 void
461 ImageRGBToRGB(const ib_t *in, /* I - Input pixels */
462 ib_t *out, /* I - Output pixels */
463 int count) /* I - Number of pixels */
464 {
465 int c, m, y, k; /* CMYK values */
466 int cr, cg, cb; /* Calibrated RGB values */
467
468
469 if (ImageHaveProfile)
470 while (count > 0)
471 {
472 c = 255 - *in++;
473 m = 255 - *in++;
474 y = 255 - *in++;
475 k = min(c, min(m, y));
476 c -= k;
477 m -= k;
478 y -= k;
479
480 cr = ImageMatrix[0][0][c] +
481 ImageMatrix[0][1][m] +
482 ImageMatrix[0][2][y] + k;
483 cg = ImageMatrix[1][0][c] +
484 ImageMatrix[1][1][m] +
485 ImageMatrix[1][2][y] + k;
486 cb = ImageMatrix[2][0][c] +
487 ImageMatrix[2][1][m] +
488 ImageMatrix[2][2][y] + k;
489
490 if (cr < 0)
491 *out++ = 255;
492 else if (cr > 255)
493 *out++ = 255 - ImageDensity[255];
494 else
495 *out++ = 255 - ImageDensity[cr];
496
497 if (cg < 0)
498 *out++ = 255;
499 else if (cg > 255)
500 *out++ = 255 - ImageDensity[255];
501 else
502 *out++ = 255 - ImageDensity[cg];
503
504 if (cb < 0)
505 *out++ = 255;
506 else if (cb > 255)
507 *out++ = 255 - ImageDensity[255];
508 else
509 *out++ = 255 - ImageDensity[cb];
510
511 count --;
512 }
513 else if (in != out)
514 memcpy(out, in, count * 3);
515 }
516
517
518 /*
519 * 'ImageLut()' - Adjust all pixel values with the given LUT.
520 */
521
522 void
523 ImageLut(ib_t *pixels, /* IO - Input/output pixels */
524 int count, /* I - Number of pixels/bytes to adjust */
525 const ib_t *lut) /* I - Lookup table */
526 {
527 while (count > 0)
528 {
529 *pixels = lut[*pixels];
530 pixels ++;
531 count --;
532 }
533 }
534
535
536 /*
537 * 'ImageRGBAdjust()' - Adjust the hue and saturation of the given RGB colors.
538 */
539
540 void
541 ImageRGBAdjust(ib_t *pixels, /* IO - Input/output pixels */
542 int count, /* I - Number of pixels to adjust */
543 int saturation, /* I - Color saturation (%) */
544 int hue) /* I - Color hue (degrees) */
545 {
546 int i, j, k; /* Looping vars */
547 float mat[3][3]; /* Color adjustment matrix */
548 static int last_sat = 100, /* Last saturation used */
549 last_hue = 0; /* Last hue used */
550 static int lut[3][3][256]; /* Lookup table for matrix */
551
552
553 if (saturation != last_sat ||
554 hue != last_hue)
555 {
556 /*
557 * Build the color adjustment matrix...
558 */
559
560 ident(mat);
561 saturate(mat, saturation * 0.01);
562 huerotate(mat, (float)hue);
563
564 /*
565 * Convert the matrix into a 3x3 array of lookup tables...
566 */
567
568 for (i = 0; i < 3; i ++)
569 for (j = 0; j < 3; j ++)
570 for (k = 0; k < 256; k ++)
571 lut[i][j][k] = mat[i][j] * k + 0.5;
572
573 /*
574 * Save the saturation and hue to compare later...
575 */
576
577 last_sat = saturation;
578 last_hue = hue;
579 }
580
581 /*
582 * Adjust each pixel in the given buffer.
583 */
584
585 while (count > 0)
586 {
587 i = lut[0][0][pixels[0]] +
588 lut[1][0][pixels[1]] +
589 lut[2][0][pixels[2]];
590 if (i < 0)
591 pixels[0] = 0;
592 else if (i > 255)
593 pixels[0] = 255;
594 else
595 pixels[0] = i;
596
597 i = lut[0][1][pixels[0]] +
598 lut[1][1][pixels[1]] +
599 lut[2][1][pixels[2]];
600 if (i < 0)
601 pixels[1] = 0;
602 else if (i > 255)
603 pixels[1] = 255;
604 else
605 pixels[1] = i;
606
607 i = lut[0][2][pixels[0]] +
608 lut[1][2][pixels[1]] +
609 lut[2][2][pixels[2]];
610 if (i < 0)
611 pixels[2] = 0;
612 else if (i > 255)
613 pixels[2] = 255;
614 else
615 pixels[2] = i;
616
617 count --;
618 pixels += 3;
619 }
620 }
621
622
623 /*
624 * The color saturation/hue matrix stuff is provided thanks to Mr. Paul
625 * Haeberli at "http://www.sgi.com/grafica/matrix/index.html".
626 */
627
628 /*
629 * 'huerotate()' - Rotate the hue, maintaining luminance.
630 */
631
632 static void
633 huerotate(float mat[3][3], /* I - Matrix to append to */
634 float rot) /* I - Hue rotation in degrees */
635 {
636 float hmat[3][3]; /* Hue matrix */
637 float lx, ly, lz; /* Luminance vector */
638 float xrs, xrc; /* X rotation sine/cosine */
639 float yrs, yrc; /* Y rotation sine/cosine */
640 float zrs, zrc; /* Z rotation sine/cosine */
641 float zsx, zsy; /* Z shear x/y */
642
643
644 /*
645 * Load the identity matrix...
646 */
647
648 ident(hmat);
649
650 /*
651 * Rotate the grey vector into positive Z...
652 */
653
654 xrs = M_SQRT1_2;
655 xrc = M_SQRT1_2;
656 xrotate(hmat,xrs,xrc);
657
658 yrs = -1.0 / sqrt(3.0);
659 yrc = -M_SQRT2 * yrs;
660 yrotate(hmat,yrs,yrc);
661
662 /*
663 * Shear the space to make the luminance plane horizontal...
664 */
665
666 xform(hmat, 0.3086, 0.6094, 0.0820, &lx, &ly, &lz);
667 zsx = lx / lz;
668 zsy = ly / lz;
669 zshear(hmat, zsx, zsy);
670
671 /*
672 * Rotate the hue...
673 */
674
675 zrs = sin(rot * M_PI / 180.0);
676 zrc = cos(rot * M_PI / 180.0);
677
678 zrotate(hmat, zrs, zrc);
679
680 /*
681 * Unshear the space to put the luminance plane back...
682 */
683
684 zshear(hmat, -zsx, -zsy);
685
686 /*
687 * Rotate the grey vector back into place...
688 */
689
690 yrotate(hmat, -yrs, yrc);
691 xrotate(hmat, -xrs, xrc);
692
693 /*
694 * Append it to the current matrix...
695 */
696
697 mult(hmat, mat, mat);
698 }
699
700
701 /*
702 * 'ident()' - Make an identity matrix.
703 */
704
705 static void
706 ident(float mat[3][3]) /* I - Matrix to identify */
707 {
708 mat[0][0] = 1.0;
709 mat[0][1] = 0.0;
710 mat[0][2] = 0.0;
711 mat[1][0] = 0.0;
712 mat[1][1] = 1.0;
713 mat[1][2] = 0.0;
714 mat[2][0] = 0.0;
715 mat[2][1] = 0.0;
716 mat[2][2] = 1.0;
717 }
718
719
720 /*
721 * 'mult()' - Multiply two matrices.
722 */
723
724 static void
725 mult(float a[3][3], /* I - First matrix */
726 float b[3][3], /* I - Second matrix */
727 float c[3][3]) /* I - Destination matrix */
728 {
729 int x, y; /* Looping vars */
730 float temp[3][3]; /* Temporary matrix */
731
732
733 /*
734 * Multiply a and b, putting the result in temp...
735 */
736
737 for (y = 0; y < 3; y ++)
738 for (x = 0; x < 3; x ++)
739 temp[y][x] = b[y][0] * a[0][x] +
740 b[y][1] * a[1][x] +
741 b[y][2] * a[2][x];
742
743 /*
744 * Copy temp to c (that way c can be a pointer to a or b).
745 */
746
747 memcpy(c, temp, sizeof(temp));
748 }
749
750
751 /*
752 * 'saturate()' - Make a saturation matrix.
753 */
754
755 static void
756 saturate(float mat[3][3], /* I - Matrix to append to */
757 float sat) /* I - Desired color saturation */
758 {
759 float smat[3][3]; /* Saturation matrix */
760
761
762 smat[0][0] = (1.0 - sat) * 0.3086 + sat;
763 smat[0][1] = (1.0 - sat) * 0.3086;
764 smat[0][2] = (1.0 - sat) * 0.3086;
765 smat[1][0] = (1.0 - sat) * 0.6094;
766 smat[1][1] = (1.0 - sat) * 0.6094 + sat;
767 smat[1][2] = (1.0 - sat) * 0.6094;
768 smat[2][0] = (1.0 - sat) * 0.0820;
769 smat[2][1] = (1.0 - sat) * 0.0820;
770 smat[2][2] = (1.0 - sat) * 0.0820 + sat;
771
772 mult(smat, mat, mat);
773 }
774
775
776 /*
777 * 'xform()' - Transform a 3D point using a matrix...
778 */
779
780 static void
781 xform(float mat[3][3], /* I - Matrix */
782 float x, /* I - Input X coordinate */
783 float y, /* I - Input Y coordinate */
784 float z, /* I - Input Z coordinate */
785 float *tx, /* O - Output X coordinate */
786 float *ty, /* O - Output Y coordinate */
787 float *tz) /* O - Output Z coordinate */
788 {
789 *tx = x * mat[0][0] + y * mat[1][0] + z * mat[2][0];
790 *ty = x * mat[0][1] + y * mat[1][1] + z * mat[2][1];
791 *tz = x * mat[0][2] + y * mat[1][2] + z * mat[2][2];
792 }
793
794
795 /*
796 * 'xrotate()' - Rotate about the x (red) axis...
797 */
798
799 static void
800 xrotate(float mat[3][3], /* I - Matrix */
801 float rs, /* I - Rotation angle sine */
802 float rc) /* I - Rotation angle cosine */
803 {
804 float rmat[3][3]; /* I - Rotation matrix */
805
806
807 rmat[0][0] = 1.0;
808 rmat[0][1] = 0.0;
809 rmat[0][2] = 0.0;
810
811 rmat[1][0] = 0.0;
812 rmat[1][1] = rc;
813 rmat[1][2] = rs;
814
815 rmat[2][0] = 0.0;
816 rmat[2][1] = -rs;
817 rmat[2][2] = rc;
818
819 mult(rmat, mat, mat);
820 }
821
822
823 /*
824 * 'yrotate()' - Rotate about the y (green) axis...
825 */
826
827 static void
828 yrotate(float mat[3][3], /* I - Matrix */
829 float rs, /* I - Rotation angle sine */
830 float rc) /* I - Rotation angle cosine */
831 {
832 float rmat[3][3]; /* I - Rotation matrix */
833
834
835 rmat[0][0] = rc;
836 rmat[0][1] = 0.0;
837 rmat[0][2] = -rs;
838
839 rmat[1][0] = 0.0;
840 rmat[1][1] = 1.0;
841 rmat[1][2] = 0.0;
842
843 rmat[2][0] = rs;
844 rmat[2][1] = 0.0;
845 rmat[2][2] = rc;
846
847 mult(rmat,mat,mat);
848 }
849
850
851 /*
852 * 'zrotate()' - Rotate about the z (blue) axis...
853 */
854
855 static void
856 zrotate(float mat[3][3], /* I - Matrix */
857 float rs, /* I - Rotation angle sine */
858 float rc) /* I - Rotation angle cosine */
859 {
860 float rmat[3][3]; /* I - Rotation matrix */
861
862
863 rmat[0][0] = rc;
864 rmat[0][1] = rs;
865 rmat[0][2] = 0.0;
866
867 rmat[1][0] = -rs;
868 rmat[1][1] = rc;
869 rmat[1][2] = 0.0;
870
871 rmat[2][0] = 0.0;
872 rmat[2][1] = 0.0;
873 rmat[2][2] = 1.0;
874
875 mult(rmat,mat,mat);
876 }
877
878
879 /*
880 * 'zshear()' - Shear z using x and y...
881 */
882
883 static void
884 zshear(float mat[3][3], /* I - Matrix */
885 float dx, /* I - X shear */
886 float dy) /* I - Y shear */
887 {
888 float smat[3][3]; /* Shear matrix */
889
890
891 smat[0][0] = 1.0;
892 smat[0][1] = 0.0;
893 smat[0][2] = dx;
894
895 smat[1][0] = 0.0;
896 smat[1][1] = 1.0;
897 smat[1][2] = dy;
898
899 smat[2][0] = 0.0;
900 smat[2][1] = 0.0;
901 smat[2][2] = 1.0;
902
903 mult(smat, mat, mat);
904 }
905
906
907 /*
908 * End of "$Id: image-colorspace.c,v 1.24 2002/01/02 17:58:58 mike Exp $".
909 */