386BSD 0.1 development
[unix-history] / usr / othersrc / public / ghostscript-2.4.1 / gscie.c
CommitLineData
e964bf85
WJ
1/* Copyright (C) 1992 Aladdin Enterprises. All rights reserved.
2 Distributed by Free Software Foundation, Inc.
3
4This file is part of Ghostscript.
5
6Ghostscript is distributed in the hope that it will be useful, but
7WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
8to anyone for the consequences of using it or for whether it serves any
9particular purpose or works at all, unless he says so in writing. Refer
10to the Ghostscript General Public License for full details.
11
12Everyone is granted permission to copy, modify and redistribute
13Ghostscript, but only under the conditions described in the Ghostscript
14General Public License. A copy of this license is supposed to have been
15given to you along with Ghostscript so you can know your rights and
16responsibilities. It should be in a file named COPYING. Among other
17things, the copyright notice and this notice must be preserved on all
18copies. */
19
20/* gscie.c */
21/* CIE color algorithms for Ghostscript */
22#include "std.h"
23#include "gscie.h"
24
25/* Default values for components. */
26private float
27fp_identity(floatp value)
28{ return (float)value;
29}
30gs_range3 Range3_default = { {0,1}, {0,1}, {0,1} };
31gs_float_proc3 Decode3_default = { fp_identity, fp_identity, fp_identity };
32gs_matrix3 Matrix3_default = { {1,0,0}, {0,1,0}, {0,0,1} };
33gs_range RangeA_default = {0,1};
34gs_float_proc DecodeA_default = fp_identity;
35gs_vector3 MatrixA_default = { 1, 1, 1 };
36gs_vector3 BlackPoint_default = { 0, 0, 0 };
37
38/* Apply procedures to a vector. */
39private void
40cie_apply3(gs_vector3 *in, gs_float_proc3 *procs, gs_vector3 *out)
41{ out->u = (*procs->u)(in->u);
42 out->v = (*procs->v)(in->v);
43 out->w = (*procs->w)(in->w);
44}
45
46/* Multiply a vector by a matrix. */
47private void
48cie_mult3(gs_vector3 *in, register gs_matrix3 *mat, gs_vector3 *out)
49{ float u = in->u, v = in->v, w = in->w;
50 out->u = (u * mat->cu.u) + (v * mat->cu.v) + (w * mat->cu.w);
51 out->v = (u * mat->cv.u) + (v * mat->cv.v) + (w * mat->cv.w);
52 out->w = (u * mat->cw.u) + (v * mat->cw.v) + (w * mat->cw.w);
53}
54
55/* Invert a matrix. */
56private void
57cie_invert3(register gs_matrix3 *in, register gs_matrix3 *out)
58{ /* This is a brute force algorithm; maybe there are better. */
59 /* We label the array elements */
60 /* [ A B C ] */
61 /* [ D E F ] */
62 /* [ G H I ] */
63#define A cu.u
64#define B cv.u
65#define C cw.u
66#define D cu.v
67#define E cv.v
68#define F cw.v
69#define G cu.w
70#define H cv.w
71#define I cw.w
72 double AE = in->A * in->E, AF = in->A * in->F,
73 AH = in->A * in->H, AI = in->A * in->I;
74 double BD = in->B * in->D, BF = in->B * in->F,
75 BG = in->B * in->G, BI = in->B * in->I;
76 double CD = in->C * in->D, CE = in->C * in->E,
77 CG = in->C * in->G, CH = in->C * in->H;
78 double DH = in->D * in->H, DI = in->D * in->I;
79 double EG = in->E * in->G, EI = in->E * in->I;
80 double FG = in->F * in->G, FH = in->F * in->H;
81 double coA = EI - FH, coB = FG - DI, coC = DH - EG;
82 double det = in->A * coA + in->B * coB + in->C * coC;
83 out->A = coA / det;
84 out->D = coB / det;
85 out->G = coC / det;
86 out->B = (CH - BI) / det;
87 out->E = (AI - CG) / det;
88 out->H = (BG - AH) / det;
89 out->C = (BF - CE) / det;
90 out->F = (CD - AF) / det;
91 out->I = (AE - BD) / det;
92#undef A
93#undef B
94#undef C
95#undef D
96#undef E
97#undef F
98#undef G
99#undef H
100#undef I
101}
102
103/* Force values within bounds. */
104#define restrict(v, r)\
105 ((v) < (r).rmin ? (r).rmin : (v) > (r).rmax ? (r).rmax : (v))
106private void
107cie_restrict3(gs_vector3 *in, gs_range3 *range, gs_vector3 *out)
108{ float temp;
109 temp = in->u; out->u = restrict(temp, range->u);
110 temp = in->v; out->v = restrict(temp, range->v);
111 temp = in->w; out->w = restrict(temp, range->w);
112}
113
114/* Decode ABC values to XYZ. */
115int
116gs_cie_abc_decode1(gs_vector3 *pabc, gs_vector3 *ptabc, gs_cie_abc *pcie)
117{ cie_restrict3(pabc, &pcie->RangeABC, ptabc);
118 return 0;
119}
120/*
121 * Client:
122 cie_apply3(ptabc, &pcie->DecodeABC, ptabc);
123 */
124int
125gs_cie_abc_decode2(gs_vector3 *ptabc, gs_vector3 *ptlmn, gs_cie_abc *pcie)
126{ cie_mult3(ptabc, &pcie->MatrixABC, ptlmn);
127 cie_restrict3(ptlmn, &pcie->RangeLMN, ptlmn);
128 return 0;
129}
130/*
131 * Client:
132 cie_apply3(ptlmn, &pcie->DecodeLMN, ptlmn);
133 */
134int
135gs_cie_abc_decode3(gs_vector3 *ptlmn, gs_vector3 *pxyz, gs_cie_abc *pcie)
136{ cie_mult3(ptlmn, &pcie->MatrixLMN, pxyz);
137 return 0;
138}
139
140/* Decode an A value to XYZ. */
141int
142gs_cie_a_decode1(floatp va, float *pta, gs_cie_a *pcie)
143{ *pta = restrict(va, pcie->RangeA);
144 return 0;
145}
146/*
147 * Client:
148 ta = (*pcie->DecodeA)(*pta);
149 */
150int
151gs_cie_a_decode2(floatp ta, gs_vector3 *ptlmn, gs_cie_a *pcie)
152{ gs_vector3 lmn;
153 lmn.u = ta * pcie->MatrixA.u;
154 lmn.v = ta * pcie->MatrixA.v;
155 lmn.w = ta * pcie->MatrixA.w;
156 cie_restrict3(&lmn, &pcie->RangeLMN, ptlmn);
157 return 0;
158}
159/*
160 * Client:
161 cie_apply3(ptlmn, &pcie->DecodeLMN, ptlmn);
162 */
163/* gs_cie_a_decode3 is the same as gs_cie_abc_decode3. */
164
165/* Initialize the computed fields of a CIE color rendering structure. */
166int
167gs_cie_render_init(gs_cie_render *pcie)
168{ cie_invert3(&pcie->MatrixPQR, &pcie->MatrixPQR_inverse);
169 cie_mult3(&pcie->points.WhitePoint, &pcie->MatrixPQR, &pcie->wdpqr);
170 cie_mult3(&pcie->points.BlackPoint, &pcie->MatrixPQR, &pcie->bdpqr);
171 return 0;
172}
173
174/* Render CIE colors */
175int
176gs_cie_render_colors1(gs_vector3 *pxyz, gs_cie_wbsd *pwbsd, gs_vector3 *ptpqr, gs_cie_wb *points, gs_cie_render *pcie)
177{ cie_mult3(pxyz, &pcie->MatrixPQR, ptpqr);
178 pwbsd->ws.xyz = points->WhitePoint;
179 cie_mult3(&pwbsd->ws.xyz, &pcie->MatrixPQR, &pwbsd->ws.pqr);
180 pwbsd->bs.xyz = points->BlackPoint;
181 cie_mult3(&pwbsd->bs.xyz, &pcie->MatrixPQR, &pwbsd->bs.pqr);
182 pwbsd->wd.xyz = pcie->points.WhitePoint;
183 pwbsd->wd.pqr = pcie->wdpqr;
184 pwbsd->bd.xyz = pcie->points.BlackPoint;
185 pwbsd->bd.pqr = pcie->bdpqr;
186 return 0;
187}
188/*
189 * Client:
190 ptpqr->u = (*pcie->TransformPQR.u)(pwbsd, ptpqr->u);
191 ptpqr->v = (*pcie->TransformPQR.v)(pwbsd, ptpqr->v);
192 ptpqr->w = (*pcie->TransformPQR.w)(pwbsd, ptpqr->w);
193 */
194int
195gs_cie_render_colors2(gs_vector3 *ptpqr, gs_vector3 *ptlmn, gs_cie_render *pcie)
196{ gs_vector3 xyzd;
197 cie_mult3(ptpqr, &pcie->MatrixPQR_inverse, &xyzd);
198 cie_mult3(&xyzd, &pcie->MatrixLMN, ptlmn);
199 return 0;
200}
201/*
202/* Client:
203 cie_apply3(ptlmn, &pcie->EncodeLMN, ptlmn);
204 */
205int
206gs_cir_render_colors3(gs_vector3 *ptlmn, gs_vector3 *ptabc, gs_cie_render *pcie)
207{ gs_vector3 lmn;
208 cie_restrict3(ptlmn, &pcie->RangeLMN, &lmn);
209 cie_mult3(&lmn, &pcie->MatrixABC, ptabc);
210 return 0;
211}
212/*
213 * Client:
214 cie_apply3(ptabc, &pcie->EncodeABC, ptabc);
215 */
216int
217gs_cie_render_colors4(gs_vector3 *ptabc, float *colors, gs_cie_render *pcie)
218{ gs_vector3 abc;
219 cie_restrict3(ptabc, &pcie->RangeABC, &abc);
220 if ( pcie->RenderTable.table == 0 )
221 { /* No further transformation */
222 colors[0] = abc.u;
223 colors[1] = abc.v;
224 colors[2] = abc.w;
225 }
226 else
227 { /* Use the RenderTable. */
228 int m = pcie->RenderTable.m;
229#define ri(s,n)\
230 (int)((abc.s - pcie->RangeABC.s.rmin) * (pcie->RenderTable.n - 1) /\
231 (pcie->RangeABC.s.rmax - pcie->RangeABC.s.rmin) + 0.5)
232 int ia = ri(u, NA);
233 int ib = ri(v, NB);
234 int ic = ri(w, NC);
235 int j;
236 byte *pdc = pcie->RenderTable.table[ia] +
237 m * (ib * pcie->RenderTable.NC + ic);
238 for ( j = 0; j < m; j++ )
239 colors[j] = (*pcie->RenderTable.T[j])(pdc[j] / 255.0);
240 }
241 return 0;
242}