/* 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; }