我知道这是一个奇怪的问题,但我真的需要这个工作。
我有一个非常小的.png
图像,我需要导入("键入它")它到一个java源文件而不从文件系统读取。 (至少在程序运行时,我可以读取系统中的图像,其他虚拟应用程序要解析为二进制或者我不知道还有什么)。
换句话说,我确实需要代表图像的代码行,我只会在那里放一次(我不需要动态导入,我只需输入它并永远留在那里)。
图像需要存储为ImageIcon
,因为您可以输入字节数组,所以我不明白为什么不可能创建一个读取image,将字节数组打印到.txt文件,然后我可以将其复制并放入源文件中。我只是不知道如何准确地完成这些步骤。
注意: 我知道 是某个人应该或应该做的事情,它是针对特定项目的,我需要这样做,其原因超出了我的范围。< / p>
注2: 我不能使用任何外部库或依赖。
答案 0 :(得分:2)
仅供参考,与此相似的问题可能有助于提供更深入的解释/答案here和here。
我的答案是解决你的问题,
我确实需要代表图像的代码行,我只会在那里放一次(我不需要动态导入,只需输入它并永远留在那里)。
是使用Base64并以该确定的格式读取图像代码。
例如,以下代码生成一个简单的JFrame,将base64字符串显示为图像图标:
import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.Scanner;
import javax.imageio.ImageIO;
import javax.swing.*;
public class App extends JFrame {
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
App app = new App();
app.setVisible(true);
}
});
}
public App() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel photo = new JLabel();
photo.setVerticalTextPosition(JLabel.BOTTOM);
photo.setHorizontalTextPosition(JLabel.CENTER);
photo.setHorizontalAlignment(JLabel.CENTER);
photo.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
add(photo, BorderLayout.CENTER);
setSize(200, 100);
setLocationRelativeTo(null);
// Ex. stackoverflow.ico (then converted to png for this example)
String imgBase64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAJ+SURBVFhH7ZXbS1RRFMb7Y5qHiu4PEfUQRS9B9FBEBBVFT70WvQQhmJpdLUkMS0mNikDKlKxIDR+iCz3YmJgWCZmlKWPNPvd9vvZeZ8+ZS3NmzlzoYn2wHmatYe/f2etbey/Ab9Z/gPkFwCcGoTVtB/8yojL5VTYA1/gGdnIV4hULoV3cBFefU5XcKusJ2G96BECEIPT2A4LKUZVglQYgNuBTo+qHJ7P3PAHIMB+dUtlglQRgdh1HvHIx7Jc3VEbI5dCvH1QQEdjRblXIrqIB3NhHsDNr/a81Oo4AlubVhB+0+s1erWop+OdhymdTSSfgfp+C3rLbh9AatoB/fU81Pv0OrGYl5VndBrhslvKZKt2E3KFeJ8zHalbAHrpPJWfksZ/XW/eSZzJVMIA92CkW7qVep8oZfuiPodzU7KkScDas/nqVE6aUuQwVBODN+mpaTLuwEdbTFsolxGc+QGvc6m+oN++COzcJ/eYhsOpl6WZVKghAjpxcNLGBDFa9HGZ3hd972AaMO0eT9dNr4IwNgM+Oe/UMFeUB/inqbSJGMAkTocvHGe2n9tivbiN+YgnYufV0CkEqyYQum4H15BLY2XUpIKI9YgStZ61wxl/kfRdCAzhv+4QB74rxGvvZzcJs9ut70K7sSAOxBhrVH4IVGkC/tie5uLhc9Ks7qffyqPnkEEFIyRfR6DhMl5RrximXS+EB2vbTjKd+YVpULoJ2eRuMzmOwnrfTRIRRYR4Q5pJut6Nd4vKpFZfLPrBabywzQ7YsjAIBmttuUYSRG5sQF9EDmH119BCR87UY1fKtUxaAXCobQLZjzhUJzR+AYvX3A5QrgvTnAvwq/esAwA/q0/BiaJrlDgAAAABJRU5ErkJggg==";
String data = imgBase64.substring(imgBase64.indexOf(",") + 1);
ByteArrayInputStream stream = new ByteArrayInputStream(Base64.getDecoder().decode(data.getBytes()));
BufferedImage image = null;
try {
image = ImageIO.read(stream);
} catch (IOException e) {
e.printStackTrace();
}
ImageIcon imgIcon = new ImageIcon(image.getScaledInstance(32, 32, 0));
photographLabel.setIcon(imgIcon);
}
}
此代码不使用任何外部库并完成您所请求的大部分任务 - 因此,要完全完成答案,请按照以下方式从控制台读取该输入(也就是用户键入控制台)。注意:以下部分代码将在带有ByteArrayInputStream流对象声明的行之后添加。
Scanner sc = new Scanner(System.in);
System.out.println("Type .png input (base64): ");
StringBuilder sb = new StringBuilder();
while (sc.hasNext())
sb.append(sc.next());
String data = sb.toString();
这基本上会取代&#39; String imgBase64&#39;和&#39;字符串数据&#39;来自早期的示例代码段。
希望这能回答您的问题,请提供反馈意见以便进一步澄清或标记为答案;)
干杯
<强> 编辑: 强> 对于从和图像到字符串,图像 - &gt;串: 注意:我在本例中使用File,您也可以选择查看可在ImageIO.read()方法中使用的URL或Stream选项。 另请注意:try-with-resources是java 1.7+(如果早期版本需要,可以很容易地恢复到try-catch)
让我们说你从某个地方加载了一个ImageIcon对象,URL / stream / file,你可以命名它。在我的示例中,我将使用本地文件:
ImageIcon icon = new ImageIcon("C:\\Users\\Nick\\Desktop\\favicon.png");
现在拿这个图像图标并获取你问的base64字符串?以下是如何操作/如何操作的方法(使用已加载的ImageIcon图标对象):
try (ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageOutputStream ios = ImageIO.createImageOutputStream(os)) {
BufferedImage img = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.BITMASK);
Graphics g = img.createGraphics();
icon.paintIcon(null, g, 0, 0);
g.dispose();
ImageIO.write(img, "png", ios);
byte[] bytes = os.toByteArray();
String data = Base64.getEncoder().encodeToString(bytes);
System.out.println(data);
} catch (IOException e) {
e.printStackTrace();
}
我想指出的是BufferedImage.BITMASK&#39; BufferedImage.BITMASK&#39;正在使用的旗帜。这很容易混淆或切换,导致解码/编码的字符串值不一致。
有关ImageIcon类的更多信息,请访问:https://docs.oracle.com/javase/7/docs/api/javax/swing/ImageIcon.html
使用此工具将stackoverflow图标转换为base64 https://www.base64-image.de/
答案 1 :(得分:1)
以netpbm格式“输入”您的图片,然后将其转换为PNG或其他任何内容。
例如,我正在使用SE降价编辑器来创建此图像:
P3 3 3 255
0 0 0 0 0 0 0 0 0
0 0 0 0 255 0 0 0 0
0 0 0 0 0 0 0 0 0
这是一个由黑色框架包围的单个绿色像素的3x3图像。
将其另存为“image.ppm”。 使用ImageMagick将其转换为PNG(将其放大20倍,以便您可以看到它):
magick convert image.ppm -sample 2000% image.png
(这里你将image.ppm转换为你的ImageIcon格式)
显示它:
你不想直接“输入”PNG格式,因为它只是奇怪:
data:image/png;base64,
UDMgMyAzIDI1NQogICAgMCAwIDAgIDAgMCAwICAgIDAgMCAwIAogICAgMCAwIDAgIDAgMjU1IDAg
IDAgMCAwCiAgICAwIDAgMCAgMCAwIDAgICAgMCAwIDAK
如果你开始使用PNG并想要“键入”它,你可以再次使用ImageMagick,但是在另一个方向。
例如,拍摄你的头像并将其转换为mark.ppm
magick convert 8ede7*.png -compress none mark.ppm
cat mark.ppm
P3 32 32 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 232 136 234 255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 229 119
231 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
255 255 255 255 239 174 241 255 255 255 255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255 255 255 232 136 234 207 1 211 255 255
255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
255 255 255 255 207 1 211 229 119 231 255 255 255 255 255 255 255 255
[...]
如果您可以处理“C”样式标题,可以尝试
magick 8ede7*.png mark.gif
magick mark.gif mark.h
cat mark.h
mark.h (GIF).
*/
static unsigned char
MagickImage[] =
{
0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x20, 0x00, 0x20, 0x00, 0xF3, 0x0E,
0x00, 0xCF, 0x01, 0xD3, 0xD7, 0x30, 0xDB, 0xD9, 0x38, 0xDC, 0xDA, 0x40,
0xDD, 0xDC, 0x49, 0xDF, 0xE2, 0x67, 0xE4, 0xE5, 0x77, 0xE7, 0xE8, 0x88,
0xEA, 0xEF, 0xAE, 0xF1, 0xF1, 0xB6, 0xF2, 0xF3, 0xBF, 0xF4, 0xF4, 0xC7,
[...]