const char * UsageLines [] = { "Usage: p6contrast (contrast factor)", "Reads P6 PPM from standard input.", "For contrast factor > 1, contrast is increased at midrange", "brightness, reduced near black and white.", "For contrast factor < 1, contrast is reduced at midrange", "brightness, increased near black and white.", "Contrast factor is the slope of the brightness transfer curve", "at midrange.", "1.0 results in output same as input.", "Passes each color component (normalized to the range 0 <= x <= 1)", "through the transfer function:", "\t1/(1 + (1/x - 1)**(contrast factor) )", "This has the additional effect of intensifying color at midrange", "brightness (for contrast factor > 1).", "Writes same dimensions PPM to standard output.", "Example of usage in pipeline to convert scanned document (3600x2700)", "from jpeg to a one-page pdf:", "\tdjpeg \\", "\t| p6contrast 5 \\", "\t| pnmtops -equalpixels -dpi 360 \\", "\t| ps2pdf -dAutoFilterColorImages=false -sPAPERSIZE=letter - -", "March 8, 2009. Newest is at gopher -p users/julianbr sdf.org", }; const int NumUsageLines = sizeof (UsageLines)/sizeof (UsageLines [0] ); /* Compile using -lm */ #include <stdlib.h> #include <stdio.h> #include <math.h> void ContrastData (int width, int height, float contrast) { int InputR, InputG, InputB, OutputR, OutputG, OutputB; int i, j; InputR = getchar (); for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { if (InputR == EOF) InputG = EOF; else InputG = getchar (); if (InputG == EOF) InputB = EOF; else InputB = getchar (); if (InputB == EOF) { putchar (128); putchar (128); putchar (128); } else { if (InputR == 0) OutputR = 0; else if (InputR == 255) OutputR = 255; else OutputR = 255/(1 + exp (contrast *log (255./InputR - 1) ) ) + .5; if (InputG == 0) OutputG = 0; else if (InputG == 255) OutputG = 255; else OutputG = 255/(1 + exp (contrast *log (255./InputG - 1) ) ) + .5; if (InputB == 0) OutputB = 0; else if (InputB == 255) OutputB = 255; else OutputB = 255/(1 + exp (contrast *log (255./InputB - 1) ) ) + .5; putchar (OutputR); putchar (OutputG); putchar (OutputB); } if (InputB == EOF) InputR = EOF; else InputR = getchar (); } } if (InputB == EOF) { fprintf (stderr, "***p6contrast: Premature end"); fprintf (stderr, " of input image data.\n"); } if (InputR != EOF) { fprintf (stderr, "***p6contrast: Extra input"); fprintf (stderr, " image data.\n"); } } void ContrastFile (float contrast) { int width, height, maxval; if (getchar () != 'P' || getchar () != '6' || scanf ("%d", & width) < 1 || width < 1 || scanf ("%d", & height) < 1 || height < 1 || scanf ("%d", & maxval) < 1 || maxval != 255 || getchar () == EOF) { fprintf (stderr, "***p6contrast: Improper input,"); fprintf (stderr, " must be P6 with maxval 255.\n"); } else { printf ("P6\n"); printf ("%d %d\n", width, height); printf ("255\n"); ContrastData (width, height, contrast); } } int main (int argc, char * argv [] ) { float contrast; int i; char c; if (argc < 2) { for (i = 0; i < NumUsageLines; i++) printf ("%s\n", UsageLines [i] ); } else if (argc == 2) { if (sscanf (argv [1], "%f%c", & contrast, & c) != 1) { fprintf (stderr, "***p6contrast: Expecting number"); fprintf (stderr, " for contrast factor, found"); fprintf (stderr, " \"%s\".\n", argv [1] ); } else ContrastFile (contrast); } else { fprintf (stderr, "Usage: p6constrast"); fprintf (stderr, " (contrast factor)\n"); } return 0; }