/*
* 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);
}