/* RAW histogram creator v.0.92 (20070305) by Peter Ruevski Copyright 2006-2007 by Peter Ruevski (ruevs atsign hotmail point com) This is a command-line ANSI C program to create RAW histograms from raw photos converted to RAW PGM files by dcraw. Use it at your own risk. */ #include #include #include #include void UnknownOption(char *option) { fprintf(stderr,"unknown option %s\n", option); } void Usage(char *programName) { fprintf(stderr,"\n\ RAW histogram creator v.0.92 (20070305) by Peter Ruevski (ruevs\100hotmail\056com)\n\ \nUsage:\n\ %s [-?][-help] file\n\ \t-?, -help\tThis message\n\ \tfile\t\tPGM input file created with dcraw.\n\ \nThis program will build histograms of RAW files processed into 16 bit RAW PGM\n\ files by using dcraw (http://www.cybercom.net/~dcoffin/dcraw/). For example\n\ if you have a Canon RAW file called IMG_0005.CR2 first use dcraw:\n\ \n\tdcraw -D -4 -t 0 -o 0 -v IMG_0005.CR2\n\n\ this will create IMG_0005.pgm. Then run this program:\n\ \n\trawhistogram IMG_0005.pgm\n\n\ The result will be a (text) file called IMG_0005.csv that contains the RAW\n\ histogram data. This file can easily be opened in a spreadsheet program to plot\n\ the RGGB histograms.\n",programName); } /* returns the index of the first argument that is not an option; i.e. does not start with a dash or a slash */ int HandleOptions(int argc,char *argv[]) { int i,firstnonoption=0; for (i=1; i< argc;i++) { if (argv[i][0] == '/' || argv[i][0] == '-') { switch (argv[i][1]) { /* An argument -? means help is requested */ case '?': Usage(argv[0]); break; case 'h': case 'H': if (!stricmp(argv[i]+1,"help")) { Usage(argv[0]); break; } /* If the option -h means anything else * in your application add code here * Note: this falls through to the default * to print an "unknow option" message */ /* add your option switches here */ default: fprintf(stderr,"unknown option %s\n",argv[i]); break; } } else { firstnonoption = i; break; } } return firstnonoption; } int CreateRAWHistogram(FILE *fin, FILE *fout) { #define HISTOGRAM_SIZE 16384 //4096 #define PROGRESSBAR_SIZE 70 // Tolerance for number of combing period matches that will make the histogram considered "bad" #define NPER0TOLR 50 #define NPER0TOLG1 50 #define NPER0TOLG2 50 #define NPER0TOLB 50 // Threshholds for combing period length that will be counted #define PER0TR_R 5 #define PER0TR_G1 5 #define PER0TR_G2 5 #define PER0TR_B 5 // Combing period length fluctuations that will be accepted #define PER0FL_R 2 #define PER0FL_G1 2 #define PER0FL_G2 2 #define PER0FL_B 2 int width, height, colors, bitpp; int row, col, c; unsigned short *ppm; unsigned long numvalues, progress; unsigned long *histR, *histG1, *histG2, *histB; long ind0R, ind0G1, ind0G2, ind0B; long per0R, per0G1, per0G2, per0B; long nper0R, nper0G1, nper0G2, nper0B; c= fscanf(fin, "P%d\n%d %d\n%d\n", &colors, &width, &height, &bitpp); if( (5!=colors) || (65535!=bitpp) ) { fprintf(stderr,"This program needs a RAW (1 color) 16 bit PGM file\nUse \"dcraw -D -4 -t 0 -o 0 -v IMG_0005.CR2\"\n"); return 1; } colors = 1; printf("Processing %d by %d image - %lu pixels.\n", width, height, (unsigned long)width*height); ppm = (unsigned short *) malloc(width*2*colors); histR = (unsigned long *) malloc(HISTOGRAM_SIZE*sizeof(histR[0])); histG1 = (unsigned long *) malloc(HISTOGRAM_SIZE*sizeof(histG1[0])); histG2 = (unsigned long *) malloc(HISTOGRAM_SIZE*sizeof(histG2[0])); histB = (unsigned long *) malloc(HISTOGRAM_SIZE*sizeof(histB[0])); if(!ppm || !histR || !histG1 ||!histG2 || !histB) { fprintf(stderr,"Not enough memory!\n"); if(histR) free(histR); if(histG1) free(histG1); if(histG2) free(histG2); if(histB) free(histB); if(ppm) free(ppm); return 1; } memset(histR, 0, HISTOGRAM_SIZE*sizeof(histR[0])); memset(histG1, 0, HISTOGRAM_SIZE*sizeof(histG1[0])); memset(histG2, 0, HISTOGRAM_SIZE*sizeof(histG2[0])); memset(histB, 0, HISTOGRAM_SIZE*sizeof(histB[0])); printf("|"); for(c=0; c=HISTOGRAM_SIZE) { printf("\nThere are values larger than %d in the file!", HISTOGRAM_SIZE-1); free(histR); free(histG1); free(histG2); free(histB); free (ppm); return 1; } /* All RGB cameras use one of these Bayer grids: 0x16161616: 0x61616161: 0x49494949: 0x94949494: 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 B G B G B G 0 G R G R G R 0 G B G B G B 0 R G R G R G 1 G R G R G R 1 B G B G B G 1 R G R G R G 1 G B G B G B 2 B G B G B G 2 G R G R G R 2 G B G B G B 2 R G R G R G 3 G R G R G R 3 B G B G B G 3 R G R G R G 3 G B G B G B CMOS Canons are 0x94949494 */ if(row&1) //odd if(col&1) //odd histB[value]++; else //even histG2[value]++; else //even if(col&1) //odd histG1[value]++; else histR[value]++; // Progress "bar" if(70*(row*width+col)*colors/numvalues >= progress) { progress++; printf("."); } } } // Write the histograms to the output file ind0R = ind0G1 = ind0G2 = ind0B = 0; nper0R = nper0G1 = nper0G2 = nper0B = 0; per0R = per0G1 = per0G2 = per0B = 0; fprintf(fout, "%4s, %10s, %10s, %10s, %10s\r\n", "val", "R", "G1", "G2", "B"); for(row=0; row1) if ( (abs(row-ind0R - per0R) <= PER0FL_R) && (PER0TR_R <= per0R) ) nper0R++; per0R = row-ind0R; ind0R=row; } if (!histG1[row]) { if ((row-ind0G1)>1) if ( (abs(row-ind0G1 - per0G1) <= PER0FL_G1) && (PER0TR_G1 <= per0G1) ) nper0G1++; per0G1 = row-ind0G1; ind0G1=row; } if (!histG2[row]) { if ((row-ind0G2)>1) if ( (abs(row-ind0G2 - per0G2) <= PER0FL_G1) && (PER0TR_G2 <= per0G2) ) nper0G2++; per0G2 = row-ind0G2; ind0G2=row; } if (!histB[row]) { if ((row-ind0B)>1) if ( (abs(row-ind0B - per0B) <= PER0FL_B) && (PER0TR_B <= per0B) ) nper0B++; per0B = row-ind0B; ind0B=row; } fprintf(fout, "%4d, %10lu, %10lu, %10lu, %10lu\r\n", row, histR[row], histG1[row], histG2[row], histB[row]); } free(histR); free(histG1); free(histG2); free(histB); free (ppm); return ( (nper0R>NPER0TOLR) || (nper0G1>NPER0TOLG1) || (nper0G2>NPER0TOLG2) || (nper0B>NPER0TOLB) ); } int main(int argc,char *argv[]) { int error; int i; FILE *fin, *fout; char outfname[1024]; /* if (argc == 1) { Usage(argv[0]); return 1; }*/ /* handle the program options */ if (! (i=HandleOptions(argc, argv)) ) { Usage(argv[0]); return 1; } if( !(fin = fopen( argv[i], "r+b" ))) { printf( "Can not open input file: %s\r\n", argv[i] ); return 1; }; strncpy(outfname, argv[i], 1024); strncpy(strstr(outfname, ".")+1, "csv", 3); if( !(fout = fopen( outfname, "w+b" ))) { if(fin) fclose(fin); printf( "Can not create output file: %s\r\n", outfname ); return 1; }; error = CreateRAWHistogram(fin, fout); if (error) printf("Combed\n"); else printf("OK\n"); if(fin) fclose(fin); if(fout) fclose(fout); return error; }