2 * $Source: s:/prj/tech/libsrc/dev2d/RCS/ipal.c $
5 * $Date: 1996/04/10 16:04:00 $
7 * RGB color manipulation routines.
9 * This file is part of the dev2d library.
16 /* Static Globals for his and her pleasure */
17 static int bcenter
, gcenter
, rcenter
;
18 static long gdist
, rdist
, cdist
;
19 static long cbinc
, cginc
, crinc
;
20 static ulong
*gdp
, *rdp
, *cdp
;
21 static uchar
*grgbp
, *rrgbp
, *crgbp
;
22 static int gstride
, rstride
;
23 static long x
, xsqr
, colormax
;
26 void inv_cmap_2(int colors
, uchar
*colormap
[3],int bits
,ulong
*dist_buf
, uchar
*rgbmap
);
28 int _greenloop(int restart
);
29 int _blueloop(int restart
);
30 void _maxfill(ulong
*buffer
);
32 /* The routines in this file operate on grs_rgb color values. The color
33 values are encoded so that each r,g, and b has 8 bits of integer, 2
34 bits of fraction, and one bit of padding. */
36 /* This routine allocates a 15 bit inverse palette for the
37 current screen palette (that 32768 bytes) and initializes
38 it for the current palette. Returns OUT_OF_MEMORY
39 if it can't allocate anything. If ipal is currently non-null
40 it tries to delete it first, in the interests of robustness */
42 int gr_alloc_ipal(void)
46 if (grd_ipal
!= NULL
) {
47 if ((err
= gr_free_ipal())<0) return err
;
50 if ((grd_ipal
= gr_malloc(32768))==NULL
) return RGB_OUT_OF_MEMORY
;
52 if ((err
= gr_init_ipal())<0) return err
;
56 int gr_free_ipal(void)
58 if (grd_ipal
==NULL
) return RGB_CANT_DEALLOCATE
;
64 /* Initializes the inverse palette to the current screen
67 int gr_init_ipal(void)
69 if (grd_ipal
== NULL
) return RGB_IPAL_NOT_ALLOCATED
;
70 return gr_calc_ipal(grd_bpal
, grd_ipal
);
73 /* Calculates an inverse palette from a given
76 int gr_calc_ipal(grs_rgb
*bpal
, uchar
*ipal
)
80 uchar
*data
,*colormap
[3];
83 if ((data
= gr_malloc(3*256)) == NULL
) return RGB_OUT_OF_MEMORY
;
84 /* needs to be split up into r,g,b planes */
86 colormap
[1] = data
+ 256;
87 colormap
[2] = data
+ 2*256;
90 gr_split_rgb(bpal
[i
],&r
,&g
,&b
);
96 if ((dist_buf
= gr_malloc(sizeof(ulong
) * 32768))==NULL
) return RGB_OUT_OF_MEMORY
;
98 inv_cmap_2(256,colormap
,5,dist_buf
,ipal
);
107 static void inv_cmap_2(int colors
, uchar
*colormap
[3],int bits
,ulong
*dist_buf
, uchar
*rgbmap
)
109 int nbits
= 8 - bits
;
111 colormax
= 1 << bits
;
113 xsqr
= 1 << (2 * nbits
);
115 /* Compute strides for accessing the arrays. */
118 rstride
= colormax
* colormax
;
122 for(cindex
= 0;cindex
<colors
; cindex
++) {
123 /* The initial position is the cell containing the colormap
124 * entry. We get this by quantiziing the colormap values.
126 rcenter
= colormap
[0][cindex
] >> nbits
;
127 gcenter
= colormap
[1][cindex
] >> nbits
;
128 bcenter
= colormap
[2][cindex
] >> nbits
;
130 rdist
= colormap
[0][cindex
] - (rcenter
* x
+ x
/2);
131 gdist
= colormap
[1][cindex
] - (gcenter
* x
+ x
/2);
132 cdist
= colormap
[2][cindex
] - (bcenter
* x
+ x
/2);
133 cdist
= rdist
*rdist
+ gdist
*gdist
+ cdist
*cdist
;
135 crinc
= 2 * ((rcenter
+1) * xsqr
- (colormap
[0][cindex
] * x
));
136 cginc
= 2 * ((gcenter
+1) * xsqr
- (colormap
[1][cindex
] * x
));
137 cbinc
= 2 * ((bcenter
+1) * xsqr
- (colormap
[2][cindex
] * x
));
139 /* Array starting points. */
140 cdp
= dist_buf
+ rcenter
*rstride
+ gcenter
*gstride
+ bcenter
;
141 crgbp
= rgbmap
+ rcenter
*rstride
+ gcenter
*gstride
+ bcenter
;
147 /* redloop -- loop up and down from red center. */
148 static int _redloop()
150 int detect
, r
, first
;
151 long txsqr
= xsqr
+ xsqr
;
157 for (r
= rcenter
, rdist
= cdist
, rxx
= crinc
,
158 rdp
= cdp
, rrgbp
= crgbp
, first
= 1;
160 r
++, rdp
+= rstride
, rrgbp
+= rstride
,
161 rdist
+= rxx
, rxx
+= txsqr
, first
= 0) {
162 if (_greenloop(first
))
168 /* Basic loop down */
169 for (r
= rcenter
- 1, rxx
= crinc
- txsqr
, rdist
= cdist
- rxx
,
170 rdp
= cdp
- rstride
, rrgbp
= crgbp
- rstride
, first
= 1;
172 r
--, rdp
-= rstride
, rrgbp
-= rstride
,
173 rxx
-= txsqr
, rdist
-= rxx
, first
= 0) {
174 if (_greenloop(first
))
184 /* greenloop -- loop up and down from green center. */
185 static int _greenloop(int restart
)
187 int detect
, g
, first
;
188 long txsqr
= xsqr
+ xsqr
;
189 static int here
, min
, max
;
190 static int prevmax
, prevmin
;
191 int thismax
, thismin
;
192 static long ginc
, gxx
, gcdist
;
194 static uchar
*gcrgbp
;
196 /* Red loop restarted, reset variables to "center" position */
206 /* finding actual min and max on this line. */
212 for (g
=here
, gcdist
= gdist
= rdist
, gxx
= ginc
,
213 gcdp
= gdp
= rdp
, gcrgbp
= grgbp
= rrgbp
, first
= 1;
215 g
++, gdp
+= gstride
, gcdp
+= gstride
,
216 grgbp
+= gstride
, gcrgbp
+= gstride
,
217 gdist
+= gxx
, gcdist
+= gxx
, gxx
+= txsqr
, first
= 0) {
218 if (_blueloop(first
)) {
220 /* remember here and associated data! */
238 /* Basic loop down */
239 for (g
=here
- 1, gxx
= ginc
- txsqr
, gcdist
= gdist
= rdist
- gxx
,
240 gcdp
= gdp
= rdp
- gstride
, gcrgbp
= grgbp
= rrgbp
- gstride
,
243 g
--, gdp
-= gstride
, gcdp
-= gstride
,
244 grgbp
-= gstride
, gcrgbp
-= gstride
,
245 gxx
-= txsqr
, gdist
-= gxx
, gcdist
-= gxx
, first
= 0) {
246 if (_blueloop(first
)) {
264 /* If we saw something, update the edge tracers. Only
265 * tracks edges that are "shrinking" (min increating, max
270 if (thismax
< prevmax
)
274 if (thismin
> prevmin
)
282 /* blueloop -- loop up and down from blue center. */
283 static int _blueloop(int restart
)
286 /* These are all registers on a Sun 3. Your mileage may differ. */
291 long txsqr
= xsqr
+ xsqr
;
292 int lim
; /* for min and max, avoid extra registers. */
293 static int here
, min
, max
;
294 static int prevmin
, prevmax
; /* For tracking min and max. */
295 int thismin
, thismax
;
312 /* First loop just finds first applicable cell. */
313 for (b
= here
, bdist
= gdist
, bxx
= binc
, dp
= gdp
, rgbp
= grgbp
,
316 b
++, dp
++, rgbp
++, bdist
+= bxx
, bxx
+= txsqr
) {
318 /* Remember new here and associated data! */
331 /* Second loop fills in a run of closer cells. */
334 b
++, dp
++, rgbp
++, bdist
+= bxx
, bxx
+= txsqr
) {
344 /* Basic loop down */
345 /* Do initializations here, since the 'find' loop might not get
354 /* The 'find' loop ios executed on ly if we didn't already find
360 b
--, dp
--, rgbp
--, bxx
-= txsqr
, bdist
-= bxx
) {
363 /* No test for b against here necessary because b <
364 * here by definition.
376 /* the 'update' loop */
379 b
--, dp
--, rgbp
--, bxx
-= txsqr
, bdist
-= bxx
) {
389 /* If we saw something, update the edge trackers. */
391 /* Only tracks edges that are 'shrinking' (*min increasin, max
394 if (thismax
< prevmax
)
396 if (thismin
> prevmin
)
399 /* Remember the min and max values. */
407 /* Fill a buffer with the largest unsigned long. */
408 static void _maxfill(ulong
*buffer
)
410 ulong maxv
= (long)-1;
414 for(i
=colormax
* colormax
* colormax
, bp
= buffer
;