0

The following code should take an image, and pixelate the areas according to the most average color, but I have to show how it works during the process not all at once, so I am trying to reattach and repaint each time but it only displays a white popup after the first image.

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.swing.JLabel;
import javax.swing.JFrame;
import javax.swing.ImageIcon;
import java.awt.Toolkit;
import java.awt.Dimension;
import javax.imageio.ImageIO;
import java.util.concurrent.TimeUnit;

class ImageUtil {
    static JFrame f;
    static Dimension screenSize;
    static JLabel lbl;

    public static BufferedImage pixelate(BufferedImage imageToPixelate, int pixelSize) {
        BufferedImage pixelateImage = new BufferedImage(
                imageToPixelate.getWidth(),
                imageToPixelate.getHeight(),
                imageToPixelate.getType());

        for (int y = 0; y < imageToPixelate.getHeight(); y += pixelSize) {
            for (int x = 0; x < imageToPixelate.getWidth(); x += pixelSize) {
                BufferedImage croppedImage = getCroppedImage(imageToPixelate, x, y, pixelSize, pixelSize);
                Color dominantColor = getDominantColor(croppedImage);
                for (int yd = y; (yd < y + pixelSize) && (yd < pixelateImage.getHeight()); yd++) {
                    for (int xd = x; (xd < x + pixelSize) && (xd < pixelateImage.getWidth()); xd++) {
                        pixelateImage.setRGB(xd, yd, dominantColor.getRGB());
                        ImageIcon img = new ImageIcon(pixelateImage);
                        display(img);
                    }
                }
            }
        }

        return pixelateImage;
    }

    public static BufferedImage getCroppedImage(BufferedImage image, int startx, int starty, int width, int height) {
        if (startx < 0)
            startx = 0;
        if (starty < 0)
            starty = 0;
        if (startx > image.getWidth())
            startx = image.getWidth();
        if (starty > image.getHeight())
            starty = image.getHeight();
        if (startx + width > image.getWidth())
            width = image.getWidth() - startx;
        if (starty + height > image.getHeight())
            height = image.getHeight() - starty;
        return image.getSubimage(startx, starty, width, height);
    }

    public static Color getDominantColor(BufferedImage image) {
        int sumR = 0, sumB = 0, sumG = 0, sum2 = 0;
        int color = 0;
        for (int x = 0; x < image.getWidth(); x++) {
            for (int y = 0; y < image.getHeight(); y++) {
                color = image.getRGB(x, y);
                Color c = new Color(color);
                sumR += c.getRed();
                sumB += c.getBlue();
                sumG += c.getGreen();
                sum2++;
            }
        }
        return new Color(sumR / sum2, sumG / sum2, sumB / sum2);
    }

    public static void display(ImageIcon image) {
        f.remove(lbl);
        lbl = new JLabel(image);
        f.getContentPane().add(lbl);
        f.repaint();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {

        String filename = args[0];
        int PIX_SIZE = Integer.parseInt(args[1]);

        f = new JFrame();
        screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        f.setUndecorated(true); // removes the surrounding border

        int x = (screenSize.width - f.getSize().width) / 2;
        int y = (screenSize.height - f.getSize().height) / 2;
        f.setLocation(x, y);

        try {
            BufferedImage img = ImageIO.read(new File("download.jpg"));
            ImageIcon image = new ImageIcon(img);
            lbl = new JLabel(image);
            f.setSize(image.getIconWidth(), image.getIconHeight());
            f.getContentPane().add(lbl);
            f.setVisible(true);
            BufferedImage imagePixelated = ImageUtil.pixelate(img, PIX_SIZE);
            // ImageIO.write(imagePixelated, "jpg", new File("pixelated.jpg"));
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

The dispay function is supposed to repaint and is called inside the pixelate function.

  • 2
    This seems to be a case of blocking the event dispatch thread (EDT), i.e. your code blocks actual updates to the UI until it is done. Use a SwingWorker instead to do the pixelation in a separate thread. – Thomas Nov 30 '21 at 10:56
  • 2
    it is also not the best idea to create a new `JLabel` and continuously add it to the frame (not even revalidating it - the new label will have zero size, ergo not be displayed even after the EDT is unblocked) - as commented above, use `SwingWorker` and just change the image assigned to the label. – user16320675 Nov 30 '21 at 11:34
  • Check out [Bubble Sort Animation](https://stackoverflow.com/questions/64196198/bubble-sort-animation) for an example of using a SwingWorker to achieve animation. – camickr Nov 30 '21 at 14:43

0 Answers0