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