]> git.pld-linux.org Git - packages/dcraw.git/blob - fuji_green.c
- updated to 9.26.0
[packages/dcraw.git] / fuji_green.c
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
16 typedef unsigned char uchar;
17 typedef unsigned short ushort;
18
19 FILE *ifp;
20 short order;
21 char *ifname, make[64], model[64];
22 int data_offset, raw_height, raw_width, height, width;
23 int fuji_layout, fuji_secondary, use_secondary=0, verbose=0;
24 ushort *image;
25 void (*load_raw)();
26 float bright=1.0;
27 void write_ppm(FILE *);
28 void (*write_fun)(FILE *) = write_ppm;
29 jmp_buf failure;
30
31 #define CLASS
32
33 void 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
40 ushort 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
52 int 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  */
69 void 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
76 void 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
95 void 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
122 void 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
150 int 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
194 void 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
220 void 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
227 void 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
233 void 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
256 int 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);
370 cleanup:
371     free (ofname);
372     free (image);
373   }
374   return status;
375 }
This page took 0.086112 seconds and 3 git commands to generate.