From: Paweł Gołaszewski Date: Thu, 23 Nov 2006 12:27:03 +0000 (+0000) Subject: - updated to 8.43 from 2006/11/21, some additional files X-Git-Tag: auto/th/dcraw-8_43-1~1 X-Git-Url: http://git.pld-linux.org/?p=packages%2Fdcraw.git;a=commitdiff_plain;h=3d481f6690f4a124e91dc67cc41e1286f66b4fee - updated to 8.43 from 2006/11/21, some additional files Changed files: clean_crw.c -> 1.1 fuji_green.c -> 1.1 fujiturn.c -> 1.1 --- diff --git a/clean_crw.c b/clean_crw.c new file mode 100644 index 0000000..729b1b0 --- /dev/null +++ b/clean_crw.c @@ -0,0 +1,80 @@ +/* + Because they are parsed from the end, Canon CRW files + become unreadable if garbage data is appended to them, as + often happens when files are recovered from damaged media. + This program truncates CRW files to the correct size. + + Copyright 2005 by Dave Coffin, dcoffin a cybercom o net + Free for all uses. + + $Revision$ + $Date$ + */ + +#include +#include +#include + +unsigned char *buffer; + +int get4 (int i) +{ + if (buffer[0] == 'I') + return buffer[i+3] << 24 | buffer[i+2] << 16 | buffer[i+1] << 8 | buffer[i]; + else + return buffer[i] << 24 | buffer[i+1] << 16 | buffer[i+2] << 8 | buffer[i+3]; +} + +int main (int argc, char **argv) +{ + int arg, size, end, diff, status=1; + unsigned char *fname; + FILE *fp; + + if (argc == 1) + fprintf (stderr, "Usage: %s crw_0001.crw crw_0002.crw ...\n", argv[0]); + + for (arg=1; arg < argc; arg++) { + status = 1; + fp = fopen (argv[arg], "rb"); + fseek (fp, 0, SEEK_END); + size = ftell(fp); + buffer = malloc (size + strlen(argv[arg]) + 10); + if (!buffer) { + fprintf (stderr, "Cannot allocate memory!\n"); + return 2; + } + fname = buffer + size; + sprintf (fname, "%s.clean", argv[arg]); + fseek (fp, 0, SEEK_SET); + fread (buffer, 1, size, fp); + fclose (fp); + if (strncmp (buffer, "II\x1a\0\0\0HEAPCCDR", 14) && + strncmp (buffer, "MM\0\0\0\x1aHEAPCCDR", 14)) { + fprintf (stderr, "%s is not a CRW file!\n", argv[arg]); + free (buffer); + continue; + } + for (end=size; end > 0xa0000; end--) { + diff = end - get4(end-4); + if (diff > 50 && diff < 120 && diff % 10 == 2) { + status = 0; + break; + } + } + if (status) + fprintf (stderr, "Failed to clean %s\n", argv[arg]); + else { + if ((fp = fopen (fname, "wb"))) { + fprintf (stderr, "Writing %s\n", fname); + fwrite (buffer, 1, end, fp); + fclose (fp); + } else { + perror (fname); + status = 1; + } + } + free (buffer); + } + return status; +} diff --git a/fuji_green.c b/fuji_green.c new file mode 100644 index 0000000..985849f --- /dev/null +++ b/fuji_green.c @@ -0,0 +1,375 @@ +/* + fuji_green -- read Fuji green pixels + + $Revision$ + $Date$ + */ + +#include +#include +#include +#include +#include +#include + +#define ushort UshORt +typedef unsigned char uchar; +typedef unsigned short ushort; + +FILE *ifp; +short order; +char *ifname, make[64], model[64]; +int data_offset, raw_height, raw_width, height, width; +int fuji_layout, fuji_secondary, use_secondary=0, verbose=0; +ushort *image; +void (*load_raw)(); +float bright=1.0; +void write_ppm(FILE *); +void (*write_fun)(FILE *) = write_ppm; +jmp_buf failure; + +#define CLASS + +void CLASS merror (void *ptr, char *where) +{ + if (ptr) return; + fprintf (stderr, "%s: Out of memory in %s\n", ifname, where); + longjmp (failure, 1); +} + +ushort CLASS get2() +{ + uchar a, b; + + a = fgetc(ifp); + b = fgetc(ifp); + if (order == 0x4949) /* "II" means little-endian */ + return a + (b << 8); + else /* "MM" means big-endian */ + return (a << 8) + b; +} + +int CLASS get4() +{ + uchar a, b, c, d; + + a = fgetc(ifp); + b = fgetc(ifp); + c = fgetc(ifp); + d = fgetc(ifp); + if (order == 0x4949) + return a + (b << 8) + (c << 16) + (d << 24); + else + return (a << 24) + (b << 16) + (c << 8) + d; +} + +/* + Faster than calling get2() multiple times. + */ +void CLASS read_shorts (ushort *pixel, int count) +{ + fread (pixel, 2, count, ifp); + if ((order == 0x4949) == (ntohs(0x1234) == 0x1234)) + swab (pixel, pixel, count*2); +} + +void CLASS fuji_load_raw() +{ + ushort *pixel, *img; + int row, col; + + pixel = calloc (raw_width, 2); + merror (pixel, "fuji_load_raw()"); + for (row=0; row < height; row++) + if (fuji_layout) { + read_shorts (image+row*width, width); + fseek (ifp, (raw_width*2 - width)*2, SEEK_CUR); + } else { + read_shorts (pixel, raw_width); + for (img=image+row*width, col=0; col < width; col++) + img[col] = pixel[col*2+1]; + } + free (pixel); +} + +void CLASS parse_fuji (int offset) +{ + unsigned entries, tag, len, save; + + fseek (ifp, offset, SEEK_SET); + entries = get4(); + if (entries > 255) return; + while (entries--) { + tag = get2(); + len = get2(); + save = ftell(ifp); + if (tag == 0x100) { + raw_height = get2(); + raw_width = get2(); + } else if (tag == 0x121) { + height = get2(); + width = get2(); + } else if (tag == 0x130) + fuji_layout = fgetc(ifp) >> 7; + fseek (ifp, save+len, SEEK_SET); + } + if (fuji_layout) { + height *= 2; + width /= 2; + } +} + +void CLASS parse_tiff (int base) +{ + int doff, entries, tag, type, len, save; + + fseek (ifp, base, SEEK_SET); + order = get2(); + get2(); /* Should be 42 for standard TIFF */ + while ((doff = get4())) { + fseek (ifp, doff+base, SEEK_SET); + entries = get2(); + while (entries--) { + tag = get2(); + type = get2(); + len = get4(); + save = ftell(ifp)+4; + fseek (ifp, base+get4(), SEEK_SET); + switch (tag) { + case 0x10f: /* Make tag */ + fgets (make, 64, ifp); + break; + case 0x110: /* Model tag */ + fgets (model, 64, ifp); + } + fseek (ifp, save, SEEK_SET); + } + } +} + +int CLASS identify() +{ + char head[32], *c; + int thumb_offset; + + make[0] = model[0] = 0; + data_offset = raw_height = raw_width = height = width = 0; + fuji_secondary = 0; + + order = 0x4d4d; + fread (head, 1, 32, ifp); + if (memcmp (head, "FUJIFILM", 8)) return 1; + fseek (ifp, 84, SEEK_SET); + thumb_offset = get4(); + fseek (ifp, 92, SEEK_SET); + parse_fuji (get4()); + if (thumb_offset > 120) { + fseek (ifp, 120, SEEK_SET); + fuji_secondary = get4() && 1; + } + fseek (ifp, 100, SEEK_SET); + data_offset = get4(); + parse_tiff (thumb_offset+12); + c = model + strlen(model); /* Remove trailing spaces */ + while (*--c == ' ') *c = 0; + if (!strcmp(model,"FinePix S5100") || + !strcmp(model,"FinePix S5500")) return 1; + load_raw = fuji_load_raw; + if (!strcmp(model+7,"S2Pro")) { + strcpy (model+7," S2Pro"); + height = 2144; + width = 2880; + } + data_offset += (raw_height - height + 1)*raw_width - width; + if (fuji_secondary) + data_offset += use_secondary * ( strcmp(model+7," S3Pro") + ? (raw_width *= 2) : raw_height*raw_width*2 ); + data_offset += fuji_layout*raw_width*2; + width >>= !fuji_layout; + height >>= fuji_layout; + fseek (ifp, data_offset, SEEK_SET); + return 0; +} + +void CLASS write_ppm (FILE *ofp) +{ + int i, size, val, total, histogram[0x2000]; + float white, r; + uchar lut[0x10000]; + + memset (histogram, 0, sizeof histogram); + size = width * height; + for (i = 0; i < size; i++) + histogram[image[i] >> 4]++; + i = size * 0.01; /* 99th percentile white point */ + for (val=0x2000, total=0; --val; ) + if ((total += histogram[val]) > i) break; + white = (val << 4) / bright; + + for (i=0; i < 0x10000; i++) { + r = i / white; + val = (r <= 0.018 ? r*4.5 : pow(r,0.45)*1.099-0.099) * 256; + if (val > 255) val = 255; + lut[i] = val; + } + fprintf (ofp, "P5\n%d %d\n255\n", width, height); + for (i=0; i < size; i++) + fputc (lut[image[i]], ofp); +} + +void CLASS write_raw16 (FILE *ofp) +{ + if (ntohs(0x1234) != 0x1234) + swab (image, image, width*height*2); + fwrite (image, width*height, 2, ofp); +} + +void CLASS write_ppm16 (FILE *ofp) +{ + fprintf (ofp, "P5\n%d %d\n%d\n", width, height, 65535); + write_raw16 (ofp); +} + +void CLASS write_psd (FILE *ofp) +{ + char head[] = { + '8','B','P','S', /* signature */ + 0,1,0,0,0,0,0,0, /* version and reserved */ + 0,1, /* number of channels */ + 0,0,0,0, /* height, big-endian */ + 0,0,0,0, /* width, big-endian */ + 0,16, /* 16-bit color */ + 0,1, /* mode (1=grey, 3=rgb) */ + 0,0,0,0, /* color mode data */ + 0,0,0,0, /* image resources */ + 0,0,0,0, /* layer/mask info */ + 0,0 }; /* no compression */ + int hw[2]; + + hw[0] = htonl(height*2); /* write the header */ + hw[1] = htonl(width*2); + memcpy (head+14, hw, sizeof hw); + fwrite (head, 40, 1, ofp); + write_raw16 (ofp); +} + +int CLASS main (int argc, char **argv) +{ + int arg, status=0; + int identify_only=0, write_to_stdout=0; + char opt, *ofname, *cp; + const char *write_ext = ".pgm"; + FILE *ofp = stdout; + + if (argc == 1) { + fprintf (stderr, + "\nFuji Green channel output" + "\nby Dave Coffin, dcoffin a cybercom o net" + "\n\nUsage: %s [options] file1 file2 ...\n" + "\nValid options:" + "\n-v Print verbose messages" + "\n-c Write image data to standard output" + "\n-i Identify files without decoding them" + "\n-s Use secondary pixels if available" + "\n-b Set brightness (default = 1.0)" + "\n-2 Write 8-bit non-linear PGM (default)" + "\n-4 Write 16-bit linear PGM" + "\n-3 Write 16-bit linear PSD (Adobe Photoshop)" + "\n\n", argv[0]); + return 1; + } + argv[argc] = ""; + for (arg=1; argv[arg][0] == '-'; ) { + opt = argv[arg++][1]; + if (strchr ("b", opt) && !isdigit(argv[arg][0])) { + fprintf (stderr, "\"-%c\" requires a numeric argument.\n", opt); + return 1; + } + switch (opt) { + case 'v': verbose = 1; break; + case 'i': identify_only = 1; break; + case 'c': write_to_stdout = 1; break; + case 's': use_secondary = 1; break; + case 'b': bright = atof(argv[arg++]); break; + case '2': write_fun = write_ppm; break; + case '4': write_fun = write_ppm16; break; + case '3': write_fun = write_psd; write_ext = ".psd"; break; + default: + fprintf (stderr, "Unknown option \"-%c\".\n", opt); + return 1; + } + } + if (arg == argc) { + fprintf (stderr, "No files to process.\n"); + return 1; + } + if (write_to_stdout) { + if (isatty(1)) { + fprintf (stderr, "Will not write an image to the terminal!\n"); + return 1; + } +#if defined(WIN32) || defined(DJGPP) + if (setmode(1,O_BINARY) < 0) { + perror("setmode()"); + return 1; + } +#endif + } + for ( ; arg < argc; arg++) { + status = 1; + image = NULL; + if (setjmp (failure)) { + if (fileno(ifp) > 2) fclose (ifp); + if (fileno(ofp) > 2) fclose (ofp); + if (image) free (image); + status = 1; + continue; + } + ifname = argv[arg]; + if (!(ifp = fopen (ifname, "rb"))) { + perror (ifname); + continue; + } + if ((status = identify())) { + fprintf (stderr, "%s: unsupported file format.\n", ifname); + fclose (ifp); + continue; + } + if (identify_only) { + fprintf (stderr, "%s is a %s %s image.\n", ifname, make, model); + fclose (ifp); + continue; + } + image = calloc (height * width, sizeof *image); + merror (image, "main()"); + if (verbose) + fprintf (stderr, + "Loading %s %s image from %s...\n", make, model, ifname); + (*load_raw)(); + fclose (ifp); + ofname = malloc (strlen(ifname) + 16); + merror (ofname, "main()"); + if (write_to_stdout) + strcpy (ofname, "standard output"); + else { + strcpy (ofname, ifname); + if ((cp = strrchr (ofname, '.'))) *cp = 0; + strcat (ofname, write_ext); + ofp = fopen (ofname, "wb"); + if (!ofp) { + status = 1; + perror (ofname); + goto cleanup; + } + } + if (verbose) + fprintf (stderr, "Writing data to %s...\n", ofname); + (*write_fun)(ofp); + if (ofp != stdout) + fclose (ofp); +cleanup: + free (ofname); + free (image); + } + return status; +} diff --git a/fujiturn.c b/fujiturn.c new file mode 100644 index 0000000..feb367a --- /dev/null +++ b/fujiturn.c @@ -0,0 +1,102 @@ +/* + fujiturn.c by Dave Coffin + + UNIX filter to correct the 45-degree rotation in images from + Fuji digital cameras. Compile with -D_16BIT to rotate 48-bit + PPM images. Sample usage: + + dcraw -c -j dscf0000.raf | fujiturn | pnmscale 0.70710678 > dscf0000.ppm + + $Revision$ + $Date$ + + */ + +#include +#include +#include + +#ifdef _16BIT +typedef unsigned short value; +#else +typedef unsigned char value; +#define ntohs(x) (x) +#define htons(x) (x) +#endif + +void merror (void *ptr, char *what) +{ + if (ptr) return; + fprintf (stderr, "Not enough memory for %s\n", what); + exit(1); +} + +int main() +{ + FILE *ifp, *ofp; + value (*in)[3], (*mid)[3], (*pix)[3], (*out)[3]; + char nl; + int maxval, i, j, iwide, ihigh, owide, ohigh; + unsigned irow, icol, orow, ocol; + +#if defined(WIN32) || defined(DJGPP) + if (setmode(0,O_BINARY) < 0) perror("setmode(0)"); + if (setmode(1,O_BINARY) < 0) perror("setmode(1)"); +#endif + ifp = stdin; + ofp = stdout; + if (fscanf (ifp, "P6 %d %d %d%c", &iwide, &ihigh, &maxval, &nl) != 4 + || abs(iwide - ihigh) > 1) { + fprintf (stderr, "Input is not a Fuji image processed by dcraw.\n"); + exit(1); + } + i = (maxval > 255) ? 16 : 8; + j = 8 * sizeof (value); + if (i != j) { + fprintf (stderr, "Input is %d-bit, fujiturn is %d-bit\n", i, j); + exit(1); + } + in = calloc (iwide, sizeof *in); + merror (in, "input array"); + fread (in, iwide, sizeof *in, ifp); + for (i = 0; i < iwide; i++) + if (in[i][0] || in[i][1] || in[i][2]) break; + ohigh = (iwide - i) * 2 - 4; + for (i = iwide; --i;) + if (in[i][0] || in[i][1] || in[i][2]) break; + owide = i; + mid = calloc (ohigh * owide, sizeof *mid); + merror (mid, "middle array"); + for (irow = 0; irow < ihigh; irow++) { + for (icol = 0; icol < iwide; icol++) { + orow = irow + icol - owide + 5; + ocol = (icol - irow + owide - 1)/2; + if (orow < ohigh && ocol < owide) + for (i = 0; i < 3; i++) + mid[orow*owide+ocol][i] = ntohs(in[icol][i]); + } + fread (in, iwide, sizeof *in, ifp); + } + free(in); + out = calloc (2*owide, sizeof *out); + merror (out, "output array"); + fprintf (ofp, "P6\n%d %d\n%d\n", owide*2, ohigh, maxval); + for (orow = 0; orow < ohigh; orow++) { + for (ocol = 0; ocol < owide*2; ocol++) { + pix = mid + orow*owide + ocol/2; + if ((orow+ocol) & 1) { + if (orow-1 < ohigh-2 && ocol-1 < owide*2-2) + for (i = 0; i < 3; i++) + out[ocol][i] = htons ( + ( pix[-owide][i] + pix[0-(orow&1)][i] + + pix[ owide][i] + pix[1-(orow&1)][i] ) >> 2); + } else + for (i = 0; i < 3; i++) + out[ocol][i] = htons(pix[0][i]); + } + fwrite (out, 2*owide, 3*sizeof (value), ofp); + } + free(mid); + free(out); + return 0; +}