package org.lemsml.jlems.viz.plot; import java.awt.Color; import java.awt.image.BufferedImage; import java.awt.image.WritableRaster; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.StringTokenizer; import javax.imageio.ImageIO; public final class Iconizer { // args: poly file, dim, r, g, b, outfile public static void main(String[] argv) throws IOException { File fin = new File(argv[0]); int dim = Integer.parseInt(argv[1]); int r = Integer.parseInt(argv[2]); int g = Integer.parseInt(argv[3]); int b = Integer.parseInt(argv[4]); File fout = new File(argv[5]); double[][] xy = readPerimiter(readStringFromFile(fin)); Color cgray = new Color(140, 140, 140); BufferedImage bim = filledPolygonImage(xy[0], xy[1], dim, cgray, 0.02, 0.04, 2.5); BufferedImage bimc = filledPolygonImage(xy[0], xy[1], dim, new Color(r, g, b), 0., 0., 1.5); bim.getGraphics().drawImage(bimc, 0, 0, null); ImageIO.write(bim, "png", fout); } private Iconizer() { } public static BufferedImage filledPolygonImage(double[] xp, double[] yp, int dim, Color col, double osx, double osy, double elf) { BufferedImage transim = new BufferedImage(dim, dim, BufferedImage.TYPE_INT_ARGB); WritableRaster alpha = transim.getAlphaRaster(); WritableRaster raster = transim.getRaster(); double[][] d = alphaPixelize(xp, yp, dim, osx, osy, elf); int w = dim; int h = dim; int r = col.getRed(); int g = col.getGreen(); int b = col.getBlue(); // transparency array; int[] itrans = new int[1]; itrans[0] = 0; int[] ipxin = new int[4]; for (int i = 0; i < w; i++) { for (int j = 0; j < h; j++) { if (d[i][j] > 0.) { ipxin[0] = r; ipxin[1] = g; ipxin[2] = b; raster.setPixel(i, j, ipxin); } itrans[0] = (int)(255 * d[i][j]); alpha.setPixel(i, j, itrans); } } return transim; } // create a dim x dim array with the internal pixels of the polygon // defined by perimeter xp,yp filled with fillColor. Boundary regins // have transparency set according to overlap. // result ints are R,G,B,alpha public static double[][] alphaPixelize(double[] xp0, double[] yp0, int dim, double osx, double osy, double elf) { double[][] ret = new double[dim][dim]; double[] xp = rerange(xp0); double[] yp = rerange(yp0); double dx = 1. / dim; double dy = 1. / dim; int nsamp = 10; for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { double x0 = (i + 0.5) * dx; double y0 = (j + 0.5) * dy; ret[i][j] = coverage(xp, yp, x0-osx, y0-osy, elf * dx, elf * dy, nsamp); } } return ret; } private static double coverage(double[] xp, double[] yp, double xc0, double yc0, double dx0, double dy0, int nsamp) { int nin = 0; double x0 = xc0 - 0.5 * dx0; double y0 = yc0 - 0.5 * dy0; double dx = dx0 / nsamp; double dy = dy0 / nsamp; for (int i = 0; i < nsamp; i++) { for (int j = 0; j < nsamp; j++) { double x = x0 + (i + 0.5) * dx; double y = y0 + (i + 0.5) * dy; if (pointIsInside(x, y, xp, yp)) { nin++; } } } return (1. * nin) / (nsamp * nsamp); } private static double[] rerange(double[] ap0) { double amin = ap0[0]; double amax = ap0[0]; for (int i = 0; i < ap0.length; i++) { if (ap0[i] < amin) { amin = ap0[i]; } if (ap0[i] > amax) { amax = ap0[i]; } } amin -= 0.1 * (amax - amin); amax += 0.1 * (amax - amin); double[] ap = new double[ap0.length]; for (int i = 0; i < ap0.length; i++) { ap[i] = (ap0[i] - amin) / (amax - amin); } return ap; } private static boolean pointIsInside(double x, double y, double[] xb, double[] yb){ int n = xb.length; int iwn = 0; for (int i = 0; i < n; i++) { int idir = 0; int p = (i+1)%n; if (yb[i] <= y && yb[p] > y) { idir = 1; } if (yb[i] > y && yb[p] <= y) { idir = -1; } if (idir != 0) { double f = (y - yb[i]) / (yb[p] - yb[i]); double xc = f * xb[p] + (1.-f) * xb[i]; int isid = (xc > x ? 1 : -1); iwn += isid * idir; } } return (iwn != 0); } private static double[][] readPerimiter(String s) { StringTokenizer st = new StringTokenizer(s, "\n\t ,"); int n = st.countTokens() / 2; double[][] sy = new double[2][n]; for (int i = 0; i < n; i++) { sy[0][i] = new Double(st.nextToken()).doubleValue(); sy[1][i] = new Double(st.nextToken()).doubleValue(); } return sy; } public static String readStringFromFile (File f) throws IOException { String sdat = ""; InputStream ins = new FileInputStream(f); InputStreamReader insr = new InputStreamReader(ins); BufferedReader fr = new BufferedReader (insr); StringBuffer sb = new StringBuffer(); while (fr.ready()) { sb.append (fr.readLine()); sb.append ("\n"); } fr.close(); sdat = sb.toString(); return sdat; } }