Reputation: 83
I know this is a strange question but I really need this to work.
I have a very small .png
image, I need to import ("type it") it into a java source file without reading from the file system. (At least not when the program runs, I can read the image on the system with other dummy applications to parse is in binary or I don't know what else).
In other words, I literally need lines of code that represent the image, which I will only put there once (I don't need to import on the fly, I just type it and leave it there forever).
The image needs to be stored as an ImageIcon
and, since you can type out byte arrays, I don't see why it wouldn't be possible to create a little jar that reads the image, prints the byte array to a .txt file, that I can then copy and put into the source file. I just don't know how to do these steps exactly.
NOTE: I know this is not something one would or should do, it's for a specific project and I need it done this way, the reasons go beyond me.
NOTE 2: I cannot use any external lib or dependency.
Upvotes: 3
Views: 3154
Reputation: 526
FYI, similar questions to this one that may help provide a more indepth explanation/answer are here and here.
My answer to solve your question about,
I literally need lines of code that represent the image, which I will only put there once (I don't need to import on the fly, I just type it and leave it there forever).
is to use Base64 and read the image code in that per-determined format.
For example, the following code makes a simple JFrame to display a base64 string as an image icon:
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);
}
}
This code doesn't use any external libraries and accomplishes most of the task you have requested - so to fully complete the answer, here's how I'd go about reading that input from the console (aka a user types into the console). Note: the following portion of code would be added after the line with the ByteArrayInputStream stream object declaration.
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();
This would essentially replace the two lines of the 'String imgBase64' and the 'String data' from the earlier example snippet.
Hope this answers your question, please provide feedback for further clarification or mark as an answer ;)
Cheers
Edit: For going from and image to string, image -> string: Note: I am using a File for this example, you may also choose to look into the URL or Stream options that could be used alternatively in the ImageIO.read() method. Also note: the try-with-resources is java 1.7+ (could revert easily to try-catch if needed for earlier versions)
Lets say you loaded up an ImageIcon object from somewhere, URL/stream/file, you name it. In my example, I'll use a local file:
ImageIcon icon = new ImageIcon("C:\\Users\\Nick\\Desktop\\favicon.png");
Now take this image icon and get the base64 string you ask? Here's one way how to do it / how I did it (using the already loaded ImageIcon icon object):
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();
}
One thing I'd like to point out is the 'BufferedImage.BITMASK' flag being used. This could easily get mixed up or switched and cause inconsistencies with the decoded/encoded string value(s).
More about the ImageIcon class here: https://docs.oracle.com/javase/7/docs/api/javax/swing/ImageIcon.html
Used this tool for converting stackoverflow icon to base64 https://www.base64-image.de/
Upvotes: 3
Reputation: 12465
"Type" your image in netpbm format, then convert it to PNG or whatever.
For example, I'm using the SE markdown editor to create this image:
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
It's a 3x3 image of a single green pixel surrounded by a black frame.
Save it out as "image.ppm". Use ImageMagick to convert it to PNG (enlarging it 20x so you can see it):
magick convert image.ppm -sample 2000% image.png
(Here you'd convert the image.ppm to your ImageIcon format instead)
Display it:
You don't want to "type" directly into the PNG format because it'd just be weird:
data:image/png;base64,
UDMgMyAzIDI1NQogICAgMCAwIDAgIDAgMCAwICAgIDAgMCAwIAogICAgMCAwIDAgIDAgMjU1IDAg
IDAgMCAwCiAgICAwIDAgMCAgMCAwIDAgICAgMCAwIDAK
If you are starting with a PNG and want to "type" it, again you can use ImageMagick, but in the other direction.
For example, taking your avatar and converting it to 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
[...]
If you can deal with "C" style headers, you could try
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,
[...]
Upvotes: 1