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 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.*;
public class main {
// see http://stackoverflow.com/questions/12552144/resize-image-in-java-without-losing-transparency
public static void main(String[] args) throws Exception {
// is 512*512
BufferedImage img = loadImage2("#1004221");
img = resizeImage(img, 256);
showImage(img);
savePNG(img, prepareProgramFile(img.getWidth() + ".png"));
}
static File prepareProgramFile(String name) {
return mkdirsForFile(getProgramFile(name));
}
static BufferedImage resizeImage(BufferedImage img, int newW, int newH) {
Image tmp = img.getScaledInstance(newW, newH, Image.SCALE_SMOOTH);
BufferedImage dimg = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = dimg.createGraphics();
g2d.drawImage(tmp, 0, 0, null);
g2d.dispose();
return dimg;
}
static BufferedImage resizeImage(BufferedImage img, int newW) {
int newH = iround(img.getHeight()*(double) newW/img.getWidth());
return resizeImage(img, newW, newH);
}
static BufferedImage loadImage2(String snippetIDOrURL) {
return loadBufferedImage(snippetIDOrURL);
}
static BufferedImage loadImage2(File file) {
return loadBufferedImage(file);
}
static ImageSurface showImage(String snippetIDOrURL, String title) {
return showImage(loadImage(snippetIDOrURL), title);
}
static ImageSurface showImage(final BufferedImage img, final String title) {
return (ImageSurface) swing(new Object() { Object get() {
ImageSurface is = showImage(img);
getFrame(is).setTitle(title);
return is;
}
public String toString() { return "ImageSurface is = showImage(img);\r\n getFrame(is).setTitle(title);\r\n return is;"; }});
}
static ImageSurface showImage(final BufferedImage img) {
return (ImageSurface) swing(new Object() { Object get() {
JFrame frame = new JFrame("JavaX");
ImageSurface is = new ImageSurface(img);
frame.getContentPane().add(new JScrollPane(is));
frame.pack();
centerFrame(frame);
frame.setVisible(true);
return is;
}
public String toString() { return "JFrame frame = new JFrame(\"JavaX\");\r\n ImageSurface is = new ImageSurface(img);\r\n frame.getContentPane().add(new JScrollPane(is));\r\n frame.pack();\r\n centerFrame(frame);\r\n frame.setVisible(true);\r\n return is;"; }});
}
static ImageSurface showImage(RGBImage img) {
return showImage(img.getBufferedImage());
}
static ImageSurface showImage(RGBImage img, String title) {
ImageSurface is = showImage(img.getBufferedImage());
getFrame(is).setTitle(title);
return is;
}
static ImageSurface showImage(String imageID) {
return showImage(loadImage(imageID));
}
static ImageSurface showImage(RGBImage img, ImageSurface surface) {
if (surface == null)
return showImage(img);
else {
surface.setImage(img);
return surface;
}
}
static void savePNG(BufferedImage img, File file) { try {
ImageIO.write(img, "png", file);
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static File getProgramFile(String progID, String fileName) {
return new File(getProgramDir(progID), fileName);
}
static File getProgramFile(String fileName) {
return getProgramFile(getProgramID(), fileName);
}
static int iround(double d) {
return (int) Math.round(d);
}
public static File mkdirsForFile(File file) {
File dir = file.getParentFile();
if (dir != null) // is null if file is in current dir
dir.mkdirs();
return file;
}
static JFrame getFrame(Object o) {
if (!(o instanceof Component)) return null;
Component c = (Component) o;
while (c != null) {
if (c instanceof JFrame) return (JFrame) c;
c = c.getParent();
}
return null;
}
static RGBImage loadImage(String snippetIDOrURL) {
return new RGBImage(loadBufferedImage(snippetIDOrURL));
}
static void centerFrame(JFrame frame) {
frame.setLocationRelativeTo(null); // magic trick
}
static Object swing(Object f) {
return swingAndWait(f);
}
static boolean loadBufferedImage_useImageCache = true;
static BufferedImage loadBufferedImage(String snippetIDOrURL) { try {
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);
try {
// TODO: androidify
File dir = new File(System.getProperty("user.home"), ".tinybrain/image-cache");
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 (IOException e) {
throw new RuntimeException(e);
}
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static BufferedImage loadBufferedImage(File file) { try {
return ImageIO.read(file);
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static String programID;
static String getProgramID() {
return nempty(programID) ? formatSnippetID(programID) : "?";
}
// TODO: ask JavaX instead
static String getProgramID(Class c) {
String id = (String) getOpt(c, "programID");
if (nempty(id))
return formatSnippetID(id);
return "?";
}
static String getProgramID(Object o) {
return getProgramID(getMainClass(o));
}
static String snippetImageURL(String snippetID) {
long id = parseSnippetID(snippetID);
String url;
if (id == 1000010 || id == 1000012)
url = "http://tinybrain.de:8080/tb/show-blobimage.php?id=" + id;
else
url = "http://eyeocr.sourceforge.net/filestore/filestore.php?cmd=serve&file=blob_" + id
+ "&contentType=image/png";
return url;
}
public static boolean isSnippetID(String s) {
try {
parseSnippetID(s);
return true;
} catch (RuntimeException e) {
return false;
}
}
static File getProgramDir() {
return programDir();
}
static File getProgramDir(String snippetID) {
return programDir(snippetID);
}
static RuntimeException fail() {
throw new RuntimeException("fail");
}
static RuntimeException fail(Object msg) {
throw new RuntimeException(String.valueOf(msg));
}
static RuntimeException fail(String msg) {
throw new RuntimeException(unnull(msg));
}
// disabled for now to shorten some programs
/*static RuntimeException fail(S msg, O... args) {
throw new RuntimeException(format(msg, args));
}*/
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 isURL(String s) {
return s.startsWith("http://") || s.startsWith("https://");
}
static void swingAndWait(Runnable r) { try {
if (isAWTThread())
r.run();
else
EventQueue.invokeAndWait(r);
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static Object swingAndWait(final Object f) {
if (isAWTThread())
return callF(f);
else {
final Var result = new Var();
swingAndWait(new Runnable() { public void run() { try {
result.set(callF(f));
} catch (Exception __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}});
return result.get();
}
}
static String unnull(String s) {
return s == null ? "" : s;
}
static List unnull(List l) {
return l == null ? emptyList() : l;
}
static Object[] unnull(Object[] a) {
return a == null ? new Object[0] : a;
}
static Object callF(Object f, Object... args) {
return callFunction(f, args);
}
static File programDir() {
return programDir(getProgramID());
}
static File programDir(String snippetID) {
return new File(javaxDataDir(), formatSnippetID(snippetID));
}
static String formatSnippetID(String id) {
return "#" + parseSnippetID(id);
}
static String formatSnippetID(long id) {
return "#" + id;
}
static boolean isAWTThread() {
return SwingUtilities.isEventDispatchThread();
}
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 Class getMainClass() { try {
return Class.forName("main");
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static Class getMainClass(Object o) { try {
return (o instanceof Class ? (Class) o : o.getClass()).getClassLoader().loadClass("main");
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static boolean nempty(Collection c) {
return !isEmpty(c);
}
static boolean nempty(CharSequence s) {
return !isEmpty(s);
}
static boolean nempty(Object[] o) {
return !isEmpty(o);
}
static Object getOpt(Object o, String field) {
if (o instanceof String) o = getBot ((String) o);
if (o == null) return null;
if (o instanceof Class) return getOpt((Class) o, field);
if (o.getClass().getName().equals("main$DynamicObject"))
return ((Map) getOpt_raw(o, "fieldValues")).get(field);
if (o instanceof Map) return ((Map) o).get(field);
return getOpt_raw(o, field);
}
static Object getOpt_raw(Object o, String field) {
try {
Field f = getOpt_findField(o.getClass(), field);
if (f == null) return null;
f.setAccessible(true);
return f.get(o);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Object getOpt(Class c, String field) {
try {
if (c == null) return null;
Field f = getOpt_findStaticField(c, field);
if (f == null) return null;
f.setAccessible(true);
return f.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Field getOpt_findStaticField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field) && (f.getModifiers() & Modifier.STATIC) != 0)
return f;
_c = _c.getSuperclass();
} while (_c != null);
return null;
}
static Field getOpt_findField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field))
return f;
_c = _c.getSuperclass();
} while (_c != null);
return null;
}
static File javaxDataDir_dir; // can be set to work on different base dir
static File javaxDataDir() {
return javaxDataDir_dir != null ? javaxDataDir_dir : new File(userHome(), "JavaX-Data");
}
static Object callFunction(Object f, Object... args) {
if (f == null) return null;
if (f instanceof Runnable) {
((Runnable) f).run();
return null;
} else if (f instanceof String)
return call(mc(), (String) f, args);
else
return call(f, "get", args);
//else throw fail("Can't call a " + getClassName(f));
}
static List emptyList() {
return new ArrayList();
//ret Collections.emptyList();
}
static Object getBot(String botID) {
return callOpt(getMainBot(), "getBot", botID);
}
static boolean isEmpty(Collection c) {
return c == null || c.isEmpty();
}
static boolean isEmpty(CharSequence s) {
return s == null || s.length() == 0;
}
static boolean isEmpty(Object[] a) {
return a == null || a.length == 0;
}
static boolean isEmpty(Map map) {
return map == null || map.isEmpty();
}
static long parseLong(String s) {
if (s == null) return 0;
return Long.parseLong(dropSuffix("L", s));
}
static long parseLong(Object s) {
return Long.parseLong((String) s);
}
static Object callOpt(Object o, String method, Object... args) {
try {
if (o == null) return null;
if (o instanceof Class) {
Method m = callOpt_findStaticMethod((Class) o, method, args, false);
if (m == null) return null;
m.setAccessible(true);
return m.invoke(null, args);
} else {
Method m = callOpt_findMethod(o, method, args, false);
if (m == null) return null;
m.setAccessible(true);
return m.invoke(o, args);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Method callOpt_findStaticMethod(Class c, String method, Object[] args, boolean debug) {
Class _c = c;
while (c != null) {
for (Method m : c.getDeclaredMethods()) {
if (debug)
System.out.println("Checking method " + m.getName() + " with " + m.getParameterTypes().length + " parameters");;
if (!m.getName().equals(method)) {
if (debug) System.out.println("Method name mismatch: " + method);
continue;
}
if ((m.getModifiers() & Modifier.STATIC) == 0 || !callOpt_checkArgs(m, args, debug))
continue;
return m;
}
c = c.getSuperclass();
}
return null;
}
static Method callOpt_findMethod(Object o, String method, Object[] args, boolean debug) {
Class c = o.getClass();
while (c != null) {
for (Method m : c.getDeclaredMethods()) {
if (debug)
System.out.println("Checking method " + m.getName() + " with " + m.getParameterTypes().length + " parameters");;
if (m.getName().equals(method) && callOpt_checkArgs(m, args, debug))
return m;
}
c = c.getSuperclass();
}
return null;
}
private static boolean callOpt_checkArgs(Method m, Object[] args, boolean debug) {
Class>[] types = m.getParameterTypes();
if (types.length != args.length) {
if (debug)
System.out.println("Bad parameter length: " + args.length + " vs " + types.length);
return false;
}
for (int i = 0; i < types.length; i++)
if (!(args[i] == null || isInstanceX(types[i], args[i]))) {
if (debug)
System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]);
return false;
}
return true;
}
static Object mainBot;
static Object getMainBot() {
return mainBot;
}
static String _userHome;
static String userHome() {
if (_userHome == null) {
if (isAndroid())
_userHome = "/storage/sdcard0/";
else
_userHome = System.getProperty("user.home");
//System.out.println("userHome: " + _userHome);
}
return _userHome;
}
static File userHome(String path) {
return new File(userDir(), path);
}
static Class mc() {
return getMainClass();
}
static String dropSuffix(String suffix, String s) {
return s.endsWith(suffix) ? s.substring(0, l(s)-l(suffix)) : s;
}
static Object call(Object o) {
return callFunction(o);
}
// varargs assignment fixer for a single string array argument
static Object call(Object o, String method, String[] arg) {
return call(o, method, new Object[] {arg});
}
static Object call(Object o, String method, Object... args) {
try {
if (o instanceof Class) {
Method m = call_findStaticMethod((Class) o, method, args, false);
m.setAccessible(true);
return m.invoke(null, args);
} else {
Method m = call_findMethod(o, method, args, false);
m.setAccessible(true);
return m.invoke(o, args);
}
} catch (Exception e) {
throw e instanceof RuntimeException ? (RuntimeException) e : new RuntimeException(e);
}
}
static Method call_findStaticMethod(Class c, String method, Object[] args, boolean debug) {
Class _c = c;
while (c != null) {
for (Method m : c.getDeclaredMethods()) {
if (debug)
System.out.println("Checking method " + m.getName() + " with " + m.getParameterTypes().length + " parameters");;
if (!m.getName().equals(method)) {
if (debug) System.out.println("Method name mismatch: " + method);
continue;
}
if ((m.getModifiers() & Modifier.STATIC) == 0 || !call_checkArgs(m, args, debug))
continue;
return m;
}
c = c.getSuperclass();
}
throw new RuntimeException("Method '" + method + "' (static) with " + args.length + " parameter(s) not found in " + _c.getName());
}
static Method call_findMethod(Object o, String method, Object[] args, boolean debug) {
Class c = o.getClass();
while (c != null) {
for (Method m : c.getDeclaredMethods()) {
if (debug)
System.out.println("Checking method " + m.getName() + " with " + m.getParameterTypes().length + " parameters");;
if (m.getName().equals(method) && call_checkArgs(m, args, debug))
return m;
}
c = c.getSuperclass();
}
throw new RuntimeException("Method '" + method + "' (non-static) with " + args.length + " parameter(s) not found in " + o.getClass().getName());
}
private static boolean call_checkArgs(Method m, Object[] args, boolean debug) {
Class>[] types = m.getParameterTypes();
if (types.length != args.length) {
if (debug)
System.out.println("Bad parameter length: " + args.length + " vs " + types.length);
return false;
}
for (int i = 0; i < types.length; i++)
if (!(args[i] == null || isInstanceX(types[i], args[i]))) {
if (debug)
System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]);
return false;
}
return true;
}
// extended over Class.isInstance() to handle primitive types
static boolean isInstanceX(Class type, Object arg) {
if (type == boolean.class) return arg instanceof Boolean;
if (type == int.class) return arg instanceof Integer;
if (type == long.class) return arg instanceof Long;
if (type == float.class) return arg instanceof Float;
if (type == short.class) return arg instanceof Short;
if (type == char.class) return arg instanceof Character;
if (type == byte.class) return arg instanceof Byte;
if (type == double.class) return arg instanceof Double;
return type.isInstance(arg);
}
static int l(Object[] array) {
return array == null ? 0 : array.length;
}
static int l(byte[] array) {
return array == null ? 0 : array.length;
}
static int l(int[] array) {
return array == null ? 0 : array.length;
}
static int l(char[] array) {
return array == null ? 0 : array.length;
}
static int l(Collection c) {
return c == null ? 0 : c.size();
}
static int l(Map m) {
return m == null ? 0 : m.size();
}
static int l(String s) {
return s == null ? 0 : s.length();
}
static int l(Object o) {
return l((List) o); // incomplete
}
static File userDir() {
return new File(userHome());
}
static File userDir(String path) {
return new File(userHome(), path);
}
static boolean isAndroid() { return System.getProperty("java.vendor").toLowerCase().indexOf("android") >= 0; }
static class Var {
A v;
Var() {}
Var(A v) {
this.v = v;}
synchronized void set(A a) { v = a; }
synchronized A get() { return v; }
}
static class RGB {
public final float r, g, b;
public RGB(float r, float g, float b) {
this.r = r;
this.g = g;
this.b = b;
}
public RGB(double r, double g, double b) {
this.r = (float) r;
this.g = (float) g;
this.b = (float) b;
}
public RGB(double brightness) {
this.r = this.g = this.b = (float) brightness;
}
public RGB(Color color) {
this.r = color.getRed()/255f;
this.g = color.getGreen()/255f;
this.b = color.getBlue()/255f;
}
public RGB(String hex) {
r = Integer.parseInt(hex.substring(0, 2), 16)/255f;
g = Integer.parseInt(hex.substring(2, 4), 16)/255f;
b = Integer.parseInt(hex.substring(4, 6), 16)/255f;
}
public float getComponent(int i) {
return i == 0 ? r : i == 1 ? g : b;
}
public Color getColor() {
return new Color(r, g, b);
}
public static RGB newSafe(float r, float g, float b) {
return new RGB(Math.max(0, Math.min(1, r)), Math.max(0, Math.min(1, g)), Math.max(0, Math.min(1, b)));
}
public int asInt() {
return getColor().getRGB() & 0xFFFFFF;
}
public float getBrightness() {
return (r+g+b)/3.0f;
}
public String getHexString() {
return Integer.toHexString(asInt() | 0xFF000000).substring(2).toUpperCase();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof RGB)) return false;
RGB rgb = (RGB) o;
if (Float.compare(rgb.b, b) != 0) return false;
if (Float.compare(rgb.g, g) != 0) return false;
if (Float.compare(rgb.r, r) != 0) return false;
return true;
}
@Override
public int hashCode() {
int result = (r != +0.0f ? Float.floatToIntBits(r) : 0);
result = 31 * result + (g != +0.0f ? Float.floatToIntBits(g) : 0);
result = 31 * result + (b != +0.0f ? Float.floatToIntBits(b) : 0);
return result;
}
public boolean isBlack() {
return r == 0f && g == 0f && b == 0f;
}
public boolean isWhite() {
return r == 1f && g == 1f && b == 1f;
}
public String toString() {
return getHexString();
}
}
static class RGBImage {
private BufferedImage bufferedImage;
private File file;
private int width, height;
private int[] pixels;
// color returned when getPixel is called with out-of-bounds position
private int background = 0xFFFFFF;
public RGBImage(BufferedImage image) {
this(image, null);
}
public RGBImage(BufferedImage image, File file) {
this.file = file;
bufferedImage = image;
width = image.getWidth();
height = image.getHeight();
pixels = new int[width*height];
PixelGrabber pixelGrabber = new PixelGrabber(image, 0, 0, width, height, pixels, 0, width);
try {
if (!pixelGrabber.grabPixels())
throw new RuntimeException("Could not grab pixels");
cleanPixels(); // set upper byte to 0
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
/** We assume it's a file name to load from */
public RGBImage(String file) throws IOException {
this(new File(file));
}
public RGBImage(Dimension size, Color color) {
this(size.width, size.height, color);
}
public RGBImage(Dimension size, RGB color) {
this(size.width, size.height, color);
}
private void cleanPixels() {
for (int i = 0; i < pixels.length; i++)
pixels[i] &= 0xFFFFFF;
}
public RGBImage(int width, int height, int[] pixels) {
this.width = width;
this.height = height;
this.pixels = pixels;
}
public RGBImage(int w, int h, RGB[] pixels) {
this.width = w;
this.height = h;
this.pixels = asInts(pixels);
}
public static int[] asInts(RGB[] pixels) {
int[] ints = new int[pixels.length];
for (int i = 0; i < pixels.length; i++)
ints[i] = pixels[i] == null ? 0 : pixels[i].getColor().getRGB();
return ints;
}
public RGBImage(int w, int h) {
this(w, h, Color.black);
}
public RGBImage(int w, int h, RGB rgb) {
this.width = w;
this.height = h;
this.pixels = new int[w*h];
int col = rgb.asInt();
if (col != 0)
for (int i = 0; i < pixels.length; i++)
pixels[i] = col;
}
public RGBImage(RGBImage image) {
this(image.width, image.height, copyPixels(image.pixels));
}
public RGBImage(int width, int height, Color color) {
this(width, height, new RGB(color));
}
public RGBImage(File file) throws IOException {
this(javax.imageio.ImageIO.read(file));
}
private static int[] copyPixels(int[] pixels) {
int[] copy = new int[pixels.length];
System.arraycopy(pixels, 0, copy, 0, pixels.length);
return copy;
}
public int getIntPixel(int x, int y) {
if (inRange(x, y))
return pixels[y * width + x];
else
return background;
}
public static RGB asRGB(int packed) {
int r = (packed >> 16) & 0xFF;
int g = (packed >> 8) & 0xFF;
int b = packed & 0xFF;
return new RGB(r / 255f, g / 255f, b / 255f);
}
public RGB getRGB(int x, int y) {
if (inRange(x, y))
return asRGB(pixels[y * width + x]);
else
return new RGB(background);
}
/** alias of getRGB - I kept typing getPixel instead of getRGB all the time, so I finally created it */
public RGB getPixel(int x, int y) {
return getRGB(x, y);
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
/** Attention: cached, i.e. does not change when image itself changes */
/** @NotNull */
public BufferedImage getBufferedImage() {
if (bufferedImage == null) {
bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//bufferedImage.setData(Raster.createRaster(new SampleModel()));
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
bufferedImage.setRGB(x, y, pixels[y*width+x]);
}
return bufferedImage;
}
public RGBImage clip(Rectangle r) {
r = fixClipRect(r);
int[] newPixels;
try {
newPixels = new int[r.width*r.height];
} catch (RuntimeException e) {
System.out.println(r);
throw e;
}
for (int y = 0; y < r.height; y++) {
System.arraycopy(pixels, (y+r.y)*width+r.x, newPixels, y*r.width, r.width);
}
return new RGBImage(r.width, r.height, newPixels);
}
private Rectangle fixClipRect(Rectangle r) {
r = r.intersection(new Rectangle(0, 0, width, height));
if (r.isEmpty())
r = new Rectangle(r.x, r.y, 0, 0);
return r;
}
public File getFile() {
return file;
}
/** can now also do GIF (not just JPEG) */
public static RGBImage load(String fileName) {
return load(new File(fileName));
}
/** can now also do GIF (not just JPEG) */
public static RGBImage load(File file) {
try {
BufferedImage bufferedImage = javax.imageio.ImageIO.read(file);
return new RGBImage(bufferedImage);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public int getInt(int x, int y) {
return pixels[y * width + x];
}
public void save(File file) throws IOException {
String name = file.getName().toLowerCase();
String type;
if (name.endsWith(".png")) type = "png";
else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) type = "jpeg";
else throw new IOException("Unknown image extension: " + name);
javax.imageio.ImageIO.write(getBufferedImage(), type, file);
}
public static RGBImage dummyImage() {
return new RGBImage(1, 1, new int[] {0xFFFFFF});
}
public int[] getPixels() {
return pixels;
}
public void setPixel(int x, int y, RGB rgb) {
if (x >= 0 && y >= 0 && x < width && y < height)
pixels[y*width+x] = rgb.asInt();
}
public void setPixel(int x, int y, Color color) {
setPixel(x, y, new RGB(color));
}
public void setPixel(int x, int y, int rgb) {
if (x >= 0 && y >= 0 && x < width && y < height)
pixels[y*width+x] = rgb;
}
public RGBImage copy() {
return new RGBImage(this);
}
public boolean inRange(int x, int y) {
return x >= 0 && y >= 0 && x < width && y < height;
}
public int getBackground() {
return background;
}
public void setBackground(int background) {
this.background = background;
}
public Dimension getSize() {
return new Dimension(width, height);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RGBImage rgbImage = (RGBImage) o;
if (height != rgbImage.height) return false;
if (width != rgbImage.width) return false;
if (!Arrays.equals(pixels, rgbImage.pixels)) return false;
return true;
}
@Override
public int hashCode() {
int result = width;
result = 31 * result + height;
result = 31 * result + Arrays.hashCode(pixels);
return result;
}
public String getHex(int x, int y) {
return getPixel(x, y).getHexString();
}
public RGBImage clip(int x, int y, int width, int height) {
return clip(new Rectangle(x, y, width, height));
}
public RGBImage clipLine(int y) {
return clip(0, y, width, 1);
}
public int numPixels() {
return width*height;
}
}
abstract static class Surface extends JPanel {
public Object AntiAlias = RenderingHints.VALUE_ANTIALIAS_ON;
public Object Rendering = RenderingHints.VALUE_RENDER_SPEED;
public AlphaComposite composite;
public Paint texture;
public BufferedImage bimg;
public int imageType;
public String name;
public boolean clearSurface = true;
// Demos using animated gif's that implement ImageObserver set dontThread.
public boolean dontThread;
protected long sleepAmount = 50; // max20 fps
private long orig, start, frame;
private Toolkit toolkit;
private boolean perfMonitor, outputPerf;
private int biw, bih;
private boolean clearOnce;
private boolean toBeInitialized = true;
public Surface() {
setDoubleBuffered(false);
toolkit = getToolkit();
name = this.getClass().getName();
name = name.substring(name.indexOf(".", 7)+1);
setImageType(0);
// To launch an individual demo with the performance str output :
// java -Djava2demo.perf= -cp Java2Demo.jar demos.Clipping.ClipAnim
try {
if (System.getProperty("java2demo.perf") != null) {
perfMonitor = outputPerf = true;
}
} catch (Exception ex) { }
}
/*protected Image getImage(String name) {
return DemoImages.getImage(name, this);
}
protected Font getFont(String name) {
return DemoFonts.getFont(name);
}*/
public int getImageType() {
return imageType;
}
public void setImageType(int imgType) {
if (imgType == 0) {
imageType = 1;
} else {
imageType = imgType;
}
bimg = null;
}
public void setAntiAlias(boolean aa) {
AntiAlias = aa
? RenderingHints.VALUE_ANTIALIAS_ON
: RenderingHints.VALUE_ANTIALIAS_OFF;
}
public void setRendering(boolean rd) {
Rendering = rd
? RenderingHints.VALUE_RENDER_QUALITY
: RenderingHints.VALUE_RENDER_SPEED;
}
public void setTexture(Object obj) {
if (obj instanceof GradientPaint) {
texture = new GradientPaint(0, 0, Color.white,
getSize().width*2, 0, Color.green);
} else {
texture = (Paint) obj;
}
}
public void setComposite(boolean cp) {
composite = cp
? AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f)
: null;
}
public void setMonitor(boolean pm) {
perfMonitor = pm;
}
public void setSleepAmount(long amount) {
sleepAmount = amount;
}
public long getSleepAmount() {
return sleepAmount;
}
public BufferedImage createBufferedImage(Graphics2D g2,
int w,
int h,
int imgType) {
BufferedImage bi = null;
if (imgType == 0) {
bi = (BufferedImage) g2.getDeviceConfiguration().
createCompatibleImage(w, h);
} else if (imgType > 0 && imgType < 14) {
bi = new BufferedImage(w, h, imgType);
} else if (imgType == 14) {
bi = createBinaryImage(w, h, 2);
} else if (imgType == 15) {
bi = createBinaryImage(w, h, 4);
} else if (imgType == 16) {
bi = createSGISurface(w, h, 32);
} else if (imgType == 17) {
bi = createSGISurface(w, h, 16);
}
biw = w;
bih = h;
return bi;
}
// Lookup tables for BYTE_BINARY 1, 2 and 4 bits.
static byte[] lut1Arr = new byte[] {0, (byte)255 };
static byte[] lut2Arr = new byte[] {0, (byte)85, (byte)170, (byte)255};
static byte[] lut4Arr = new byte[] {0, (byte)17, (byte)34, (byte)51,
(byte)68, (byte)85,(byte) 102, (byte)119,
(byte)136, (byte)153, (byte)170, (byte)187,
(byte)204, (byte)221, (byte)238, (byte)255};
private BufferedImage createBinaryImage(int w, int h, int pixelBits) {
int bytesPerRow = w * pixelBits / 8;
if (w * pixelBits % 8 != 0) {
bytesPerRow++;
}
byte[] imageData = new byte[h * bytesPerRow];
IndexColorModel cm = null;
switch (pixelBits) {
case 1:
cm = new IndexColorModel(pixelBits, lut1Arr.length,
lut1Arr, lut1Arr, lut1Arr);
break;
case 2:
cm = new IndexColorModel(pixelBits, lut2Arr.length,
lut2Arr, lut2Arr, lut2Arr);
break;
case 4:
cm = new IndexColorModel(pixelBits, lut4Arr.length,
lut4Arr, lut4Arr, lut4Arr);
break;
default:
{new Exception("Invalid # of bit per pixel").printStackTrace();}
}
DataBuffer db = new DataBufferByte(imageData, imageData.length);
WritableRaster r = Raster.createPackedRaster(db, w, h, pixelBits, null);
return new BufferedImage(cm, r, false, null);
}
private BufferedImage createSGISurface(int w, int h, int pixelBits) {
int rMask32 = 0xFF000000;
int rMask16 = 0xF800;
int gMask32 = 0x00FF0000;
int gMask16 = 0x07C0;
int bMask32 = 0x0000FF00;
int bMask16 = 0x003E;
DirectColorModel dcm = null;
DataBuffer db = null;
WritableRaster wr = null;
switch (pixelBits) {
case 16:
short[] imageDataUShort = new short[w * h];
dcm = new DirectColorModel(16, rMask16, gMask16, bMask16);
db = new DataBufferUShort(imageDataUShort, imageDataUShort.length);
wr = Raster.createPackedRaster(db, w, h, w,
new int[] {rMask16, gMask16, bMask16},
null);
break;
case 32:
int[] imageDataInt = new int[w * h];
dcm = new DirectColorModel(32, rMask32, gMask32, bMask32);
db = new DataBufferInt(imageDataInt, imageDataInt.length);
wr = Raster.createPackedRaster(db, w, h, w,
new int[] {rMask32, gMask32, bMask32},
null);
break;
default:
{new Exception("Invalid # of bit per pixel").printStackTrace();}
}
return new BufferedImage(dcm, wr, false, null);
}
public Graphics2D createGraphics2D(int width,
int height,
BufferedImage bi,
Graphics g) {
Graphics2D g2 = null;
if (bi != null) {
g2 = bi.createGraphics();
} else {
g2 = (Graphics2D) g;
}
g2.setBackground(getBackground());
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, AntiAlias);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, Rendering);
if (clearSurface || clearOnce) {
g2.clearRect(0, 0, width, height);
clearOnce = false;
}
if (texture != null) {
// set composite to opaque for texture fills
g2.setComposite(AlphaComposite.SrcOver);
g2.setPaint(texture);
g2.fillRect(0, 0, width, height);
}
if (composite != null) {
g2.setComposite(composite);
}
return g2;
}
public abstract void render(int w, int h, Graphics2D g);
/**
* It's possible to turn off double-buffering for just the repaint
* calls invoked directly on the non double buffered component.
* This can be done by overriding paintImmediately() (which is called
* as a result of repaint) and getting the current RepaintManager and
* turning off double buffering in the RepaintManager before calling
* super.paintImmediately(g).
*/
public void paintImmediately(int x,int y,int w, int h) {
RepaintManager repaintManager = null;
boolean save = true;
if (!isDoubleBuffered()) {
repaintManager = RepaintManager.currentManager(this);
save = repaintManager.isDoubleBufferingEnabled();
repaintManager.setDoubleBufferingEnabled(false);
}
super.paintImmediately(x, y, w, h);
if (repaintManager != null) {
repaintManager.setDoubleBufferingEnabled(save);
}
}
public void paint(Graphics g) {
Dimension d = getSize();
if (imageType == 1)
bimg = null;
else if (bimg == null || biw != d.width || bih != d.height) {
bimg = createBufferedImage((Graphics2D)g,
d.width, d.height, imageType-2);
clearOnce = true;
toBeInitialized = true;
}
if (toBeInitialized) {
toBeInitialized = false;
startClock();
}
Graphics2D g2 = createGraphics2D(d.width, d.height, bimg, g);
render(d.width, d.height, g2);
g2.dispose();
if (bimg != null) {
g.drawImage(bimg, 0, 0, null);
toolkit.sync();
}
}
public void startClock() {
orig = System.currentTimeMillis();
start = orig;
frame = 0;
}
private static final int REPORTFRAMES = 30;
public static void setAlpha(Graphics2D g, float alpha) {
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
}
}
static class ImageSurface extends Surface {
private BufferedImage image;
private double zoomX = 1, zoomY = 1;
private Rectangle selection;
public ImageSurface() {
this(new RGBImage(1, 1, new int[] { 0xFFFFFF }));
}
public ImageSurface(RGBImage image) {
this(image.getBufferedImage());
}
public ImageSurface(BufferedImage image) {
clearSurface = false;
this.image = image;
/*addMouseMotionListener(new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
getMousePosition()
}
});*/
}
public ImageSurface(RGBImage image, double zoom) {
this(image);
setZoom(zoom);
}
public void render(int w, int h, Graphics2D g) {
g.setColor(Color.white);
g.fillRect(0, 0, w, h);
if (image != null)
g.drawImage(image, 0, 0, getZoomedWidth(), getZoomedHeight(), null);
if (selection != null) {
// drawRect is inclusive, selection is exclusive, so... whatever, tests show it's cool.
drawSelectionRect(g, selection, Color.green, Color.white);
}
}
public void drawSelectionRect(Graphics2D g, Rectangle selection, Color green, Color white) {
g.setColor(green);
int top = (int) (selection.y * zoomY);
int bottom = (int) ((selection.y+selection.height) * zoomY);
int left = (int) (selection.x * zoomX);
int right = (int) ((selection.x+selection.width) * zoomX);
g.drawRect(left-1, top-1, right-left+1, bottom-top+1);
g.setColor(white);
g.drawRect(left - 2, top - 2, right - left + 3, bottom - top + 3);
}
public void setZoom(double zoom) {
setZoom(zoom, zoom);
}
public void setZoom(double zoomX, double zoomY) {
this.zoomX = zoomX;
this.zoomY = zoomY;
revalidate();
repaint();
}
public Dimension getMinimumSize() {
int w = getZoomedWidth();
int h = getZoomedHeight();
Dimension min = super.getMinimumSize();
return new Dimension(Math.max(w, min.width), Math.max(h, min.height));
}
private int getZoomedHeight() {
return (int) (image.getHeight() * zoomY);
}
private int getZoomedWidth() {
return (int) (image.getWidth() * zoomX);
}
public void setImage(RGBImage image) {
setImage(image.getBufferedImage());
}
public void setImage(BufferedImage image) {
this.image = image;
revalidate();
repaint();
}
public BufferedImage getImage() {
return image;
}
public double getZoomX() {
return zoomX;
}
public double getZoomY() {
return zoomY;
}
public Dimension getPreferredSize() {
return new Dimension(getZoomedWidth(), getZoomedHeight());
}
/** returns a scrollpane with the scroll-mode prevent-garbage-drawing fix applied */
public JScrollPane makeScrollPane() {
JScrollPane scrollPane = new JScrollPane(this);
scrollPane.getViewport().setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE);
return scrollPane;
}
public void zoomToDisplaySize() {
if (image == null) return;
Dimension display = getDisplaySize();
double xRatio = display.width/(double) image.getWidth();
double yRatio = display.height/(double) image.getHeight();
setZoom(Math.min(xRatio, yRatio));
revalidate();
}
/** tricky magic to get parent scroll pane */
private Dimension getDisplaySize() {
Container c = getParent();
while (c != null) {
if (c instanceof JScrollPane)
return c.getSize();
c = c.getParent();
}
return getSize();
}
public void setSelection(Rectangle r) {
selection = r;
repaint();
}
public Rectangle getSelection() {
return selection;
}
public RGBImage getRGBImage() {
return new RGBImage(getImage());
}
}
static Class> getClass(String name) {
try {
return Class.forName(name);
} catch (ClassNotFoundException e) {
return null;
}
}
static Class getClass(Object o) {
return o instanceof Class ? (Class) o : o.getClass();
}
static Class getClass(Object realm, String name) { try {
return getClass(realm).getClassLoader().loadClass(classNameToVM(name));
} catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}
static void revalidate(Component c) {
if (c == null) return;
// magic combo to actually relayout and repaint
c.revalidate();
c.repaint();
}
static boolean inRange(int x, int n) {
return x >= 0 && x < n;
}
static int asInt(Object o) {
return toInt(o);
}
// get purpose 1: access a list/array (safer version of x.get(y))
static A get(List l, int idx) {
return idx >= 0 && idx < l(l) ? l.get(idx) : null;
}
static A get(A[] l, int idx) {
return idx >= 0 && idx < l(l) ? l[idx] : null;
}
// get purpose 2: access a field by reflection or a map
static Object get(Object o, String field) {
if (o instanceof Class) return get((Class) o, field);
if (o instanceof Map)
return ((Map) o).get(field);
if (o.getClass().getName().equals("main$DynamicObject"))
return call(get_raw(o, "fieldValues"), "get", field);
return get_raw(o, field);
}
static Object get_raw(Object o, String field) {
try {
Field f = get_findField(o.getClass(), field);
f.setAccessible(true);
return f.get(o);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Object get(Class c, String field) {
try {
Field f = get_findStaticField(c, field);
f.setAccessible(true);
return f.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Field get_findStaticField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field) && (f.getModifiers() & Modifier.STATIC) != 0)
return f;
_c = _c.getSuperclass();
} while (_c != null);
throw new RuntimeException("Static field '" + field + "' not found in " + c.getName());
}
static Field get_findField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field))
return f;
_c = _c.getSuperclass();
} while (_c != null);
throw new RuntimeException("Field '" + field + "' not found in " + c.getName());
}
static boolean equals(Object a, Object b) {
return a == null ? b == null : a.equals(b);
}
static String classNameToVM(String name) {
return name.replace(".", "$");
}
static int toInt(Object o) {
if (o == null) return 0;
if (o instanceof Number)
return ((Number) o).intValue();
if (o instanceof String)
return parseInt((String) o);
throw fail("woot not int: " + getClassName(o));
}
static String getClassName(Object o) {
return o == null ? "null" : o.getClass().getName();
}
static int parseInt(String s) {
return empty(s) ? 0 : Integer.parseInt(s);
}
static boolean empty(Collection c) {
return isEmpty(c);
}
static boolean empty(String s) {
return isEmpty(s);
}
static boolean empty(Map map) {
return map == null || map.isEmpty();
}
static boolean empty(Object[] o) {
return o == null || o.length == 0;
}
static boolean empty(Object o) {
if (o instanceof Collection) return empty((Collection) o);
if (o instanceof String) return empty((String) o);
if (o instanceof Map) return empty((Map) o);
if (o instanceof Object[]) return empty((Object[]) o);
throw fail("unknown type for 'empty': " + getType(o));
}
static String getType(Object o) {
return getClassName(o);
}
}