Panda3D

colrops.c
1 /* Filename: colrops.c
2 * Created by:
3 *
4 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
5 *
6 * PANDA 3D SOFTWARE
7 * Copyright (c) Carnegie Mellon University. All rights reserved.
8 *
9 * All use of this software is subject to the terms of the revised BSD
10 * license. You should have received a copy of this license along
11 * with this source code in a file named "LICENSE."
12 *
13 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
14
15 /*
16 * Integer operations on COLR scanlines
17 */
18
19 #include "color.h"
20
21 #ifndef NULL
22 #define NULL 0
23 #endif
24
25 #define bmalloc malloc
26 #if !defined(WIN32_VC) && !defined(WIN64_VC)
27 extern char *bmalloc(int);
28 #else
29 #include <malloc.h>
30 #include <math.h>
31 #endif
32
33 #define MAXGSHIFT 31 /* maximum shift for gamma table */
34
35 static BYTE *g_mant = NULL, *g_nexp = NULL;
36
37 static BYTE (*g_bval)[256] = NULL;
38
39 #ifndef pow
40 #if !defined(WIN32_VC) && !defined(WIN64_VC)
41 extern double pow(double, double);
42 #endif
43 #endif
44
45
46 int setcolrcor(double (*f)(double, double), double a2)
47 /* set brightness correction */
48 {
49 double mult;
50 int i, j;
51 /* allocate tables */
52 if (g_bval == NULL && (g_bval =
53 (BYTE (*)[256])bmalloc((MAXGSHIFT+1)*256)) == NULL)
54 return(-1);
55 /* compute colr -> gamb mapping */
56 mult = 1.0/256.0;
57 for (i = 0; i <= MAXGSHIFT; i++) {
58 for (j = 0; j < 256; j++)
59 g_bval[i][j] = (BYTE) (256.0 * (*f)((j+.5)*mult, a2));
60 mult *= 0.5;
61 }
62 return(0);
63 }
64
65
66 int setcolrinv(double (*f)(double, double), double a2)
67 /* set inverse brightness correction */
68 {
69 double mult;
70 int i, j;
71 /* allocate tables */
72 if (g_mant == NULL && (g_mant = (BYTE *)bmalloc(256)) == NULL)
73 return(-1);
74 if (g_nexp == NULL && (g_nexp = (BYTE *)bmalloc(256)) == NULL)
75 return(-1);
76 /* compute gamb -> colr mapping */
77 i = 0;
78 mult = 256.0;
79 for (j = 255; j > 0; j--) {
80 while ((g_mant[j] = (BYTE)(mult * (*f)(j/256.0, a2))) < 128) {
81 i++;
82 mult *= 2.0;
83 }
84 g_nexp[j] = i;
85 }
86 g_mant[0] = 0;
87 g_nexp[0] = COLXS;
88 return(0);
89 }
90
91
92 int setcolrgam(double g) /* set gamma conversion */
93 {
94 if (setcolrcor(pow, 1.0/g) < 0)
95 return(-1);
96 return(setcolrinv(pow, g));
97 }
98
99
100 int colrs_gambs(COLR *scan, int len)
101 /* convert scanline of colrs to gamma bytes */
102 {
103 int i, expo;
104
105 if (g_bval == NULL)
106 return(-1);
107 while (len-- > 0) {
108 expo = scan[0][EXP] - COLXS;
109 if (expo < -MAXGSHIFT) {
110 if (expo < -MAXGSHIFT-8) {
111 scan[0][RED] =
112 scan[0][GRN] =
113 scan[0][BLU] = 0;
114 } else {
115 i = (-MAXGSHIFT-1) - expo;
116 scan[0][RED] =
117 g_bval[MAXGSHIFT][((scan[0][RED]>>i)+1)>>1];
118 scan[0][GRN] =
119 g_bval[MAXGSHIFT][((scan[0][GRN]>>i)+1)>>1];
120 scan[0][BLU] =
121 g_bval[MAXGSHIFT][((scan[0][BLU]>>i)+1)>>1];
122 }
123 } else if (expo > 0) {
124 if (expo > 8) {
125 scan[0][RED] =
126 scan[0][GRN] =
127 scan[0][BLU] = 255;
128 } else {
129 i = (scan[0][RED]<<1 | 1) << (expo-1);
130 scan[0][RED] = i > 255 ? 255 : g_bval[0][i];
131 i = (scan[0][GRN]<<1 | 1) << (expo-1);
132 scan[0][GRN] = i > 255 ? 255 : g_bval[0][i];
133 i = (scan[0][BLU]<<1 | 1) << (expo-1);
134 scan[0][BLU] = i > 255 ? 255 : g_bval[0][i];
135 }
136 } else {
137 scan[0][RED] = g_bval[-expo][scan[0][RED]];
138 scan[0][GRN] = g_bval[-expo][scan[0][GRN]];
139 scan[0][BLU] = g_bval[-expo][scan[0][BLU]];
140 }
141 scan[0][EXP] = COLXS;
142 scan++;
143 }
144 return(0);
145 }
146
147
148 int gambs_colrs(COLR *scan, int len)
149 /* convert gamma bytes to colr scanline */
150 {
151 int nexpo;
152
153 if (g_mant == NULL || g_nexp == NULL)
154 return(-1);
155 while (len-- > 0) {
156 nexpo = g_nexp[scan[0][RED]];
157 if (g_nexp[scan[0][GRN]] < nexpo)
158 nexpo = g_nexp[scan[0][GRN]];
159 if (g_nexp[scan[0][BLU]] < nexpo)
160 nexpo = g_nexp[scan[0][BLU]];
161 if (nexpo < g_nexp[scan[0][RED]])
162 scan[0][RED] = g_mant[scan[0][RED]]
163 >> (g_nexp[scan[0][RED]]-nexpo);
164 else
165 scan[0][RED] = g_mant[scan[0][RED]];
166 if (nexpo < g_nexp[scan[0][GRN]])
167 scan[0][GRN] = g_mant[scan[0][GRN]]
168 >> (g_nexp[scan[0][GRN]]-nexpo);
169 else
170 scan[0][GRN] = g_mant[scan[0][GRN]];
171 if (nexpo < g_nexp[scan[0][BLU]])
172 scan[0][BLU] = g_mant[scan[0][BLU]]
173 >> (g_nexp[scan[0][BLU]]-nexpo);
174 else
175 scan[0][BLU] = g_mant[scan[0][BLU]];
176 scan[0][EXP] = COLXS - nexpo;
177 scan++;
178 }
179 return(0);
180 }
181
182
183 void
184 shiftcolrs(COLR *scan, int len, int adjust)
185 /* shift a scanline of colors by 2^adjust */
186 {
187 int minexp;
188
189 if (adjust == 0)
190 return;
191 minexp = adjust < 0 ? -adjust : 0;
192 while (len-- > 0) {
193 if (scan[0][EXP] <= minexp)
194 scan[0][RED] = scan[0][GRN] = scan[0][BLU] =
195 scan[0][EXP] = 0;
196 else
197 scan[0][EXP] += adjust;
198 scan++;
199 }
200 }
201
202
203 void
204 normcolrs(COLR *scan, int len, int adjust)
205 /* normalize a scanline of colrs */
206 {
207 int c;
208 int shift;
209
210 while (len-- > 0) {
211 shift = scan[0][EXP] + adjust - COLXS;
212 if (shift > 0) {
213 if (shift > 8) {
214 scan[0][RED] =
215 scan[0][GRN] =
216 scan[0][BLU] = 255;
217 } else {
218 shift--;
219 c = (scan[0][RED]<<1 | 1) << shift;
220 scan[0][RED] = c > 255 ? 255 : c;
221 c = (scan[0][GRN]<<1 | 1) << shift;
222 scan[0][GRN] = c > 255 ? 255 : c;
223 c = (scan[0][BLU]<<1 | 1) << shift;
224 scan[0][BLU] = c > 255 ? 255 : c;
225 }
226 } else if (shift < 0) {
227 if (shift < -8) {
228 scan[0][RED] =
229 scan[0][GRN] =
230 scan[0][BLU] = 0;
231 } else {
232 shift = -1-shift;
233 scan[0][RED] = ((scan[0][RED]>>shift)+1)>>1;
234 scan[0][GRN] = ((scan[0][GRN]>>shift)+1)>>1;
235 scan[0][BLU] = ((scan[0][BLU]>>shift)+1)>>1;
236 }
237 }
238 scan[0][EXP] = COLXS - adjust;
239 scan++;
240 }
241 }