Related
I am asking this today for the purpose of comparing the two.
What I am trying to do is make a bot that is able to click the space-bar at a certain time.
Anyway, let me show what I am trying to compare.
Robot robot = new Robot();
This will be out Robot. (java.awt.Robot;)
My question is, which is faster for the purpose of try to constantly read one (or more) pixels on the screen at once?
My current (in progress) programs that are the same with the exception of one using
Robot.getPixelColor(int, int)
and the other uses
BufferedImage image Robot.createScreenCapture(Rectangle)
imaage.getRGB
These are being run at many times a second, and I am simply trying to figure out which is more consistently faster. They both seem random at the speed at which they operate, so any advice is appreciated.
In case you wish for an example to put these into, here is the setup for it.
Here is the example using Robot.getPixelColor(int, int)
Robot robot = new Robot();
Rectangle rect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
Point prompt = new Point(913, 506, robot);
BufferedImage screenImage = robot.createScreenCapture(rect);
for(int i = 0; i < 360; i++) {
zones.add(new Point(radius * Math.cos(Math.toRadians(i)) + centerX, radius * Math.sin(Math.toRadians(i)) + centerY, robot));
}
System.out.println("Resolution: " + width + " * " + height/* + " " + robot.getPixelColor(20, 20)/* + " " + screenImage.getRGB((int) prompt.getX(), (int) prompt.getY())*/);
while(true) {
tempZone = null;
while(prompt.hasColor(promptColor)) {
System.out.println("Found prompt, trying to find zone.");
int count = 0;
for(int i = 0; i < zones.size(); i++) {
if(zones.get(i).hasColor(zoneColor)){
tempZone = zones.get(i);
break;
}
}
if(tempZone != null) {
System.out.println("Found zone at: " + tempZone.getX() + ", " + tempZone.getY() + ". Looking for ticker...");
tempZone.whenHasColor(zoneColor);
}else{
System.out.println("Unable to find zone.");
}
while(prompt.hasColor(promptColor)) {}
}
}
With its Point Class:
public class Point {
private double x;
private double y;
private final Robot robot;
public Point(double x, double y, Robot rob) {
this.x = x;
this.y = y;
this.robot = rob;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public boolean hasColor(Color color) {
return (robot.getPixelColor((int )x, (int) y).equals(color));
}
public void whenHasColor(Color color) throws IOException {
Rectangle rect = new Rectangle(889 + (int) x, 449 + (int) y, 1, 1);
while(hasColor(color)) {
//Nothing
}
BufferedImage cap = robot.createScreenCapture(rect);
if(Math.abs(Math.abs(cap.getRGB(0, 0)) - 15657182) < 350000) {
System.out.println("Missed Zone, failure.");
}else {
robot.keyPress(Main.promptKey);
System.out.println("Found ticker pressing key. ");
}
}
}
For anyone wondering where could something this specific come from, I am using a modified version of this website as my medium for making this bot.
Now for the example with using Robot.createScreenCapture(Rectangle) and BufferedImage.getRGB(int, int)
Robot robot = new Robot();
Rectangle rect = new Rectangle(889, 449, 149, 149);
Point prompt = new Point(24, 57, robot);
String format = "png";
String fileName = "fullDebug1." + format;
BufferedImage screenImage = robot.createScreenCapture(rect);
for(int i = 0; i < 360; i++) {
zones.add(new Point(radius * Math.cos(Math.toRadians(i)) + centerX, radius * Math.sin(Math.toRadians(i)) + centerY, robot));
}
System.out.println("Resolution: " + width + " * " + height/* + " " + screenImage.getRGB((int) prompt.getX(), (int) prompt.getY())*/);
while(true) {
tempZone = null;
int zoneFinal = 0;
while(prompt.hasColor(promptColor)) {
System.out.println("Found prompt, trying to find zone.");
BufferedImage zoneImage = robot.createScreenCapture(rect);
int count = 0;
for(int i = 0; i < zones.size(); i++) {
if(zones.get(i).hasColorZones(zoneColor, zoneImage)){
tempZone = zones.get(i);
break;
}
}
if(tempZone != null) {
System.out.println("Found zone at: " + tempZone.getX() + ", " + tempZone.getY() + ". Looking for ticker...");
tempZone.whenHasColor(zoneColor);
}else{
System.out.println("Unable to find zone.");
}
while(prompt.hasColor(promptColor)) {}
}
and its Point class:
public class Point {
private double x;
private double y;
private final Robot robot;
public Point(double x, double y, Robot rob) {
this.x = x;
this.y = y;
this.robot = rob;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public boolean hasColor(int color) {
Rectangle rect = new Rectangle(889, 449, 149, 149);
BufferedImage screenImage = robot.createScreenCapture(rect);
return (Math.abs(screenImage.getRGB((int) x, (int) y)) == Math.abs(color))
}
public boolean hasColorPixel(int color, Rectangle rect) throws IOException {
BufferedImage cap = robot.createScreenCapture(rect);
return Math.abs(cap.getRGB(0, 0)) == Math.abs(color);
}
public boolean hasColorZones(int color, BufferedImage screenImage) {
return Math.abs(screenImage.getRGB((int) x, (int) y)) == Math.abs(color);
}
public boolean hasColorList(int[] colors, BufferedImage screenImage) {
for(int i : colors) {
if(Math.abs(screenImage.getRGB((int) x, (int) y)) == Math.abs(i)) {
return true;
}
}
return false;
}
public void whenHasColor(int color) throws IOException {
Rectangle rect = new Rectangle(889 + (int) x, 449 + (int) y, 1, 1);
while(hasColorPixel(color, rect)) {
//Nothing
}
BufferedImage cap = robot.createScreenCapture(rect);
if(Math.abs(Math.abs(cap.getRGB(0, 0)) - 15657182) < 350000) {
System.out.println("Missed Zone, failure.");
}else {
robot.keyPress(Main.promptKey);
System.out.println("Found ticker pressing key. ");
}
}
}
So my question is, which will run faster? Sometimes the latter option (which I more thoroughly debugged) gets 10 in a row, but then will fail randomly too. At first I thought it was that my laptop could not handle it, but upon running it on my desktop I had the same results. I would rather not have the bot be inconsistent with working properly or not.
I do hope I was able to give enough information for anyone to be able to help me. If there is anything I need to add or change, please tell me! This is my first question and I would like to learn to be better with this site.
Another apologies to if 1) the pixels are not the same on your screen, therefore you would not be able to run this to simulate my situation, and 2) if this post was long. I wanted to make a good "Minimal, Complete, and Verifiable example," but I wasn't sure how to shorten it any more.
EDIT
To make the code put in more relevant, as Ben pointed out, I could have cut it. But I thought of something that makes it more useful.
What can be done to that code to optimize it to run faster, so the bot will be 100% consistently working, or at least closer to 100% than it is now (~60%)
I write a plugin in ImageJ, and I need some idea.
I have a plugin which generate plots for every image in a stack. So if I have 4 image in a stack, it will generate 4 plot from a vector.
But I need to be one plot with 4 curve. Please help me. `
This is the code.
public void run(String arg){
openImage();
if (cancel==false){
options();
}
if (cancel==false){
for (int k=0;k<imp.getStackSize();k++){
imp.setSlice(k+1);
generateESFArray("ESF Plot",imp,roi);
generateLSFArray("LSF Plot",ESFArray);
calculateMax();
ESFArrayF=alignArray(ESFArray);
if (cancel==false){
LSFArrayF=alignArray(LSFArray);
}
if (cancel==false){
ESFVector=averageVector(ESFArrayF);
}
if (cancel==false){
LSFVector=averageVector(LSFArrayF);
int aura = (LSFVector.length * 2);
LSFDVector = new double [aura];
int j = 0;
int aura2 = (LSFVector.length);
for(i=0;i<(LSFDVector.length-3); i++){
if(i % 2 == 0) {
LSFDVector[i]= LSFVector[j];
j=j+1;
}else {
LSFDVector[i]= ((0.375*LSFVector[(j-1)]) + (0.75*LSFVector[(j)]) - (0.125*LSFVector[(j+1)]));
}
}
LSFDVector[i] = ((LSFVector[j-1] + LSFVector[j])*0.5);
LSFDVector[i+1] = LSFVector[j];
LSFDVector[i+2] = LSFVector[j];
int indexMax = 0;
double valorMax = LSFDVector[0];
for(int i=0;i<LSFDVector.length;i++){
if(valorMax < LSFDVector[i]){
indexMax = i;
valorMax = LSFDVector[i];
}
}
i=indexMax;
LSFDVector[i-1]=((LSFDVector[i-2] + LSFDVector[i])*0.5);
MTFVector=fftConversion(LSFDVector, "MTF");
Max=obtenerMax();
SPPVector=fftConversion(Max,"SPP");
LSFArrayF=alignArray(LSFArray);
if (MTFButton.isSelected()){
generatePlot (MTFVector,"MTF");
...
}
void generatePlot(double[] Vector, String plot){
double[]xValues;
String ejeX="pixel";
String ejeY="";
String allTitle="";
ImageProcessor imgProc;
xValues=calculateXValues(Vector,plot);
//plot titles
if (plot=="ESF"){
ejeY="Grey Value";
...
allTitle=plot + "_" + title;
plotResult = new Plot(allTitle, ejeX, ejeY, xValues, Vector);
//plot limits
if (plot=="ESF"){
plotResult.setLimits(1,Vector.length,0,yMax);
}
plotResult.draw();
plotResult.show();
}
`
The ij.gui.Plot class has an addPoints method allowing you to add multiple data series to a plot. The Groovy script below illustrates its usage. Just paste the code into ImageJ's script editor, choose Language > Groovy and press Run to try it.
import ij.gui.Plot
plot = new Plot("Multiple Line Plot", "x values", "y values", (double[])[0,1,2,3,4], (double[])[0.1,0.3,0.5,0.6,0.7])
plot.addPoints((double[])[0,1,2,3,4], (double[])[0.2,0.15,0.1,0.05,0.05], Plot.LINE)
plot.setLimits(0, 4, 0, 1)
plot.draw()
plot.show()
For any further questions regarding the usage of the ImageJ API, you might get better help on the ImageJ forum.
I've been wanting to design a generator for dragon curves.
(If you want info on that check this out, but it doesn't really matter for the issue)
A dragon curve is a repeating mathematical construct.
I've already written a generator for what the canvas should draw, it works by returning a char array consisting of 'r' or 'l', saying whether the line has to turn left or right next. In the code here, it's the method input(). This part works perfectly.
The problem is that whenever I want to draw it on the canvas (using drawLine), it only draws the first two lines as actual lines, the rest are just dots.
The dots are on the right positions and if you make the thing really big, you can't tell the difference anymore, but nevertheless, there are supposed to be lines there.
Image:
This is the code I used:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
/**
*
* Description
*
* #version 1.0 from 4/20/2016
* #author
*/
public class CurveGen extends JFrame {
// start attributes
private Canvas display = new Canvas();
private JButton startButton = new JButton();
private JLabel jLabel1 = new JLabel();
private JTextArea outText = new JTextArea("");
private JScrollPane outTextScrollPane = new JScrollPane(outText);
private JLabel jLabel2 = new JLabel();
private JSlider xSlider = new JSlider();
private JSlider ySlider = new JSlider();
private JNumberField iterationsNF = new JNumberField();
private JNumberField sizeNF = new JNumberField();
// end attributes
public CurveGen(String title) {
// Frame-Init
super(title);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
int frameWidth = 1022;
int frameHeight = 731;
setSize(frameWidth, frameHeight);
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int x = (d.width - getSize().width) / 2;
int y = (d.height - getSize().height) / 2;
setLocation(x, y);
setResizable(false);
Container cp = getContentPane();
cp.setLayout(null);
// start components
display.setBounds(16, 64, 601, 601);
cp.add(display);
startButton.setBounds(736, 464, 241, 129);
startButton.setText("START!");
startButton.setMargin(new Insets(2, 2, 2, 2));
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
startButton_ActionPerformed(evt);
}
});
startButton.setFont(new Font("Dialog", Font.BOLD, 36));
cp.add(startButton);
jLabel1.setBounds(760, 96, 75, 41);
jLabel1.setText("Iterations:");
cp.add(jLabel1);
outTextScrollPane.setBounds(728, 392, 257, 57);
cp.add(outTextScrollPane);
jLabel2.setBounds(768, 144, 67, 41);
jLabel2.setText("Size:");
cp.add(jLabel2);
xSlider.setBounds(0, 8, 633, 49);
xSlider.setMinorTickSpacing(25);
xSlider.setMajorTickSpacing(100);
xSlider.setPaintTicks(true);
xSlider.setPaintLabels(true);
xSlider.setToolTipText("Starting point y-coordinate");
xSlider.setMaximum(600);
xSlider.setValue(300);
cp.add(xSlider);
ySlider.setBounds(624, 56, 65, 625);
ySlider.setMinorTickSpacing(25);
ySlider.setMajorTickSpacing(100);
ySlider.setPaintTicks(true);
ySlider.setPaintLabels(true);
ySlider.setOrientation(SwingConstants.VERTICAL);
ySlider.setMaximum(600);
ySlider.setInverted(true);
ySlider.setValue(300);
ySlider.setToolTipText("Starting point x-coordinate");
cp.add(ySlider);
iterationsNF.setBounds(856, 96, 81, 41);
iterationsNF.setText("");
cp.add(iterationsNF);
sizeNF.setBounds(856, 144, 81, 41);
sizeNF.setText("");
cp.add(sizeNF);
// end components
setVisible(true);
} // end of public CurveGen
// start methods
public static void main(String[] args) {
new CurveGen("CurveGen");
} // end of main
public char[] input(int iter) {
char oldOut[] = new char[0];
for (int i=1;i<=iter;i++) {
char newOut[] = new char[((int)Math.pow(2, i))-1];
for (int n=0;n<oldOut.length;n++) {
newOut[n] = oldOut[n];
if (oldOut[n]=='r') {
newOut[newOut.length-n-1] = 'l';
}
if (oldOut[n]=='l') {
newOut[newOut.length-n-1] = 'r';
} // end of if
} // end of for
newOut[oldOut.length]='l';
oldOut = newOut;
} // end of for
return oldOut;
}
public void startButton_ActionPerformed(ActionEvent evt) {
int iterations = iterationsNF.getInt();
int size = sizeNF.getInt();
char com[] = input(iterations);
outText.setText(String.valueOf(com));
int dir = 0;
int newDir = 0;
int lastPos[] = {xSlider.getValue(),ySlider.getValue()-size};
int newPos[] = {0,0};
Graphics g = display.getGraphics();
g.clearRect(0,0,601,601);
g.drawLine(xSlider.getValue(),ySlider.getValue(),xSlider.getValue(),ySlider.getValue()-size);
for (int i=0;i<=com.length-1;i++) {
dir = newDir;
if (dir==0) {
if (com[i]=='l') {
newPos[0] = lastPos[0]-size;
newPos[1] = lastPos[1];
newDir = 3;
}
if (com[i]=='r') {
newPos[0] = lastPos[0]+size;
newPos[1] = lastPos[1];
newDir = 1;
}
}
if (dir==1) {
if (com[i]=='l') {
newPos[0] = lastPos[0];
newPos[1] = lastPos[1]-size;
newDir = 0;
}
if (com[i]=='r') {
newPos[0] = lastPos[0];
newPos[1] = lastPos[1]+size;
newDir = 2;
}
}
if (dir==2) {
if (com[i]=='l') {
newPos[0] = lastPos[0]+size;
newPos[1] = lastPos[1];
newDir = 1;
}
if (com[i]=='r') {
newPos[0] = lastPos[0]-size;
newPos[1] = lastPos[1];
newDir = 3;
}
}
if (dir==3) {
if (com[i]=='l') {
newPos[0] = lastPos[0];
newPos[1] = lastPos[1]+size;
newDir = 2;
}
if (com[i]=='r') {
newPos[0] = lastPos[0];
newPos[1] = lastPos[1]-size;
newDir = 0;
}
}
g.drawLine(lastPos[0],lastPos[1],newPos[0],newPos[1]);
lastPos=newPos;
} // end of for
} // end of startButton_ActionPerformed
// end methods
} // end of class CurveGen
Okay, so I've gone back over the code...
Mixing heavyweight (java.awt.Canvas) and lightweight (Swing) components is unadvisable as they can cause or sorts of painting issues
getGraphics is not how paint should be done. Instead, I'd start with a custom JPanel and override its paintComponent. See Painting in AWT and Swing and Performing Custom Painting for more details
Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify
I believe the problem is associated with this...
lastPos=newPos;
All you are doing is making lastPos point to the same place in memory as newPos, so when you assign values to newPos, lastPos will have the same values, hence the reason you're seeing dots.
What I would do first, is separate the responsible for the generation of the data from the display.
I'd start with some kind of model (note, you could create a model which took iterations instead and which generated the data itself, but I was focusing on solving the initial problem)
public class DragonModel {
private Point startPoint;
private int size;
private char[] values;
public DragonModel(Point startPoint, int size, char[] values) {
this.startPoint = startPoint;
this.size = size;
this.values = values;
}
public Point getStartPoint() {
return startPoint;
}
public int getSize() {
return size;
}
public char[] getValues() {
return values;
}
}
and then the display...
public class DragonPane extends JPanel {
private DragonModel model;
public void setModel(DragonModel model) {
this.model = model;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (model != null) {
Graphics2D g2d = (Graphics2D) g.create();
int size = model.getSize();
int dir = 0;
int newDir = 0;
Point lastPos = model.getStartPoint();
Point newPos = new Point(0, 0);
for (char value : model.values) {
if (dir == 0) {
if (value == 'l') {
newPos.x = lastPos.x - size;
newPos.y = lastPos.y;
newDir = 3;
}
if (value == 'r') {
newPos.x = lastPos.x + size;
newPos.y = lastPos.y;
newDir = 1;
}
}
if (dir == 1) {
if (value == 'l') {
newPos.x = lastPos.x;
newPos.y = lastPos.y - size;
newDir = 0;
}
if (value == 'r') {
newPos.x = lastPos.x;
newPos.y = lastPos.y + size;
newDir = 2;
}
}
if (dir == 2) {
if (value == 'l') {
newPos.x = lastPos.x + size;
newPos.y = lastPos.y;
newDir = 1;
}
if (value == 'r') {
newPos.x = lastPos.x - size;
newPos.y = lastPos.y;
newDir = 3;
}
}
if (dir == 3) {
if (value == 'l') {
newPos.x = lastPos.x;
newPos.y = lastPos.y + size;
newDir = 2;
}
if (value == 'r') {
newPos.x = lastPos.x;
newPos.y = lastPos.y - size;
newDir = 0;
}
}
g.drawLine(lastPos.x, lastPos.y, newPos.x, newPos.y);
dir = newDir;
lastPos = new Point(newPos);
}
}
}
}
The idea here is to try and decouple of the responsibility a little, the responsibility for the generation and displaying of the data sit firmly in two different areas.
Then in your actionPerformed method you could simply do...
public void startButton_ActionPerformed(ActionEvent evt) {
int iterations = Integer.parseInt(iterationsNF.getText());
int size = Integer.parseInt(sizeNF.getText());
char com[] = input(iterations);
outText.setText(String.valueOf(com));
DragonModel model = new DragonModel(new Point(xSlider.getValue(), ySlider.getValue()), size, com);
display.setModel(model);
} // end of startButton_ActionPerformed
which could result in something like...
The drawing code should be inside the paint(Graphics) method to synchronize with the rendering loop properly. In an event handler, update the data model of the component (calculate the lines and keep them in a data structure inside the component), then call the method repaint() to trigger the event rendering loop, which will call your paint method.
There are some other variations of this, but the general idea is that you change the data and then request rendering. The rendering engine may call your paint method in other cases as well, not only when you change the data, so ideally paint() has all the data it needs to render fast, meaning it should not do calculations or heavy operations other than rendering on the Graphics object.
This means that you have to subclass JComponent in a new class, and implement paint inside it. This class should have an internal data structure with the lines ready to render at any point in time. Then use your new class in the JFrame.
I'm working on a project for my comp sci class which deals with image processing. My group and I are going to vertically flip and rotate a picture 90 degrees. The first part of my code is the sample from my teacher that turns the photo gray. I'm able to compile my code, but I get the error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at Project6b.main(Project6b.java:10)
Press any key to continue...
I'm not even sure if what I've coded so far works, and I can't get this to run. Can anyone help me solve my runtime error?
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import java.awt.*;
public class Project6b
{
public static void main (String args[]) throws Exception
{
// I would use these, if the program is finished.
//grayscale(args[0], args[1]);
//verticalFlip(args[0], args[1]);
// I would comment the first two lines and
//uncomment these for testing purposes.
//grayscale("Vicc.jpg", "Vicc2.jpg");
verticalFlip("Vic.png", "Vic2.png");
}
/*public static void grayscale(String originalImage, String convertedImage) throws Exception
{
BufferedImage bufferImg = ImageIO.read(new File(originalImage));
int r,g,b;
Color color = null;
for( int x = 0; x <bufferImg.getWidth(); x++)
{
for(int y = 0; y<bufferImg.getHeight(); y++)
{
int rgb = bufferImg.getRGB(x,y);
color = new Color(rgb,true);
r = color.getRed();
g = color.getGreen();
b = color.getBlue();
color = new Color((r+g+b)/3, (r+g+b)/3, (r+g+b)/3);
bufferImg.setRGB(x,y, color.getRGB());
}
}
File outputfile = new File(convertedImage);
ImageIO.write(bufferImg, "png", outputfile);
} */
public static void verticalFlip(String originalImage, String convertedImage) throws Exception
{
BufferedImage bufferImg = ImageIO.read(new File(originalImage));
BufferedImage bufferImgOut = new BufferedImage(bufferImg.getWidth(),bufferImg.getHeight(), bufferImg.getType());
for (int x = 0; x < bufferImg.getWidth(); x++)
{
for (int y = 0; y < bufferImg.getHeight(); y++)
{
int px = bufferImg.getRGB(x, y);
int destY = bufferImg.getHeight() - y - 1;
bufferImg.setRGB(x, destY, px);
}
}
File outputfile = new File(convertedImage);
ImageIO.write(bufferImgOut, "png", outputfile);
}
//public static void Rotate(String originalImage, String convertedImage) throws Exception
//{
//}
}
The problem occurs when you don't pass any arguments at start up, like reimeus already mentioned.
If you are using an IDE like Eclipse or Netbeans, there should be some kind of start cfg where you can enter the arguments, which should be passed to the app. In case you are launching your app from the command line, use:
java Project6b Jack.jpg Jack2.jpg
java PROGRAM INPUT-IMAGE OUTPUT-IMAGE
Then you can change your main respectively:
public static void main (String args[]) throws Exception
{
// I would use these, if the program is finished.
grayscale(args[0], args[1]);
verticalFlip(args[0], args[1]);
// I would comment the first two lines and
//uncomment these for testing purposes.
//grayscale("Jack.jpg", "Jack.jpg");
//verticalFlip("Jack.jpg", "Jack.jpg");
}
(If you use the function calls at the bottom, you don't need to pass any arguments. This is good for quick debugging.)
Hope it helps!
Regarding verticalFlip:
public static void verticalFlip(String originalImage, String convertedImage)
throws Exception {
BufferedImage bufferImg = ImageIO.read(new File(originalImage));
// create a new Image, which will be your output img, so that
// you do NOT override some pixels in your source img - you'll need them.
BufferedImage bufferImgOut = new BufferedImage(bufferImg.getWidth(), bufferImg.getHeight(), bufferImg.getType());
for (int x = 0; x < bufferImg.getWidth(); x++) {
for (int y = 0; y < bufferImg.getHeight(); y++) {
int px = bufferImg.getRGB(x, y);
int destY = bufferImg.getHeight() - y - 1;
// your x-coordinate should stay the same, since you only flip vertically.
bufferImgOut.setRGB(x, destY, px);
}
}
File outputfile = new File(convertedImage);
ImageIO.write(bufferImgOut, "png", outputfile);
}
I'm trying to imitate a similar code seen here http://www.openprocessing.org/sketch/7050 but I seem to have gotten a little mixed up with the code. I'm trying to get the effect of the letters essentially drawing the posterized image of the picture. But I have getting a NullPointException and assume is has to do with how I'm initializing the string variables but i can't seem to find what I'm doing wrong.
The Error
Exception in thread "Animation Thread" java.lang.NullPointerException
at processing.opengl.PGL.getString(PGL.java:1029)
at processing.opengl.PGraphicsOpenGL.getGLParameters(PGraphicsOpenGL.java:6076)
at processing.opengl.PGraphicsOpenGL.beginDraw(PGraphicsOpenGL.java:1547)
at MLKpractice.letterfit(MLKpractice.java:147)
at MLKpractice.draw(MLKpractice.java:98)
at processing.core.PApplet.handleDraw(PApplet.java:2120)
at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:197)
at processing.core.PApplet.run(PApplet.java:1998)
at java.lang.Thread.run(Thread.java:680)
The program says the error is on line 127
lettersquare.beginDraw();
But I believe the error is somewhere above
PFont font;
String fontpath = "ArialMT-200.vlw";
int fontstart = 300;
int fontend = 8;
float fontsize = fontstart;
float fontsizedecrease = 0.97;
PImage bg;
PImage australia;
PImage austria;
String country1 = "australia.jpg";
String country2 = "austria.jpg";
String letters = "Australia";
char[] chars = new char[52];
int nchars = 0;
int iterations = 500;
int c = 0;
PGraphics letter,lettersquare,drawing;
void setup(){
//initialize the sketch
size(900,600);
//background(255);
//initialize the font
//font = loadFont(fontpath);
///*
for(int i=0;i<letters.length();i++){
boolean found = false;
char lc = letters.charAt(i);
for(int j=0;j<nchars;j++){
if(chars[j]==lc){
found = true;
break;
}
}
if(!found) chars[nchars++] = lc;
}
chars = (char[]) subset(chars,0,nchars);
font = createFont("Arial",200,true,chars);
//*/
textAlign(CENTER,CENTER);
//load the image that will be filled with letters
australia = loadImage(country1);
austria = loadImage(country2);
bg = loadImage("background.jpg");
//posterize the image
australia.filter(THRESHOLD,0.4);
australia.filter(BLUR,3);
australia.filter(THRESHOLD,0.6);
//initialize the drawing buffers
letter = createGraphics((int)fontsize,(int)fontsize,JAVA2D);
lettersquare = createGraphics((int)fontsize,(int)fontsize,P2D);
drawing = createGraphics(width,height,JAVA2D);
drawing.beginDraw();
drawing.background(255);
// THIS STUPID THING NEEDS TO GO HERE!!!!
drawing.image(bg,0,0);
drawing.endDraw();
}
void draw(){
if(floor(fontsize)>fontend&&c<letters.length()-1){
if(!letterfit()){
fontsize *= fontsizedecrease;
}else{
c++;
if(c==11){
fontsize *= 0.75;
}
}
tint(255);
image(drawing,0,0);
if (keyCode == LEFT) {
image(austria,0,0);
}
// if (keyCode == RIGHT) {
// frog1.frogx = frog1.frogx + 1;
// }
if(mousePressed){
tint(255,100);
image(australia,0,0);
}
}else{
tint(255);
image(drawing,0,0);
println(c+" "+letters.length());
/*
save("mlk-"+hour()+""+minute()+""+second()+".tif");
exit();
*/
noLoop();
}
}
boolean letterfit(){
letter.beginDraw();
letter.background(255,0);
letter.fill(0);
letter.textAlign(CENTER,CENTER);
letter.translate(fontsize/2,fontsize/2);
letter.rotate(random(TWO_PI));
letter.scale(fontsize/fontstart);
letter.textFont(font);
letter.smooth();
letter.text(letters.charAt(c),0,0);
letter.endDraw();
lettersquare.beginDraw();
You've most likely been hit by issue 1217, which prevents you from using an OpenGL PGraphics renderer if the main renderer is Java2D.
The link has a workaround, which basically involves changing the main renderer to OpenGL.
A newer version of PGraphics should give you a more detailed exception.