]> git.pld-linux.org Git - packages/dcraw.git/blame - fuji_green.c
- drop obsolete files
[packages/dcraw.git] / fuji_green.c
CommitLineData
3d481f66
PG
1/*
2 fuji_green -- read Fuji green pixels
3
4 $Revision$
5 $Date$
6 */
7
8#include <ctype.h>
9#include <math.h>
10#include <setjmp.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14
15#define ushort UshORt
16typedef unsigned char uchar;
17typedef unsigned short ushort;
18
19FILE *ifp;
20short order;
21char *ifname, make[64], model[64];
22int data_offset, raw_height, raw_width, height, width;
23int fuji_layout, fuji_secondary, use_secondary=0, verbose=0;
24ushort *image;
25void (*load_raw)();
26float bright=1.0;
27void write_ppm(FILE *);
28void (*write_fun)(FILE *) = write_ppm;
29jmp_buf failure;
30
31#define CLASS
32
33void CLASS merror (void *ptr, char *where)
34{
35 if (ptr) return;
36 fprintf (stderr, "%s: Out of memory in %s\n", ifname, where);
37 longjmp (failure, 1);
38}
39
40ushort CLASS get2()
41{
42 uchar a, b;
43
44 a = fgetc(ifp);
45 b = fgetc(ifp);
46 if (order == 0x4949) /* "II" means little-endian */
47 return a + (b << 8);
48 else /* "MM" means big-endian */
49 return (a << 8) + b;
50}
51
52int CLASS get4()
53{
54 uchar a, b, c, d;
55
56 a = fgetc(ifp);
57 b = fgetc(ifp);
58 c = fgetc(ifp);
59 d = fgetc(ifp);
60 if (order == 0x4949)
61 return a + (b << 8) + (c << 16) + (d << 24);
62 else
63 return (a << 24) + (b << 16) + (c << 8) + d;
64}
65
66/*
67 Faster than calling get2() multiple times.
68 */
69void CLASS read_shorts (ushort *pixel, int count)
70{
71 fread (pixel, 2, count, ifp);
72 if ((order == 0x4949) == (ntohs(0x1234) == 0x1234))
73 swab (pixel, pixel, count*2);
74}
75
76void CLASS fuji_load_raw()
77{
78 ushort *pixel, *img;
79 int row, col;
80
81 pixel = calloc (raw_width, 2);
82 merror (pixel, "fuji_load_raw()");
83 for (row=0; row < height; row++)
84 if (fuji_layout) {
85 read_shorts (image+row*width, width);
86 fseek (ifp, (raw_width*2 - width)*2, SEEK_CUR);
87 } else {
88 read_shorts (pixel, raw_width);
89 for (img=image+row*width, col=0; col < width; col++)
90 img[col] = pixel[col*2+1];
91 }
92 free (pixel);
93}
94
95void CLASS parse_fuji (int offset)
96{
97 unsigned entries, tag, len, save;
98
99 fseek (ifp, offset, SEEK_SET);
100 entries = get4();
101 if (entries > 255) return;
102 while (entries--) {
103 tag = get2();
104 len = get2();
105 save = ftell(ifp);
106 if (tag == 0x100) {
107 raw_height = get2();
108 raw_width = get2();
109 } else if (tag == 0x121) {
110 height = get2();
111 width = get2();
112 } else if (tag == 0x130)
113 fuji_layout = fgetc(ifp) >> 7;
114 fseek (ifp, save+len, SEEK_SET);
115 }
116 if (fuji_layout) {
117 height *= 2;
118 width /= 2;
119 }
120}
121
122void CLASS parse_tiff (int base)
123{
124 int doff, entries, tag, type, len, save;
125
126 fseek (ifp, base, SEEK_SET);
127 order = get2();
128 get2(); /* Should be 42 for standard TIFF */
129 while ((doff = get4())) {
130 fseek (ifp, doff+base, SEEK_SET);
131 entries = get2();
132 while (entries--) {
133 tag = get2();
134 type = get2();
135 len = get4();
136 save = ftell(ifp)+4;
137 fseek (ifp, base+get4(), SEEK_SET);
138 switch (tag) {
139 case 0x10f: /* Make tag */
140 fgets (make, 64, ifp);
141 break;
142 case 0x110: /* Model tag */
143 fgets (model, 64, ifp);
144 }
145 fseek (ifp, save, SEEK_SET);
146 }
147 }
148}
149
150int CLASS identify()
151{
152 char head[32], *c;
153 int thumb_offset;
154
155 make[0] = model[0] = 0;
156 data_offset = raw_height = raw_width = height = width = 0;
157 fuji_secondary = 0;
158
159 order = 0x4d4d;
160 fread (head, 1, 32, ifp);
161 if (memcmp (head, "FUJIFILM", 8)) return 1;
162 fseek (ifp, 84, SEEK_SET);
163 thumb_offset = get4();
164 fseek (ifp, 92, SEEK_SET);
165 parse_fuji (get4());
166 if (thumb_offset > 120) {
167 fseek (ifp, 120, SEEK_SET);
168 fuji_secondary = get4() && 1;
169 }
170 fseek (ifp, 100, SEEK_SET);
171 data_offset = get4();
172 parse_tiff (thumb_offset+12);
173 c = model + strlen(model); /* Remove trailing spaces */
174 while (*--c == ' ') *c = 0;
175 if (!strcmp(model,"FinePix S5100") ||
176 !strcmp(model,"FinePix S5500")) return 1;
177 load_raw = fuji_load_raw;
178 if (!strcmp(model+7,"S2Pro")) {
179 strcpy (model+7," S2Pro");
180 height = 2144;
181 width = 2880;
182 }
183 data_offset += (raw_height - height + 1)*raw_width - width;
184 if (fuji_secondary)
185 data_offset += use_secondary * ( strcmp(model+7," S3Pro")
186 ? (raw_width *= 2) : raw_height*raw_width*2 );
187 data_offset += fuji_layout*raw_width*2;
188 width >>= !fuji_layout;
189 height >>= fuji_layout;
190 fseek (ifp, data_offset, SEEK_SET);
191 return 0;
192}
193
194void CLASS write_ppm (FILE *ofp)
195{
196 int i, size, val, total, histogram[0x2000];
197 float white, r;
198 uchar lut[0x10000];
199
200 memset (histogram, 0, sizeof histogram);
201 size = width * height;
202 for (i = 0; i < size; i++)
203 histogram[image[i] >> 4]++;
204 i = size * 0.01; /* 99th percentile white point */
205 for (val=0x2000, total=0; --val; )
206 if ((total += histogram[val]) > i) break;
207 white = (val << 4) / bright;
208
209 for (i=0; i < 0x10000; i++) {
210 r = i / white;
211 val = (r <= 0.018 ? r*4.5 : pow(r,0.45)*1.099-0.099) * 256;
212 if (val > 255) val = 255;
213 lut[i] = val;
214 }
215 fprintf (ofp, "P5\n%d %d\n255\n", width, height);
216 for (i=0; i < size; i++)
217 fputc (lut[image[i]], ofp);
218}
219
220void CLASS write_raw16 (FILE *ofp)
221{
222 if (ntohs(0x1234) != 0x1234)
223 swab (image, image, width*height*2);
224 fwrite (image, width*height, 2, ofp);
225}
226
227void CLASS write_ppm16 (FILE *ofp)
228{
229 fprintf (ofp, "P5\n%d %d\n%d\n", width, height, 65535);
230 write_raw16 (ofp);
231}
232
233void CLASS write_psd (FILE *ofp)
234{
235 char head[] = {
236 '8','B','P','S', /* signature */
237 0,1,0,0,0,0,0,0, /* version and reserved */
238 0,1, /* number of channels */
239 0,0,0,0, /* height, big-endian */
240 0,0,0,0, /* width, big-endian */
241 0,16, /* 16-bit color */
242 0,1, /* mode (1=grey, 3=rgb) */
243 0,0,0,0, /* color mode data */
244 0,0,0,0, /* image resources */
245 0,0,0,0, /* layer/mask info */
246 0,0 }; /* no compression */
247 int hw[2];
248
249 hw[0] = htonl(height*2); /* write the header */
250 hw[1] = htonl(width*2);
251 memcpy (head+14, hw, sizeof hw);
252 fwrite (head, 40, 1, ofp);
253 write_raw16 (ofp);
254}
255
256int CLASS main (int argc, char **argv)
257{
258 int arg, status=0;
259 int identify_only=0, write_to_stdout=0;
260 char opt, *ofname, *cp;
261 const char *write_ext = ".pgm";
262 FILE *ofp = stdout;
263
264 if (argc == 1) {
265 fprintf (stderr,
266 "\nFuji Green channel output"
267 "\nby Dave Coffin, dcoffin a cybercom o net"
268 "\n\nUsage: %s [options] file1 file2 ...\n"
269 "\nValid options:"
270 "\n-v Print verbose messages"
271 "\n-c Write image data to standard output"
272 "\n-i Identify files without decoding them"
273 "\n-s Use secondary pixels if available"
274 "\n-b <num> Set brightness (default = 1.0)"
275 "\n-2 Write 8-bit non-linear PGM (default)"
276 "\n-4 Write 16-bit linear PGM"
277 "\n-3 Write 16-bit linear PSD (Adobe Photoshop)"
278 "\n\n", argv[0]);
279 return 1;
280 }
281 argv[argc] = "";
282 for (arg=1; argv[arg][0] == '-'; ) {
283 opt = argv[arg++][1];
284 if (strchr ("b", opt) && !isdigit(argv[arg][0])) {
285 fprintf (stderr, "\"-%c\" requires a numeric argument.\n", opt);
286 return 1;
287 }
288 switch (opt) {
289 case 'v': verbose = 1; break;
290 case 'i': identify_only = 1; break;
291 case 'c': write_to_stdout = 1; break;
292 case 's': use_secondary = 1; break;
293 case 'b': bright = atof(argv[arg++]); break;
294 case '2': write_fun = write_ppm; break;
295 case '4': write_fun = write_ppm16; break;
296 case '3': write_fun = write_psd; write_ext = ".psd"; break;
297 default:
298 fprintf (stderr, "Unknown option \"-%c\".\n", opt);
299 return 1;
300 }
301 }
302 if (arg == argc) {
303 fprintf (stderr, "No files to process.\n");
304 return 1;
305 }
306 if (write_to_stdout) {
307 if (isatty(1)) {
308 fprintf (stderr, "Will not write an image to the terminal!\n");
309 return 1;
310 }
311#if defined(WIN32) || defined(DJGPP)
312 if (setmode(1,O_BINARY) < 0) {
313 perror("setmode()");
314 return 1;
315 }
316#endif
317 }
318 for ( ; arg < argc; arg++) {
319 status = 1;
320 image = NULL;
321 if (setjmp (failure)) {
322 if (fileno(ifp) > 2) fclose (ifp);
323 if (fileno(ofp) > 2) fclose (ofp);
324 if (image) free (image);
325 status = 1;
326 continue;
327 }
328 ifname = argv[arg];
329 if (!(ifp = fopen (ifname, "rb"))) {
330 perror (ifname);
331 continue;
332 }
333 if ((status = identify())) {
334 fprintf (stderr, "%s: unsupported file format.\n", ifname);
335 fclose (ifp);
336 continue;
337 }
338 if (identify_only) {
339 fprintf (stderr, "%s is a %s %s image.\n", ifname, make, model);
340 fclose (ifp);
341 continue;
342 }
343 image = calloc (height * width, sizeof *image);
344 merror (image, "main()");
345 if (verbose)
346 fprintf (stderr,
347 "Loading %s %s image from %s...\n", make, model, ifname);
348 (*load_raw)();
349 fclose (ifp);
350 ofname = malloc (strlen(ifname) + 16);
351 merror (ofname, "main()");
352 if (write_to_stdout)
353 strcpy (ofname, "standard output");
354 else {
355 strcpy (ofname, ifname);
356 if ((cp = strrchr (ofname, '.'))) *cp = 0;
357 strcat (ofname, write_ext);
358 ofp = fopen (ofname, "wb");
359 if (!ofp) {
360 status = 1;
361 perror (ofname);
362 goto cleanup;
363 }
364 }
365 if (verbose)
366 fprintf (stderr, "Writing data to %s...\n", ofname);
367 (*write_fun)(ofp);
368 if (ofp != stdout)
369 fclose (ofp);
370cleanup:
371 free (ofname);
372 free (image);
373 }
374 return status;
375}
This page took 0.090853 seconds and 4 git commands to generate.