#include #include #include #include #include #include "OutputOptions.h" #include "GFilter.h" /* Class used to handle processing of command line parameters passed to * kdc2tiff and kdc2jpeg. * * Written by: Chris Studholme * Last Update: 6-Dec-2003 * Copyright: GPL (http://www.fsf.org/copyleft/gpl.html) */ void OutputOptions::SetOutputParameters() { image=srcimage; // contrast enhancement int min=0; int max=255; if (contrastenhance) { // find best min and max srcimage->FindBestMinMax(min,max); min-=contrastenhance; max+=contrastenhance; if (min<0) min=0; if (max>255) max=255; if ((min>0)||(max<255)) { fprintf(stderr,"Adjusting constrast (%d,%d) -> (0,255).\n",min,max); GFilter_ContrastAdjustment* ca = new GFilter_ContrastAdjustment(*image,(min-128)*128,(max+1-128)*128); image=ca; } } // white balance if (lightwhite) { float red=1; float blue=1; srcimage->FindWhiteBalance(red,blue,min); fprintf(stderr,"Light source (%.2f,1.00,%.2f).\n",red,blue); // preferred light source // red *= 1.0169; // blue *= 1.003; // check for sane values if (red>1.4) red=1.4; if (red<0.7) red=0.7; if (blue>1.4) blue=1.4; if (blue<0.7) blue=0.7; // don't balance images that undergo insane contrast enhancement if (max-min<150) { float factor = ((float)max-min)/150; red = 1 + factor*(red-1); blue = 1 + factor*(blue-1); } if ((red<0.995)||(red>1.005)||(blue<0.995)||(blue>1.005)) { fprintf(stderr,"Balancing white (%.2f,1.00,%.2f).\n",red,blue); GFilter_WhiteBalance* wb = new GFilter_WhiteBalance(*image,1/red,1/blue); image=wb; } } // gamma correction if (gammacorrection!=1) { fprintf(stderr,"Applying gamma correction of %.2f.\n",gammacorrection); GFilter_GammaCorrection* gc = new GFilter_GammaCorrection(*image,gammacorrection); image=gc; } // rotate image if (rotate) { GFilter_Rotate* rot = new GFilter_Rotate(*image); switch (rotate) { case 1: rot->setClockwiseRotate(); fprintf(stderr,"Rotating image clockwise.\n"); break; case -1: rot->setCounterClockwiseRotate(); fprintf(stderr,"Rotating image counter-clockwise.\n"); break; default: fprintf(stderr,"invalid rotate value (%d)\n", rotate); } image=rot; } // default image dimensions if ((outputwidth==0)&&(outputheight==0)) { outputwidth=image->getPreferredWidth(); outputheight=image->getPreferredHeight(); } // scale image GFilter_Scale* scale = new GFilter_Scale(*image,outputwidth,outputheight); if ((outputwidth>0)&&(outputheight>0)) { if (!squarepixels) scale->setDimensions(outputwidth,outputheight,false); else if (nocrop) scale->setMaximumDimensions(outputwidth,outputheight); } image=scale; outputwidth=image->getWidth(); outputheight=image->getHeight(); fprintf(stderr,"Scaling image to %dx%d%s",outputwidth,outputheight, squarepixels?"":" (non-square pixels)"); int uncropwidth=scale->getUncropWidth(); int uncropheight=scale->getUncropHeight(); if ((uncropwidth!=outputwidth)||(uncropheight!=outputheight)) fprintf(stderr," cropping from %dx%d",uncropwidth,uncropheight); fprintf(stderr,".\n"); } void OutputOptions::SetOutputFilename() { if (outputname==0) { outputname = new char[strlen(inputname)+5]; strcpy(outputname,inputname); char* extension = strrchr(outputname,'.'); if ((extension!=0)&&(extension>strrchr(outputname,'/'))) strcpy(extension, outputtiff?".tif":".jpg"); else strcat(outputname,outputtiff?".tif":".jpg"); } } void OutputOptions::CalculateScanLine(unsigned char* dest, int y) { int w=image->getWidth(); short r[w],g[w],b[w]; image->getScanLineHorz(r,g,b,0,y,w,y+1,w); for (int x=0; x16383 ? 255 : 128+r[x]/128; dest[x*3+1] = g[x]<-16383 ? 0 : g[x]>16383 ? 255 : 128+g[x]/128; dest[x*3+2] = b[x]<-16383 ? 0 : b[x]>16383 ? 255 : 128+b[x]/128; } } // returns 0 if error char** OutputOptions::ParseOptions(int& argc, char*argv[]) { while (argc>0) { if (argv[0][0]=='-') { // stdin or stdout if (strcmp(argv[0],"-")==0) return argv; // next argument is a filename if (strcmp(argv[0],"--")==0) { --argc; return ++argv; } const char* switches = argv[0]+1; while (switches[0]) { switch (switches[0]) { // copyright case 'C': ++argv; if (--argc>0) copyright=argv[0]; else return 0; break; // compression scheme case 'c': ++argv; if (--argc>0) compresstype=argv[0]; else return 0; break; // output filename case 'o': ++argv; if (--argc>0) { outputname=argv[0]; overwrite=true; } else return 0; break; // rows per strip case 'r': ++argv; if (--argc>0) rowsperstrip=atoi(argv[0]); else return 0; if (rowsperstrip<=0) { fprintf(stderr,"invalid rows per strip value (%d)\n",rowsperstrip); return 0; } break; // don't create progressive jpeg case 'P': progressive=false; break; // jpeg quality setting case 'q': ++argv; if (--argc>0) quality=atoi(argv[0]); else return 0; if ((quality<0)||(quality>100)) { fprintf(stderr,"invalid quality value (%d)\n",quality); return 0; } break; // width case 'w': ++argv; if (--argc>0) outputwidth=atoi(argv[0]); else { return 0; } if (outputwidth<=0) { fprintf(stderr,"invalid image width (%d)\n",outputwidth); return 0; } break; // height case 'h': ++argv; if (--argc>0) outputheight=atoi(argv[0]); else return 0; if (outputheight<=0) { fprintf(stderr,"invalid image height (%d)\n",outputheight); return 0; } break; // gamma correction case 'g': ++argv; if (--argc>0) gammacorrection=atof(argv[0]); else return 0; if ((gammacorrection<0.2)||(gammacorrection>5)) { fprintf(stderr,"invalid gamma setting (%.1f)\n",gammacorrection); return 0; } break; // no grain reduction case 'G': grainreduction=0; break; // non-square pixels case 's': squarepixels=false; break; // non-fast de-bayer (highest quality) case 'f': fastdebayer=false; break; // no contrast enhancement case 'e': contrastenhance=0; break; // no cropping case 'p': nocrop=true; break; // don't rotate case 'R': rotate=0; break; // colour of light source (white) case 'W': ++argv; if (--argc>0) { if (strcasecmp(argv[0],"none")==0) lightwhite=0; else if (strcasecmp(argv[0],"auto")==0) lightwhite=-1; else if (strcasecmp(argv[0],"sun")==0) lightwhite=-1; else if (strcasecmp(argv[0],"shade")==0) lightwhite=-1; else if (strcasecmp(argv[0],"cloud")==0) lightwhite=-1; else if (strcasecmp(argv[0],"incandecent")==0) lightwhite=-1; else if (strcasecmp(argv[0],"flourescent")==0) lightwhite=-1; else { lightwhite=atoi(argv[0]); if ((lightwhite<500)||(lightwhite>15000)) { fprintf(stderr,"invalid light source temperature, assuming ttl mode\n"); lightwhite=-1; } } } else return 0; break; default: return 0; } ++switches; } } else if (argv[0][0]=='+') { const char* switches = argv[0]+1; float tempf; while (switches[0]) { switch (switches[0]) { // create progressive jpeg case 'P': progressive=true; break; // square pixels case 's': squarepixels=true; break; // fast de-bayer (sacrifice quality) case 'f': fastdebayer=true; break; // gamma correction case 'g': ++argv; if (--argc>0) tempf=atof(argv[0]); else return 0; if ((tempf<0.2)||(tempf>5)) { fprintf(stderr,"invalid gamma setting (%.1f)\n",tempf); return 0; } else gammacorrection*=tempf; break; // grain reduction case 'G': if (++grainreduction>2) grainreduction=2; break; // normal contrast enhancement case 'e': contrastenhance=2; break; case 'E': ++argv; if (--argc>0) contrastenhance=atoi(argv[0]); else return 0; if ((contrastenhance<=0)||(contrastenhance>255)) { fprintf(stderr,"invalid contrast enhancement (%d)\n", contrastenhance); return 0; } break; // crop if necessary case 'p': nocrop=false; break; // rotate clockwise case 'R': rotate=1; break; // rotate counter-clockwise case 'B': rotate=-1; break; default: return 0; } ++switches; } } // must be a filename else return argv; ++argv; --argc; } return argv; }