2017-12-02 24 views
0

私は非常に非効率的な "イメージコピー"を作成しようとしています。私は元の画像からピクセルを配列に読み込んだ後、同じピクセルをリセットすることでそれをやっています。default BufferedImage。そしてフレームを再描画します。行ごとにimage.setRGB()が意図したとおりに動作しない

ピクセルの各行が配列に格納された後にフレームを再描画しようとしています。しかし、フレームは一度しか更新されません。画素の格納が終了したときに終了する。

私のコードはどこにでもあり、おそらく間違っています。これは譲渡のためのもので、私はしばらくそれを行っており、本当に助けに感謝します。ここで

は私のコードです:ここでは

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

プログラムでは何かエラーや何かを与える。

+0

* "フレームは一度しか更新されず、ピクセルの保存が完了すると" * - イベントディスパッチスレッドをブロックしています – MadProgrammer

+0

こんにちは@MadProgrammer、それについて詳しく説明できますか?私は一般的にスレッドに少し新しいです。 –

答えて

1

質問に対する基本的な答えは、イベントディスパッチスレッドをブロックすることです。

スイングはシングルスレッドであり、スレッドセーフではありません。これは、EDT内から長時間の実行やブロッキング操作を実行できないことを意味し、UIを更新したり、EDTの外部からUIが依存している状態を更新したりしないでください。

まず、Concurrency in Swingをご覧ください。

これは、3つの基本的なオプションで葉:

  1. Threadを使用してください。これは、UIが依存する状態がEDTのコンテキスト内からのみ更新されるようにする必要があるため、問題があります
  2. SwingWorkerを使用します。これは基本的に前のオプションですが、のEDTにの更新を許可する管理機能が組み込まれています
  3. スイングTimerを使用してください。あなたの場合、これはおそらく最善の解決策ではありませんが、最も簡単です。 SwingWorkerThread.sleepは、二つのことを行うことを意図している例

    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); 
         } 
    
        } 
    } 
    

    については

  1. processコールと
  2. からの結果を処理するためにEDTのための時間を与え結果をUIで更新できるように、作業者を遅らせる。

私のテストでは、イメージはほとんど即座に更新されました。

私も見たことから始め、あなたがより良いスイングで塗装プロセスを理解するための時間を取るお勧めします。

を使用していたスケーリングメカニズムを(そして私が実装したもの)は最良の解決策ではありません。いくつかのより良いアイデアを

:私は見て持つことをお勧めします。

+0

オケイ - ダウン投票の理由を強調したい人は誰ですか?回答はどのようにしてOP問題の解決策を提供しないのですか?どのように改善できるか?どの情報が欠落していましたか? – MadProgrammer

+0

私はちょうどいくつかの編集と適切なコードインデントが必要だと思います。あなたのインポートはフォーマットされていません。答える時間をとっていただきありがとうございます、私はそれを見てみましょう。 –

+0

あなたの答えは一般的には有用かもしれませんが、OPには問題はありません。彼のコードにはいくつかのバグがあります。 – Oleg

1

あなたは2つの間違いを犯しました。最初は0をscansizeとして使用しています。これは画像の幅にする必要があります。同じ行にはijではなく幅と高さを使用してください。

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

私は自分で見つけるようになる一つの他の間違いがありますが、上記の固定回線で画像を見た後、それは明らかです。

+0

ええ。それは横に出てくる。しかし、バグの修正をありがとう。 –

+0

forループを前後に反転しました。それはそれを世話しました。 –

関連する問題