2014-02-07 61 views
0

我正在開發一個遊戲,您只能下載該jar,並且當您下載jar時,遊戲將下載新緩存。Java將圖像像素保存到數組中並繪製圖像

同時我想展示一個很好的背景,但是沒有加載鏈接,我想到了這個想法,但我不確定它是否可行。

每個圖像被加載並且通過像素正在繪製的像素,是有可能得到的所有像素的圖像,寬度,高度的顏色,然後打印值&然後把它們在陣列中例如:

public int[] imagePixels = new int[]{PUT PIXELS HERE...}; 

然後只需使用一種方法來繪製背景?這可能嗎?

是否有任何更好的解決方案,如將圖像打包成jar或其他東西?

說明:

你有一個形象,我想加載圖像和負載的每一個像素,我們從第0行開始,通過寬度&高度。

我想要收集每一個像素並將其保存到圖像中,這樣我就可以在不使用任何文件的情況下加載圖像,只需從陣列中繪製像素即可。

+0

請什麼的問題,爲更好地幫助越早張貼SSCCE或MCVE或MCTaRE – mKorbel

+0

加入微小的解釋。 – Artemkller545

+0

是的,它可能,但你必須加載圖像開始和訪問柵格數據,這也會給你的寬度和高度。 – MadProgrammer

回答

2

好的,所以你會遇到的基本問題。大多數圖像格式都會對圖像數據進行某種壓縮,它們也可能會將有關圖像的重要數據附加到文件末尾,例如顏色模型信息,這使得渲染它們時會產生一些困難。

您需要的是將圖像的「塊」寫入文件的某種方式,該文件可以輕鬆讀回但不會顯着增加文件大小。

我的測試圖像開始於301.68 kb,我的「chunk」文件格式最終爲1.42 mb,在我測試了一個最終爲5.63 mb的未壓縮文件之前,我並不特別滿意......想想我可以活着爲momement。

的例子使用內置的GZip壓縮,可以使用類似Apache-Commons-Compress

在紙面上,這是什麼基本上沒有得到更好的壓縮...

  • 讀取像素數據的塊,將其寫入以逗號分隔的String,其中每個值都是圖像中給定的像素值。該示例讀取每個塊的10%的文件。
  • 然後使用GZip壓縮對每個塊進行壓縮
  • 然後使用Base64編碼對得到的壓縮字節進行編碼。就個人而言,我寧願使用Apache-Commons-Encode,因爲它減少了對內部/私人課程的依賴。
  • 然後將生成的編碼String寫入File,並將新行放在行的末尾。

