/* * tiffcine -- recognize and crop out frames from * a scan of a strip of movie film * * Copyright 2002 Richard J Kinch * * RJK March 2002 */ #include #include #if FFTW #include #endif #include "tiffio.h" #define mag(c) sqrt((c).re*(c).re+(c).im*(c).im) #define ang(c) (fabs((c).re)>=1e-6?atan((c).im/(c).re):0) #define deg(r) ((r)*180.0/3.1415926) /* Greyscale value for a given RGB raster word */ #define greyscale(v) (TIFFGetR(v)+TIFFGetG(v)+TIFFGetB(v)) #define threshold(v) ((greyscale(v)>382)) #define greyscale_white 255*3 #define greyscale_black 0 /* SOME DIMENSIONS AT 600 PIXELS/INCH FOR 16 MM FILM: Frame vertical interval is 180 pixels Film total width is 377 pixels Clear image width between sprockets 248 pixels Center-to-center of sprockets 291 pixels Sprocket height 0.050in +/- 0.0004in, i.e., 30 pixels +/- 0.24 pixel 16 mm full frame at 600 dpi is 377 x 180 pixels Image059.tif sample image frames at X=62, with lower-left sprocket centered at Y=39 Image011.tif sample image frames at X=57, with lower-left sprocket centered at Y=39 #define START_OF_FIRST_FRAME 57 */ /* 16mm */ #define FILM_FRAME_HEIGHT 180 #define FILM_PERFORATION_HEIGHT 30 /* Must be < FILM_FRAME_HEIGHT */ #define CROPPED_FRAME_HEIGHT 180 #define CROPPED_FRAME_WIDTH 291 #define CROPPED_FRAME_LEFT 39 #define LEFT_SPROCKET_CENTERLINE 40 /* image058.tif */ #define RIGHT_SPROCKET_CENTERLINE 331 /* image058.tif */ /* Number of text columns to use to plot greyscale values */ #define PLOT_COLUMNS 75 void crop(uint32 *raster,uint32 w,uint32 h, float xres, float yres, uint16 resunits, uint32 x0, uint32 y0, uint32 xN, uint32 yN, char *fname, int rotate) { /* Given an input RGB raster of dimensions (w,h), write a new TIFF */ /* file named fname, the new image being cropped from the input */ /* raster starting at (x0,y0) and having size (xN,yN). If "rotate" */ /* we apply a 90 degree clockwise rotation to the output file. */ TIFF *out; unsigned char *buf, *p; uint32 *q; uint32 row, i; uint32 cw, ch; /* Cropped width/height after rotation */ tsize_t scanlinesize; if (w==0 || h==0) return; if (x0>=w || y0>=h || (x0+xN)>w || (y0+yN)>h) return; if (fopen(fname,"rb")) { fprintf(stderr,"File \"%s\" already exists\n",fname); return; } out = TIFFOpen(fname,"w"); if (out==NULL) return; if (rotate) { cw = yN ; ch = xN ; } else { cw = xN ; ch = yN ; } TIFFSetField(out,TIFFTAG_IMAGEWIDTH,cw); TIFFSetField(out,TIFFTAG_IMAGELENGTH,ch); TIFFSetField(out,TIFFTAG_PHOTOMETRIC,((uint16)PHOTOMETRIC_RGB)); TIFFSetField(out,TIFFTAG_COMPRESSION,((uint16)COMPRESSION_NONE)); TIFFSetField(out,TIFFTAG_SAMPLESPERPIXEL,((uint16)3)); TIFFSetField(out,TIFFTAG_PLANARCONFIG,((uint16)PLANARCONFIG_CONTIG)); TIFFSetField(out,TIFFTAG_BITSPERSAMPLE,((uint16)8)); TIFFSetField(out,TIFFTAG_RESOLUTIONUNIT,(uint16)resunits); TIFFSetField(out,TIFFTAG_XRESOLUTION,(float)xres); TIFFSetField(out,TIFFTAG_YRESOLUTION,(float)yres); scanlinesize = TIFFScanlineSize(out); if (scanlinesize<=0) return; buf = (unsigned char *) _TIFFmalloc(scanlinesize); if (buf==NULL) return; if (rotate) for (row=0; rowPLOT_COLUMNS) { v = PLOT_COLUMNS; s = "...\n"; } else s = "\n"; for (j=0; jmax_weight) { max_weight = weight; max_weight_offset = offset; } } return(max_weight_offset+X0); } main(int argc, char **argv) { TIFF *tif; uint32 w, h; size_t npixels; uint32 *raster; float xres, yres; uint16 resunits; int i; if (argc!=3) { fprintf(stderr,"Use: tiffcine input-TIFF-file starting-frame-number\n"); return(-1); } /* Open input TIFF file */ tif = TIFFOpen(argv[1],"r"); if (tif==NULL) { fprintf(stderr,"Cannot open input TIFF file\n"); return(-1); } /* Load and characterize TIFF image as an RGB raster */ TIFFGetField(tif,TIFFTAG_IMAGEWIDTH,&w); TIFFGetField(tif,TIFFTAG_IMAGELENGTH,&h); TIFFGetField(tif,TIFFTAG_RESOLUTIONUNIT,&resunits); TIFFGetField(tif,TIFFTAG_XRESOLUTION,&xres); TIFFGetField(tif,TIFFTAG_YRESOLUTION,&yres); npixels = w * h; printf("# file=%s w=%ld h=%ld npixels=%ld\n",argv[1], (long)w,(long)h,(long)npixels); raster = (uint32*) _TIFFmalloc(npixels * sizeof(uint32)); if (raster==NULL) { fprintf(stderr,"Out of memory!\n"); return(-1); } if (TIFFReadRGBAImage(tif,w,h,raster,0)==0) { fprintf(stderr,"Cannot read image from TIFF file!\n"); return(-1); } #if 0 /* FFT correlation methods */ /* Initialize FFT plans */ FFT = fftw_create_plan(FILM_FRAME_HEIGHT,FFTW_FORWARD,FFTW_ESTIMATE); IFFT = fftw_create_plan(FILM_FRAME_HEIGHT,FFTW_BACKWARD,FFTW_ESTIMATE); /* Initialize ideal perforation scanline and its DFT conjugate */ for (i=0; i