2 fuji_green -- read Fuji green pixels
16 typedef unsigned char uchar;
17 typedef unsigned short ushort;
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;
27 void write_ppm(FILE *);
28 void (*write_fun)(FILE *) = write_ppm;
33 void CLASS merror (void *ptr, char *where)
36 fprintf (stderr, "%s: Out of memory in %s\n", ifname, where);
46 if (order == 0x4949) /* "II" means little-endian */
48 else /* "MM" means big-endian */
61 return a + (b << 8) + (c << 16) + (d << 24);
63 return (a << 24) + (b << 16) + (c << 8) + d;
67 Faster than calling get2() multiple times.
69 void CLASS read_shorts (ushort *pixel, int count)
71 fread (pixel, 2, count, ifp);
72 if ((order == 0x4949) == (ntohs(0x1234) == 0x1234))
73 swab (pixel, pixel, count*2);
76 void CLASS fuji_load_raw()
81 pixel = calloc (raw_width, 2);
82 merror (pixel, "fuji_load_raw()");
83 for (row=0; row < height; row++)
85 read_shorts (image+row*width, width);
86 fseek (ifp, (raw_width*2 - width)*2, SEEK_CUR);
88 read_shorts (pixel, raw_width);
89 for (img=image+row*width, col=0; col < width; col++)
90 img[col] = pixel[col*2+1];
95 void CLASS parse_fuji (int offset)
97 unsigned entries, tag, len, save;
99 fseek (ifp, offset, SEEK_SET);
101 if (entries > 255) return;
109 } else if (tag == 0x121) {
112 } else if (tag == 0x130)
113 fuji_layout = fgetc(ifp) >> 7;
114 fseek (ifp, save+len, SEEK_SET);
122 void CLASS parse_tiff (int base)
124 int doff, entries, tag, type, len, save;
126 fseek (ifp, base, SEEK_SET);
128 get2(); /* Should be 42 for standard TIFF */
129 while ((doff = get4())) {
130 fseek (ifp, doff+base, SEEK_SET);
137 fseek (ifp, base+get4(), SEEK_SET);
139 case 0x10f: /* Make tag */
140 fgets (make, 64, ifp);
142 case 0x110: /* Model tag */
143 fgets (model, 64, ifp);
145 fseek (ifp, save, SEEK_SET);
155 make[0] = model[0] = 0;
156 data_offset = raw_height = raw_width = height = width = 0;
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);
166 if (thumb_offset > 120) {
167 fseek (ifp, 120, SEEK_SET);
168 fuji_secondary = get4() && 1;
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");
183 data_offset += (raw_height - height + 1)*raw_width - width;
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);
194 void CLASS write_ppm (FILE *ofp)
196 int i, size, val, total, histogram[0x2000];
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;
209 for (i=0; i < 0x10000; i++) {
211 val = (r <= 0.018 ? r*4.5 : pow(r,0.45)*1.099-0.099) * 256;
212 if (val > 255) val = 255;
215 fprintf (ofp, "P5\n%d %d\n255\n", width, height);
216 for (i=0; i < size; i++)
217 fputc (lut[image[i]], ofp);
220 void CLASS write_raw16 (FILE *ofp)
222 if (ntohs(0x1234) != 0x1234)
223 swab (image, image, width*height*2);
224 fwrite (image, width*height, 2, ofp);
227 void CLASS write_ppm16 (FILE *ofp)
229 fprintf (ofp, "P5\n%d %d\n%d\n", width, height, 65535);
233 void CLASS write_psd (FILE *ofp)
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 */
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);
256 int CLASS main (int argc, char **argv)
259 int identify_only=0, write_to_stdout=0;
260 char opt, *ofname, *cp;
261 const char *write_ext = ".pgm";
266 "\nFuji Green channel output"
267 "\nby Dave Coffin, dcoffin a cybercom o net"
268 "\n\nUsage: %s [options] file1 file2 ...\n"
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)"
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);
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;
298 fprintf (stderr, "Unknown option \"-%c\".\n", opt);
303 fprintf (stderr, "No files to process.\n");
306 if (write_to_stdout) {
308 fprintf (stderr, "Will not write an image to the terminal!\n");
311 #if defined(WIN32) || defined(DJGPP)
312 if (setmode(1,O_BINARY) < 0) {
318 for ( ; arg < argc; arg++) {
321 if (setjmp (failure)) {
322 if (fileno(ifp) > 2) fclose (ifp);
323 if (fileno(ofp) > 2) fclose (ofp);
324 if (image) free (image);
329 if (!(ifp = fopen (ifname, "rb"))) {
333 if ((status = identify())) {
334 fprintf (stderr, "%s: unsupported file format.\n", ifname);
339 fprintf (stderr, "%s is a %s %s image.\n", ifname, make, model);
343 image = calloc (height * width, sizeof *image);
344 merror (image, "main()");
347 "Loading %s %s image from %s...\n", make, model, ifname);
350 ofname = malloc (strlen(ifname) + 16);
351 merror (ofname, "main()");
353 strcpy (ofname, "standard output");
355 strcpy (ofname, ifname);
356 if ((cp = strrchr (ofname, '.'))) *cp = 0;
357 strcat (ofname, write_ext);
358 ofp = fopen (ofname, "wb");
366 fprintf (stderr, "Writing data to %s...\n", ofname);