【问题标题】:Java save image pixels into an array & draw imageJava将图像像素保存到数组中并绘制图像
【发布时间】:2014-02-08 09:16:24
【问题描述】:

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

同时我想展示一个漂亮的背景,而不是从链接中加载它,我想到了这个想法,但我不确定是否可行。

每个图像都已加载并逐像素绘制,是否可以获取图像的所有像素颜色、宽度、高度,然后打印这些值,然后将它们放入数组中,例如:

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

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

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

解释:

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

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

【问题讨论】:

  • 请问有什么问题,尽快发布 SSCCE 或 MCVE 或 MCTaRE 以获得更好的帮助
  • 添加了小解释。
  • 是的,有可能,但您必须先加载图像并访问栅格数据,这也会为您提供宽度和高度。
  • @MadProgrammer 我可以将它们全部打印(),然后将其复制/粘贴到一个数组中,这样当我再次执行应用程序时,我可以简单地将这些整数加载为像素?
  • 理论上是的,但我想你会发现这是一个难以置信的大量数据

标签: java swing


【解决方案1】:

好的,那么您将面临的基本问题。大多数图像格式都对图像数据进行某种压缩,它们还可能将有关图像的重要数据附加到文件的末尾,例如颜色模型信息,这使得在读取它们时渲染它们有些困难。

您需要通过某种方式将图像的“块”写入文件,以便轻松读回但不会显着增加文件大小。

我的测试图像从 301.68 kb 开始,我的“块”文件格式最终为 1.42 mb,直到我测试了一个最终为 5.63 mb 的未压缩文件时我才特别满意......我想我可以活下去暂时。

该示例使用内置的GZip 压缩,您可以通过使用Apache-Commons-Compress 之类的方式获得更好的压缩

在纸面上,这基本上是做什么的......

  • 读取像素数据块,将其写入以逗号分隔的String,其中每个值都是图像中的给定像素值。该示例读取每个块 10% 的文件。
  • 然后使用GZip 压缩对每个块进行压缩
  • 然后使用Base64 编码对生成的压缩字节进行编码。我个人更喜欢使用Apache-Commons-Encode,因为它减少了对内部/私人课程的依赖。
  • 然后将生成的编码String 写入File,并在行尾放置一个新行。

图片是反向加载的……

  • 从文件中读取一行(Base64 编码String
  • String 被解码(到压缩的byte 数组)
  • 然后将byte 数组解压缩为逗号分隔的String
  • 逗号分隔的Stringsplit,生成的像素数据被绘制到后备缓冲区
  • 生成的后备缓冲区更新到屏幕...

理论都很好,实现...有点混乱,抱歉,可能会更整洁一些,但你明白了。

这个想法的目的不是一次读取整个Image.dat 文件,而是将其留在原处并一次读取一行......这允许延迟。

现在,在这个例子中,我使用了javax.swing.Timer 来注入一点暂停,老实说,使用SwingWorker 会更好......但我相信你明白了。 ..

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

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多