]>
git.ipfire.org Git - thirdparty/cups.git/blob - filter/image-colorspace.c
2 * "$Id: image-colorspace.c,v 1.24 2002/01/02 17:58:58 mike Exp $"
4 * Colorspace conversions for the Common UNIX Printing System (CUPS).
6 * Copyright 1993-2002 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
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
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...
52 * Include necessary headers...
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 */
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);
84 * 'ImageSetProfile()' - Set the device color profile.
88 ImageSetProfile(float d
, /* I - Ink/marker density */
89 float g
, /* I - Ink/marker gamma */
90 float matrix
[3][3]) /* I - Color transform matrix */
92 int i
, j
, k
; /* Looping vars */
93 float m
; /* Current matrix value */
94 int *im
; /* Pointer into ImageMatrix */
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);
103 for (k
= 0, im
= ImageDensity
; k
< 256; k
++)
104 *im
++ = 255.0 * d
* pow((float)k
/ 255.0, g
) + 0.5;
109 * 'ImageWhiteToWhite()' - Convert luminance colors to device-dependent
114 ImageWhiteToWhite(const ib_t
*in
, /* I - Input pixels */
115 ib_t
*out
, /* I - Output pixels */
116 int count
) /* I - Number of pixels */
118 if (ImageHaveProfile
)
121 *out
++ = 255 - ImageDensity
[255 - *in
++];
125 memcpy(out
, in
, count
);
130 * 'ImageWhiteToRGB()' - Convert luminance data to RGB.
134 ImageWhiteToRGB(const ib_t
*in
, /* I - Input pixels */
135 ib_t
*out
, /* I - Output pixels */
136 int count
) /* I - Number of pixels */
138 if (ImageHaveProfile
)
141 out
[0] = 255 - ImageDensity
[255 - *in
++];
159 * 'ImageWhiteToBlack()' - Convert luminance colors to black.
163 ImageWhiteToBlack(const ib_t
*in
, /* I - Input pixels */
164 ib_t
*out
, /* I - Output pixels */
165 int count
) /* I - Number of pixels */
167 if (ImageHaveProfile
)
170 *out
++ = ImageDensity
[255 - *in
++];
176 *out
++ = 255 - *in
++;
183 * 'ImageWhiteToCMY()' - Convert luminance colors to CMY.
187 ImageWhiteToCMY(const ib_t
*in
, /* I - Input pixels */
188 ib_t
*out
, /* I - Output pixels */
189 int count
) /* I - Number of pixels */
191 if (ImageHaveProfile
)
194 out
[0] = ImageDensity
[255 - *in
++];
205 *out
++ = 255 - *in
++;
212 * 'ImageWhiteToCMYK()' - Convert luminance colors to CMYK.
216 ImageWhiteToCMYK(const ib_t
*in
, /* I - Input pixels */
217 ib_t
*out
, /* I - Output pixels */
218 int count
) /* I - Number of pixels */
220 if (ImageHaveProfile
)
226 *out
++ = ImageDensity
[255 - *in
++];
235 *out
++ = 255 - *in
++;
242 * 'ImageRGBToBlack()' - Convert RGB data to black.
246 ImageRGBToBlack(const ib_t
*in
, /* I - Input pixels */
247 ib_t
*out
, /* I - Output pixels */
248 int count
) /* I - Number of pixels */
250 if (ImageHaveProfile
)
253 *out
++ = ImageDensity
[255 - (31 * in
[0] + 61 * in
[1] + 8 * in
[2]) / 100];
260 *out
++ = 255 - (31 * in
[0] + 61 * in
[1] + 8 * in
[2]) / 100;
268 * 'ImageRGBToCMY()' - Convert RGB colors to CMY.
272 ImageRGBToCMY(const ib_t
*in
, /* I - Input pixels */
273 ib_t
*out
, /* I - Output pixels */
274 int count
) /* I - Number of pixels */
276 int c
, m
, y
, k
; /* CMYK values */
277 int cc
, cm
, cy
; /* Calibrated CMY values */
280 if (ImageHaveProfile
)
286 k
= min(c
, min(m
, y
));
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
;
304 *out
++ = ImageDensity
[255];
306 *out
++ = ImageDensity
[cc
];
311 *out
++ = ImageDensity
[255];
313 *out
++ = ImageDensity
[cm
];
318 *out
++ = ImageDensity
[255];
320 *out
++ = ImageDensity
[cy
];
330 k
= min(c
, min(m
, y
));
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
;
342 * 'ImageRGBToCMYK()' - Convert RGB colors to CMYK.
346 ImageRGBToCMYK(const ib_t
*in
, /* I - Input pixels */
347 ib_t
*out
, /* I - Output pixels */
348 int count
)/* I - Number of pixels */
350 int c
, m
, y
, k
, /* CMYK values */
351 km
; /* Maximum K value */
352 int cc
, cm
, cy
; /* Calibrated CMY values */
355 if (ImageHaveProfile
)
361 k
= min(c
, min(m
, y
));
363 if ((km
= max(c
, max(m
, y
))) > k
)
364 k
= k
* k
* k
/ (km
* km
);
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
]);
383 *out
++ = ImageDensity
[255];
385 *out
++ = ImageDensity
[cc
];
390 *out
++ = ImageDensity
[255];
392 *out
++ = ImageDensity
[cm
];
397 *out
++ = ImageDensity
[255];
399 *out
++ = ImageDensity
[cy
];
401 *out
++ = ImageDensity
[k
];
411 k
= min(c
, min(m
, y
));
413 if ((km
= max(c
, max(m
, y
))) > k
)
414 k
= k
* k
* k
/ (km
* km
);
431 * 'ImageRGBToWhite()' - Convert RGB colors to luminance.
435 ImageRGBToWhite(const ib_t
*in
, /* I - Input pixels */
436 ib_t
*out
, /* I - Output pixels */
437 int count
) /* I - Number of pixels */
439 if (ImageHaveProfile
)
442 *out
++ = 255 - ImageDensity
[255 - (31 * in
[0] + 61 * in
[1] + 8 * in
[2]) / 100];
449 *out
++ = (31 * in
[0] + 61 * in
[1] + 8 * in
[2]) / 100;
457 * 'ImageRGBToRGB()' - Convert RGB colors to device-dependent RGB.
461 ImageRGBToRGB(const ib_t
*in
, /* I - Input pixels */
462 ib_t
*out
, /* I - Output pixels */
463 int count
) /* I - Number of pixels */
465 int c
, m
, y
, k
; /* CMYK values */
466 int cr
, cg
, cb
; /* Calibrated RGB values */
469 if (ImageHaveProfile
)
475 k
= min(c
, min(m
, y
));
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
;
493 *out
++ = 255 - ImageDensity
[255];
495 *out
++ = 255 - ImageDensity
[cr
];
500 *out
++ = 255 - ImageDensity
[255];
502 *out
++ = 255 - ImageDensity
[cg
];
507 *out
++ = 255 - ImageDensity
[255];
509 *out
++ = 255 - ImageDensity
[cb
];
514 memcpy(out
, in
, count
* 3);
519 * 'ImageLut()' - Adjust all pixel values with the given LUT.
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 */
529 *pixels
= lut
[*pixels
];
537 * 'ImageRGBAdjust()' - Adjust the hue and saturation of the given RGB colors.
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) */
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 */
553 if (saturation
!= last_sat
||
557 * Build the color adjustment matrix...
561 saturate(mat
, saturation
* 0.01);
562 huerotate(mat
, (float)hue
);
565 * Convert the matrix into a 3x3 array of lookup tables...
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;
574 * Save the saturation and hue to compare later...
577 last_sat
= saturation
;
582 * Adjust each pixel in the given buffer.
587 i
= lut
[0][0][pixels
[0]] +
588 lut
[1][0][pixels
[1]] +
589 lut
[2][0][pixels
[2]];
597 i
= lut
[0][1][pixels
[0]] +
598 lut
[1][1][pixels
[1]] +
599 lut
[2][1][pixels
[2]];
607 i
= lut
[0][2][pixels
[0]] +
608 lut
[1][2][pixels
[1]] +
609 lut
[2][2][pixels
[2]];
624 * The color saturation/hue matrix stuff is provided thanks to Mr. Paul
625 * Haeberli at "http://www.sgi.com/grafica/matrix/index.html".
629 * 'huerotate()' - Rotate the hue, maintaining luminance.
633 huerotate(float mat
[3][3], /* I - Matrix to append to */
634 float rot
) /* I - Hue rotation in degrees */
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 */
645 * Load the identity matrix...
651 * Rotate the grey vector into positive Z...
656 xrotate(hmat
,xrs
,xrc
);
658 yrs
= -1.0 / sqrt(3.0);
659 yrc
= -M_SQRT2
* yrs
;
660 yrotate(hmat
,yrs
,yrc
);
663 * Shear the space to make the luminance plane horizontal...
666 xform(hmat
, 0.3086, 0.6094, 0.0820, &lx
, &ly
, &lz
);
669 zshear(hmat
, zsx
, zsy
);
675 zrs
= sin(rot
* M_PI
/ 180.0);
676 zrc
= cos(rot
* M_PI
/ 180.0);
678 zrotate(hmat
, zrs
, zrc
);
681 * Unshear the space to put the luminance plane back...
684 zshear(hmat
, -zsx
, -zsy
);
687 * Rotate the grey vector back into place...
690 yrotate(hmat
, -yrs
, yrc
);
691 xrotate(hmat
, -xrs
, xrc
);
694 * Append it to the current matrix...
697 mult(hmat
, mat
, mat
);
702 * 'ident()' - Make an identity matrix.
706 ident(float mat
[3][3]) /* I - Matrix to identify */
721 * 'mult()' - Multiply two matrices.
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 */
729 int x
, y
; /* Looping vars */
730 float temp
[3][3]; /* Temporary matrix */
734 * Multiply a and b, putting the result in temp...
737 for (y
= 0; y
< 3; y
++)
738 for (x
= 0; x
< 3; x
++)
739 temp
[y
][x
] = b
[y
][0] * a
[0][x
] +
744 * Copy temp to c (that way c can be a pointer to a or b).
747 memcpy(c
, temp
, sizeof(temp
));
752 * 'saturate()' - Make a saturation matrix.
756 saturate(float mat
[3][3], /* I - Matrix to append to */
757 float sat
) /* I - Desired color saturation */
759 float smat
[3][3]; /* Saturation matrix */
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
;
772 mult(smat
, mat
, mat
);
777 * 'xform()' - Transform a 3D point using a matrix...
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 */
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];
796 * 'xrotate()' - Rotate about the x (red) axis...
800 xrotate(float mat
[3][3], /* I - Matrix */
801 float rs
, /* I - Rotation angle sine */
802 float rc
) /* I - Rotation angle cosine */
804 float rmat
[3][3]; /* I - Rotation matrix */
819 mult(rmat
, mat
, mat
);
824 * 'yrotate()' - Rotate about the y (green) axis...
828 yrotate(float mat
[3][3], /* I - Matrix */
829 float rs
, /* I - Rotation angle sine */
830 float rc
) /* I - Rotation angle cosine */
832 float rmat
[3][3]; /* I - Rotation matrix */
852 * 'zrotate()' - Rotate about the z (blue) axis...
856 zrotate(float mat
[3][3], /* I - Matrix */
857 float rs
, /* I - Rotation angle sine */
858 float rc
) /* I - Rotation angle cosine */
860 float rmat
[3][3]; /* I - Rotation matrix */
880 * 'zshear()' - Shear z using x and y...
884 zshear(float mat
[3][3], /* I - Matrix */
885 float dx
, /* I - X shear */
886 float dy
) /* I - Y shear */
888 float smat
[3][3]; /* Shear matrix */
903 mult(smat
, mat
, mat
);
908 * End of "$Id: image-colorspace.c,v 1.24 2002/01/02 17:58:58 mike Exp $".