圖像反向加載...

  • 甲線從文件中讀出(Base64編碼String
  • String進行解碼(到壓縮byte陣列)
  • 然後byte陣列被解壓縮爲逗號分隔String
  • 的將逗號分隔String然後split,並將得到的像素數據繪製到背景緩衝區
  • 將得到的背景緩衝區更新爲屏幕。 ..

理論是一切都很好,實施是...有點混亂,對不起,可能有點整齊,但你明白了。

這個想法的意圖是不一次讀取整個Image.dat文件,而是將其保留在原來的位置並一次讀取一行......這可以實現延遲。現在

,在這個例子中,我使用了javax.swing.Timer注入一點停頓,說實話,這將是更好地使用SwingWorker ...但我敢肯定,你的想法...

SlowLoad

import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; 
import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.image.BufferedImage; 
import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.FileReader; 
import java.io.FileWriter; 
import java.io.IOException; 
import java.util.zip.GZIPInputStream; 
import java.util.zip.GZIPOutputStream; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class ConvertImage { 

    public static void main(String[] args) { 
     try { 
      exportImage(new File("/path/to/your/image.jpg"), new File("Image.dat")); 
     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } 
     new ConvertImage(); 
    } 

    public ConvertImage() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException ex) { 
       } catch (InstantiationException ex) { 
       } catch (IllegalAccessException ex) { 
       } catch (UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Test"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private int imgWidth = 0; 
     private int imgHeight = 0; 

     private BufferedReader br = null; 
     private BufferedImage imgBuffer; 
     private int offset; 

     public TestPane() { 
      try { 
       br = new BufferedReader(new FileReader(new File("Image.dat"))); 
       String header = br.readLine(); 
       String[] parts = header.split("x"); 
       imgWidth = Integer.parseInt(parts[0]); 
       imgHeight = Integer.parseInt(parts[1]); 

       imgBuffer = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_ARGB); 

       Timer timer = new Timer(1000, new ActionListener() { 
        @Override 
        public void actionPerformed(ActionEvent e) { 
         Graphics2D g2d = null; 
         try { 
          String text = br.readLine(); 
          if (text != null) { 
           // Decode the String back to a compressed byte array 
           byte[] decode = Base64.decode(text); 
           GZIPInputStream zis = null; 
           try { 
            // Decompress the byte array 
            zis = new GZIPInputStream(new ByteArrayInputStream(decode)); 
            // Build the text representation of the pixels 
            StringBuilder sb = new StringBuilder(128); 
            byte[] buffer = new byte[1024]; 
            int bytesRead = -1; 
            while ((bytesRead = zis.read(buffer)) > -1) { 
             sb.append(new String(buffer, 0, bytesRead, "UTF-8")); 
            } 
            // Split the pixels into individual packed ints 
            String[] elements = sb.toString().split(","); 
            g2d = imgBuffer.createGraphics(); 
            for (String element : elements) { 
             Point p = getPointAt(offset, imgWidth, imgHeight); 
             g2d.setColor(new Color(Integer.parseInt(element), true)); 
             g2d.drawLine(p.x, p.y, p.x, p.y); 
             offset++; 
            } 
            g2d.dispose(); 
            repaint(); 
           } catch (Exception exp) { 
            exp.printStackTrace(); 
           } 
          } else { 
           try { 
            br.close(); 
           } catch (Exception exp) { 
           } 
           ((Timer) e.getSource()).stop(); 
          } 
         } catch (IOException ex) { 
          ex.printStackTrace(); 
          try { 
           br.close(); 
          } catch (Exception exp) { 
          } 
          ((Timer) e.getSource()).stop(); 
         } finally { 
          try { 
           g2d.dispose(); 
          } catch (Exception exp) { 
          } 
         } 
        } 
       }); 
       timer.start(); 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
       try { 
        br.close(); 
       } catch (Exception e) { 
       } 
      } 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(imgWidth, imgHeight); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      int x = (getWidth() - imgBuffer.getWidth())/2; 
      int y = (getHeight() - imgBuffer.getHeight())/2; 
      g.drawImage(imgBuffer, x, y, this); 
     } 

    } 

    protected static void exportImage(File in, File out) throws IOException { 
     BufferedImage img = ImageIO.read(in); 
     int width = img.getWidth(); 
     int height = img.getHeight(); 

     // Calculate the total "length" of the image 
     int imageLength = width * height; 
     // Calculate the length of each line we will produce 
     // This is the number of pixels per chunk 
     int runLength = Math.round((width * height) * 0.1f); 

     // The place to write the output 
     BufferedWriter bw = null; 
     try { 
      bw = new BufferedWriter(new FileWriter(out)); 
      bw.write(width + "x" + height); 
      bw.newLine(); 

      // Start converting the pixels... 
      int offset = 0; 
      while (offset < imageLength) { 

       // Calculate the size of the next buffer run, we don't want to 
       // over run the end of the image 
       int bufferSize = runLength; 
       if (offset + bufferSize > imageLength) { 
        bufferSize = imageLength - offset; 
       } 

       // Create a buffer to store the pixel results in... 
       StringBuilder sb = new StringBuilder(bufferSize * 2); 
       for (int index = 0; index < bufferSize; index++) { 
        Point p = getPointAt(offset + index, width, height); 
        if (sb.length() > 0) { 
         sb.append(","); 
        } 
        // Store the pixel 
        sb.append(img.getRGB(p.x, p.y)); 
       } 
       // Write the contents to a compressed stream... 
       ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
       GZIPOutputStream zos = new GZIPOutputStream(baos); 
       zos.write(sb.toString().getBytes()); 
       zos.flush(); 
       zos.close(); 
       // Encode the compressed results to Base64 
       String encoded = Base64.encode(baos.toByteArray()); 
       // Write the content... 
       bw.write(encoded); 
       bw.newLine(); 

       // Jump to the next "chunk" 
       offset += bufferSize; 
      } 
     } catch (IOException exp) { 
      exp.printStackTrace(); 
     } finally { 
      try { 
       bw.close(); 
      } catch (Exception e) { 
      } 
     } 
    } 

    public static Point getPointAt(int index, int width, int height) { 
     Point p = new Point(); 
     p.y = index/width; 
     p.x = index % width; 
     return p; 
    } 

} 
相關問題