2 * "$Id: image-colorspace.c,v 1.22.2.8 2003/01/07 18:26:53 mike Exp $"
4 * Colorspace conversions for the Common UNIX Printing System (CUPS).
6 * Copyright 1993-2003 by Easy Software Products.
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
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
24 * This file is subject to the Apple OS-Developed Software exception.
28 * ImageSetProfile() - Set the device color profile.
29 * ImageWhiteToWhite() - Convert luminance colors to device-dependent
30 * ImageWhiteToRGB() - Convert luminance data to RGB.
31 * ImageWhiteToBlack() - Convert luminance colors to black.
32 * ImageWhiteToCMY() - Convert luminance colors to CMY.
33 * ImageWhiteToCMYK() - Convert luminance colors to CMYK.
34 * ImageRGBToBlack() - Convert RGB data to black.
35 * ImageRGBToCMY() - Convert RGB colors to CMY.
36 * ImageRGBToCMYK() - Convert RGB colors to CMYK.
37 * ImageRGBToWhite() - Convert RGB colors to luminance.
38 * ImageRGBToRGB() - Convert RGB colors to device-dependent RGB.
39 * ImageCMYKToBlack() - Convert CMYK data to black.
40 * ImageCMYKToCMY() - Convert CMYK colors to CMY.
41 * ImageCMYKToCMYK() - Convert CMYK colors to CMYK.
42 * ImageCMYKToWhite() - Convert CMYK colors to luminance.
43 * ImageCMYKToRGB() - Convert CMYK colors to device-dependent RGB.
44 * ImageLut() - Adjust all pixel values with the given LUT.
45 * ImageRGBAdjust() - Adjust the hue and saturation of the given RGB
47 * huerotate() - Rotate the hue, maintaining luminance.
48 * ident() - Make an identity matrix.
49 * mult() - Multiply two matrices.
50 * saturate() - Make a saturation matrix.
51 * xform() - Transform a 3D point using a matrix...
52 * xrotate() - Rotate about the x (red) axis...
53 * yrotate() - Rotate about the y (green) axis...
54 * zrotate() - Rotate about the z (blue) axis...
55 * zshear() - Shear z using x and y...
59 * Include necessary headers...
67 * Define some math constants that are required...
71 # define M_PI 3.14159265358979323846
75 # define M_SQRT2 1.41421356237309504880
79 # define M_SQRT1_2 0.70710678118654752440
80 #endif /* !M_SQRT1_2 */
87 static int ImageHaveProfile
= 0;
88 /* Do we have a color profile? */
89 static int ImageDensity
[256];
90 /* Ink/marker density LUT */
91 static int ImageMatrix
[3][3][256];
92 /* Color transform matrix LUT */
93 static cups_cspace_t ImageColorSpace
= CUPS_CSPACE_RGB
;
94 /* Destination colorspace */
101 static float cielab(float x
, float xn
);
102 static void rgb_to_xyz(ib_t
*val
);
103 static void rgb_to_lab(ib_t
*val
);
105 static void huerotate(float [3][3], float);
106 static void ident(float [3][3]);
107 static void mult(float [3][3], float [3][3], float [3][3]);
108 static void saturate(float [3][3], float);
109 static void xform(float [3][3], float, float, float, float *, float *, float *);
110 static void xrotate(float [3][3], float, float);
111 static void yrotate(float [3][3], float, float);
112 static void zrotate(float [3][3], float, float);
113 static void zshear(float [3][3], float, float);
117 * 'ImageSetColorSpace()' - Set the destination colorspace.
121 ImageSetColorSpace(cups_cspace_t cs
) /* I - Destination colorspace */
124 * Set the destination colorspace...
127 ImageColorSpace
= cs
;
130 * Don't use color profiles in colorimetric colorspaces...
133 if (cs
>= CUPS_CSPACE_CIEXYZ
)
134 ImageHaveProfile
= 0;
139 * 'ImageSetProfile()' - Set the device color profile.
143 ImageSetProfile(float d
, /* I - Ink/marker density */
144 float g
, /* I - Ink/marker gamma */
145 float matrix
[3][3]) /* I - Color transform matrix */
147 int i
, j
, k
; /* Looping vars */
148 float m
; /* Current matrix value */
149 int *im
; /* Pointer into ImageMatrix */
151 ImageHaveProfile
= 1;
153 for (i
= 0, im
= ImageMatrix
[0][0]; i
< 3; i
++)
154 for (j
= 0; j
< 3; j
++)
155 for (k
= 0, m
= matrix
[i
][j
]; k
< 256; k
++)
156 *im
++ = (int)(k
* m
+ 0.5);
158 for (k
= 0, im
= ImageDensity
; k
< 256; k
++)
159 *im
++ = 255.0 * d
* pow((float)k
/ 255.0, g
) + 0.5;
164 * 'ImageWhiteToWhite()' - Convert luminance colors to device-dependent
169 ImageWhiteToWhite(const ib_t
*in
, /* I - Input pixels */
170 ib_t
*out
, /* I - Output pixels */
171 int count
) /* I - Number of pixels */
173 if (ImageHaveProfile
)
176 *out
++ = 255 - ImageDensity
[255 - *in
++];
180 memcpy(out
, in
, count
);
185 * 'ImageWhiteToRGB()' - Convert luminance data to RGB.
189 ImageWhiteToRGB(const ib_t
*in
, /* I - Input pixels */
190 ib_t
*out
, /* I - Output pixels */
191 int count
) /* I - Number of pixels */
193 if (ImageHaveProfile
)
197 out
[0] = 255 - ImageDensity
[255 - *in
++];
212 if (ImageColorSpace
== CUPS_CSPACE_CIELab
)
214 else if (ImageColorSpace
>= CUPS_CSPACE_CIEXYZ
)
224 * 'ImageWhiteToBlack()' - Convert luminance colors to black.
228 ImageWhiteToBlack(const ib_t
*in
, /* I - Input pixels */
229 ib_t
*out
, /* I - Output pixels */
230 int count
) /* I - Number of pixels */
232 if (ImageHaveProfile
)
235 *out
++ = ImageDensity
[255 - *in
++];
241 *out
++ = 255 - *in
++;
248 * 'ImageWhiteToCMY()' - Convert luminance colors to CMY.
252 ImageWhiteToCMY(const ib_t
*in
, /* I - Input pixels */
253 ib_t
*out
, /* I - Output pixels */
254 int count
) /* I - Number of pixels */
256 if (ImageHaveProfile
)
259 out
[0] = ImageDensity
[255 - *in
++];
270 *out
++ = 255 - *in
++;
277 * 'ImageWhiteToCMYK()' - Convert luminance colors to CMYK.
281 ImageWhiteToCMYK(const ib_t
*in
, /* I - Input pixels */
282 ib_t
*out
, /* I - Output pixels */
283 int count
) /* I - Number of pixels */
285 if (ImageHaveProfile
)
291 *out
++ = ImageDensity
[255 - *in
++];
300 *out
++ = 255 - *in
++;
307 * 'ImageRGBToBlack()' - Convert RGB data to black.
311 ImageRGBToBlack(const ib_t
*in
, /* I - Input pixels */
312 ib_t
*out
, /* I - Output pixels */
313 int count
) /* I - Number of pixels */
315 if (ImageHaveProfile
)
318 *out
++ = ImageDensity
[255 - (31 * in
[0] + 61 * in
[1] + 8 * in
[2]) / 100];
325 *out
++ = 255 - (31 * in
[0] + 61 * in
[1] + 8 * in
[2]) / 100;
333 * 'ImageRGBToCMY()' - Convert RGB colors to CMY.
337 ImageRGBToCMY(const ib_t
*in
, /* I - Input pixels */
338 ib_t
*out
, /* I - Output pixels */
339 int count
) /* I - Number of pixels */
341 int c
, m
, y
, k
; /* CMYK values */
342 int cc
, cm
, cy
; /* Calibrated CMY values */
345 if (ImageHaveProfile
)
351 k
= min(c
, min(m
, y
));
356 cc
= ImageMatrix
[0][0][c
] +
357 ImageMatrix
[0][1][m
] +
358 ImageMatrix
[0][2][y
] + k
;
359 cm
= ImageMatrix
[1][0][c
] +
360 ImageMatrix
[1][1][m
] +
361 ImageMatrix
[1][2][y
] + k
;
362 cy
= ImageMatrix
[2][0][c
] +
363 ImageMatrix
[2][1][m
] +
364 ImageMatrix
[2][2][y
] + k
;
369 *out
++ = ImageDensity
[255];
371 *out
++ = ImageDensity
[cc
];
376 *out
++ = ImageDensity
[255];
378 *out
++ = ImageDensity
[cm
];
383 *out
++ = ImageDensity
[255];
385 *out
++ = ImageDensity
[cy
];
395 k
= min(c
, min(m
, y
));
397 *out
++ = (255 - in
[1] / 4) * (c
- k
) / 255 + k
;
398 *out
++ = (255 - in
[2] / 4) * (m
- k
) / 255 + k
;
399 *out
++ = (255 - in
[0] / 4) * (y
- k
) / 255 + k
;
407 * 'ImageRGBToCMYK()' - Convert RGB colors to CMYK.
411 ImageRGBToCMYK(const ib_t
*in
, /* I - Input pixels */
412 ib_t
*out
, /* I - Output pixels */
413 int count
)/* I - Number of pixels */
415 int c
, m
, y
, k
, /* CMYK values */
416 km
; /* Maximum K value */
417 int cc
, cm
, cy
; /* Calibrated CMY values */
420 if (ImageHaveProfile
)
426 k
= min(c
, min(m
, y
));
428 if ((km
= max(c
, max(m
, y
))) > k
)
429 k
= k
* k
* k
/ (km
* km
);
435 cc
= (ImageMatrix
[0][0][c
] +
436 ImageMatrix
[0][1][m
] +
437 ImageMatrix
[0][2][y
]);
438 cm
= (ImageMatrix
[1][0][c
] +
439 ImageMatrix
[1][1][m
] +
440 ImageMatrix
[1][2][y
]);
441 cy
= (ImageMatrix
[2][0][c
] +
442 ImageMatrix
[2][1][m
] +
443 ImageMatrix
[2][2][y
]);
448 *out
++ = ImageDensity
[255];
450 *out
++ = ImageDensity
[cc
];
455 *out
++ = ImageDensity
[255];
457 *out
++ = ImageDensity
[cm
];
462 *out
++ = ImageDensity
[255];
464 *out
++ = ImageDensity
[cy
];
466 *out
++ = ImageDensity
[k
];
476 k
= min(c
, min(m
, y
));
478 if ((km
= max(c
, max(m
, y
))) > k
)
479 k
= k
* k
* k
/ (km
* km
);
496 * 'ImageRGBToWhite()' - Convert RGB colors to luminance.
500 ImageRGBToWhite(const ib_t
*in
, /* I - Input pixels */
501 ib_t
*out
, /* I - Output pixels */
502 int count
) /* I - Number of pixels */
504 if (ImageHaveProfile
)
508 *out
++ = 255 - ImageDensity
[255 - (31 * in
[0] + 61 * in
[1] + 8 * in
[2]) / 100];
517 *out
++ = (31 * in
[0] + 61 * in
[1] + 8 * in
[2]) / 100;
526 * 'ImageRGBToRGB()' - Convert RGB colors to device-dependent RGB.
530 ImageRGBToRGB(const ib_t
*in
, /* I - Input pixels */
531 ib_t
*out
, /* I - Output pixels */
532 int count
) /* I - Number of pixels */
534 int c
, m
, y
, k
; /* CMYK values */
535 int cr
, cg
, cb
; /* Calibrated RGB values */
538 if (ImageHaveProfile
)
545 k
= min(c
, min(m
, y
));
550 cr
= ImageMatrix
[0][0][c
] +
551 ImageMatrix
[0][1][m
] +
552 ImageMatrix
[0][2][y
] + k
;
553 cg
= ImageMatrix
[1][0][c
] +
554 ImageMatrix
[1][1][m
] +
555 ImageMatrix
[1][2][y
] + k
;
556 cb
= ImageMatrix
[2][0][c
] +
557 ImageMatrix
[2][1][m
] +
558 ImageMatrix
[2][2][y
] + k
;
563 *out
++ = 255 - ImageDensity
[255];
565 *out
++ = 255 - ImageDensity
[cr
];
570 *out
++ = 255 - ImageDensity
[255];
572 *out
++ = 255 - ImageDensity
[cg
];
577 *out
++ = 255 - ImageDensity
[255];
579 *out
++ = 255 - ImageDensity
[cb
];
587 memcpy(out
, in
, count
* 3);
589 if (ImageColorSpace
>= CUPS_CSPACE_CIEXYZ
)
593 if (ImageColorSpace
== CUPS_CSPACE_CIELab
)
607 * 'ImageCMYKToBlack()' - Convert CMYK data to black.
611 ImageCMYKToBlack(const ib_t
*in
, /* I - Input pixels */
612 ib_t
*out
, /* I - Output pixels */
613 int count
) /* I - Number of pixels */
615 int k
; /* Black value */
618 if (ImageHaveProfile
)
621 k
= (31 * in
[0] + 61 * in
[1] + 8 * in
[2]) / 100 + in
[3];
624 *out
++ = ImageDensity
[k
];
626 *out
++ = ImageDensity
[255];
634 k
= (31 * in
[0] + 61 * in
[1] + 8 * in
[2]) / 100 + in
[3];
648 * 'ImageCMYKToCMY()' - Convert CMYK colors to CMY.
652 ImageCMYKToCMY(const ib_t
*in
, /* I - Input pixels */
653 ib_t
*out
, /* I - Output pixels */
654 int count
)/* I - Number of pixels */
656 int c
, m
, y
, k
; /* CMYK values */
657 int cc
, cm
, cy
; /* Calibrated CMY values */
660 if (ImageHaveProfile
)
668 cc
= ImageMatrix
[0][0][c
] +
669 ImageMatrix
[0][1][m
] +
670 ImageMatrix
[0][2][y
] + k
;
671 cm
= ImageMatrix
[1][0][c
] +
672 ImageMatrix
[1][1][m
] +
673 ImageMatrix
[1][2][y
] + k
;
674 cy
= ImageMatrix
[2][0][c
] +
675 ImageMatrix
[2][1][m
] +
676 ImageMatrix
[2][2][y
] + k
;
681 *out
++ = ImageDensity
[255];
683 *out
++ = ImageDensity
[cc
];
688 *out
++ = ImageDensity
[255];
690 *out
++ = ImageDensity
[cm
];
695 *out
++ = ImageDensity
[255];
697 *out
++ = ImageDensity
[cy
];
734 * 'ImageCMYKToCMYK()' - Convert CMYK colors to CMYK.
738 ImageCMYKToCMYK(const ib_t
*in
, /* I - Input pixels */
739 ib_t
*out
,/* I - Output pixels */
740 int count
)/* I - Number of pixels */
742 int c
, m
, y
, k
; /* CMYK values */
743 int cc
, cm
, cy
; /* Calibrated CMY values */
746 if (ImageHaveProfile
)
754 cc
= (ImageMatrix
[0][0][c
] +
755 ImageMatrix
[0][1][m
] +
756 ImageMatrix
[0][2][y
]);
757 cm
= (ImageMatrix
[1][0][c
] +
758 ImageMatrix
[1][1][m
] +
759 ImageMatrix
[1][2][y
]);
760 cy
= (ImageMatrix
[2][0][c
] +
761 ImageMatrix
[2][1][m
] +
762 ImageMatrix
[2][2][y
]);
767 *out
++ = ImageDensity
[255];
769 *out
++ = ImageDensity
[cc
];
774 *out
++ = ImageDensity
[255];
776 *out
++ = ImageDensity
[cm
];
781 *out
++ = ImageDensity
[255];
783 *out
++ = ImageDensity
[cy
];
785 *out
++ = ImageDensity
[k
];
805 * 'ImageCMYKToWhite()' - Convert CMYK colors to luminance.
809 ImageCMYKToWhite(const ib_t
*in
, /* I - Input pixels */
810 ib_t
*out
, /* I - Output pixels */
811 int count
) /* I - Number of pixels */
813 int w
; /* White value */
816 if (ImageHaveProfile
)
820 w
= 255 - (31 * in
[0] + 61 * in
[1] + 8 * in
[2]) / 100 - in
[3];
823 *out
++ = ImageDensity
[w
];
825 *out
++ = ImageDensity
[0];
835 w
= 255 - (31 * in
[0] + 61 * in
[1] + 8 * in
[2]) / 100 - in
[3];
850 * 'ImageCMYKToRGB()' - Convert CMYK colors to device-dependent RGB.
854 ImageCMYKToRGB(const ib_t
*in
, /* I - Input pixels */
855 ib_t
*out
, /* I - Output pixels */
856 int count
)/* I - Number of pixels */
858 int c
, m
, y
, k
; /* CMYK values */
859 int cr
, cg
, cb
; /* Calibrated RGB values */
862 if (ImageHaveProfile
)
871 cr
= ImageMatrix
[0][0][c
] +
872 ImageMatrix
[0][1][m
] +
873 ImageMatrix
[0][2][y
] + k
;
874 cg
= ImageMatrix
[1][0][c
] +
875 ImageMatrix
[1][1][m
] +
876 ImageMatrix
[1][2][y
] + k
;
877 cb
= ImageMatrix
[2][0][c
] +
878 ImageMatrix
[2][1][m
] +
879 ImageMatrix
[2][2][y
] + k
;
884 *out
++ = 255 - ImageDensity
[255];
886 *out
++ = 255 - ImageDensity
[cr
];
891 *out
++ = 255 - ImageDensity
[255];
893 *out
++ = 255 - ImageDensity
[cg
];
898 *out
++ = 255 - ImageDensity
[255];
900 *out
++ = 255 - ImageDensity
[cb
];
933 if (ImageColorSpace
== CUPS_CSPACE_CIELab
)
935 else if (ImageColorSpace
>= CUPS_CSPACE_CIEXYZ
)
945 * 'ImageLut()' - Adjust all pixel values with the given LUT.
949 ImageLut(ib_t
*pixels
, /* IO - Input/output pixels */
950 int count
, /* I - Number of pixels/bytes to adjust */
951 const ib_t
*lut
) /* I - Lookup table */
955 *pixels
= lut
[*pixels
];
963 * 'ImageRGBAdjust()' - Adjust the hue and saturation of the given RGB colors.
967 ImageRGBAdjust(ib_t
*pixels
, /* IO - Input/output pixels */
968 int count
, /* I - Number of pixels to adjust */
969 int saturation
, /* I - Color saturation (%) */
970 int hue
) /* I - Color hue (degrees) */
972 int i
, j
, k
; /* Looping vars */
973 float mat
[3][3]; /* Color adjustment matrix */
974 static int last_sat
= 100, /* Last saturation used */
975 last_hue
= 0; /* Last hue used */
976 static int lut
[3][3][256]; /* Lookup table for matrix */
979 if (saturation
!= last_sat
||
983 * Build the color adjustment matrix...
987 saturate(mat
, saturation
* 0.01);
988 huerotate(mat
, (float)hue
);
991 * Convert the matrix into a 3x3 array of lookup tables...
994 for (i
= 0; i
< 3; i
++)
995 for (j
= 0; j
< 3; j
++)
996 for (k
= 0; k
< 256; k
++)
997 lut
[i
][j
][k
] = mat
[i
][j
] * k
+ 0.5;
1000 * Save the saturation and hue to compare later...
1003 last_sat
= saturation
;
1008 * Adjust each pixel in the given buffer.
1013 i
= lut
[0][0][pixels
[0]] +
1014 lut
[1][0][pixels
[1]] +
1015 lut
[2][0][pixels
[2]];
1023 i
= lut
[0][1][pixels
[0]] +
1024 lut
[1][1][pixels
[1]] +
1025 lut
[2][1][pixels
[2]];
1033 i
= lut
[0][2][pixels
[0]] +
1034 lut
[1][2][pixels
[1]] +
1035 lut
[2][2][pixels
[2]];
1050 * Convert from RGB to CIE XYZ or Lab...
1053 #define D65_X (0.412453 + 0.357580 + 0.180423)
1054 #define D65_Y (0.212671 + 0.715160 + 0.072169)
1055 #define D65_Z (0.019334 + 0.119193 + 0.950227)
1059 * 'cielab()' - Map CIE Lab transformation...
1062 static float /* O - Adjusted color value */
1063 cielab(float x
, /* I - Raw color value */
1064 float xn
) /* I - Whitepoint color value */
1066 float x_xn
; /* Fraction of whitepoint */
1071 if (x_xn
> 0.008856)
1072 return (cbrt(x_xn
));
1074 return (7.787 * x_xn
+ 16.0 / 116.0);
1079 * 'rgb_to_xyz()' - Convert an RGB color to CIE XYZ.
1083 rgb_to_xyz(ib_t
*val
) /* IO - Color value */
1085 float r
, /* Red value */
1086 g
, /* Green value */
1088 ciex
, /* CIE X value */
1089 ciey
, /* CIE Y value */
1090 ciez
; /* CIE Z value */
1094 * Convert sRGB to linear RGB...
1097 r
= pow(val
[0] / 255.0, 0.58823529412);
1098 g
= pow(val
[1] / 255.0, 0.58823529412);
1099 b
= pow(val
[2] / 255.0, 0.58823529412);
1102 * Convert to CIE XYZ...
1105 ciex
= 0.412453 * r
+ 0.357580 * g
+ 0.180423 * b
;
1106 ciey
= 0.212671 * r
+ 0.715160 * g
+ 0.072169 * b
;
1107 ciez
= 0.019334 * r
+ 0.119193 * g
+ 0.950227 * b
;
1110 * Output 8-bit values...
1115 else if (ciex
< 255.0)
1122 else if (ciey
< 255.0)
1129 else if (ciez
< 255.0)
1137 * 'rgb_to_lab()' - Convert an RGB color to CIE Lab.
1141 rgb_to_lab(ib_t
*val
) /* IO - Color value */
1143 float r
, /* Red value */
1144 g
, /* Green value */
1146 ciex
, /* CIE X value */
1147 ciey
, /* CIE Y value */
1148 ciez
, /* CIE Z value */
1149 ciey_yn
, /* Normalized luminance */
1150 ciel
, /* CIE L value */
1151 ciea
, /* CIE a value */
1152 cieb
; /* CIE b value */
1156 * Convert sRGB to linear RGB...
1159 r
= pow(val
[0] / 255.0, 0.58823529412);
1160 g
= pow(val
[1] / 255.0, 0.58823529412);
1161 b
= pow(val
[2] / 255.0, 0.58823529412);
1164 * Convert to CIE XYZ...
1167 ciex
= 0.412453 * r
+ 0.357580 * g
+ 0.180423 * b
;
1168 ciey
= 0.212671 * r
+ 0.715160 * g
+ 0.072169 * b
;
1169 ciez
= 0.019334 * r
+ 0.119193 * g
+ 0.950227 * b
;
1172 * Normalize and convert to CIE Lab...
1175 ciey_yn
= ciey
/ D65_Y
;
1177 if (ciey_yn
> 0.008856)
1178 ciel
= 116 * cbrt(ciey_yn
) - 16;
1180 ciel
= 903.3 * ciey_yn
;
1183 ciea
= 500 * (cielab(ciex
, D65_X
) - cielab(ciey
, D65_Y
));
1184 cieb
= 200 * (cielab(ciey
, D65_Y
) - cielab(ciez
, D65_Z
));
1187 * Scale the L value and bias the a and b values by 128 so that all
1188 * numbers are from 0 to 255.
1196 * Output 8-bit values...
1201 else if (ciel
< 255.0)
1208 else if (ciea
< 255.0)
1215 else if (cieb
< 255.0)
1223 * The color saturation/hue matrix stuff is provided thanks to Mr. Paul
1224 * Haeberli at "http://www.sgi.com/grafica/matrix/index.html".
1228 * 'huerotate()' - Rotate the hue, maintaining luminance.
1232 huerotate(float mat
[3][3], /* I - Matrix to append to */
1233 float rot
) /* I - Hue rotation in degrees */
1235 float hmat
[3][3]; /* Hue matrix */
1236 float lx
, ly
, lz
; /* Luminance vector */
1237 float xrs
, xrc
; /* X rotation sine/cosine */
1238 float yrs
, yrc
; /* Y rotation sine/cosine */
1239 float zrs
, zrc
; /* Z rotation sine/cosine */
1240 float zsx
, zsy
; /* Z shear x/y */
1244 * Load the identity matrix...
1250 * Rotate the grey vector into positive Z...
1255 xrotate(hmat
,xrs
,xrc
);
1257 yrs
= -1.0 / sqrt(3.0);
1258 yrc
= -M_SQRT2
* yrs
;
1259 yrotate(hmat
,yrs
,yrc
);
1262 * Shear the space to make the luminance plane horizontal...
1265 xform(hmat
, 0.3086, 0.6094, 0.0820, &lx
, &ly
, &lz
);
1268 zshear(hmat
, zsx
, zsy
);
1274 zrs
= sin(rot
* M_PI
/ 180.0);
1275 zrc
= cos(rot
* M_PI
/ 180.0);
1277 zrotate(hmat
, zrs
, zrc
);
1280 * Unshear the space to put the luminance plane back...
1283 zshear(hmat
, -zsx
, -zsy
);
1286 * Rotate the grey vector back into place...
1289 yrotate(hmat
, -yrs
, yrc
);
1290 xrotate(hmat
, -xrs
, xrc
);
1293 * Append it to the current matrix...
1296 mult(hmat
, mat
, mat
);
1301 * 'ident()' - Make an identity matrix.
1305 ident(float mat
[3][3]) /* I - Matrix to identify */
1320 * 'mult()' - Multiply two matrices.
1324 mult(float a
[3][3], /* I - First matrix */
1325 float b
[3][3], /* I - Second matrix */
1326 float c
[3][3]) /* I - Destination matrix */
1328 int x
, y
; /* Looping vars */
1329 float temp
[3][3]; /* Temporary matrix */
1333 * Multiply a and b, putting the result in temp...
1336 for (y
= 0; y
< 3; y
++)
1337 for (x
= 0; x
< 3; x
++)
1338 temp
[y
][x
] = b
[y
][0] * a
[0][x
] +
1343 * Copy temp to c (that way c can be a pointer to a or b).
1346 memcpy(c
, temp
, sizeof(temp
));
1351 * 'saturate()' - Make a saturation matrix.
1355 saturate(float mat
[3][3], /* I - Matrix to append to */
1356 float sat
) /* I - Desired color saturation */
1358 float smat
[3][3]; /* Saturation matrix */
1361 smat
[0][0] = (1.0 - sat
) * 0.3086 + sat
;
1362 smat
[0][1] = (1.0 - sat
) * 0.3086;
1363 smat
[0][2] = (1.0 - sat
) * 0.3086;
1364 smat
[1][0] = (1.0 - sat
) * 0.6094;
1365 smat
[1][1] = (1.0 - sat
) * 0.6094 + sat
;
1366 smat
[1][2] = (1.0 - sat
) * 0.6094;
1367 smat
[2][0] = (1.0 - sat
) * 0.0820;
1368 smat
[2][1] = (1.0 - sat
) * 0.0820;
1369 smat
[2][2] = (1.0 - sat
) * 0.0820 + sat
;
1371 mult(smat
, mat
, mat
);
1376 * 'xform()' - Transform a 3D point using a matrix...
1380 xform(float mat
[3][3], /* I - Matrix */
1381 float x
, /* I - Input X coordinate */
1382 float y
, /* I - Input Y coordinate */
1383 float z
, /* I - Input Z coordinate */
1384 float *tx
, /* O - Output X coordinate */
1385 float *ty
, /* O - Output Y coordinate */
1386 float *tz
) /* O - Output Z coordinate */
1388 *tx
= x
* mat
[0][0] + y
* mat
[1][0] + z
* mat
[2][0];
1389 *ty
= x
* mat
[0][1] + y
* mat
[1][1] + z
* mat
[2][1];
1390 *tz
= x
* mat
[0][2] + y
* mat
[1][2] + z
* mat
[2][2];
1395 * 'xrotate()' - Rotate about the x (red) axis...
1399 xrotate(float mat
[3][3], /* I - Matrix */
1400 float rs
, /* I - Rotation angle sine */
1401 float rc
) /* I - Rotation angle cosine */
1403 float rmat
[3][3]; /* I - Rotation matrix */
1418 mult(rmat
, mat
, mat
);
1423 * 'yrotate()' - Rotate about the y (green) axis...
1427 yrotate(float mat
[3][3], /* I - Matrix */
1428 float rs
, /* I - Rotation angle sine */
1429 float rc
) /* I - Rotation angle cosine */
1431 float rmat
[3][3]; /* I - Rotation matrix */
1451 * 'zrotate()' - Rotate about the z (blue) axis...
1455 zrotate(float mat
[3][3], /* I - Matrix */
1456 float rs
, /* I - Rotation angle sine */
1457 float rc
) /* I - Rotation angle cosine */
1459 float rmat
[3][3]; /* I - Rotation matrix */
1479 * 'zshear()' - Shear z using x and y...
1483 zshear(float mat
[3][3], /* I - Matrix */
1484 float dx
, /* I - X shear */
1485 float dy
) /* I - Y shear */
1487 float smat
[3][3]; /* Shear matrix */
1502 mult(smat
, mat
, mat
);
1507 * End of "$Id: image-colorspace.c,v 1.22.2.8 2003/01/07 18:26:53 mike Exp $".