/* * colorfield.c * * (c) 2010-2011 Mark J. Stock * * 2010-11-15 MJS began project with copy of tracefield program * 2010-12-02 MJS modified to use HSV colors * 2011-01-26 MJS wrap hue around---don't bounce between [v0.1] * * A program to create a PNG image of bands of related colors * * gcc -o colorfield colorfield.c -lm -lpng -O3 -ffast-math -Wall * gcc -o colorfield colorfield.c -I/Developer/SDKs/MacOSX10.5.sdk/usr/X11/include -L/Developer/SDKs/MacOSX10.5.sdk/usr/X11/lib -lm -lpng -O3 -ffast-math -Wall * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include #include #include #include #include #define TRUE 1 #define FALSE 0 #define FLOAT float // not used yet, but should be! enum colorspace { rgb, hsv, hsl, lab } colorspace = rgb; // locally-defined subroutines FLOAT** allocate_2d_array_F(int, int); png_byte** allocate_2d_array_pb(int, int, int); png_byte** allocate_2d_rgb_array_pb(int, int, int); int write_png_image(int, FLOAT**, FLOAT**, FLOAT**, int, int, int); int usage(char*, int); /* * main routine controls execution */ int main (int argc, char **argv) { int debug = FALSE; int i,y; int seed = 235125; int x_resolution = 128; int y_resolution = 512; int depth = 8; int use_color = TRUE; int use_rgb = TRUE; int basecolorset = FALSE; int num[3]; int imaxrgb,iminrgb; FLOAT **red = NULL; FLOAT **grn = NULL; FLOAT **blu = NULL; FLOAT **seq = NULL; FLOAT f,n,m,v; FLOAT basecolor[3]; FLOAT maxrgb,minrgb,chroma,hue,saturation,value; FLOAT scale[3]; FLOAT variance[3]; char progname[80]; //char infilename[80]; // default number string length (like a time constant) num[0] = 100; num[1] = 100; num[2] = 100; // default base color basecolor[0] = 0.5; basecolor[1] = 0.5; basecolor[2] = 0.5; // default color scale (larger more pronounced changes) scale[0] = 1.0; scale[1] = 1.0; scale[2] = 1.0; // parse command-line args (void) strcpy(progname,argv[0]); if (argc < 1) (void) usage(progname,0); for (i=1; i maxrgb) { maxrgb = basecolor[i]; imaxrgb = i; } if (basecolor[i] < minrgb) { minrgb = basecolor[i]; iminrgb = i; } } chroma = maxrgb - minrgb; hue = 0.0; if (chroma < 1.e-5) { // hue really is undefined in this case } else if (imaxrgb == 0) { hue = fmod( (basecolor[1]-basecolor[2])/chroma, 6.0); } else if (imaxrgb == 1) { hue = 2 + (basecolor[2]-basecolor[0]) / chroma; } else if (imaxrgb == 2) { hue = 4 + (basecolor[0]-basecolor[1]) / chroma; } value = maxrgb; if (chroma < 1.e-5) { saturation = 0.; } else { saturation = chroma/value; } basecolor[0] = hue; basecolor[1] = saturation; basecolor[2] = value; //fprintf(stderr,"base color in HSV is %g %g %g\n",basecolor[0],basecolor[1],basecolor[2]); } // set hue again to remind us hue = basecolor[0]; // sequences are r,g,b or h,s,v for (i=0; i<3; i++) if (num[i] < 1) num[i] = 1; for (i=0; i<3; i++) if (num[i] > 1000000) num[i] = 1000000; // find a multiplier that proportional to 1/RMS for (i=0; i<3; i++) variance[i] = 1./sqrt((FLOAT)num[i]); // allocate array for random number sequence i = num[0]; if (num[1] > i) i = num[1]; if (num[2] > i) i = num[2]; seq = allocate_2d_array_F(i,3); // sequences are r,g,b or h,s,v for (i=0; i 6.0) hue -= 6.; i = ((int)hue) % 6; f = hue - (FLOAT)i; if ( !(i&1) ) f = 1 - f; // if i is even m = value * (1 - saturation); n = value * (1 - saturation * f); v = value; //if (fabs(hue)<0.1) fprintf(stderr,"%d %g %d %g\n",y,hue,i,f); //if (y>65 && y<75) fprintf(stderr,"%d %g %d %g\n",y,hue,i,f); switch (i) { case 6: case 0: red[0][y] = v; grn[0][y] = n; blu[0][y] = m; break; case 1: red[0][y] = n; grn[0][y] = v; blu[0][y] = m; break; case 2: red[0][y] = m; grn[0][y] = v; blu[0][y] = n; break; case 3: red[0][y] = m; grn[0][y] = n; blu[0][y] = v; break; case 4: red[0][y] = n; grn[0][y] = m; blu[0][y] = v; break; case 5: red[0][y] = v; grn[0][y] = m; blu[0][y] = n; break; } } else { // no color // just use value channel grn[0][y] = blu[0][y]; } } // hsv // debug print if (debug) fprintf(stdout,"%g %g %g\n",red[0][y],grn[0][y],blu[0][y]); } // convert the single column into a PNG file if (!debug) write_png_image (use_color,red,grn,blu,x_resolution,y_resolution,depth); // quit, we must be done. exit(0); } /* * write a png file */ int write_png_image (int use_color, FLOAT **red, FLOAT **grn, FLOAT **blu, int xres, int yres, int depth) { static png_byte **image; static png_byte **imgrgb; png_uint_32 height,width; FILE *fp; png_structp png_ptr; png_infop info_ptr; int i,j; float thisGamma = 1.0; int printval,thisRed,thisGrn,thisBlu; height=yres; width=xres; // allocate the space for the image if (use_color) { imgrgb = allocate_2d_rgb_array_pb(xres,yres,depth); } else { image = allocate_2d_array_pb(xres,yres,depth); } // convert the double array into png_bytes! fprintf(stderr,"Writing PNG image\n"); fflush(stderr); // gamma-correct and check for peak value for (i=0; i<1; i++) { for (j=yres-1; j>-1; j--) { grn[i][j] = (FLOAT)exp((1./thisGamma)*log((double)grn[i][j])); } } if (use_color) { for (i=0; i<1; i++) { for (j=yres-1; j>-1; j--) { red[i][j] = (FLOAT)exp((1./thisGamma)*log((double)red[i][j])); } } for (i=0; i<1; i++) { for (j=yres-1; j>-1; j--) { blu[i][j] = (FLOAT)exp((1./thisGamma)*log((double)blu[i][j])); } } } // color image, read data from red array if (use_color) { if (depth == 16) { for (j=yres-1; j>-1; j--) { // red printval = (int)(red[0][j]*65536.0); if (printval<0) printval = 0; if (printval>65535) printval = 65535; thisRed = printval; // green printval = (int)(grn[0][j]*65536.0); if (printval<0) printval = 0; if (printval>65535) printval = 65535; thisGrn = printval; // blue printval = (int)(blu[0][j]*65536.0); if (printval<0) printval = 0; if (printval>65535) printval = 65535; thisBlu = printval; for (i=0; i-1; j--) { // red printval = (int)(red[0][j]*256.0); if (printval<0) printval = 0; if (printval>255) printval = 255; thisRed = printval; // green printval = (int)(grn[0][j]*256.0); if (printval<0) printval = 0; if (printval>255) printval = 255; thisGrn = printval; // blue printval = (int)(blu[0][j]*256.0); if (printval<0) printval = 0; if (printval>255) printval = 255; thisBlu = printval; //fprintf(stderr,"%d %d %d\n",thisRed,thisGrn,thisBlu); fflush(stderr); for (i=0; i-1; j--) { printval = (int)(grn[0][j]*65536.0); if (printval<0) printval = 0; if (printval>65535) printval = 65535; for (i=0; i-1; j--) { printval = (int)(grn[0][j]*256.0); if (printval<0) printval = 0; if (printval>255) printval = 255; for (i=0; i out.png\n\n", progname); fprintf(stderr, "usage:\n %s [-options] > out.png\n\n", progname); for (cpp = help_message; *cpp; cpp++) fprintf(stderr, "%s\n", *cpp); fflush(stderr); exit(status); return(0); }