Image read in Java - java

I am trying to read a image with the following code, I wasn't able to figure it out why its happening. If there is anything I done wrong in the following code, please tell me.
System.out.println("Image Bytes ::"+imageBytes);
InputStream in = new ByteArrayInputStream(imageBytes);
BufferedImage img = ImageIO.read(in);
System.out.println("Buff Image :: "+img);
and the Output is as follows:
Image Bytes ::[B#4554617c
Buff Image :: null

Since the Source of your imageByte is unknown, it's would be hard to say what went wrong. But if your are creating that byteSource, then probably the below code will help you, because From the Javadocs for ImageIO.read()
Returns a BufferedImage as the result of decoding a supplied File with
an ImageReader chosen automatically from among those currently
registered. The File is wrapped in an ImageInputStream. If no
registered ImageReader claims to be able to read the resulting
stream, null is returned.
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
/**
* Created by ankur on 13/7/15.
* The Following program will read an image file.
* convert it into byte array, and then reuse the
* converted byte array, and convert it back to new BufferedImage
*
*/
public class ImageToBuf {
public static void main(String... strings) throws IOException {
byte[] imageInByte;
//read the image
BufferedImage originalImage = ImageIO.read(new File("/home/ankur/Pictures/BlpRb.png"));
//convert BufferedImage to byte array
ByteArrayOutputStream byteOutS = new ByteArrayOutputStream();
ImageIO.write(originalImage, "png", byteOutS);
byteOutS.flush();
imageInByte = byteOutS.toByteArray();
byteOutS.close();
//convert byte array back to BufferedImage
InputStream readedImage = new ByteArrayInputStream(imageInByte);
BufferedImage bfImage = ImageIO.read(readedImage);
System.out.println(bfImage);
}
}
OutPut(on my amchine):
BufferedImage#21b8d17c: type = 13 IndexColorModel: #pixelBits = 8 numComponents = 3 color space = java.awt.color.ICC_ColorSpace#6433a2 transparency = 1 transIndex = -1 has alpha = false isAlphaPre = false ByteInterleavedRaster: width = 4959 height = 3505 #numDataElements 1 dataOff[0] = 0

Related

From image to BufferedImage to image

I'm trying to read a 256x256 image using ImageIO.read, transform it into a ByteArray, then into a BufferedImage, and back into an image file using ImageIO.write. It all seems to work as it should, but the final image is quite corrupted (although clearly still based on the original image. I can't find what's wrong in the process, I am suspicious of the scansize parameter, which I don't completely understand.
The idea is to manipulate pixels in between the reading and writing, but at the moment I can't even recreate the original image back into itself.
I attach the original image and the processed one below:
import java.awt.image.BufferedImage
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.IOException
import javax.imageio.ImageIO
fun main(args: Array<String>) {
val bImage = ImageIO.read(File("original.tiff"))
val bos = ByteArrayOutputStream()
ImageIO.write(bImage, "tiff", bos)
val data = bos.toByteArray()
val width = 256
val height = 256
val bytesPerPixel = 3
val len = width * height * bytesPerPixel
val image = BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)
val arr = IntArray(len)
for (i in 0 until len) arr[i] = data.get(i).toInt()
image.setRGB(0, 0, width, height, arr, 0, 256) // Seems like something is wrong here
try {
ImageIO.write(image, "jpg", File("converted-grayscale-002.jpg"))
} catch (e: IOException) {
System.err.println("IOException: $e")
}
}
This line is not returning the RGB image data:
val data = bos.toByteArray()
it is returning the compressed stream of the image in tiff format, surely it is not the correct image.
To get the pixels, use Image.getPixel(), alternatively you can get the buffer of the image directly, but to this you need to know what is the underlying buffer type - this is broad topic.
Take a look at this answer, it should give you idea how to do it: convert a RGB image to grayscale Image reducing the memory in java

