image.setRGB()无法正常工作

时间:2017-12-02 07:46:15

标签: java swing bufferedimage

我试图制作自己的,非常低效的图像复印机"。我是通过将原始图像中的像素读取到数组上然后重置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);
   }
}

以下是我从以下位置读取像素的图片:

this is the original picture

这就是它的出现方式:

enter image description here

该程序不会给出任何错误或任何错误。

2 个答案:

答案 0 :(得分:1)

您问题的基本答案是,您正在阻止事件调度线程。

Swing既是单线程的,也不是线程安全的。这意味着您无法在EDT中运行长时间运行或阻止操作,并且您不应该更新UI或UI取决于EDT外部的某些状态。

我建议您首先查看Concurrency in Swing

这留下了三个基本选项:

  1. 使用其他Thread。这是有问题的,因为您需要确保UI所依赖的任何状态仅在EDT的上下文中更新
  2. 使用SwingWorker。这基本上是以前的选项,但内置管理允许您在EDT上publish更新process更新
  3. 使用Swing Timer。在您的情况下,这可能不是最好的解决方案,但它是最简单的。
  4. 例如

    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旨在做两件事:

    1. 为EDT提供时间来处理process来电和
    2. 的结果
    3. 减慢工作人员的速度,以便在UI上更新结果。
    4. 在我没有测试的情况下,图像会立即更新。

      我还建议你花时间更好地了解Swing中的绘画过程,首先看看:

      您使用的缩放机制(以及我实施的缩放机制)不是最佳解决方案。我建议看看:

      获得一些更好的想法。

答案 1 :(得分:1)

你犯了几个错误,第一个使用0作为scansize应该是图像的宽度,同样也应该使用宽度和高度而不是ij

newImg.setRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());

另外还有一个错误,我会让你自己找到,在用上面的固定线看到图像后应该很明显。

相关问题