import java.util.*;
import java.util.zip.*;
import java.util.List;
import java.util.regex.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.table.*;
import java.io.*;
import java.net.*;
import java.lang.reflect.*;
import java.lang.ref.*;
import java.lang.management.*;
import java.security.*;
import java.security.spec.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;
import java.math.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.DataFlavor;
import javax.swing.event.AncestorListener;
import javax.swing.event.AncestorEvent;
import javax.swing.Timer;
import javax.net.ssl.*;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.awt.datatransfer.UnsupportedFlavorException;
class main {
static RGB probeRandomPixel(RGBImage image) {
int x = (int) (random()*(image.getWidth()-1));
int y = (int) (random()*(image.getHeight()-1));
return image.getPixel(x, y);
}
static float probeRandomPixel(BWImage image) {
int x = (int) (random()*(image.getWidth()-1));
int y = (int) (random()*(image.getHeight()-1));
return image.getPixel(x, y);
}
static RGB randomColor() {
return new RGB(random(), random(), random());
}
static float randomBrightness() {
return (float) random();
}
static RGBImage resizeToWidth(RGBImage image, int w) {
return resize(image, w, (int) ((image.getHeight()*(double) w)/image.getWidth()));
}
public static RGBImage resize(RGBImage image, int w, int h) {
if (w == image.getWidth() && h == image.getHeight()) return image;
int[] pixels = new int[w*h];
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++)
pixels[y*w+x] = image.getInt(x*image.getWidth()/w, y*image.getHeight()/h);
return new RGBImage(w, h, pixels);
}
static Random _random = new Random();
static double random() {
return _random.nextInt(100001)/100000.0;
}
static int random(int max) {
return _random.nextInt(max);
}
static double random(double min, double max) {
return min+random()*(max-min);
}
static double normalize(double d) {
return Math.max(0, Math.min(1, d));
}
static int round(double d) {
return (int) Math.round(d);
}
static double mix(double a, double b, double bishness) {
return a+(b-a)*bishness;
}
public static double pixelDiff(RGB a, RGB b) {
return (Math.abs(a.r-b.r) + Math.abs(a.g-b.g) + Math.abs(a.b-b.b))/3;
}
public static double diff(RGBImage image, RGBImage image2) {
int w = image.getWidth(), h = image.getHeight();
double sum = 0;
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++)
sum += pixelDiff(image.getRGB(x, y), image2.getRGB(x, y));
return sum/(w*h);
}
static double diff(BWImage image, BWImage image2) {
int w = image.getWidth(), h = image.getHeight();
double sum = 0;
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++)
sum += Math.abs(image.getPixel(x, y) - image2.getPixel(x, y));
return sum/(w*h);
}
public static void copy(RGBImage src, int srcX, int srcY, RGBImage dst, int dstX, int dstY, int w, int h) {
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++)
dst.setPixel(dstX+x, dstY+y, src.getPixel(srcX+x, srcY+y));
}
public static void copy(BWImage src, int srcX, int srcY, BWImage dst, int dstX, int dstY, int w, int h) {
w = min(w, dst.getWidth()-dstX);
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++)
dst.setByte(dstX+x, dstY+y, src.getByte(srcX+x, srcY+y));
}
static float varyChannel(float x) {
return Math.max(0f, Math.min(1f, (float) (x+random(-0.1, 0.1))));
}
static double vary01(double x) {
return Math.max(0, Math.min(1, x+random(-0.1, 0.1)));
}
static RGB varyColor(RGB rgb) {
int s = random(3);
if (s == 0)
return new RGB(varyChannel(rgb.r), rgb.g, rgb.b);
else if (s == 1)
return new RGB(rgb.r, varyChannel(rgb.g), rgb.b);
else
return new RGB(rgb.r, rgb.g, varyChannel(rgb.b));
}
static RGBImage originalImage;
static int imageWidth = 200;
// XXX - main reproduce function
static Reproducer reproducer =
new Layers(
new RandomSolid())
.add(2, RandomBox.class)
.varyBest;
static abstract class Base {
abstract Base copy();
abstract void vary();
Base copyVary() {
Base copy = copy();
copy.vary();
return copy;
}
}
static abstract class Overlay extends Base {
abstract Overlay copy();
abstract void renderOn(RGBImage image);
}
// Params must be immutable!
static abstract class Params extends Base {
RGBImage originalImage;
abstract Params copy();
abstract RGBImage render();
void baseClone(Params p) {
p.originalImage = originalImage;
}
RGBImage rendered;
RGBImage getImage() {
if (rendered == null)
rendered = render();
return rendered;
}
double score = 2.0;
double getScore() {
if (score == 2.0)
score = calcScore();
return score;
}
double calcScore() {
return diff(originalImage, getImage());
}
boolean isBetterThan(Params p) {
return getScore() < p.getScore();
}
}
static class Box extends Overlay {
double cx, cy, w, h;
RGB color;
Box copy() {
Box p = new Box();
p.cx = cx;
p.cy = cy;
p.w = w;
p.h = h;
p.color = color;
return p;
}
public String toString() {
return "Box " + cx + " " + cy + " " + w + " " + h + " " + color;
}
void renderOn(RGBImage image) {
box(image, this);
}
void vary() {
int s = random(5);
if (s == 0)
cx = vary01(cx);
else if (s == 1)
cy = vary01(cy);
else if (s == 2)
w = vary01(w);
else if (s == 3)
h = vary01(h);
else
color = varyColor(color);
}
}
static class Solid extends Overlay {
RGB col;
Solid copy() {
Solid p = new Solid();
p.col = col;
return p;
}
public String toString() {
return "Solid " + col;
}
void renderOn(RGBImage image) {
int w = image.getWidth(), h = image.getHeight();
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++)
image.setPixel(x, y, col);
}
void vary() {
col = varyColor(col);
}
}
interface Reproducer {
public Params reproduce(RGBImage original);
}
interface OverlayReproducer {
public Overlay reproduce(RGBImage original);
}
static class RandomBox implements OverlayReproducer {
int n = -1;
public Overlay reproduce(RGBImage original) {
++n;
Box p = new Box();
p.cx = random();
p.cy = random();
p.w = random()*0.1;
p.h = random()*0.1;
if (n % 2 == 0)
p.color = randomColor();
else
p.color = probeRandomPixel(original);
return p;
}
}
static class RandomSolid implements OverlayReproducer {
int n = -1;
public Overlay reproduce(RGBImage original) {
++n;
Solid p = new Solid();
if (n % 2 == 0) {
p.col = randomColor();
} else {
p.col = probeRandomPixel(original);
}
return p;
}
}
static class WhiteSolid implements OverlayReproducer {
public Overlay reproduce(RGBImage original) {
Solid p = new Solid();
p.col = new RGB(Color.white);
return p;
}
}
static class VaryBest implements Reproducer {
Reproducer base;
Params best;
VaryBest(Reproducer base) {
this.base = base;
}
public Params reproduce(RGBImage original) {
Params p = base.reproduce(original);
if (best == null || p.isBetterThan(best))
best = p;
Params variation = (Params) best.copyVary();
//System.out.println("Best: " + best.getScore() + ", variation: " + variation.getScore());
if (variation.isBetterThan(best)) {
//System.out.println("Using variation, diff=" + (best.getScore()-variation.getScore()));
best = variation;
}
return best;
}
void reset() {
best = null;
}
}
static class Layered extends Params {
Layers myMaker;
Overlay[] list;
Layered(Layers myMaker, Overlay[] list) {
this.myMaker = myMaker;
this.list = list;
}
Layered copy() {
Layered p = new Layered(myMaker, new Overlay[list.length]);
baseClone(p);
for (int i = 0; i < list.length; i++)
p.list[i] = (Overlay) list[i].copy();
return p;
}
public String toString() {
StringBuilder buf = new StringBuilder("layered{");
for (int i = 0; i < list.length; i++) {
if (i != 0)
buf.append(", ");
buf.append(list[i]);
}
return buf + "}";
}
RGBImage render() {
RGBImage image = new RGBImage(originalImage.getWidth(), originalImage.getHeight(), Color.white);
for (int i = 0; i < list.length; i++)
list[i].renderOn(image);
return image;
}
void vary() {
int i = random(list.length);
if (random(2) == 0) {
//System.out.println("Varying layer " + i);
list[i] = (Overlay) list[i].copyVary();
} else {
//double score = getScore();
OverlayReproducer maker = myMaker.list[i];
list[i] = maker.reproduce(originalImage);
//System.out.println("Exchanging layer " + i + " from " + maker + ", improvement: " + (score-getFreshScore()));
}
}
}
static class Layers implements Reproducer {
OverlayReproducer[] list;
long ntry = -1;
int stepTime = 0/*500*/;
VaryBest varyBest = new VaryBest(this);
Layers(OverlayReproducer... list) {
this.list = list;
}
Layers add(int n, Class extends OverlayReproducer> xClass) { try {
OverlayReproducer l[] = new OverlayReproducer[list.length+n];
System.arraycopy(list, 0, l, 0, list.length);
for (int i = 0; i < n; i++)
l[list.length+i] = xClass.newInstance();
list = l;
return this;
} catch (Exception __e) { throw rethrow(__e); } }
public Params reproduce(RGBImage original) {
++ntry;
int n = this.list.length;
if (stepTime != 0) {
// build up image gradually to optimize lower layers first
n = (int) Math.min(n, ntry/stepTime+1);
varyBest.reset();
}
Overlay[] list = new Overlay[n];
for (int i = 0; i < n; i++)
list[i] = this.list[i].reproduce(original);
Layered result = new Layered(this, list);
result.originalImage = original;
return result;
}
}
static Params reproduce(RGBImage original) {
int w = original.getWidth(), h = original.getHeight();
return reproducer.reproduce(original);
}
public static void main(final String[] args) throws Exception {
String imageID = "#1000332"; // Picture of two coins
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (arg.equals("width"))
imageWidth = Integer.parseInt(args[++i]);
else if (isSnippetID(arg))
imageID = arg;
}
final String _imageID = imageID;
JFrame frame = new JFrame("A JavaX Frame");
JPanel grid = new JPanel(new GridLayout(2, 1));
final ImageSurface imageSurface = new ImageSurface();
final ImageSurface original = new ImageSurface();
grid.add(imageSurface);
grid.add(original);
frame.add(grid);
frame.setBounds(100, 100, 100+imageWidth+20, 300);
frame.setVisible(true);
exitOnFrameClose(frame);
new Thread() {
public void run() {
originalImage = loadImage(_imageID);
originalImage = resizeToWidth(originalImage, imageWidth);
original.setImage(originalImage);
reproduceOpenEnd(originalImage, imageSurface);
}
}.start();
}
static void reproduceOpenEnd(RGBImage original, ImageSurface imageSurface) {
Params best = null;
long lastPrint = 0, lastN = 0;
for (long ntry = 1; ; ntry++) {
long now = System.currentTimeMillis();
if (now >= lastPrint+1000) {
long tps = (ntry-lastN)*1000/(now-lastPrint);
lastPrint = now;
lastN = ntry;
String s = "Try " + ntry + " (" + tps + "/s)";
if (best == null)
System.out.println(s);
else {
System.out.println("Best: " + best);
System.out.println(s + ", score: " + formatDouble(best.getScore()*100, 2) + "%, structure size: " + structureSize(best, Params.class));
}
}
Params p = reproduce(original);
if (best == null || p != null && p.getScore() < best.getScore()) {
//System.out.println("New best! " + p.getScore());
best = p;
imageSurface.setImage(p.getImage());
}
if (p != null && p.getScore() == 0.0)
break;
}
}
static void box(RGBImage img, Box p) {
int w = img.getWidth(), h = img.getHeight();
double x1 = normalize(p.cx-p.w), x2 = normalize(p.cx+p.w);
double y1 = normalize(p.cy-p.h), y2 = normalize(p.cy+p.h);
int xx1 = round(x1*(w-1)), xx2 = round(x2*(w-1));
int yy1 = round(y1*(h-1)), yy2 = round(y2*(h-1));
for (int yy = yy1; yy <= yy2; yy++)
for (int xx = xx1; xx <= xx2; xx++)
img.setPixel(xx, yy, p.color);
}
static void add(BitSet bs, int i) {
bs.set(i);
}
static boolean add(Collection c, A a) {
return c != null && c.add(a);
}
static RuntimeException rethrow(Throwable t) {
if (t instanceof Error)
_handleError((Error) t);
throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
static String formatDouble(double d, int digits) {
String format = "0." + rep(digits, '#');
return new java.text.DecimalFormat(format, new java.text.DecimalFormatSymbols(Locale.ENGLISH)).format(d);
}
static Map _registerThread_threads = newWeakHashMap();
static Thread _registerThread(Thread t) {
_registerThread_threads.put(t, true);
return t;
}
static void _registerThread() { _registerThread(Thread.currentThread()); }
public static boolean isSnippetID(String s) {
try {
parseSnippetID(s);
return true;
} catch (RuntimeException e) {
return false;
}
}
public static int structureSize(Object o, Class baseClass) {
return structureSize(o, baseClass, new IdentityHashMap());
}
static int structureSize(Object o, Class baseClass,
IdentityHashMap seen) {
if (o == null || seen.containsKey(o)) return 0;
seen.put(o, Boolean.TRUE);
int size = 1;
Class c = o.getClass();
if (c.isArray()) {
int n = Array.getLength(o);
for (int i = 0; i < n; i++)
size += structureSize(Array.get(o, i), baseClass, seen);
} else
while (c != Object.class && c != baseClass) {
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
if ((field.getModifiers() & Modifier.STATIC) != 0)
continue;
if (field.getType().isPrimitive())
++size;
else {
Object value = null;
try {
value = field.get(o);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
size += structureSize(value, baseClass, seen);
}
}
c = c.getSuperclass();
}
return size;
}
static RGBImage loadImage(String snippetIDOrURL) {
return new RGBImage(loadBufferedImage(snippetIDOrURL));
}
static int min(int a, int b) {
return Math.min(a, b);
}
static long min(long a, long b) {
return Math.min(a, b);
}
static float min(float a, float b) { return Math.min(a, b); }
static float min(float a, float b, float c) { return min(min(a, b), c); }
static double min(double a, double b) {
return Math.min(a, b);
}
static double min(double[] c) {
double x = Double.MAX_VALUE;
for (double d : c) x = Math.min(x, d);
return x;
}
static float min(float[] c) {
float x = Float.MAX_VALUE;
for (float d : c) x = Math.min(x, d);
return x;
}
static byte min(byte[] c) {
byte x = 127;
for (byte d : c) if (d < x) x = d;
return x;
}
static short min(short[] c) {
short x = 0x7FFF;
for (short d : c) if (d < x) x = d;
return x;
}
static int min(int[] c) {
int x = Integer.MAX_VALUE;
for (int d : c) if (d < x) x = d;
return x;
}
static void exitOnFrameClose(JFrame frame) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
// TODO: send hard errors to core
static AtomicLong _handleError_nonVMErrors = new AtomicLong();
static AtomicLong _handleError_vmErrors = new AtomicLong();
static AtomicLong _handleError_outOfMemoryErrors = new AtomicLong();
static volatile long _handleError_lastOutOfMemoryError;
static volatile Error _handleError_lastHardError;
static void _handleError(Error e) {
if (!(e instanceof VirtualMachineError)) {
incAtomicLong(_handleError_nonVMErrors);
return;
}
print("\nHARD ERROR\n");
printStackTrace2(e);
print("\nHARD ERROR\n");
_handleError_lastHardError = e;
incAtomicLong(_handleError_vmErrors);
if (e instanceof OutOfMemoryError) {
incAtomicLong(_handleError_outOfMemoryErrors);
_handleError_lastOutOfMemoryError = sysNow();
}
}
static Map newWeakHashMap() {
return _registerWeakMap(synchroMap(new WeakHashMap()));
}
public static long parseSnippetID(String snippetID) {
long id = Long.parseLong(shortenSnippetID(snippetID));
if (id == 0) throw fail("0 is not a snippet ID");
return id;
}
static boolean loadBufferedImage_useImageCache = true;
static BufferedImage loadBufferedImage(String snippetIDOrURL) { try {
if (snippetIDOrURL == null) return null;
if (isURL(snippetIDOrURL))
return ImageIO.read(new URL(snippetIDOrURL));
if (!isSnippetID(snippetIDOrURL)) throw fail("Not a URL or snippet ID: " + snippetIDOrURL);
String snippetID = "" + parseSnippetID(snippetIDOrURL);
File dir = getCacheProgramDir("Image-Snippets");
if (loadBufferedImage_useImageCache) {
dir.mkdirs();
File file = new File(dir, snippetID + ".png");
if (file.exists() && file.length() != 0)
try {
return ImageIO.read(file);
} catch (Throwable e) {
e.printStackTrace();
// fall back to loading from sourceforge
}
}
String imageURL = snippetImageURL(snippetID);
System.err.println("Loading image: " + imageURL);
BufferedImage image = ImageIO.read(new URL(imageURL));
if (loadBufferedImage_useImageCache) {
File tempFile = new File(dir, snippetID + ".tmp." + System.currentTimeMillis());
ImageIO.write(image, "png", tempFile);
tempFile.renameTo(new File(dir, snippetID + ".png"));
//Log.info("Cached image.");
}
//Log.info("Loaded image.");
return image;
} catch (Exception __e) { throw rethrow(__e); } }
static BufferedImage loadBufferedImage(File file) { try {
return file.isFile() ? ImageIO.read(file) : null;
} catch (Exception __e) { throw rethrow(__e); } }
static String rep(int n, char c) {
return repeat(c, n);
}
static String rep(char c, int n) {
return repeat(c, n);
}
static List rep(A a, int n) {
return repeat(a, n);
}
static List rep(int n, A a) {
return repeat(n, a);
}
static Map synchroMap() {
return synchroHashMap();
}
static Map synchroMap(Map map) {
return Collections.synchronizedMap(map);
}
static File getCacheProgramDir() {
return getCacheProgramDir(getProgramID());
}
static File getCacheProgramDir(String snippetID) {
return new File(userHome(), "JavaX-Caches/" + formatSnippetIDOpt(snippetID));
}
static long sysNow() {
return System.nanoTime()/1000000;
}
static String repeat(char c, int n) {
n = Math.max(n, 0);
char[] chars = new char[n];
for (int i = 0; i < n; i++)
chars[i] = c;
return new String(chars);
}
static List repeat(A a, int n) {
n = Math.max(n, 0);
List l = new ArrayList(n);
for (int i = 0; i < n; i++)
l.add(a);
return l;
}
static List repeat(int n, A a) {
return repeat(a, n);
}
static boolean isURL(String s) {
return s.startsWith("http://") || s.startsWith("https://");
}
static void incAtomicLong(AtomicLong l) {
l.incrementAndGet();
}
static String shortenSnippetID(String snippetID) {
if (snippetID.startsWith("#"))
snippetID = snippetID.substring(1);
String httpBlaBla = "http://tinybrain.de/";
if (snippetID.startsWith(httpBlaBla))
snippetID = snippetID.substring(httpBlaBla.length());
return "" + parseLong(snippetID);
}
static String snippetImageURL(String snippetID) {
return snippetImageURL(snippetID, "png");
}
static String snippetImageURL(String snippetID, String contentType) {
long id = parseSnippetID(snippetID);
String url;
if (id == 1000010 || id == 1000012)
url = "http://tinybrain.de:8080/tb/show-blobimage.php?id=" + id;
else if (isImageServerSnippet(id))
url = imageServerLink(id);
else
//url = "http://eyeocr.sourceforge.net/filestore/filestore.php?cmd=serve&file=blob_" + id + "&contentType=image/" + contentType;
url = "https://www.botcompany.de:8443/img/" + id;
return url;
}
static RuntimeException fail() { throw new RuntimeException("fail"); }
static RuntimeException fail(Throwable e) { throw asRuntimeException(e); }
static RuntimeException fail(Object msg) { throw new RuntimeException(String.valueOf(msg)); }
static RuntimeException fail(String msg) { throw new RuntimeException(msg == null ? "" : msg); }
static RuntimeException fail(String msg, Throwable innerException) { throw new RuntimeException(msg, innerException); }
static volatile StringBuffer local_log = new StringBuffer(); // not redirected
static volatile StringBuffer print_log = local_log; // might be redirected, e.g. to main bot
// in bytes - will cut to half that
static volatile int print_log_max = 1024*1024;
static volatile int local_log_max = 100*1024;
//static int print_maxLineLength = 0; // 0 = unset
static boolean print_silent; // total mute if set
static Object print_byThread_lock = new Object();
static volatile ThreadLocal