Draw a pixel-by-pixel image

2

I'm trying to do a beast program but I can not do it.

I want to redraw a pixel-by-pixel image randomly, doing this with multiple threads.

I do not handle much of Java Swing, so I'm beating myself a lot.

I did some research before posting, which meant I should use BufferedImage for this.

I found an example of multi-processing that comes close to what I'd like to do. The difference is that it actually draws an image and does this line by line, I would like to upload it, but I could not adapt it to my need.

Here is the complete source: MultiProcessing - Image .

And here where he draws the image:

private class Runner extends Thread {
    double xmin, xmax, ymin, ymax;
    int maxIterations;
    int[] rgb;
    int[] palette;
    int width, height;
    int startRow, endRow;

    Runner(int startRow, int endRow) {
        this.startRow = startRow;
        this.endRow = endRow;
        width = image.getWidth();
        height = image.getHeight();
        rgb = new int[width];
        palette = new int[256];
        for (int i = 0; i < 256; i++)
            palette[i] = Color.getHSBColor(i / 255F, 1, 1).getRGB();
        xmin = -1.6744096740931858;
        xmax = -1.674409674093473;
        ymin = 4.716540768697223E-5;
        ymax = 4.716540790246652E-5;
        maxIterations = 10000;
    }

    public void run() {
        try {
            double x, y;
            double dx, dy;
            dx = (xmax - xmin) / (width - 1);
            dy = (ymax - ymin) / (height - 1);

            for (int row = startRow; row <= endRow; row++) { 
                y = ymax - dy * row;
                for (int col = 0; col < width; col++) {
                    x = xmin + dx * col;
                    int count = 0;
                    double xx = x;
                    double yy = y;
                    while (count < maxIterations && (xx * xx + yy * yy) < 4) {
                        count++;
                        double newxx = xx * xx - yy * yy + x;
                        yy = 2 * xx * yy + y;
                        xx = newxx;
                    }
                    if (count == maxIterations)
                        rgb[col] = 0;
                    else
                        rgb[col] = palette[count % palette.length];
                }
                if (!running) { 
                    return;
                }
                synchronized (image) {
                    image.setRGB(0, row, width, 1, rgb, 0, width);
                }
                display.repaint(0, row, width, 1); 
            }
        } finally {
            threadFinished();
        }
    }
}

How can I load my own image and redraw the pixels?

EDITED:

I tested the example below, but it does not draw pixel by pixel as the example, it looks like it is drawn in rectangles.

The way I did it. What could be wrong ?? I'm using JPanel and not Canvas.

private class Runner extends Thread {
    int width, height;
    Random randomi = new Random();
    Random randomj = new Random();
    Graphics g = image.getGraphics();

    Runner(int startRow, int endRow) {
        width = image.getWidth();
        height = image.getHeight();
    }

    public void run() {
        try {

            for (int xx = 0; xx < (width + height); xx++) {

                int i = randomi.nextInt(width);
                int j = randomj.nextInt(height);

                //System.out.println("i = " + i + "  j = " + j);
                //g.setColor(getColor(i, j));
                //g.drawLine(i, j, i, j);

                image.setRGB(i, j, getColor(i, j).getRGB());
                display.repaint(i, j, i, j);

                try {
                    Thread.sleep(5);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }    
            }    
        } finally {
            threadFinished();
        }
    }
}
    
asked by anonymous 09.10.2014 / 15:23

2 answers

1

It's far from a good code, but you can get an idea of how it works at least.

This code does

  • take the picture
  • then draw the image pixel by pixel randomly

In my test the image was 60 by 60, as it is random there are always points that the function did not fetch, so it did not paint the entire image on the screen ...

Test yourself and see if you can get ideas for what you want to do.

Code:

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;

import javax.swing.JFrame;
import org.openide.util.Exceptions;

public class PixelCanvas extends Canvas {

    private static final int WIDTH = 100;
    private static final int HEIGHT = 100;
    private static final Random random = new Random();
    private static final Random randomi = new Random();
    private static final Random randomj = new Random();
    private static BufferedImage image = null;

    public PixelCanvas() {
        getImg();
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        for (int xx = 0; xx < 10000; xx++) {

            int i = randomi.nextInt(image.getWidth());
            int j = randomj.nextInt(image.getHeight());
            g.setColor(getColor(i, j));
            g.drawLine(i, j, i, j);


            try {
                Thread.sleep(1);
            } catch (InterruptedException ex) {
                Exceptions.printStackTrace(ex);
            }

        }



    }

    private Color getColor(int i, int j) {
        return marchThroughImage(image, i, j);
    }

    public void getImg() {
        try {
            // get the BufferedImage, using the ImageIO class
            image = ImageIO.read(this.getClass().getResource("sms2.png"));
            System.out.println(" with" + image.getWidth());
            System.out.println(" height" + image.getHeight());
        } catch (IOException e) {
            System.err.println(e.getMessage());
        }
    }

    private Color marchThroughImage(BufferedImage image, int i, int j) {
        System.out.println("width, height: " + randomi + ", " + randomj);

        Color cor = new Color(image.getRGB(i, j));
        return cor;

    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setSize(WIDTH, HEIGHT);
        frame.add(new PixelCanvas());


        frame.setVisible(true);
    }
}

Image used:

Howitwas:

Attention: the image should be in the same place where the file is .java if you do not want there you have to change the path in this code:

 ImageIO.read(this.getClass().getResource("sms2.png"));

CODE EDITION

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;

import javax.swing.JFrame;
import javax.swing.JPanel;
import org.openide.util.Exceptions;

public class PixelCanvas extends Canvas {

    private static final int WIDTH = 100;
    private static final int HEIGHT = 100;
    private static BufferedImage image = null;
    private List<imgByPosicaoCor> listpixel = new ArrayList<>();

    public PixelCanvas() {
        getImg();
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);

        Collections.shuffle(listpixel);

        for (imgByPosicaoCor pixel : listpixel) {
            g.setColor(pixel.getCor());
            g.drawLine(pixel.getI(), pixel.getJ(), pixel.getI(), pixel.getJ());

            try {
                Thread.sleep(5);
            } catch (InterruptedException ex) {
                Exceptions.printStackTrace(ex);
            }

        }

    }

    public void getImg() {
        try {
            // get the BufferedImage, using the ImageIO class
            image = ImageIO.read(this.getClass().getResource("sms2.png"));
            int whith = image.getWidth();
            int heigth = image.getHeight();

            System.out.println(" with" + image.getWidth());
            System.out.println(" height" + image.getHeight());

            for (int i = 0; i < whith; i++) {
                for (int j = 0; j < heigth; j++) {
                    imgByPosicaoCor pixel = new imgByPosicaoCor(i, j, new Color(image.getRGB(i, j)));
                    listpixel.add(pixel);
                }
            }
            System.out.println("TOTAL NA LISTA" + listpixel.size());
        } catch (IOException e) {
            System.err.println(e.getMessage());
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setSize(WIDTH, HEIGHT);
        frame.add(new PixelCanvas());
        frame.setVisible(true);
    }

}

@Peter thanks for the tip, now the code is much better (compared to the first).

    
09.10.2014 / 18:09
2

I find it difficult to take pixels randomly because you strong chance to forget some. This is what happens in the solution given by jsantos.

The solution is to place all the pixel coordinates (x, y) in a table. If the image is 60x60, then you will have an array with 3600 entries. Then you mix the array. Then it would be enough to read the 'mixed' array and each time, you will be sure to have a new pixel. To "mix" an array in Java, you can use:

 Collections.shuffle(arrayList);
    
10.10.2014 / 03:53