import java.io.*;
import java.util.*;
/**
* This class generates a Mandelbrot fractal and outputs to an XPM.
* The fractal is an escape map. Each pixel in the map array corresponds
* with a coordinate (on the complex plane).
*
*
* Copyright (c) 1997 Jon Lin
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation.
*
* This file is provided AS IS with no warranties of any kind. The author
* shall have no liability with respect to the infringement of copyrights,
* trade secrets or any patents by this file or any part thereof. In no
* event will the author be liable for any lost revenue or profits or
* other special, indirect and consequential damages.
*
*
* @author jonlin@tesuji.org
*/
public class MandelbrotGenerator
{
// Cache for the mapping of colors to letters
private static String[] letters;
// constants for sweeping variations
public static final int LINEAR_SWEEP = 0;
public static final int LOG_SWEEP = 1;
public static final int EXP_SWEEP = 2;
// constants for bailout test variations
public static final int ZMAG_TEST = 0;
public static final int REAL_TEST = 1;
public static final int IMAG_TEST = 2;
public static final int ABS_TEST = 3;
// flags for various sweeping
boolean sweep_X_coef = false;
boolean sweep_Y_coef = false;
boolean sweep_X_shift = false;
boolean sweep_Y_shift = false;
boolean sweep_X_perturb = false;
boolean sweep_Y_perturb = false;
boolean zoom = false;
boolean random_zoom = false;
// vars used for coef sweeping.
int coef_sweep = 0;
double x_coef_sweep_value = 0;
double y_coef_sweep_value = 0;
int x_coef_sweep_period = 1;
int y_coef_sweep_period = 1;
// vars used for shift sweeping.
int shift_sweep = 0;
double x_shift_sweep_value = 0;
double y_shift_sweep_value = 0;
int x_shift_sweep_period = 1;
int y_shift_sweep_period = 1;
// vars used for perturn sweeping.
int perturb_sweep = 0;
double x_perturb_sweep_value = 0;
double y_perturb_sweep_value = 0;
int x_perturb_sweep_period = 1;
int y_perturb_sweep_period = 1;
// vars used for zooming.
int start_x_zoom_value = 0;
int start_y_zoom_value = 0;
int start_x_zoom_period = 1;
int start_y_zoom_period = 1;
int end_x_zoom_value = 0;
int end_y_zoom_value = 0;
int end_x_zoom_period = 1;
int end_y_zoom_period = 1;
int x_zoom_shift = 0;
int y_zoom_shift = 0;
int x_zoom_shift_period = 1;
int y_zoom_shift_period = 1;
int x_zoom_limit = -1;
int y_zoom_limit = -1;
double x_zoom_limit_point = -1;
double y_zoom_limit_point = -1;
double x_zoom_limit_error = -1;
double y_zoom_limit_error = -1;
// vars used for generating.
double start_x = -2;
double end_x = 2;
double start_y = -2;
double end_y = 2;
double x_coef = 0;
double y_coef = 0;
double x_perturb = 0;
double y_perturb = 0;
double x_shift = 30;
double y_shift = 0;
double bailout = 16;
static int bailout_test = 0;
int max_iter = 150;
int width = 640;
int height = 480;
int num_frames = 1;
int frame_offset = 0;
int frame_count = 0;
int num_colors;
String[] colorMap = null;
String colorMapFile = null;
String outputPrefix = "mandel";
// random number generator for Random zooming.
Random rand;
public MandelbrotGenerator(String[] args)
{
// First thing, parse the arguments.
parseArgs(args);
rand = new Random();
// Make the color map to use.
colorMap = makeColorMap(colorMapFile,num_colors);
// This is the array which stores all the escape values.
int[][] map = new int[width][height];
// This loop continually generates and changes the parameters
for(int x=0;x-1) && (y_zoom_limit>-1)) {
zoomRandom();
zoomLimit();
}
else {
zoomRandom();
}
}
else if(zoom) {
if((x_zoom_limit>-1) && (y_zoom_limit>-1)) {
zoomLinear();
zoomLimit();
}
else {
zoomLinear();
zoomShift();
}
}
// Change parameters for coef sweep
if(coef_sweep == LINEAR_SWEEP) {
sweepCoefLinear();
}
else if(coef_sweep == LOG_SWEEP) {
sweepCoefLogrithmic();
}
else if(coef_sweep == EXP_SWEEP) {
sweepCoefExponential();
}
// Change parameters for shift sweep
if(shift_sweep == LINEAR_SWEEP) {
sweepShiftLinear();
}
else if(shift_sweep == LOG_SWEEP) {
sweepShiftLogrithmic();
}
else if(shift_sweep == EXP_SWEEP) {
sweepShiftExponential();
}
// Change parameters for perturb sweep
if(perturb_sweep == LINEAR_SWEEP) {
sweepPerturbLinear();
}
else if(perturb_sweep == LOG_SWEEP) {
sweepPerturbLogrithmic();
}
else if(perturb_sweep == EXP_SWEEP) {
sweepPerturbExponential();
}
}
System.exit(1);
}
/**
* shrinks the bounding box (start_x, start_y),(end_x, end_y)
* according to the zooming parameters.
*/
public void zoomLinear()
{
double x_unit = (end_x - start_x)/width;
double y_unit = (end_y - start_y)/height;
if((frame_count % start_x_zoom_period)==0) {
start_x = start_x + (x_unit * start_x_zoom_value);
}
if((frame_count % end_x_zoom_period)==0) {
end_x = end_x - (x_unit * end_x_zoom_value);
}
if((frame_count % start_y_zoom_period)==0) {
start_y = start_y + (y_unit * start_y_zoom_value);
}
if((frame_count % end_y_zoom_period)==0) {
end_y = end_y - (y_unit * end_y_zoom_value);
}
}
/**
* shifts the bounding box (start_x, start_y),(end_x, end_y)
* accoring to the shifting parameters.
*/
public void zoomShift()
{
double x_unit = (end_x - start_x)/width;
double y_unit = (end_y - start_y)/height;
if((frame_count % x_zoom_shift_period)==0) {
start_x = start_x + (x_unit * x_zoom_shift);
end_x = end_x + (x_unit * x_zoom_shift);
}
if((frame_count % y_zoom_shift_period)==0) {
start_y = start_y + (y_unit * y_zoom_shift);
end_y = end_y + (y_unit * y_zoom_shift);
}
}
/**
* shifts the bounding box (start_x, start_y),(end_x, end_y)
* according to the zoom limit. The center of the bounding box
* approaches the zoom limit parameters.
*/
public void zoomLimit()
{
// First find the units per pixel
double x_unit = (end_x - start_x)/width;
double y_unit = (end_y - start_y)/height;
// Then the center coordinates of the current map
double x_center = (x_unit*width)/2 + start_x;
double y_center = (y_unit*height)/2 + start_y;
// Then the lengths from the center to the zoom limit
double x_length = Math.abs(x_zoom_limit_point - x_center);
double y_length = Math.abs(y_zoom_limit_point - y_center);
// If the length is smaller than the limit error, bail.
if((x_length < x_zoom_limit_error) && (y_length < y_zoom_limit_error)) {
print("Reached zoom limit! Exiting.");
System.exit(0);
}
// These are the x,y lengths to shift.
double x_shift = 20*x_unit;
double y_shift = 20*y_unit;
// If the zoom shift parameters are used, reset the lengths to the parameters
if(x_zoom_shift>0) {
x_shift = Math.abs(x_zoom_shift)*x_unit;
}
if(y_zoom_shift>0) {
y_shift = Math.abs(y_zoom_shift)*y_unit;
}
// If the shift exceeds the distance to the limit point, just shift by the distance
if(x_shift > x_length) {
x_shift = x_length;
}
if(y_shift > y_length) {
y_shift = y_length;
}
// scale the shift according to the incident angle of the limit point
if(x_length>=y_length) {
y_shift = (y_length*x_shift)/x_length;
}
else {
x_shift = (x_length*y_shift)/y_length;
}
// Shift the bounding box
if(x_center > x_zoom_limit_point) {
start_x = start_x - (x_shift);
end_x = end_x - (x_shift);
}
else {
start_x = start_x + (x_shift);
end_x = end_x + (x_shift);
}
if(y_center > y_zoom_limit_point) {
start_y = start_y - (y_shift);
end_y = end_y - (y_shift);
}
else {
start_y = start_y + (y_shift);
end_y = end_y + (y_shift);
}
}
/**
* shrinks and shifts the bounding box (start_x, start_y),(end_x, end_y)
* according to the bounds set by the zoom parameters.
*/
public void zoomRandom()
{
double x_unit = (end_x - start_x)/width;
double y_unit = (end_y - start_y)/height;
int tmp_start_x_zoom = Math.abs(rand.nextInt()%start_x_zoom_value);
int tmp_end_x_zoom = Math.abs(rand.nextInt()%end_x_zoom_value);
int tmp_start_y_zoom = Math.abs(rand.nextInt()%start_y_zoom_value);
int tmp_end_y_zoom = Math.abs(rand.nextInt()%end_y_zoom_value);
if((frame_count % start_x_zoom_period)==0) {
start_x = start_x + (x_unit * tmp_start_x_zoom);
}
if((frame_count % end_x_zoom_period)==0) {
end_x = end_x - (x_unit * tmp_end_x_zoom);
}
if((frame_count % start_y_zoom_period)==0) {
start_y = start_y + (y_unit * tmp_start_y_zoom);
}
if((frame_count % end_y_zoom_period)==0) {
end_y = end_y - (y_unit * tmp_end_y_zoom);
}
if((x_zoom_limit==-1) && (y_zoom_limit==-1)) {
x_unit = (end_x - start_x)/width;
y_unit = (end_y - start_y)/height;
int tmp_x_shift = Math.abs(rand.nextInt()%x_zoom_shift);
int tmp_y_shift = Math.abs(rand.nextInt()%y_zoom_shift);
if((frame_count % x_zoom_shift_period)==0) {
start_x = start_x + (x_unit * tmp_x_shift);
end_x = end_x + (x_unit * tmp_x_shift);
}
if((frame_count % y_zoom_shift_period)==0) {
start_y = start_y + (y_unit * tmp_y_shift);
end_y = end_y + (y_unit * tmp_y_shift);
}
}
}
/**
* Sweeps the coef vector linearly according to the coef sweep parameters.
*/
public void sweepCoefLinear()
{
if(sweep_X_coef && ((frame_count % x_coef_sweep_period)==0)) {
x_coef = x_coef + x_coef_sweep_value;
}
if(sweep_Y_coef && ((frame_count % y_coef_sweep_period)==0)) {
y_coef = y_coef + y_coef_sweep_value;
}
}
/**
* Sweeps the coef vector logrithmicly according to the coef sweep parameters.
*/
public void sweepCoefLogrithmic()
{
if(sweep_X_coef && ((frame_count % x_coef_sweep_period)==0)) {
x_coef = (x_coef + x_coef_sweep_value) / 2;
}
if(sweep_Y_coef && ((frame_count % y_coef_sweep_period)==0)) {
y_coef = (y_coef + y_coef_sweep_value) / 2;
}
}
/**
* Sweeps the coef vector exponentially according to the coef sweep parameters.
*/
public void sweepCoefExponential()
{
if(sweep_X_coef && ((frame_count % x_coef_sweep_period)==0)) {
x_coef = (2 * x_coef) - x_coef_sweep_value;
}
if(sweep_Y_coef && ((frame_count % y_coef_sweep_period)==0)) {
y_coef = (2 * y_coef) - y_coef_sweep_value;
}
}
/**
* Sweeps the shift vector linearly according to the shift sweep parameters.
*/
public void sweepShiftLinear()
{
if(sweep_X_shift && ((frame_count % x_shift_sweep_period)==0)) {
x_shift = x_shift + x_shift_sweep_value;
}
if(sweep_Y_shift && ((frame_count % y_shift_sweep_period)==0)) {
y_shift = y_shift + y_shift_sweep_value;
}
}
/**
* Sweeps the shift vector logrithmicly according to the shift sweep parameters.
*/
public void sweepShiftLogrithmic()
{
if(sweep_X_shift && ((frame_count % x_shift_sweep_period)==0)) {
x_shift = (x_shift + x_shift_sweep_value) / 2;
}
if(sweep_Y_shift && ((frame_count % y_shift_sweep_period)==0)) {
y_shift = (y_shift + y_shift_sweep_value) / 2;
}
}
/**
* Sweeps the shift vector exponentially according to the shift sweep parameters.
*/
public void sweepShiftExponential()
{
if(sweep_X_shift && ((frame_count % x_shift_sweep_period)==0)) {
x_shift = (2 * x_shift) - x_shift_sweep_value;
}
if(sweep_Y_shift && ((frame_count % y_shift_sweep_period)==0)) {
y_shift = (2 * y_shift) - y_shift_sweep_value;
}
}
/**
* Sweeps the perturb vector linearly according to the perturb sweep parameters.
*/
public void sweepPerturbLinear()
{
if(sweep_X_perturb && ((frame_count % x_perturb_sweep_period)==0)) {
x_perturb = x_perturb + x_perturb_sweep_value;
}
if(sweep_Y_perturb && ((frame_count % y_perturb_sweep_period)==0)) {
y_perturb = y_perturb + y_perturb_sweep_value;
}
}
/**
* Sweeps the perturb vector logrithmically according to the perturb sweep parameters.
*/
public void sweepPerturbLogrithmic()
{
if(sweep_X_perturb && ((frame_count % x_perturb_sweep_period)==0)) {
x_perturb = (x_perturb + x_perturb_sweep_value) / 2;
}
if(sweep_Y_perturb && ((frame_count % y_perturb_sweep_period)==0)) {
y_perturb = (y_perturb + y_perturb_sweep_value) / 2;
}
}
/**
* Sweeps the perturb vector exponentially according to the perturb sweep parameters.
*/
public void sweepPerturbExponential()
{
if(sweep_X_perturb && ((frame_count % x_perturb_sweep_period)==0)) {
x_perturb = (2 * x_perturb) - x_perturb_sweep_value;
}
if(sweep_Y_perturb && ((frame_count % y_perturb_sweep_period)==0)) {
y_perturb = (2 * y_perturb) - y_perturb_sweep_value;
}
}
/**
* This method parses the arguments passed to the MandelbrotGenerator.
* These arguments determine what this class will do.
*/
public void parseArgs(String[] args)
{
try {
// First, read in the required parameters
width = Integer.parseInt(args[0]);
height = Integer.parseInt(args[1]);
colorMapFile = args[2];
num_colors = Integer.parseInt(args[3]);
// if there are more arguments (the options), parse them
if(args.length>4) {
for(int x=4;x#####.xpm'.");
print(" ");
print(" -num_frames The number of frames to generate. Each frame will undergo ");
print(" the specified zoom, shift, and sweeps.");
print(" -outputPrefix The filename prefix of the output file(s).");
print(" -frame_offset The offset to start the output file numbering.");
print(" ");
}
else {
print("Valid help options are: ");
print(" bounding_box, fractal_params, iter_params, zooming, sweeping, output_params");
}
System.exit(2);
}
}
}
}
}
catch(Exception e) {
print("Error: "+e);
e.printStackTrace();
print("Usage: MandelbrotGenerator [x_size] [y_size] [colorMapFile] [num_colors] ");
print(" -start_x [double]");
print(" -start_y [double]");
print(" -end_x [double]");
print(" -end_y [double]");
print(" -x_coef [double]");
print(" -y_coef [double]");
print(" -x_shift [double]");
print(" -y_shift [double]");
print(" -x_perturb [double]");
print(" -y_perturb [double]");
print(" -bailout [double]");
print(" -bailout_test [0|1|2|3] (zmag,real,imag,abs)");
print(" -max_iter [integer]");
print(" -num_frames [integer]");
print(" -outputPrefix [filename]");
print(" -frame_offset [integer]");
print(" -coef_sweep_type [0|1|2] (linear,log,exp)");
print(" -sweep_x_coef ");
print(" -sweep_y_coef ");
print(" -x_coef_sweep_value [double]");
print(" -y_coef_sweep_value [double]");
print(" -x_coef_sweep_period [integer]");
print(" -y_coef_sweep_period [integer]");
print(" -shift_sweep_type [0|1|2] (linear,log,exp)");
print(" -sweep_x_shift ");
print(" -sweep_y_shift ");
print(" -x_shift_sweep_value [double]");
print(" -y_shift_sweep_value [double]");
print(" -x_shift_sweep_period [integer]");
print(" -y_shift_sweep_period [integer]");
print(" -perturb_sweep_type [0|1|2] (linear,log,exp)");
print(" -sweep_x_perturb ");
print(" -sweep_y_perturb ");
print(" -x_perturb_sweep_value [double]");
print(" -y_perturb_sweep_value [double]");
print(" -x_perturb_sweep_period [integer]");
print(" -y_perturb_sweep_period [integer]");
print(" -zoom ");
print(" -random_zoom");
print(" -start_x_zoom_value [integer] (pixels)");
print(" -start_y_zoom_value [integer] (pixels)");
print(" -end_x_zoom_value [integer] (pixels)");
print(" -end_y_zoom_value [integer] (pixels)");
print(" -x_zoom_shift [integer] (pixels)");
print(" -y_zoom_shift [integer] (pixels)");
print(" -start_x_zoom_period [integer]");
print(" -start_y_zoom_period [integer]");
print(" -end_x_zoom_period [integer]");
print(" -end_y_zoom_period [integer]");
print(" -x_zoom_shift_period [integer]");
print(" -y_zoom_shift_period [integer]");
print(" -zoom_limit [integer] [integer] (x y) (pixels)");
print(" -help ");
System.exit(-1);
}
// If zooming to a limit, calculate the initial zoom limit parameters
if((x_zoom_limit>-1) && (y_zoom_limit>-1)) {
x_zoom_limit_error = (end_x - start_x)/width;
y_zoom_limit_error = (end_y - start_y)/height;
x_zoom_limit_point = ((x_zoom_limit_error)*x_zoom_limit) + start_x;
y_zoom_limit_point = ((y_zoom_limit_error)*y_zoom_limit) + start_y;
}
System.out.println(printStatus());
}
/**
* This method returns a status String.
*/
public String printStatus()
{
StringBuffer rval = new StringBuffer();
rval.append(" Image size: "+width+" x "+height+", color map: "+colorMapFile+" ("+num_colors+")\n");
if(bailout_test==REAL_TEST) {
rval.append(" Maximum number of iterations: "+max_iter+", Bailout value: "+bailout+" (x*x)\n");
}
else if(bailout_test==IMAG_TEST) {
rval.append(" Maximum number of iterations: "+max_iter+", Bailout value: "+bailout+" (y*y)\n");
}
else if(bailout_test==ABS_TEST) {
rval.append(" Maximum number of iterations: "+max_iter+", Bailout value: "+bailout+" (|x|+|y|)\n");
}
else {
rval.append(" Maximum number of iterations: "+max_iter+", Bailout value: "+bailout+" ((x*x)+(y*y))\n");
}
rval.append(" Bounding box: ("+start_x+","+start_y+") , ("+end_x+","+end_y+")\n");
rval.append(" Coeficient vector: ["+x_coef+","+y_coef+"]\n");
rval.append(" Shift vector: ["+x_shift+","+y_shift+"]\n");
rval.append(" Perturb vector: ["+x_perturb+","+y_perturb+"]\n");
if(random_zoom) {
rval.append(" Random zooming and shifting (bounded by given values)\n");
}
else if(zoom) {
rval.append(" Zooming and shifting\n");
}
if(random_zoom||zoom) {
rval.append(" Bounding box shrink (pixels): +("+start_x_zoom_value+","+start_y_zoom_value+") , -("+end_x_zoom_value+","+end_y_zoom_value+") \n");
rval.append(" Bounding box shift (pixels): ("+x_zoom_shift+","+y_zoom_shift+")\n");
if((x_zoom_limit>-1) && (y_zoom_limit>-1)) {
rval.append(" Zoom approaches the point ("+x_zoom_limit_point+","+y_zoom_limit_point+") +/- ("+x_zoom_limit_error+","+y_zoom_limit_error+")\n");
}
}
if(sweep_X_coef || sweep_Y_coef) {
rval.append(" Sweeping coeficient vector ");
if(coef_sweep==LINEAR_SWEEP) {
rval.append("linearly ");
}
else if(coef_sweep==LOG_SWEEP) {
rval.append("logrithmically ");
}
else if(coef_sweep==EXP_SWEEP) {
rval.append("exponentially ");
}
rval.append("by ("+x_coef_sweep_value+","+y_coef_sweep_value+")\n");
}
if(sweep_X_shift || sweep_Y_shift) {
rval.append(" Sweeping shift vector ");
if(shift_sweep==LINEAR_SWEEP) {
rval.append("linearly ");
}
else if(shift_sweep==LOG_SWEEP) {
rval.append("logrithmically ");
}
else if(shift_sweep==EXP_SWEEP) {
rval.append("exponentially ");
}
rval.append("by ("+x_shift_sweep_value+","+y_shift_sweep_value+")\n");
}
if(sweep_X_perturb || sweep_Y_perturb) {
rval.append(" Sweeping perturb vector ");
if(perturb_sweep==LINEAR_SWEEP) {
rval.append("linearly ");
}
else if(perturb_sweep==LOG_SWEEP) {
rval.append("logrithmically ");
}
else if(perturb_sweep==EXP_SWEEP) {
rval.append("exponentially ");
}
rval.append("by ("+x_perturb_sweep_value+","+y_perturb_sweep_value+")\n");
}
return(rval.toString());
}
/**
* This method prints the XPM file.
*/
public void printXPM(int[][] map, int frame, String status)
{
String filename = outputPrefix;
String number = ""+frame;
while(number.length()<5) {
number = "0"+number;
}
filename = filename+number+".xpm";
String XPM = generateXPM(filename,map,width,height,colorMap,status);
print("Writing XPM: "+filename);
try {
File xpmFile = new File(filename);
BufferedWriter writer = new BufferedWriter(new FileWriter(xpmFile));
writer.write(XPM);
writer.flush();
writer.close();
}
catch(Exception e) {
print("Error writing XPM: "+e);
e.printStackTrace();
}
}
/**
* Generates an escape map using the mandelbrot attractor.
* The escape values are stored the map array.
* @param map This is where the results are stored.
* @param width The number of pixels on the X axis.
* @param height The number of pixels on the Y axis.
* @param start_x The starting X coordinate.
* @param end_x The ending X coordinate.
* @param start_y The starting Y coordinate.
* @param end_y The ending Y coordinate.
* @param x_coef The coeficient added to the X value.
* @param y_coef The coeficient added to the Y value.
* @param x_perturb The initial X value.
* @param y_perturb The initial Y value.
* @param bailout_value This is the square of the magnitude of the complex number denoting infinity.
* @param max_iter This is the maximum number of iterations.
*/
public static void generate(int[][] map,
int width, int height,
double start_x, double end_x,
double start_y, double end_y,
double x_coef, double y_coef,
double x_shift, double y_shift,
double x_perturb, double y_perturb,
double bailout_value,
int max_iter)
{
double k=0;
double l=0;
double x=0;
double y=0;
double tx=0;
double ty=0;
double tmp_k = ((end_x-start_x) + x_coef) / width;
double tmp_l = ((end_y-start_y) + y_coef) / height;
double last_x_sqr = 0;
double last_y_sqr = 0;
// f(z) = z*z : f(x+(i)y) = ((x*x)-(y*y)-k) + (i)((2*x*y)-l)
for(int q=0;q bailout_value) {
map[p][q] = 1;
}
else {
x = tx;
y = ty;
boolean bailed = false;
for(int iteration=2; iteration <= max_iter; iteration++) {
// calculate f(x+(i)y)
tx = last_x_sqr - last_y_sqr - k;
ty = (2 * x * y) - l;
// calculate the new squares for x and y, these are cached for the next iteration
last_x_sqr = tx*tx;
last_y_sqr = ty*ty;
if(((bailout_test==ZMAG_TEST) && ((last_x_sqr + last_y_sqr) > bailout_value)) ||
((bailout_test==REAL_TEST) && (last_x_sqr > bailout_value)) ||
((bailout_test==IMAG_TEST) && (last_y_sqr > bailout_value)) ||
((bailout_test==ABS_TEST) && ((Math.abs(tx) + Math.abs(ty)) > bailout_value))) {
map[p][q] = iteration;
iteration = max_iter;
bailed = true;
}
else {
x = tx;
y = ty;
}
}
if(!bailed) {
map[p][q] = 0;
}
}
}
}
}
public static void main(String[] args)
{
new MandelbrotGenerator(args);
}
public static void print(String s)
{
System.out.println("Mandelbrot: "+s);
}
/**
* This method generates a XPM from a 2 dimensional array. The XPM is returned as a String.
* @param xpmName The name of this XPM.
* @param image The array of pixels representing the image. The orientation of the image is assumed to be image[x][y].
* @param width The number of columns in the image map (x size).
* @param height The number of rows in the image map (y size).
* @param colorMap An array of Hex color values. (i.e. #FF00AA).
* @param comment The comment to include in the XPM. If null, no comment is included.
* @return Returns the XPM of this image as a String.
*/
public static String generateXPM(String xpmName, int[][] image, int width, int height, String[] colorMap, String comment)
{
StringBuffer rval = new StringBuffer();
rval.append(generateHeader(xpmName, comment));
String[] colorMapping = makeColorMapping(colorMap);
rval.append(generateColorMapping(width, height, colorMap, colorMapping));
rval.append("/* pixels */\n");
for(int y=0;y
* 0 0 0
* 0 4 0
* 0 16 0
*
* And so on.
* @param filename The full pathname of the file which contains the RGB values.
* @param num_colors The number of colors expected in this file.
* @return Returns a String array of colors suitable for the 'generateXPM()' method.
*/
public static String[] makeColorMap(String filename, int num_colors)
{
String[] colors = new String[num_colors];
File mapFile = new File(filename);
BufferedReader reader = null;
try {
int cIndex = 0;
reader = new BufferedReader(new FileReader(mapFile));
String line = reader.readLine();
while(line!=null) {
String thiscolor = "#";
for(int x=0;x<3;x++) {
line = line.trim();
int end = 0;
try {
while(line.charAt(end++)!=' ') {
;
}
}
catch(StringIndexOutOfBoundsException esadas) {
end=line.length();
}
thiscolor = thiscolor+getHexValue(Integer.parseInt(line.substring(0,end).trim()));
line = line.substring(end);
}
colors[cIndex++] = thiscolor;
line = reader.readLine();
}
if(cIndex9) {
if(rem==10) {
rval = "A";
}
else if(rem==11) {
rval = "B";
}
else if(rem==12) {
rval = "C";
}
else if(rem==13) {
rval = "D";
}
else if(rem==14) {
rval = "E";
}
else if(rem==15) {
rval = "F";
}
}
else {
rval = rem+"";
}
rem = decimalValue%16;
decimalValue = (int)(decimalValue/16);
if(decimalValue>0) {
rval = "FF";
}
else {
if(rem>9) {
if(rem==10) {
rval = "A"+rval;
}
else if(rem==11) {
rval = "B"+rval;
}
else if(rem==12) {
rval = "C"+rval;
}
else if(rem==13) {
rval = "D"+rval;
}
else if(rem==14) {
rval = "E"+rval;
}
else if(rem==15) {
rval = "F"+rval;
}
}
else {
rval = rem+rval;
}
}
return(rval);
}
private static String[] makeColorMapping(String[] colorMap)
{
String[] mapping = new String[colorMap.length];
if(letters == null) {
makeLetters();
}
try {
int x=0;
while(true) {
mapping[x]=letters[x%64];
x++;
}
}
catch(ArrayIndexOutOfBoundsException e) {;}
try {
if(mapping.length>64) {
try {
int x=0;
int z=0;
while(true) {
for(int y=0;y<64;y++) {
mapping[x+y]=letters[z]+mapping[x+y];
}
z++;
x=x+64;
}
}
catch(ArrayIndexOutOfBoundsException e) {;}
}
if(mapping.length>(64*64)) {
try {
int x=0;
int z=0;
while(true) {
for(int y=0;y<(64*64);y++) {
mapping[x+y]=letters[z]+mapping[x+y];
}
z++;
x=x+(64*64);
}
}
catch(ArrayIndexOutOfBoundsException e) {;}
}
if(mapping.length>(64*64*64)) {
try {
int x=0;
int z=0;
while(true) {
for(int y=0;y<(64*64*64);y++) {
mapping[x+y]=letters[z]+mapping[x+y];
}
z++;
x=x+(64*64*64);
}
}
catch(ArrayIndexOutOfBoundsException e) {;}
}
}
catch(Exception e) {;}
return(mapping);
}
private static String generateColorMapping(int width, int height, String[] colorMap, String[] colorMapping)
{
StringBuffer rval = new StringBuffer();
rval.append("/* width height num_colors chars_per_pixel */\n");
rval.append("\" "+width+" "+height+" "+colorMap.length+" "+colorMapping[0].length()+"\",\n");
rval.append("/* colors */\n");
for(int x=0;x