6

After scouring the internet for days, I found a Question that seemed to address my goal. (I'm trying to draw/edit an individual pixel in an image, and render it.) In said question, The ask-er requested code for a Black BufferedImage. The top Answer provided that code, and appears to work beautifully, until you try to change it to something other than black. Here's the Code:

package myProjectPackage;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.*;

public class Copypasta {

public static JFrame frame;
BufferedImage img;
public static int WIDTH = 500;
public static int HEIGHT = 500;

public Copypasta() {
}

public static void main(String[] a){

    Copypasta t=new Copypasta();

    frame = new JFrame("WINDOW");
    frame.setVisible(true);

    t.start();
    frame.add(new JLabel(new ImageIcon(t.getImage())));

    frame.pack();
    // Better to DISPOSE than EXIT
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}

public Image getImage() {
    return img;
}

public void start(){

    img = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
    int[] pixels = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();
    boolean running=true;
    while(running){
        BufferStrategy bs=frame.getBufferStrategy();
        if(bs==null){
            frame.createBufferStrategy(4);
            return;
        }
        for (int i = 0; i < WIDTH * HEIGHT; i++)
            pixels[i] = 0; //This is what i've been trying to change.

        Graphics g= bs.getDrawGraphics();
        g.drawImage(img, 0, 0, WIDTH, HEIGHT, null);
        g.dispose();
        bs.show();

    }
}
}

I Apologize for the indentation errors. I promise it looks right in the editor.

When set to BufferedImage type ARGB, the black background disappears, causing me to believe that the start function isn't drawing to the Image at all, or the drawn image is not being drawn on the screen. Either way, There is something that I don't understand. If you have the time, I would appreciate some help Identifying What is going wrong, if not an explanation of why. Thank you all, -Navi.

Link to Original Question: drawing your own buffered image on frame

Community
  • 1
  • 1
Navigatron
  • 416
  • 1
  • 4
  • 12
  • I "think" the problem is because the `JFrame` has "stuff" already on it which is preventing the whatever is been painted to the `BufferStrategy` from been made visible. Can you explain why you need to use `BufferStrategy` to do this...Also, the `pixels` array is not a "live" copy of the pixel data, meaning that modifying won't change the underlying image...some more information about what you are actually trying to achieve might allow us to provide other solutions for you – MadProgrammer Apr 23 '14 at 03:52
  • Thank you very much. I don't need to use Bufferstrategy at all, It is simply what was in the example. Im rather new to java, I used javascript for unity3d, but decided I want to take it up a level. My current goal is Editing the pixels in a window. If you have any tips/tricks, any method at all would be great. – Navigatron Apr 23 '14 at 19:41

1 Answers1

7

Several things jump out, the use of BufferStrategy is probably overkill. Unless you absolutely must have control over the paint process, you really don't need it. Using a BufferStrategy also precludes the use of Swing based components which might or might not be an issue.

Trying to manipulate the pixel data directly is probably also a little overkill, instead you can use BufferedImage.setRGB(int, int, int), which allows you to set the color of the pixel at the specified x/y position, for example...

img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < img.getWidth(); x++) {
    for (int y = 0; y < img.getHeight(); y++) {
        img.setRGB(x, y, Color.RED.getRGB());
    }
}

But, even this is a little overkill, the same thing can be achieved by using the provided 2D Graphics API...

Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.RED);
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
g2d.dispose();

Which you will probably find is faster (not just from a coding point of view).

Take a look at:

For more details...

Working example...

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestImage1 {

    public static void main(String[] args) {
        new TestImage1();
    }

    public TestImage1() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage img;

        public TestPane() {
            img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
            //for (int x = 0; x < img.getWidth(); x++) {
            //    for (int y = 0; y < img.getHeight(); y++) {
            //        img.setRGB(x, y, Color.RED.getRGB());
            //    }
            //}

            Graphics2D g2d = img.createGraphics();
            g2d.setColor(Color.RED);
            g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
            g2d.dispose();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.drawImage(img, 0, 0, this);
            g2d.dispose();
        }
    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Great answer, thanks. I beleive I remember reading somewhere about speed and setRGB, but im sure it wont slow me down that bad. Im trying to edit the pixels so as to draw some 3d graphics eventualy, I have all the formulas for 3d graphics, but no way to put that data on the screen. That's why im asking how to edit pixels. The 2d graphics API is an exellent Idea. Ill go check if it can draw triangles now... Thanks Again! – Navigatron Apr 25 '14 at 18:32