Andy Vincent
Andy Vincent

Reputation: 83

Draw/display TV noise - black and white pixels blinking randomly on full screen

Could get a similar effect to this

https://www.youtube.com/watch?v=ubFq-wV3Eic

in Java? The goal is to have it as fast as possible - my mission is to find out if it's possible to burn pixels in my lcd this way. It may sound ridiculous, but I still need to find out.

Upvotes: 0

Views: 183

Answers (1)

VGR
VGR

Reputation: 44328

The links Spektre shared say that 16 levels of gray are enough, so you can generate a random value in the [0, 15] range, and multiply that to get a pixel value.

Since you’re concerned about speed, you can directly manipulate the DataBuffer of a BufferedImage to update the pixels. TYPE_USHORT_GRAY guarantees an image with a ComponentColorModel and ComponentSampleModel:

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GraphicsEnvironment;
import java.awt.GraphicsDevice;

import java.awt.image.BufferedImage;
import java.awt.image.DataBufferUShort;
import java.awt.image.ComponentSampleModel;

import java.awt.event.KeyEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

import java.util.Random;

public class NoiseGenerator
extends JPanel {
    private static final long serialVersionUID = 1;

    private static final int FPS = Math.max(1, Integer.getInteger("fps", 30));

    private final int width;
    private final int height;

    private final BufferedImage image;

    private final Random random = new Random();

    public NoiseGenerator(GraphicsDevice screen) {
        this(screen.getDefaultConfiguration().getBounds().getSize());
    }

    public NoiseGenerator(Dimension size) {
        this(size.width, size.height);
    }

    public NoiseGenerator(int width,
                          int height) {
        this.width = width;
        this.height = height;

        this.image = new BufferedImage(width, height,
            BufferedImage.TYPE_USHORT_GRAY);

        setFocusable(true);
    }

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

    private void generateFrame() {
        DataBufferUShort buffer = (DataBufferUShort)
            image.getRaster().getDataBuffer();
        short[] data = buffer.getData();

        ComponentSampleModel sampleModel = (ComponentSampleModel)
            image.getSampleModel();
        int stride = sampleModel.getScanlineStride();

        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                data[y * stride + x] = (short) (random.nextInt(16) * 4096);
            }
        }
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(image, 0, 0, this);
    }

    public void start() {
        Timer timer = new Timer(1000 / FPS, e -> generateFrame());
        timer.start();
    }

    public static void main(String[] args) {
        int screenNumber = args.length > 0 ? Integer.parseInt(args[0]) : -1;

        EventQueue.invokeLater(() -> {
            GraphicsEnvironment env =
                GraphicsEnvironment.getLocalGraphicsEnvironment();

            GraphicsDevice screen = env.getDefaultScreenDevice();

            if (screenNumber >= 0) {
                GraphicsDevice[] screens = env.getScreenDevices();
                if (screenNumber >= screens.length) {
                    System.err.println("Cannot detect screen " + screenNumber);
                    System.exit(2);
                }
                screen = screens[screenNumber];
            }

            NoiseGenerator generator = new NoiseGenerator(screen);
            generator.start();

            JFrame window = new JFrame("Noise Generator",
                screen.getDefaultConfiguration());
            window.setUndecorated(true);
            window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            generator.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent event) {
                    System.exit(0);
                }
            });
            generator.addKeyListener(new KeyAdapter() {
                @Override
                public void keyTyped(KeyEvent event) {
                    System.exit(0);
                }

                @Override
                public void keyPressed(KeyEvent event) {
                    if (event.getKeyCode() == KeyEvent.VK_ESCAPE) {
                        System.exit(0);
                    }
                }
            });
            window.getContentPane().add(generator);
            screen.setFullScreenWindow(window);
        });
    }
}

Upvotes: 3

Related Questions