Java将图像像素保存为数组并绘制图像

我正在开发一个只下载jar的游戏,当你下载jar时,游戏将下载新的缓存。

同时我想展示一个漂亮的背景,没有加载链接,我想到了这个想法,我不确定它是否可能。

每个图像都被加载并逐个像素地绘制,是否可以获得图像,宽度,高度的所有像素颜色,然后打印值然后将它们放在一个数组中,例如:

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

然后简单地使用一种方法来绘制背景? 这可能吗?

有没有更好的解决方案,如将图像打包到jar子里?

说明:

你有一个图像,我想加载该图像并加载每个像素,我们从第0行开始,按宽度和高度。

我想收集每个像素并将其保存到图像中,这样我就可以在不使用任何文件的情况下加载图像,只需从数组中提取像素。

好的,你将面临的基本问题。 大多数图像格式都会对图像数据进行某种压缩,它们也可能会将关于图像的重要数据附加到文件的末尾,例如颜色模型信息,这会使它们在阅读时有些难以阅读。

您需要的是将图像的“块”写入文件的一些方法,该文件可以轻松读回但不会显着增加文件大小。

我的测试图像起始于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
  • 然后split逗号分隔的String ,并将得到的像素数据绘制到后备缓冲区
  • 生成的后备缓冲区更新到屏幕…

理论一切都很好,实施是……有点凌乱,对不起,可能会有点整洁,但你明白了。

这个想法的意图是不要一次读取整个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(px, py, px, py); 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(px, py)); } // 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(); py = index / width; px = index % width; return p; } }