From byte array to image java - java

I need to read a image in java ad convert to byte array for postgreSQL.
I have tried the following code, is it ok?
import java.nio.file.Files;
import java.nio.file.Path;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Arrays;
public class ConvertImage {
public static void main(String[] args) throws IOException {
Path filepath = Paths.get("image.jpg");
byte[] byteContent = Files.readAllBytes(filepath);
System.out.println(Arrays.toString(byteContent));
}
}
And how to do the way back, form byte array to image?

You can create a ByteArrayInputStream from the byte array and supply it to ImageIO as follows:
ByteArrayInputStream is = new ByteArrayInputStream( byteContent );
BufferedImage image = ImageIO.read( is );

Related

How to convert image to qr code using java?

If we search image to qr code, there are many websites which converts image to qr code online.
But how can I do this in java?
I am using the following code for converting text to qr code:-
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.NotFoundException;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
public class MyQr {
public static void createQR(String data, String path,
String charset, Map hashMap,
int height, int width)
throws WriterException, IOException
{
BitMatrix matrix = new MultiFormatWriter().encode(
new String(data.getBytes(charset), charset),
BarcodeFormat.QR_CODE, width, height);
MatrixToImageWriter.writeToFile(
matrix,
path.substring(path.lastIndexOf('.') + 1),
new File(path));
}
public static void main(String[] args)
throws WriterException, IOException,
NotFoundException
{
String data = "TEXT IN QR CODE";
String path = "image.png";
String charset = "UTF-8";
Map<EncodeHintType, ErrorCorrectionLevel> hashMap
= new HashMap<EncodeHintType,
ErrorCorrectionLevel>();
hashMap.put(EncodeHintType.ERROR_CORRECTION,
ErrorCorrectionLevel.L);
createQR(data, path, charset, hashMap, 200, 200);
}
}
But how to encode a image in qr code?
Images are too big to be embedded into QR codes (with the exception of tiny icons). So instead, the image is put on a publicly accessible server and the URL of the image is embedded in the QR code.
Thus you need access to a server that can fulfill this. That's probably the bigger part of what you are about to implement.
Otherwise, it's straight-forward:
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
public class MyQr {
/**
* Uploads the image to a server and returns to image URL.
* #param imagePath path to the image
* #return image URL
*/
public static URL uploadImage(String imagePath)
{
// implement a solution to put an image on a public server
try {
return new URL("https://yourserver/some_path/image.jpg");
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
public static void createQR(String payloadImagePath, String qrCodeImagePath,
Map<EncodeHintType, ?> hints, int height, int width)
throws WriterException, IOException
{
URL imageURL = uploadImage(payloadImagePath);
BitMatrix matrix = new MultiFormatWriter().encode(
imageURL.toString(), BarcodeFormat.QR_CODE, width, height, hints);
String imageFormat = qrCodeImagePath.substring(qrCodeImagePath.lastIndexOf('.') + 1);
MatrixToImageWriter.writeToPath(matrix, imageFormat, Path.of(qrCodeImagePath));
}
public static void main(String[] args)
throws WriterException, IOException
{
String payloadImagePath = "embed_this.jpg";
String qrCodeImagePath = "qrcode.png";
Map<EncodeHintType, ErrorCorrectionLevel> hints = new HashMap<>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
createQR(payloadImagePath, qrCodeImagePath, hints, 200, 200);
}
}
BTW: The below code (from your code sample) is non-sense. At best, it creates a copy of the string, which is unnecessary. At worst, it corrupts all characters not supported by charset. I don't think you intended either one.
new String(data.getBytes(charset), charset)
I assume that you mean that you want to add an image (e.g. logo) to the QR Code.
This is generally done by overlaying a small image on top of the QR Code, usually in the center. QR Codes are still readable when a small portion is obscured, especially in the center.
You can use MatrixToImageWriter.toBufferedImage(matrix) to get a BufferedImage containing the QR Code image, and then use Java image methods to overlay the image. See, for example, overlay images in java

BufferUnderflowException while trying to read an Int from a binary file in Java

I am trying to read 4 bytes which represent an int, located at byte position 64 in a binary file.
This is what I have tried:
package testbinaryfile2;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class TestBinaryFile2 {
public static void main(String[] args) throws IOException {
FileChannel fc;
ByteBuffer indexField = ByteBuffer.allocate(4);
fc = (FileChannel.open(Paths.get("myBinaryFile.bin"), StandardOpenOption.READ));
fc.position(64);
fc.read(indexField);
System.out.println(indexField.getInt());
}
}
This is the error I get:
run:
Exception in thread "main" java.nio.BufferUnderflowException
at java.nio.Buffer.nextGetIndex(Buffer.java:509)
at java.nio.HeapByteBuffer.getInt(HeapByteBuffer.java:373)
at testbinaryfile2.TestBinaryFile2.main(TestBinaryFile2.java:30)
/home/user/.cache/netbeans/11.3/executor-snippets/run.xml:111: The following error occurred while executing this line:
/home/user/.cache/netbeans/11.3/executor-snippets/run.xml:94: Java returned: 1
BUILD FAILED (total time: 0 seconds)
After read indexField is pointing to its end, so it is necessary to use .rewind() method before getting the int.
This code works:
package testbinaryfile2;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class TestBinaryFile2 {
public static void main(String[] args) throws IOException {
FileChannel fc;
ByteBuffer indexField = ByteBuffer.allocate(4);
fc = (FileChannel.open(Paths.get("myBinaryFile.bin"), StandardOpenOption.READ));
fc.position(64);
fc.read(indexField);
indexField.rewind(); // <-- ADD THIS
System.out.println(indexField.getInt());
}
}
Additionally I got a suggestion to use mapped buffer:
public static void main(String[] args) throws Exception {
FileChannel fc = (FileChannel.open(Paths.get("myBinaryFile.bin"), StandardOpenOption.READ));
MappedByteBuffer buffer = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
buffer.position(64);
System.out.println(buffer.getInt());
}
But I am wondering if fc.map reads the whole file at once and uses as much memory as the size of the file.

Unzip protected archive to a byte array

I'm given a zip archive that is protected by a password,
And I need to write a piece of code that would decrypt the archive to a byte [] without saving intermediate results to a file system,
So far I've found that standard java JDK does not allow to perform operations like this,
And also that there is a library Zip4j, but it doesn't seem to allow decryption of file directly to byte[] but it writes result to a file system instead,
If would really really appreciate any help,
Thanks
You can do this with zip4j. Here is an example from the documentation:
import net.lingala.zip4j.io.inputstream.ZipInputStream;
import net.lingala.zip4j.model.LocalFileHeader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class ZipInputStreamExample {
public void extractWithZipInputStream(File zipFile, char[] password) throws IOException {
LocalFileHeader localFileHeader;
int readLen;
byte[] readBuffer = new byte[4096];
try (ZipInputStream zipInputStream = new ZipInputStream(fileInputStream, password)) {
while ((localFileHeader = zipInputStream.getNextEntry()) != null) {
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
while ((readLen = zipInputStream.read(readBuffer)) != -1) {
outputStream.write(readBuffer, 0, readLen);
}
}
}
}
}
}
You can then do outputStream.toByteArray() on each entry to get the byte content of that entry in the zip.

LWJGL / STB: Inconsistency when running in IntelliJ vs. running over Console

I have a problem when using LWJGL and STB TrueType in IntelliJ.
When I now try to create a bitmap and put everything in Main ('Code 1' below), everything works fine.
As soon as I try to split this up and create an OpenGL context (If I split it up without creating an OpenGL context it works fine as well), the loaded font gets corrupted somehow and either the program crashes with an ACCESS_VIOLATION or runs without generating the bitmap. You can see the broken code as 'Code 2' below.
The wrong behaviour though only occurs when running with the java run arguments, that IntelliJ uses - either via Intellij Run or via Console.
It doesnt occur dont happen when building into a JAR and running this.
The problematic argument is the following. If this one is missing in the console, it runs.
-javaagent:<INTELLIJ_HOME>\lib\idea_rt.jar=52850:<INTELLIJ_HOME>\bin
I have read here that the idea_rt.jar file "is needed to provide graceful shutdown/exit/stacktrace features" and therefore I do not want to disable it in IntelliJ.
NOTE: In the broken code ('Code 2' below) you will notice an 'unnecessary' line
ByteBuffer data2 = loadByteBufferFromResource("/fonts/arial.ttf"); which simulates loading multiple fonts. If I only load one font, everything works fine.
You will also notice the OpenGL context creation in code 2, which also seems to be a cause of the problem (as I described above)
Code 1 (works)
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL;
import org.lwjgl.stb.STBTTFontinfo;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.Map;
import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
import static org.lwjgl.glfw.GLFW.glfwDefaultWindowHints;
import static org.lwjgl.glfw.GLFW.glfwInit;
import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent;
import static org.lwjgl.stb.STBTruetype.stbtt_GetCodepointBitmap;
import static org.lwjgl.stb.STBTruetype.stbtt_InitFont;
public class STBTTExampleOnlyMain {
private static ByteBuffer loadByteBufferFromResource(String resource) throws IOException {
try(InputStream stream = STBTTExampleOnlyMain .class.getResourceAsStream(resource)) {
byte[] bytes = stream.readAllBytes();
ByteBuffer buffer = BufferUtils.createByteBuffer(bytes.length);
buffer.put(bytes);
buffer.flip();
return buffer;
}
}
public static void main(String[] args) throws IOException {
ByteBuffer data = loadByteBufferFromResource("/fonts/arial.ttf");
ByteBuffer data2 = loadByteBufferFromResource("/fonts/arial.ttf");
STBTTFontinfo font = STBTTFontinfo.create();
stbtt_InitFont(font, data);
IntBuffer bufWidth = BufferUtils.createIntBuffer(1);
IntBuffer bufHeight = BufferUtils.createIntBuffer(1);
ByteBuffer bitmap = stbtt_GetCodepointBitmap(font, 0, 1, 'a', bufWidth, bufHeight, null, null);
System.out.println(bitmap);
}
}
Code 2 (broken)
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL;
import org.lwjgl.stb.STBTTFontinfo;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.Map;
import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
import static org.lwjgl.glfw.GLFW.glfwDefaultWindowHints;
import static org.lwjgl.glfw.GLFW.glfwInit;
import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent;
import static org.lwjgl.stb.STBTruetype.stbtt_GetCodepointBitmap;
import static org.lwjgl.stb.STBTruetype.stbtt_InitFont;
public class STBTTExample {
private static final Map<Integer, STBTTFontinfo> fontMap = new HashMap<>();
private static ByteBuffer loadByteBufferFromResource(String resource) throws IOException {
try(InputStream stream = STBTTExample.class.getResourceAsStream(resource)) {
byte[] bytes = stream.readAllBytes();
ByteBuffer buffer = BufferUtils.createByteBuffer(bytes.length);
buffer.put(bytes);
buffer.flip();
return buffer;
}
}
private static void initFont() throws IOException {
ByteBuffer data = loadByteBufferFromResource("/fonts/arial.ttf");
ByteBuffer data2 = loadByteBufferFromResource("/fonts/arial.ttf");
STBTTFontinfo font = STBTTFontinfo.create();
stbtt_InitFont(font, data);
fontMap.put(0, font);
}
public static void main(String[] args) throws IOException {
initFont();
glfwInit();
glfwDefaultWindowHints();
long windowHandle = glfwCreateWindow(800, 600, "Test", 0, 0);
glfwMakeContextCurrent(windowHandle);
GL.createCapabilities();
IntBuffer bufWidth = BufferUtils.createIntBuffer(1);
IntBuffer bufHeight = BufferUtils.createIntBuffer(1);
ByteBuffer bitmap = stbtt_GetCodepointBitmap(fontMap.get(0), 0, 1, 'a', bufWidth, bufHeight, null, null);
System.out.println(bitmap);
}
}
How can fix the problem of not being able to run the program out of IntelliJ when working with text rendering?
Am I maybe misunderstanding the STBTT library and actually can't work with fonts this way?
Any help would be appreciated to understand what is wrong and fix this.
I have asked the question in the LWJGL forum and got it solved.
The STBTTFontinfo object contains metadata only. The actual font data is NOT copied from the ByteBuffer you pass to stbtt_InitFont. Only its memory address is copied and the font data is accessed via that pointer when necessary. The segfault you're seeing happens because you don't store a reference to the ByteBuffer anywhere, it is GCed/deallocated by the time you try to use the font. An easy fix would be to change your Font class to also store the ByteBuffer.
You can look at the post here.

How to fix this java.lang.ClassCastException: [B cannot be cast to java.util.List

I'm creating a digital signature software in Java and I wanna the software to verify the message with parameters (string filename, string keyfile).
But I've got this exception at line
this.list2 = (List<byte[]>) in.readObject();
java.lang.ClassCastException: [B cannot be cast to java.util.List. How
to solve this?
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.nio.file.Files;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
private boolean verifySignature(byte[] data, byte[] signature, String
keyFile) throws Exception {
Signature sig = Signature.getInstance("SHA1withRSA");
sig.initVerify(getPublic(keyFile));
sig.update(data);
return sig.verify(signature);
}
public void VerifyMessage(String filename, String keyFile) throws Exception
{
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename)))
{
this.list2 = (List<byte[]>) in.readObject();
}
lbl13.setText(verifySignature(list2.get(0), list2.get(1), keyFile) ? "VERIFIED MESSAGE" +
"\n----------------\n" + new String(list2.get(0)) : "Could not verify the signature.");
}
You are trying to cast your in.readObject() file to a List
This does not work in Java because the file is written as a byte[] Array data structure, not an Array List. You're going to have to convert the byte[] Array to a list before making it the value for this.list2.
Here is how you can do that:
this.list2 = Arrays.asList((byte[])in.readObject());
Array.asList() will convert your Array of byte primitives to a List (I'm assuming you're using byte primitives and not the Byte class here based on your code). It is not possible to simply cast an Array to a List in Java.

Categories

Resources