source: trunk/JPGPROC/source/gbmsrc/gbmgamma.c@ 2

Last change on this file since 2 was 2, checked in by stevenhl, 8 years ago

Import sources from cwmm-full.zip dated 2005-03-21

File size: 8.4 KB
Line 
1/*
2
3gbmgamma.c - Gamma correct General Bitmap
4
5*/
6
7/*...sincludes:0:*/
8#include <stdio.h>
9#include <ctype.h>
10#include <math.h>
11#include <string.h>
12#include <stddef.h>
13#include <stdlib.h>
14#include <stdarg.h>
15#if defined(AIX) || defined(LINUX) || defined(MAC)
16#include <unistd.h>
17#else
18#include <io.h>
19#endif
20#include <fcntl.h>
21#ifdef MAC
22#include <types.h>
23#include <stat.h>
24#else
25#include <sys/types.h>
26#include <sys/stat.h>
27#endif
28#ifndef O_BINARY
29#define O_BINARY 0
30#endif
31#include "gbm.h"
32
33/*...vgbm\46\h:0:*/
34/*...e*/
35
36static char progname[] = "gbmgamma";
37
38/*...sfatal:0:*/
39static void fatal(const char *fmt, ...)
40 {
41 va_list vars;
42 char s[256+1];
43
44 va_start(vars, fmt);
45 vsprintf(s, fmt, vars);
46 va_end(vars);
47 fprintf(stderr, "%s: %s\n", progname, s);
48 exit(1);
49 }
50/*...e*/
51/*...susage:0:*/
52static void usage(void)
53 {
54 int ft, n_ft;
55
56 fprintf(stderr, "usage: %s [-m map] [-g gamma] [-s shelf] fn1.ext{,opt} [--] [fn2.ext{,opt}]\n", progname);
57 fprintf(stderr, "flags: -m map mapping in the form ?_to_? (default: i_to_l), where ? is\n");
58 fprintf(stderr, " i physical intensitys (eg: raytracer output)\n");
59 fprintf(stderr, " p gamma corrected for a specific monitor\n");
60 fprintf(stderr, " l L* cyclometric linear perceived intensitys (as in PM)\n");
61 fprintf(stderr, " -g gamma set monitor gamma (default 2.1)\n");
62 fprintf(stderr, " -s shelf set monitor shelf (default 0.0)\n");
63 fprintf(stderr, " gamma and shelf only used for mapping to or from p\n");
64 fprintf(stderr, " for 8514 monitor gamma=2.3,shelf=0.136\n");
65 fprintf(stderr, " for 8515 monitor gamma=2.1,shelf=0.0\n");
66 fprintf(stderr, " fn1.ext{,opt} input filename (with any format specific options)\n");
67 fprintf(stderr, " fn2.ext{,opt} optional output filename (or will use fn1 if not present)\n");
68 fprintf(stderr, " ext's are used to deduce desired bitmap file formats\n");
69
70 gbm_init();
71 gbm_query_n_filetypes(&n_ft);
72 for ( ft = 0; ft < n_ft; ft++ )
73 {
74 GBMFT gbmft;
75
76 gbm_query_filetype(ft, &gbmft);
77 fprintf(stderr, " %s when ext in [%s]\n",
78 gbmft.short_name, gbmft.extensions);
79 }
80 gbm_deinit();
81
82 fprintf(stderr, " opt's bitmap format specific options\n");
83
84 exit(1);
85 }
86/*...e*/
87/*...sget_opt_double:0:*/
88static double get_opt_double(const char *s, const char *name)
89 {
90 double v;
91
92 if ( s == NULL )
93 fatal("missing %s argument", name);
94 sscanf(s, "%lf", &v);
95
96 return v;
97 }
98/*...e*/
99/*...ssame:0:*/
100static BOOLEAN same(const char *s1, const char *s2, int n)
101 {
102 for ( ; n--; s1++, s2++ )
103 if ( tolower(*s1) != tolower(*s2) )
104 return FALSE;
105 return TRUE;
106 }
107/*...e*/
108/*...smain:0:*/
109/*...smapinfos:0:*/
110#define CVT_NONE 0
111#define CVT_I_TO_P 1
112#define CVT_P_TO_I 2
113#define CVT_I_TO_L 3
114#define CVT_L_TO_I 4
115#define CVT_P_TO_L 5
116#define CVT_L_TO_P 6
117
118typedef struct { char *name; int m; } MAPINFO;
119
120static MAPINFO mapinfos[] =
121 {
122 "none", CVT_NONE,
123 "i_to_p", CVT_I_TO_P,
124 "p_to_i", CVT_P_TO_I,
125 "i_to_l", CVT_I_TO_L,
126 "l_to_i", CVT_L_TO_I,
127 "p_to_l", CVT_P_TO_L,
128 "l_to_p", CVT_L_TO_P,
129 };
130
131#define N_MAPINFOS (sizeof(mapinfos)/sizeof(mapinfos[0]))
132/*...e*/
133
134/*...smap_compute:0:*/
135/*...slstar_from_i:0:*/
136static double lstar_from_i(double y)
137 {
138 y = pow(1.16 * y, 1.0/3.0) - 0.16;
139
140 if ( y < 0.0 ) y = 0.0; else if ( y > 1.0 ) y = 1.0;
141
142 return y;
143 }
144/*...e*/
145/*...si_from_lstar:0:*/
146static double i_from_lstar(double y)
147 {
148 y = pow(y + 0.16, 3.0) / 1.16;
149
150 if ( y < 0.0 ) y = 0.0; else if ( y > 1.0 ) y = 1.0;
151
152 return y;
153 }
154/*...e*/
155/*...spal_from_i:0:*/
156static double pal_from_i(double y, double gam, double shelf)
157 {
158 y = pow(y,1.0 / gam) * (1.0 - shelf) + shelf;
159
160 if ( y < 0.0 ) y = 0.0; else if ( y > 1.0 ) y = 1.0;
161
162 return y;
163 }
164/*...e*/
165/*...si_from_pal:0:*/
166static double i_from_pal(double y, double gam, double shelf)
167 {
168 if ( y >= shelf )
169 y = pow((y - shelf) / (1.0 - shelf), gam);
170 else
171 y = 0.0;
172
173 if ( y < 0.0 ) y = 0.0; else if ( y > 1.0 ) y = 1.0;
174
175 return y;
176 }
177/*...e*/
178
179static void map_compute(int m, byte remap[], double gam, double shelf)
180 {
181 int i;
182
183 for ( i = 0; i < 0x100; i++ )
184 {
185 double y = (double) i / 255.0;
186
187 switch ( m )
188 {
189 case CVT_I_TO_P: y = pal_from_i(y, gam, shelf); break;
190 case CVT_P_TO_I: y = i_from_pal(y, gam, shelf); break;
191 case CVT_I_TO_L: y = lstar_from_i(y); break;
192 case CVT_L_TO_I: y = i_from_lstar(y); break;
193 case CVT_P_TO_L: y = lstar_from_i(i_from_pal(y, gam, shelf)); break;
194 case CVT_L_TO_P: y = pal_from_i(i_from_lstar(y), gam, shelf); break;
195 }
196
197 remap[i] = (byte) (y * 255.0);
198 }
199 }
200/*...e*/
201/*...smap_data:0:*/
202static void map_data(byte *data, int w, int h, const byte remap[])
203 {
204 int stride = ((w * 3 + 3) & ~3);
205 int x, y;
206
207 for ( y = 0; y < h; y++, data += stride )
208 for ( x = 0; x < w * 3; x++ )
209 data[x] = remap[data[x]];
210 }
211/*...e*/
212/*...smap_palette:0:*/
213static void map_palette(GBMRGB *gbmrgb, int npals, const byte remap[])
214 {
215 for ( ; npals--; gbmrgb++ )
216 {
217 gbmrgb->b = remap[gbmrgb->b];
218 gbmrgb->g = remap[gbmrgb->g];
219 gbmrgb->r = remap[gbmrgb->r];
220 }
221 }
222/*...e*/
223
224int main(int argc, char *argv[])
225 {
226 char fn_src[500+1], fn_dst[500+1], *opt_src, *opt_dst;
227 int fd, ft_src, ft_dst, i, stride, bytes, flag, m;
228 GBM_ERR rc;
229 GBMFT gbmft;
230 GBM gbm;
231 GBMRGB gbmrgb[0x100];
232 byte *data;
233 char *map = "none";
234 byte remap[0x100];
235 double gam = 2.1, shelf = 0.0;
236
237/*...scommand line arguments:8:*/
238for ( i = 1; i < argc; i++ )
239 {
240 if ( argv[i][0] != '-' )
241 break;
242 else if ( argv[i][1] == '-' )
243 { ++i; break; }
244 switch ( argv[i][1] )
245 {
246 case 'm':
247 if ( ++i == argc )
248 fatal("expected map argument");
249 map = argv[i];
250 break;
251 case 'g':
252 if ( ++i == argc ) usage();
253 gam = get_opt_double(argv[i], "gam");
254 if ( gam < 0.1 || gam > 10.0 )
255 fatal("only gammas in the range 0.1 to 10.0 are sensible");
256 break;
257 case 's':
258 if ( ++i == argc ) usage();
259 shelf = get_opt_double(argv[i], "shelf");
260 break;
261 default:
262 usage();
263 break;
264 }
265 }
266/*...e*/
267
268/*...sdeduce mapping and bits per pixel etc\46\:8:*/
269{
270int j;
271
272for ( j = 0; j < N_MAPINFOS; j++ )
273 if ( same(map, mapinfos[j].name, (int) strlen(map) + 1) )
274 break;
275if ( j == N_MAPINFOS )
276 fatal("unrecognised mapping %s", map);
277m = mapinfos[j].m;
278}
279/*...e*/
280
281 if ( i == argc )
282 usage();
283 strcpy(fn_src, argv[i++]);
284 strcpy(fn_dst, ( i == argc ) ? fn_src : argv[i++]);
285 if ( i < argc )
286 usage();
287
288 if ( (opt_src = strchr(fn_src, ',')) != NULL )
289 *opt_src++ = '\0';
290 else
291 opt_src = "";
292
293 if ( (opt_dst = strchr(fn_dst, ',')) != NULL )
294 *opt_dst++ = '\0';
295 else
296 opt_dst = "";
297
298 gbm_init();
299
300 if ( gbm_guess_filetype(fn_src, &ft_src) != GBM_ERR_OK )
301 fatal("can't guess bitmap file format for %s", fn_src);
302
303 if ( gbm_guess_filetype(fn_dst, &ft_dst) != GBM_ERR_OK )
304 fatal("can't guess bitmap file format for %s", fn_dst);
305
306 if ( (fd = gbm_io_open(fn_src, O_RDONLY|O_BINARY)) == -1 )
307 fatal("can't open %s", fn_src);
308
309 if ( (rc = gbm_read_header(fn_src, fd, ft_src, &gbm, opt_src)) != GBM_ERR_OK )
310 {
311 gbm_io_close(fd);
312 fatal("can't read header of %s: %s", fn_src, gbm_err(rc));
313 }
314
315 gbm_query_filetype(ft_dst, &gbmft);
316 switch ( gbm.bpp )
317 {
318 case 24: flag = GBM_FT_W24; break;
319 case 8: flag = GBM_FT_W8; break;
320 case 4: flag = GBM_FT_W4; break;
321 case 1: flag = GBM_FT_W1; break;
322 }
323 if ( (gbmft.flags & flag) == 0 )
324 {
325 gbm_io_close(fd);
326 fatal("output bitmap format %s does not support writing %d bpp data",
327 gbmft.short_name, gbm.bpp);
328 }
329
330 if ( (rc = gbm_read_palette(fd, ft_src, &gbm, gbmrgb)) != GBM_ERR_OK )
331 {
332 gbm_io_close(fd);
333 fatal("can't read palette of %s: %s", fn_src, gbm_err(rc));
334 }
335
336 stride = ( ((gbm.w * gbm.bpp + 31)/32) * 4 );
337 bytes = stride * gbm.h;
338 if ( (data = malloc((size_t) bytes)) == NULL )
339 {
340 gbm_io_close(fd);
341 fatal("out of memory allocating %d bytes for bitmap", bytes);
342 }
343
344 if ( (rc = gbm_read_data(fd, ft_src, &gbm, data)) != GBM_ERR_OK )
345 {
346 gbm_io_close(fd);
347 fatal("can't read bitmap data of %s: %s", fn_src, gbm_err(rc));
348 }
349
350 gbm_io_close(fd);
351
352 map_compute(m, remap, gam, shelf);
353
354 if ( gbm.bpp == 24 )
355 map_data(data, gbm.w, gbm.h, remap);
356 else
357 map_palette(gbmrgb, 1 << gbm.bpp, remap);
358
359 if ( (fd = gbm_io_create(fn_dst, O_WRONLY|O_BINARY)) == -1 )
360 fatal("can't create %s", fn_dst);
361
362 if ( (rc = gbm_write(fn_dst, fd, ft_dst, &gbm, gbmrgb, data, opt_dst)) != GBM_ERR_OK )
363 {
364 gbm_io_close(fd);
365 remove(fn_dst);
366 fatal("can't write %s: %s", fn_dst, gbm_err(rc));
367 }
368
369 gbm_io_close(fd);
370
371 free(data);
372
373 gbm_deinit();
374
375 return 0;
376 }
377/*...e*/
Note: See TracBrowser for help on using the repository browser.