|
|
@ -51,6 +51,8 @@ import java.awt.Graphics2D;
|
|
|
|
import java.awt.Color;
|
|
|
|
import java.awt.Color;
|
|
|
|
import java.awt.image.BufferedImage;
|
|
|
|
import java.awt.image.BufferedImage;
|
|
|
|
import java.awt.image.WritableRaster;
|
|
|
|
import java.awt.image.WritableRaster;
|
|
|
|
|
|
|
|
import java.util.HashSet;
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
|
|
|
|
|
|
|
public class ImagePainter {
|
|
|
|
public class ImagePainter {
|
|
|
|
|
|
|
|
|
|
|
@ -64,6 +66,53 @@ public class ImagePainter {
|
|
|
|
public static final byte MODE_REPLACE = 0;
|
|
|
|
public static final byte MODE_REPLACE = 0;
|
|
|
|
public static final byte MODE_REVERSE = 1;
|
|
|
|
public static final byte MODE_REVERSE = 1;
|
|
|
|
public static final byte MODE_MIX = 2;
|
|
|
|
public static final byte MODE_MIX = 2;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static long[] font = new long[]{
|
|
|
|
|
|
|
|
0x0,0x421004,0xa50000,0xafabea,0xfa38be,0x9b39b2,0xe82a8a,0x420000,0x221082,0x821080,0x51040,0x23880,0x1088,0x3800,0x4,0x111110,
|
|
|
|
|
|
|
|
0xe9d72e,0x46108e,0xe8991f,0xe88a2e,0x657c42,0x1f8783e,0xe87a2e,0x1f11084,0xe8ba2e,0xe8bc2e,0x20080,0x20088,0x222082,0xf83e0,0x820888,0xe11004,
|
|
|
|
|
|
|
|
0xeefa0e,0x4547f1,0x1c97a3e,0xe8420e,0x1e8c63e,0x1f8721f,0x1f87210,0xe85e2e,0x118fe31,0x1f2109f,0x1f0862e,0x1197251,0x108421f,0x11dd631,0x11cd671,0xe8c62e,
|
|
|
|
|
|
|
|
0x1e8fa10,0xe8d64d,0x1e8fa51,0xe8382e,0x1f21084,0x118c62e,0x118c544,0x118c6aa,0x1151151,0x1151084,0x1f1111f,0xe4210e,0x1041041,0xe1084e,0x454400,0x1f
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static final int radiusPrecalc = 120;
|
|
|
|
|
|
|
|
private static HashSet crds = new HashSet();
|
|
|
|
|
|
|
|
private static ArrayList crc;
|
|
|
|
|
|
|
|
private static int[][][] circles = new int[radiusPrecalc][][];
|
|
|
|
|
|
|
|
static {
|
|
|
|
|
|
|
|
// calculate coordinates
|
|
|
|
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
String co;
|
|
|
|
|
|
|
|
crds.add("0|0");
|
|
|
|
|
|
|
|
for (int r = 0; r < radiusPrecalc; r++) {
|
|
|
|
|
|
|
|
crc = new ArrayList();
|
|
|
|
|
|
|
|
for (int a = 0; a <= 2 * (r + 1); a++) {
|
|
|
|
|
|
|
|
x = (int) ((r + 1) * Math.cos(Math.PI * a / (4 * (r + 1))));
|
|
|
|
|
|
|
|
y = (int) ((r + 1) * Math.sin(Math.PI * a / (4 * (r + 1))));
|
|
|
|
|
|
|
|
co = x + "|" + y;
|
|
|
|
|
|
|
|
if (!(crds.contains(co))) {
|
|
|
|
|
|
|
|
crc.add(new int[]{x, y});
|
|
|
|
|
|
|
|
crds.add(co);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
x = (int) ((r + 0.5) * Math.cos(Math.PI * a / (4 * (r + 1))));
|
|
|
|
|
|
|
|
y = (int) ((r + 0.5) * Math.sin(Math.PI * a / (4 * (r + 1))));
|
|
|
|
|
|
|
|
co = x + "|" + y;
|
|
|
|
|
|
|
|
if (!(crds.contains(co))) {
|
|
|
|
|
|
|
|
crc.add(new int[]{x, y});
|
|
|
|
|
|
|
|
crds.add(co);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// put coordinates into array
|
|
|
|
|
|
|
|
//System.out.print("Radius " + r + " => " + crc.size() + " points: ");
|
|
|
|
|
|
|
|
circles[r] = new int[crc.size() - 1][];
|
|
|
|
|
|
|
|
for (int i = 0; i < crc.size() - 1; i++) {
|
|
|
|
|
|
|
|
circles[r][i] = (int[]) crc.get(i);
|
|
|
|
|
|
|
|
//System.out.print(circles[r][i][0] + "," +circles[r][i][1] + "; ");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//System.out.println();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
crc = null;
|
|
|
|
|
|
|
|
crds = null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private long[] grid; // one-dimensional arrays are much faster than two-dimensional
|
|
|
|
private long[] grid; // one-dimensional arrays are much faster than two-dimensional
|
|
|
|
private int width, height;
|
|
|
|
private int width, height;
|
|
|
@ -98,6 +147,32 @@ public class ImagePainter {
|
|
|
|
defaultMode = m;
|
|
|
|
defaultMode = m;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
private void plot(int x, int y) {
|
|
|
|
|
|
|
|
if ((x < 0) || (x >= width)) return;
|
|
|
|
|
|
|
|
if ((y < 0) || (y >= height)) return;
|
|
|
|
|
|
|
|
if (defaultMode == MODE_REPLACE) {
|
|
|
|
|
|
|
|
grid[x + y * width] = defaultCol;
|
|
|
|
|
|
|
|
} else if (defaultMode == MODE_MIX) {
|
|
|
|
|
|
|
|
int n = x + y * width;
|
|
|
|
|
|
|
|
long c = grid[n];
|
|
|
|
|
|
|
|
if (c < 0) {
|
|
|
|
|
|
|
|
//grid[n] = defaultCol;
|
|
|
|
|
|
|
|
int r = (int) (0xFF - (defaultCol >> 16));
|
|
|
|
|
|
|
|
int g = (int) (0xFF - ((defaultCol >> 8) & 0xff));
|
|
|
|
|
|
|
|
int b = (int) (0xFF - (defaultCol & 0xff));
|
|
|
|
|
|
|
|
grid[n] = r << 16 | g << 8 | b;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
int r = (int) ((c >> 16) - (defaultCol >> 16));
|
|
|
|
|
|
|
|
int g = (int) (((c >> 8) & 0xff) - ((defaultCol >> 8) & 0xff));
|
|
|
|
|
|
|
|
int b = (int) ((c & 0xff) - (defaultCol & 0xff));
|
|
|
|
|
|
|
|
grid[n] = ((r < 0) ? 0 : r << 16) | ((g < 0) ? 0 : g << 8) | ((b < 0) ? 0 : b);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void plot(int x, int y) {
|
|
|
|
private void plot(int x, int y) {
|
|
|
|
if ((x < 0) || (x >= width)) return;
|
|
|
|
if ((x < 0) || (x >= width)) return;
|
|
|
|
if ((y < 0) || (y >= height)) return;
|
|
|
|
if ((y < 0) || (y >= height)) return;
|
|
|
@ -106,13 +181,18 @@ public class ImagePainter {
|
|
|
|
} else if (defaultMode == MODE_MIX) {
|
|
|
|
} else if (defaultMode == MODE_MIX) {
|
|
|
|
int n = x + y * width;
|
|
|
|
int n = x + y * width;
|
|
|
|
long c = grid[n];
|
|
|
|
long c = grid[n];
|
|
|
|
int r = ((int) ((c >> 16) + (defaultCol >> 16))) & 0xff;
|
|
|
|
if (c < 0) {
|
|
|
|
int g = ((int) (((c >> 8) & 0xff) + ((defaultCol >> 8) & 0xff))) & 0xff;
|
|
|
|
grid[n] = defaultCol;
|
|
|
|
int b = ((int) ((c & 0xff) + (defaultCol & 0xff))) & 0xff;
|
|
|
|
} else {
|
|
|
|
grid[n] = r << 16 | g << 8 | b;
|
|
|
|
int r = ((int) ((c >> 16) + (defaultCol >> 16))) & 0xff;
|
|
|
|
|
|
|
|
int g = ((int) (((c >> 8) & 0xff) + ((defaultCol >> 8) & 0xff))) & 0xff;
|
|
|
|
|
|
|
|
int b = ((int) ((c & 0xff) + (defaultCol & 0xff))) & 0xff;
|
|
|
|
|
|
|
|
grid[n] = r << 16 | g << 8 | b;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void line(int Ax, int Ay, int Bx, int By) {
|
|
|
|
private void line(int Ax, int Ay, int Bx, int By) {
|
|
|
|
// Bresenham's line drawing algorithm
|
|
|
|
// Bresenham's line drawing algorithm
|
|
|
|
int dX = Math.abs(Bx-Ax);
|
|
|
|
int dX = Math.abs(Bx-Ax);
|
|
|
@ -153,12 +233,59 @@ public class ImagePainter {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void circle(int xc, int yc, int radius) {
|
|
|
|
private void circle(int xc, int yc, int radius) {
|
|
|
|
int xn, yn;
|
|
|
|
if (radius == 0) {
|
|
|
|
for (int i = 359; i >= 0; i--) {
|
|
|
|
plot(xc, yc);
|
|
|
|
xn = xc + (int) (radius * Math.cos(Math.PI * 2 * i / 360));
|
|
|
|
} else {
|
|
|
|
yn = yc + (int) (radius * Math.sin(Math.PI * 2 * i / 360));
|
|
|
|
int[][] c = circles[radius - 1];
|
|
|
|
plot(xn, yn);
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
for (int i = c.length - 1; i >= 0; i--) {
|
|
|
|
|
|
|
|
x = c[i][0];
|
|
|
|
|
|
|
|
y = c[i][1];
|
|
|
|
|
|
|
|
plot(xc + x, yc + y);
|
|
|
|
|
|
|
|
plot(xc - x + 1, yc + y);
|
|
|
|
|
|
|
|
plot(xc + x, yc - y + 1);
|
|
|
|
|
|
|
|
plot(xc - x + 1, yc - y + 1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void circle(int xc, int yc, int radius, int fromArc, int toArc) {
|
|
|
|
|
|
|
|
// draws only a part of a circle
|
|
|
|
|
|
|
|
// arc is given in degree
|
|
|
|
|
|
|
|
if (radius == 0) {
|
|
|
|
|
|
|
|
plot(xc, yc);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
int[][] c = circles[radius - 1];
|
|
|
|
|
|
|
|
int q = c.length;
|
|
|
|
|
|
|
|
int[][] c4 = new int[q * 4][];
|
|
|
|
|
|
|
|
for (int i = 0; i < q; i++) {
|
|
|
|
|
|
|
|
c4[i ] = new int[]{ c[i ][0],1-c[i ][1]};
|
|
|
|
|
|
|
|
c4[i + q] = new int[]{1-c[q - 1 - i][0],1-c[q - 1 - i][1]};
|
|
|
|
|
|
|
|
c4[i + 2 * q] = new int[]{1-c[i ][0], c[i ][1]};
|
|
|
|
|
|
|
|
c4[i + 3 * q] = new int[]{ c[q - 1 - i][0], c[q - 1 - i][1]};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = q * 4 * fromArc / 360; i <= q * 4 * toArc / 360; i++) {
|
|
|
|
|
|
|
|
plot(xc + c4[i][0], yc + c4[i][1]);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void print(int x, int y, char letter) {
|
|
|
|
|
|
|
|
int index = (int) letter - 0x20;
|
|
|
|
|
|
|
|
if (index >= font.length) return;
|
|
|
|
|
|
|
|
long character = font[index];
|
|
|
|
|
|
|
|
long row;
|
|
|
|
|
|
|
|
for (int i = 0; i < 5; i++) {
|
|
|
|
|
|
|
|
row = character & 0x1f;
|
|
|
|
|
|
|
|
character = character >> 5;
|
|
|
|
|
|
|
|
for (int j = 0; j < 5; j++) {
|
|
|
|
|
|
|
|
if ((row & 1) == 1) plot(x + 5 - j, y);
|
|
|
|
|
|
|
|
row = row >> 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
y--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -166,14 +293,29 @@ public class ImagePainter {
|
|
|
|
setColor(color);
|
|
|
|
setColor(color);
|
|
|
|
setMode(mode);
|
|
|
|
setMode(mode);
|
|
|
|
if (filled) {
|
|
|
|
if (filled) {
|
|
|
|
for (int i = radius; i >= 0; i--) circle(x, y, i);
|
|
|
|
for (int r = radius; r >= 0; r--) circle(x, y, r);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
circle(x, y, radius);
|
|
|
|
circle(x, y, radius);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void arc(int x, int y, int innerRadius, int outerRadius, int fromArc, int toArc, long color, byte mode) {
|
|
|
|
|
|
|
|
setColor(color);
|
|
|
|
|
|
|
|
setMode(mode);
|
|
|
|
|
|
|
|
for (int r = innerRadius; r <= outerRadius; r++) circle(x, y, r, fromArc, toArc);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public BufferedImage toImage() {
|
|
|
|
public void print(int x, int y, String message, long color, byte mode) {
|
|
|
|
|
|
|
|
setColor(color);
|
|
|
|
|
|
|
|
setMode(mode);
|
|
|
|
|
|
|
|
for (int i = 0; i < message.length(); i++) {
|
|
|
|
|
|
|
|
print(x, y, message.charAt(i));
|
|
|
|
|
|
|
|
x += 6;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public BufferedImage toImage(boolean complementary) {
|
|
|
|
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
|
|
|
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
|
|
|
Graphics2D g = bi.createGraphics();
|
|
|
|
Graphics2D g = bi.createGraphics();
|
|
|
|
g.setBackground(Color.white);
|
|
|
|
g.setBackground(Color.white);
|
|
|
@ -184,7 +326,13 @@ public class ImagePainter {
|
|
|
|
for (int i = width - 1; i >= 0; i--) {
|
|
|
|
for (int i = width - 1; i >= 0; i--) {
|
|
|
|
for (int j = height - 1; j >= 0; j--) {
|
|
|
|
for (int j = height - 1; j >= 0; j--) {
|
|
|
|
c = grid[i + j * width];
|
|
|
|
c = grid[i + j * width];
|
|
|
|
if (c >= 0) r.setPixel(i, j, new int[]{(int) (c >> 16), (int) ((c >> 8) & 0xff), (int) (c & 0xff)});
|
|
|
|
if (c >= 0) {
|
|
|
|
|
|
|
|
if (complementary) {
|
|
|
|
|
|
|
|
r.setPixel(i, j, new int[]{0xff - (int) ((((c >> 8) & 0xff) + (c & 0xff)) / 2), 0xff - (int) (((c >> 16) + (c & 0xff)) / 2) , 0xff - (int) ((((c >> 8) & 0xff) + (c >> 16)) / 2)});
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
r.setPixel(i, j, new int[]{(int) (c >> 16), (int) ((c >> 8) & 0xff), (int) (c & 0xff)});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|