我试图制作自己的,非常低效的图像复印机"。我是通过将原始图像中的像素读取到数组上然后重置default BufferedImage
中的相同像素来实现的。然后重新绘制框架。一排一排。
我尝试在每行像素存储在数组后重新绘制帧。但框架只更新一次;当它完成存储像素时。
我的代码到处都是,我可能做了很多错事。这是一项任务,我已经有一段时间了,我真的很感激一些帮助。
这是我的代码:
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.awt.*;
import javax.swing.JComponent;
import javax.swing.JFrame;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class pixelReloc extends JComponent {
static BufferedImage image,newImg;
static JFrame frame;
public void initialize() {
int width = getSize().width;
int height = getSize().height;
int pixels[];
int index = 0;
int j=0,i=0;
File f = new File("/path/to/file/images/shrek4life.jpg");
try{
image = ImageIO.read(f);
}catch(IOException e){}
System.out.println("checkpoint 1");
image = createResizedCopy(image,500,500,true);
newImg = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
pixels = new int[(image.getWidth()) * (image.getHeight())];
System.out.println("checkpoint 2");
for(i= 0; i < newImg.getWidth(); i++){
for(j = 0; j < newImg.getHeight(); j++){
//get the rgb color of the old image
Color c = new Color(image.getRGB(i, j));
int r = c.getRed();
int g = c.getGreen();
int b = c.getBlue();
pixels[index++] = (r<<16) | (g<<8) | b;
}
newImg.setRGB(0, 0, i, j, pixels, 0, 0);
frame.getContentPane().validate();
frame.getContentPane().repaint();
}
System.out.println("checkpoint 4");
//image.setRGB(0, 0, width, height, data, 0, width);
}
public BufferedImage createResizedCopy(BufferedImage originalImage,
int scaledWidth, int scaledHeight,
boolean preserveAlpha)
{
System.out.println("resizing...");
int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
Graphics2D g = scaledBI.createGraphics();
if (preserveAlpha) {
g.setComposite(AlphaComposite.Src);
}
g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null);
g.dispose();
return scaledBI;
}
public void paint(Graphics g) {
if (image == null)
initialize();
g.drawImage(newImg, 0, 0, this);
}
public static void main(String[] args) {
frame = new JFrame("P I X E L S");
frame.getContentPane().add(new pixelReloc ());
frame.setSize(500, 500);
frame.setLocation(100, 100);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
}
以下是我从以下位置读取像素的图片:
这就是它的出现方式:
该程序不会给出任何错误或任何错误。
答案 0 :(得分:1)
您问题的基本答案是,您正在阻止事件调度线程。
Swing既是单线程的,也不是线程安全的。这意味着您无法在EDT中运行长时间运行或阻止操作,并且您不应该更新UI或UI取决于EDT外部的某些状态。
我建议您首先查看Concurrency in Swing。
这留下了三个基本选项:
Thread
。这是有问题的,因为您需要确保UI所依赖的任何状态仅在EDT的上下文中更新SwingWorker
。这基本上是以前的选项,但内置管理允许您在EDT上publish
更新process
更新Timer
。在您的情况下,这可能不是最好的解决方案,但它是最简单的。例如
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new PixelReloc());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Pixel {
private int x, y;
private int color;
public Pixel(int x, int y, int color) {
this.x = x;
this.y = y;
this.color = color;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getColor() {
return color;
}
}
public class PixelReloc extends JComponent {
private BufferedImage image;
private BufferedImage newImg;
public PixelReloc() {
SwingWorker<Integer[], List<Pixel>> worker = new SwingWorker<Integer[], List<Pixel>>() {
Integer pixels[];
@Override
protected Integer[] doInBackground() throws Exception {
pixels = new Integer[image.getWidth() * image.getHeight()];
int index = 0;
List<Pixel> pixies = new ArrayList<>(image.getWidth());
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
int color = image.getRGB(x, y);
pixels[index++] = color;
pixies.add(new Pixel(x, y, color));
}
publish(new ArrayList<Pixel>(pixies));
pixies = new ArrayList<>(image.getWidth());
Thread.sleep(100);
}
return pixels;
}
@Override
protected void process(List<List<Pixel>> chunks) {
for (List<Pixel> pixels : chunks) {
for (Pixel pixel : pixels) {
newImg.setRGB(pixel.getX(), pixel.getY(), pixel.getColor());
}
}
repaint();
}
};
File f = new File("/Volumes/Big Fat Extension/Dropbox/MegaTokyo/chaotic_megatokyo_by_fredrin-d9k84so.jpg");
try {
image = ImageIO.read(f);
} catch (IOException e) {
}
System.out.println("checkpoint 1");
image = createResizedCopy(image, 200, 200, true);
newImg = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
worker.execute();
// pixels = new int[(image.getWidth()) * (image.getHeight())];
// System.out.println("checkpoint 2");
// for (i = 0; i < newImg.getWidth(); i++) {
// for (j = 0; j < newImg.getHeight(); j++) {
// //get the rgb color of the old image
// Color c = new Color(image.getRGB(i, j));
// int r = c.getRed();
// int g = c.getGreen();
// int b = c.getBlue();
// pixels[index++] = (r << 16) | (g << 8) | b;
// }
// }
// System.out.println("checkpoint 4");
//image.setRGB(0, 0, width, height, data, 0, width);
}
@Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(200, 200) : new Dimension(image.getWidth(), image.getHeight());
}
public BufferedImage createResizedCopy(BufferedImage originalImage,
int scaledWidth, int scaledHeight,
boolean preserveAlpha) {
System.out.println("resizing...");
Image scaled = originalImage.getScaledInstance(scaledWidth, -1, Image.SCALE_SMOOTH);
BufferedImage scaledBI = new BufferedImage(scaled.getWidth(null), scaled.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics2D g = scaledBI.createGraphics();
g.drawImage(scaled, 0, 0, null);
g.dispose();
return scaledBI;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(newImg, 0, 0, this);
}
}
}
Thread.sleep
中的SwingWorker
旨在做两件事:
process
来电和在我没有测试的情况下,图像会立即更新。
我还建议你花时间更好地了解Swing中的绘画过程,首先看看:
您使用的缩放机制(以及我实施的缩放机制)不是最佳解决方案。我建议看看:
获得一些更好的想法。
答案 1 :(得分:1)
你犯了几个错误,第一个使用0作为scansize
应该是图像的宽度,同样也应该使用宽度和高度而不是i
和j
。
newImg.setRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
另外还有一个错误,我会让你自己找到,在用上面的固定线看到图像后应该很明显。