Is it possible to read multiple images from an InputStream using Java ImageIO?

I'm trying to have a Kotlin thread which simply reads multiple images from a single InputStream.
For testing, I have an input stream that receives the content of two small image files in a separate thread. This seems to be working correctly as if I write the content of this input stream to disk, the resulting file is identical to the concatenation of the two source image files.
The problem occurs when reading images from the input stream with ImageIO:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.InputStream;
import javax.imageio.ImageIO;
class ImgReader {
InputStream input;
ImgReader(InputStream input) {
this.input = input;
}
public void run() {
ImageIO.setUseCache(false);
System.out.println("read start");
int counter = 1;
try {
BufferedImage im = ImageIO.read(input);
System.out.println("read: " + counter + " " + (im != null));
if (im != null)
ImageIO.write(im, "jpg", new File("pics/out/" + (counter++) +".jpeg"));
} catch (Exception e){
System.out.println("error while reading stream");
e.printStackTrace(System.out);
}
System.out.println("read done");
}
}
This works for the first image, which is received and saved to file correctly. However, the second image is not read: ImageIO.read(input) returns null.
Is it possible to read multiple images from an InputStream? What am I doing wrong?
--- EDIT ---
I tried a variation, where only one image is decoded from the stream (this is done correctly). After this, I tried saving the rest of the stream content into a binary file, without trying to decode it as an image. This second binary file is empty, meaning that the first ImageIO.read seems to consume the whole stream.
Yes, it is possible to read multiple images from a (single) InputStream.
I believe the most obvious solution is to use a file format that already has widespread support for multiple images, like TIFF. The javax.imageio API has good support for reading and writing multi-image files, even though the ImageIO class doesn't have any convenience methods for it, like the ImageIO.read(...)/ImageIO.write(...) methods for reading/writing a single image. This means the you need to write a bit more code (code samples below).
However, if the input is created by a third-party outside of your control, using a different format may not be an option. From the comments, it is explained that your input is actually a stream of concatenated Exif JPEGs. The good news is that Java's JPEGImageReader/Writer does allow multiple JPEGs in the same stream, even though this is not a very common format.
To read multiple JPEGs from the same stream, you can use the following example (note that the code is completely generic, and will work for reading other multi-image files, like TIFF too):
File file = ...; // May also use InputStream here
List<BufferedImage> images = new ArrayList<>();
try (ImageInputStream in = ImageIO.createImageInputStream(file)) {
Iterator<ImageReader> readers = ImageIO.getImageReaders(in);
if (!readers.hasNext()) {
throw new AssertionError("No reader for file " + file);
}
ImageReader reader = readers.next();
reader.setInput(in);
// It's possible to use reader.getNumImages(true) and a for-loop here.
// However, for many formats, it is more efficient to just read until there's no more images in the stream.
try {
int i = 0;
while (true) {
images.add(reader.read(i++));
}
}
catch (IndexOutOfBoundsException expected) {
// We're done
}
reader.dispose();
}
Anything below this line is just bonus extra-information.
Here's how to write multi-image files using the ImageIO API (the code example uses TIFF, but it is quite generic, and should in theory also work for other formats, except for the compression type parameter).
File file = ...; // May also use OutputStream/InputStream here
List<BufferedImage> images = new ArrayList<>(); // Just add images...
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("TIFF");
if (!writers.hasNext()) {
throw new AssertionError("Missing plugin");
}
ImageWriter writer = writers.next();
if (!writer.canWriteSequence()) {
throw new AssertionError("Plugin doesn't support multi page file");
}
ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionType("JPEG"); // The allowed compression types may vary from plugin to plugin
// The most common values for TIFF, are NONE, LZW, Deflate or Zip, or JPEG
try (ImageOutputStream out = ImageIO.createImageOutputStream(file)) {
writer.setOutput(out);
writer.prepareWriteSequence(null); // No stream metadata needed for TIFF
for (BufferedImage image : images) {
writer.writeToSequence(new IIOImage(image, null, null), param);
}
writer.endWriteSequence();
}
writer.dispose();
Note that before Java 9, you will also need a third party TIFF plugin, like JAI or my own TwelveMonkeys ImageIO, to read/write TIFF using ImageIO.
Another option, if you really don't like to write this verbose code, is to wrap the images in your own minimal container format, that includes (at least) the length of each image. Then you can write using ImageIO.write(...) and read using ImageIO.read(...), but you need to implement some simple stream logic around it. And the main argument against it, of course, is that it will be entirely proprietary.
But, if you are reading/writing asynchronously in a client/server-like setup (as I suspect, from your question), this may make perfect sense, and could be an acceptable trade-off.
Something like:
File file = new File(args[0]);
List<BufferedImage> images = new ArrayList<>();
try (DataOutputStream out = new DataOutputStream(new FileOutputStream(file))) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream(1024 * 1024); // Use larger buffer for large images
for (BufferedImage image : images) {
buffer.reset();
ImageIO.write(image, "JPEG", buffer); // Or PNG or any other format you like, really
out.writeInt(buffer.size());
buffer.writeTo(out);
out.flush();
}
out.writeInt(-1); // EOF marker (alternatively, catch EOFException while reading)
}
// And, reading back:
try (DataInputStream in = new DataInputStream(new FileInputStream(file))) {
int size;
while ((size = in.readInt()) != -1) {
byte[] buffer = new byte[size];
in.readFully(buffer); // May be more efficient to create a FilterInputStream that counts bytes read, with local EOF after size
images.add(ImageIO.read(new ByteArrayInputStream(buffer)));
}
}
PS: If all you want to do is to write the images you receive to disk, you should not use ImageIO for this. Instead, use plain I/O (assuming format from the previous example):
try (DataInputStream in = new DataInputStream(new FileInputStream(file))) {
int counter = 0;
int size;
while ((size = in.readInt()) != -1) {
byte[] buffer = new byte[size];
in.readFully(buffer);
try (FileOutputStream out = new FileOutputStream(new File("pics/out/" + (counter++) +".jpeg"))) {
out.write(buffer);
out.flush();
}
}
}
This is a well known "feature" of the inputstreams.
An inputstream can be read only once (ok, there is mark() and reset(), but not every implementation supports it (check markSupported() in Javadoc), and IMHO it is not so convinient to use), you should either persist your image and pass the path as an argument, or you should read it to a byte array and create a ByteArrayInputStream for every call where you are trying to read it:
// read your original stream once (e.g. with commons IO, just the sake of shortness)
byte[] imageByteArray = IOUtils.toByteArray(input);
...
// and create new input stream every time
InputStream newInput = new ByteArrayInputStream(imageByteArray);
...
// and call your reader in this way:
new ImgReader(newInput);
Update:
Scroll down to the last code snippet for an update to this answer.
It is not a satisfactory answer, but an answer to the question:
No, this is (almost certainly) not possible.
When passing an InputStream to ImageIO, it will internally be wrapped into an ImageInputStream. This stream is then passed to an ImageReader. The exact implementation will depend on the type of the image data. (This is usually determined from the "magic header", i.e. the first few bytes of the input data).
Now, the behavior of these ImageReader implementations cannot be altered or controlled sensibly. (For some of them the actual reading even takes place in native methods).
The following is an example showing the different behaviors:
First, it generates an input stream containing one JPG image and one PNG image. The output shows that the input stream is read fully before the JPG image is returned.
Then, it generates an input stream containing one PNG and one JPG image. One can see that it only reads a few bytes, until it can decode the result of the first PNG image.
_
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
public class MultipleImagesFromSingleStream
{
public static void main(String[] args) throws IOException
{
readJpgAndPng();
readPngAndJpg();
}
private static void readJpgAndPng() throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(createDummyImage("Image 0", 50), "jpg", baos);
ImageIO.write(createDummyImage("Image 1", 60), "png", baos);
byte data[] = baos.toByteArray();
InputStream inputStream = createSlowInputStream(data);
BufferedImage image0 = ImageIO.read(inputStream);
System.out.println("Read " + image0);
BufferedImage image1 = ImageIO.read(inputStream);
System.out.println("Read " + image1);
}
private static void readPngAndJpg() throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(createDummyImage("Image 0", 50), "png", baos);
ImageIO.write(createDummyImage("Image 1", 60), "jpg", baos);
byte data[] = baos.toByteArray();
InputStream inputStream = createSlowInputStream(data);
BufferedImage image0 = ImageIO.read(inputStream);
System.out.println("Read " + image0);
BufferedImage image1 = ImageIO.read(inputStream);
System.out.println("Read " + image1);
}
private static InputStream createSlowInputStream(byte data[])
{
ByteArrayInputStream bais = new ByteArrayInputStream(data);
return new InputStream()
{
private long counter = 0;
#Override
public int read() throws IOException
{
counter++;
if (counter % 100 == 0)
{
System.out.println(
"Read " + counter + " of " + data.length + " bytes");
try
{
Thread.sleep(50);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
return bais.read();
}
};
}
private static BufferedImage createDummyImage(String text, int h)
{
int w = 100;
BufferedImage image =
new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
g.setColor(Color.BLACK);
g.fillRect(0, 0, w, h);
g.setColor(Color.WHITE);
g.drawString(text, 20, 20);
g.dispose();
return image;
}
}
The output is as follows:
Read 100 of 1519 bytes
Read 200 of 1519 bytes
Read 300 of 1519 bytes
Read 400 of 1519 bytes
Read 500 of 1519 bytes
Read 600 of 1519 bytes
Read 700 of 1519 bytes
Read 800 of 1519 bytes
Read 900 of 1519 bytes
Read 1000 of 1519 bytes
Read 1100 of 1519 bytes
Read 1200 of 1519 bytes
Read 1300 of 1519 bytes
Read 1400 of 1519 bytes
Read 1500 of 1519 bytes
Read BufferedImage#3eb07fd3: type = 0 DirectColorModel: rmask=ff000000 gmask=ff0000 bmask=ff00 amask=ff IntegerInterleavedRaster: width = 100 height = 50 #Bands = 4 xOff = 0 yOff = 0 dataOffset[0] 0
Read null
Read 100 of 1499 bytes
Read 200 of 1499 bytes
Read BufferedImage#42110406: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace#531d72ca transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 100 height = 50 #numDataElements 4 dataOff[0] = 3
Read null
Note that although it does not read the full stream in the second case, this still does not necessarily mean that the input stream then is located at the "beginning of the JPG data". It only means that it does not read the full stream!
I also tried to dive deeper into this. Iff one could be sure that the images are always only PNG images, one could try to manually create a PNGImageReader instance and hook into its reading process, to check when it actually finished the first image. But again, the input stream is wrapped internally into several other (buffered- and deflating) input streams, and there is no way to sensibly detect whether a certain set of bytes already has been "used" for an image.
So I think that the only sensible solution here is to close the stream after the image has been read, and open a new stream for the next image.
A workaround that has been discussed in the comments is to add length information to the stream. This means that the producer of the image data first writes an int into the stream, describing the length of the image data. Then it writes the byte[length] data with the actual image data.
The receiver can then use this information to load individual images.
This is implemented here, as an example:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class MultipleImagesFromSingleStreamWorkaround
{
public static void main(String[] args) throws IOException
{
workaround();
}
private static void workaround() throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
write(createDummyImage("Image 0", 50), "jpg", baos);
write(createDummyImage("Image 1", 60), "png", baos);
write(createDummyImage("Image 2", 70), "gif", baos);
byte data[] = baos.toByteArray();
InputStream inputStream = createSlowInputStream(data);
BufferedImage image0 = read(inputStream);
System.out.println("Read " + image0);
BufferedImage image1 = read(inputStream);
System.out.println("Read " + image1);
BufferedImage image2 = read(inputStream);
System.out.println("Read " + image2);
showImages(image0, image1, image2);
}
private static void write(BufferedImage bufferedImage,
String formatName, OutputStream outputStream) throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, formatName, baos);
byte data[] = baos.toByteArray();
DataOutputStream dos = new DataOutputStream(outputStream);
dos.writeInt(data.length);
dos.write(data);
dos.flush();
}
private static BufferedImage read(
InputStream inputStream) throws IOException
{
DataInputStream dis = new DataInputStream(inputStream);
int length = dis.readInt();
byte data[] = new byte[length];
dis.read(data);
ByteArrayInputStream bais = new ByteArrayInputStream(data);
return ImageIO.read(bais);
}
private static InputStream createSlowInputStream(byte data[])
{
ByteArrayInputStream bais = new ByteArrayInputStream(data);
return new InputStream()
{
private long counter = 0;
#Override
public int read() throws IOException
{
counter++;
if (counter % 100 == 0)
{
System.out.println(
"Read " + counter + " of " + data.length + " bytes");
try
{
Thread.sleep(50);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
return bais.read();
}
};
}
private static BufferedImage createDummyImage(String text, int h)
{
int w = 100;
BufferedImage image =
new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
g.setColor(Color.BLACK);
g.fillRect(0, 0, w, h);
g.setColor(Color.WHITE);
g.drawString(text, 20, 20);
g.dispose();
return image;
}
private static void showImages(BufferedImage ... images)
{
SwingUtilities.invokeLater(() ->
{
JFrame f = new JFrame();
f.getContentPane().setLayout(new GridLayout(1,0));
for (BufferedImage image : images)
{
f.getContentPane().add(new JLabel(new ImageIcon(image)));
}
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
Update
This is based on the answer from haraldK (upvote his answer, not this one!)
An example implementation showing the approach that haraldK proposed. It manages to read a sequence of images, although there are some limitations:
It seems to have to read "more" bytes than strictly necessary before it delivers the first image.
It cannot load different types of images (i.e. it cannot read a sequence of mixed PNG and JPG images)
Specifically, it seemed to work only for JPG images for me. For PNG or GIF, only the first image was read (at least for me...)
However, posting it here for others to easily test it:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class MultipleImagesFromSingleStreamWorking
{
public static void main(String[] args) throws IOException
{
readExample();
}
private static void readExample() throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(createDummyImage("Image 0", 50), "jpg", baos);
//ImageIO.write(createDummyImage("Image 1", 60), "png", baos);
ImageIO.write(createDummyImage("Image 2", 70), "jpg", baos);
ImageIO.write(createDummyImage("Image 3", 80), "jpg", baos);
ImageIO.write(createDummyImage("Image 4", 90), "jpg", baos);
ImageIO.write(createDummyImage("Image 5", 100), "jpg", baos);
ImageIO.write(createDummyImage("Image 6", 110), "jpg", baos);
ImageIO.write(createDummyImage("Image 7", 120), "jpg", baos);
byte data[] = baos.toByteArray();
InputStream inputStream = createSlowInputStream(data);
List<BufferedImage> images = readImages(inputStream);
showImages(images);
}
private static List<BufferedImage> readImages(InputStream inputStream)
throws IOException
{
// From https://stackoverflow.com/a/53501316/3182664
List<BufferedImage> images = new ArrayList<BufferedImage>();
try (ImageInputStream in = ImageIO.createImageInputStream(inputStream))
{
Iterator<ImageReader> readers = ImageIO.getImageReaders(in);
if (!readers.hasNext())
{
throw new AssertionError("No reader for file " + inputStream);
}
ImageReader reader = readers.next();
reader.setInput(in);
// It's possible to use reader.getNumImages(true) and a for-loop
// here.
// However, for many formats, it is more efficient to just read
// until there's no more images in the stream.
try
{
int i = 0;
while (true)
{
BufferedImage image = reader.read(i++);
System.out.println("Read " + image);
images.add(image);
}
}
catch (IndexOutOfBoundsException expected)
{
// We're done
}
reader.dispose();
}
return images;
}
private static InputStream createSlowInputStream(byte data[])
{
ByteArrayInputStream bais = new ByteArrayInputStream(data);
return new InputStream()
{
private long counter = 0;
#Override
public int read() throws IOException
{
counter++;
if (counter % 100 == 0)
{
System.out.println(
"Read " + counter + " of " + data.length + " bytes");
try
{
Thread.sleep(50);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
return bais.read();
}
};
}
private static BufferedImage createDummyImage(String text, int h)
{
int w = 100;
BufferedImage image =
new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
g.setColor(Color.BLACK);
g.fillRect(0, 0, w, h);
g.setColor(Color.WHITE);
g.drawString(text, 20, 20);
g.dispose();
return image;
}
private static void showImages(List<BufferedImage> images)
{
SwingUtilities.invokeLater(() ->
{
JFrame f = new JFrame();
f.getContentPane().setLayout(new GridLayout(1,0));
for (BufferedImage image : images)
{
f.getContentPane().add(new JLabel(new ImageIcon(image)));
}
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}

To read an image from Android Emulator

This is my code to convert image file into byte array.
public String GetQRCode() throws FileNotFoundException, IOException {
/*
* In this function the first part shows how to convert an image file to
* byte array. The second part of the code shows how to change byte array
* back to a image.
*/
AssetManager mgr = mAppView.getContext().getAssets();
InputStream in = mgr.open("www/Siemens_QR.jpg");
InputStreamReader isr = new InputStreamReader(in);
char[] buf = new char[20];
isr.read(buf, 0, 20);
isr.close();
// byte[] bytes = bos.toByteArray();
String abc = buf.toString();
return abc;
}
Here I am converting an image file into byte array. I am able to do this. But when try to read this image file using the path ("sdcard/Download/Siemens_QR.jpg") stored in emulator then I am getting VM aborting error. Please suggest me the correct path to read the image file stored in the emulator.
if you have jpg image stored on SD card then get the file path and try to convert the image to byte using following method...
Bitmap bitmap = BitmapFactory.decodeFile(file path);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 60, baos);
byte[] byte_img_data = baos.toByteArray();

How to convert image to byte array and convert back byte array to image

I am trying to convert an image to byte array and converting back byte array to image in Android Emulator.
First part is working fine but the second part is not creating the image file in Android emulator.
Please suggest me if there is any correction in my second part of the code.
Following is my code.
public String GetQRCode() throws FileNotFoundException, IOException {
/*
* In this function the first part shows how to convert an image file to
* byte array. The second part of the code shows how to change byte array
* back to an image.
*/
Bitmap bitmap = BitmapFactory.decodeFile("sdcard/Download/QR.jpg");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 60, baos);
byte[] byte_img_data = baos.toByteArray();
byte[] buf = new byte[200];
// Second Part: Convert byte array back to an image
Bitmap bitmap2 = BitmapFactory.decodeByteArray(byte_img_data, 0, 200);
ByteArrayOutputStream img= new ByteArrayOutputStream();
Bitmap imageFile= BitmapFactory.decodeFile("sdcard/Download/QR3.jpg");
String abc = buf.toString();
return abc;
}
your call to BitmapFactory.decodeByteArray(..) - this method returns a Bitmap object, but you're not assigning it to anything. You also need to change the call to pass in the actual length of byte_img_data, rather then 200.
Bitmap bitmap2 = BitmapFactory.decodeByteArray(byte_img_data, 0, byte_img_data.length);
However, whether decodeByteArray(..) can handle compressed streams, i don't know

Convert an image to binary data (0s and 1s) in java

I want to read an image from a url and convert it into binary data. Please help me..
byte[] data = null;
ByteArrayOutputStream bas = null;
try {
URL u = new URL(
"http://www.eso.org/public/archives/images/screen/eso0844a.jpg");
HttpURLConnection con1 = (HttpURLConnection) u.openConnection();
con1.setAllowUserInteraction(true);
con1.setRequestMethod("GET");
con1.connect();
InputStream is = con1.getInputStream();
BufferedImage imgToServe = null;
if (is != null) {
imgToServe = ImageIO.read(is);
}
bas = new ByteArrayOutputStream();
ImageIO.write(imgToServe, "jpg", bas);
File f = new File("C:\\img.jpg");
ImageIO.write(imgToServe, "jpg", f);
data = bas.toByteArray();
String str = "";
for (int i = 0; i < data.length; i++) {
str = str + toBinary(data[i]);
}
System.out.println(str);
} catch (HTTPException he) {
} catch (IOException ioe) {
}
}
private static String toBinary(byte b) {
StringBuilder sb = new StringBuilder("00000000");
for (int bit = 0; bit < 8; bit++) {
if (((b >> bit) & 1) > 0) {
sb.setCharAt(7 - bit, '1');
}
}
return (sb.toString());
}
If you're reading the image from a URL, it will already be in a binary format. Just download the data and ignore the fact that it's an image. The code which is involved in download it won't care, after all. Assuming you want to write it to a file or something similar, just open the URLConnection and open the FileOutputStream, and repeatedly read from the input stream from the web, writing the data you've read to the output stream.
If that's not what you were after, please clarify the question.
EDIT: If you really want to get the data as individual bits (which seems somewhat odd to me) you should separate the problem in two:
Downloading the data (see above; if you don't need it on disk, consider writing to a ByteArrayOutputStream)
Converting arbitrary binary data (a byte array or an input stream) into 0s and 1s
How you tackle the latter task will depend on what you actually want to do with the bits. What's the real aim here?
You can use the standard ImageIO for this. The read method takes a URL and retrieves it to an Image. Then you can use the write method to write it to a File or like in this case a ByteArrayOutputStream which outputs the image to a in-memory buffer.
public static void main(String[] args) throws Exception {
// read "any" type of image (in this case a png file)
BufferedImage image = ImageIO.read(new URL("http://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png"));
// write it to byte array in-memory (jpg format)
ByteArrayOutputStream b = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", b);
// do whatever with the array...
byte[] jpgByteArray = b.toByteArray();
// convert it to a String with 0s and 1s
StringBuilder sb = new StringBuilder();
for (byte by : jpgByteArray)
sb.append(Integer.toBinaryString(by & 0xFF));
System.out.println(sb.toString());
}
Load the image from path/url into BufferedImage
public static Raster loadImageRaster(String file_path) throws IOException
{
File input = new File(file_path);
BufferedImage buf_image = ImageIO.read(input);
buf_image = binarizeImage(buf_image);
return buf_image.getData(); //return raster
}
Make a Binary Type BufferedImage from the original BufferedImage
public static BufferedImage binarizeImage(BufferedImage img_param)
{
BufferedImage image = new BufferedImage(
img_param.getWidth(),
img_param.getHeight(),
BufferedImage.TYPE_BYTE_BINARY
);
Graphics g = image.getGraphics();
g.drawImage(img_param, 0, 0, null);
g.dispose();
return image;
}
Convert the BufferedImage to Raster so that you can manipulate it pixel by pixel
imageRaster.getSample(x, y, 0)
Raster.getSample(x,y, channel) will return 0s or 1s.
channel = 0 for TYPE_BYTE_BINARY images

Categories

Resources