JAVA : How to create .PNG image from a byte[]? - java

I have seen some code source, but I do not understand...
I use Java 7
Please, how to convert a RGB (Red,Green,Blue) Byte Array (or something similar) to a .PNG file format ?
Example from an array that could represent "a RGB pixel" :
byte[] aByteArray={0xa,0x2,0xf};
Important Aspect :
I try to generate a .PNG file only from a byte[] "not from a previous existing file"
is it possible with an existing API? ;)
Here my first code :
byte[] aByteArray={0xa,0x2,0xf};
ByteArrayInputStream bais = new ByteArrayInputStream(aByteArray);
File outputfile = new File("image.png");
ImageIO.write(bais, "png", outputfile);
....Error : No suitable Method Found
Here the other version modified from Jeremy but look similar :
byte[] aByteArray={0xa,0x2,0xf};
ByteArrayInputStream bais = new ByteArrayInputStream(aByteArray);
final BufferedImage bufferedImage = ImageIO.read(newByteArrayInputStream(aByteArray));
ImageIO.write(bufferedImage, "png", new File("image.png"));
....multiple Errors : image == null! ...... Sure ? Note : I do not search to use a source file

The Image I/O API deals with images, so you need to make an image from your byte array first before you write it out.
byte[] aByteArray = {0xa,0x2,0xf,(byte)0xff,(byte)0xff,(byte)0xff};
int width = 1;
int height = 2;
DataBuffer buffer = new DataBufferByte(aByteArray, aByteArray.length);
//3 bytes per pixel: red, green, blue
WritableRaster raster = Raster.createInterleavedRaster(buffer, width, height, 3 * width, 3, new int[] {0, 1, 2}, (Point)null);
ColorModel cm = new ComponentColorModel(ColorModel.getRGBdefault().getColorSpace(), false, true, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
BufferedImage image = new BufferedImage(cm, raster, true, null);
ImageIO.write(image, "png", new File("image.png"));
This assumes the byte array has three bytes per pixel (red, green then blue) and the range of values is 0-255.

Related

Cannot cast DataBufferInt to DataBufferByte on specific picture(s)

I am trying to threshold my images, but some of them have problem with casting to DataBufferByte. I post here two types of pictures - the first (the test1.jpg is good and can be casted to DataBufferByte), the second (test2.jpg throwing an exception).
Images:
Here is my code:
public static void main(String[] args) throws IOException {
System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
BufferedImage bufferedImage = ImageIO.read(new File("/test/test2.jpg"));
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "jpg", byteArrayOutputStream);
byte[] input = byteArrayOutputStream.toByteArray();
InputStream is = new ByteArrayInputStream(input);
bufferedImage = ImageIO.read(is);
byte[] data = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData();
Mat mat = new Mat(bufferedImage.getHeight(), bufferedImage.getWidth(), CvType.CV_8UC3);
mat.put(0, 0, data);
Mat mat1 = new Mat(bufferedImage.getHeight(),bufferedImage.getWidth(),CvType.CV_8UC1);
Imgproc.cvtColor(mat, mat1, Imgproc.COLOR_RGB2GRAY);
byte[] data1 = new byte[mat1.rows() * mat1.cols() * (int)(mat1.elemSize())];
mat1.get(0, 0, data1);
Mat dst = new Mat();
Imgproc.adaptiveThreshold(mat1, dst, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 11, 15);
MatOfByte matOfByte = new MatOfByte();
Imgcodecs.imencode(".jpg", dst, matOfByte);
ByteArrayInputStream inputStream = new ByteArrayInputStream(matOfByte.toArray());
bufferedImage = ImageIO.read(inputStream);
ImageIO.write(bufferedImage, "jpg", new File("/test_output/test2.jpg"));
}
The output for test1.jpg image is correct:
But the second image throwing an exception
Exception in thread "main" java.lang.ClassCastException:
java.awt.image.DataBufferInt cannot be cast to
java.awt.image.DataBufferByte
at line
byte[] data = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData();
What is the problem ? Why the one .jpg image is converted without problems but second throwing an exception?
Both are not of the same format. One using 8-bit for color representation and the other 3x8-bit (so 4 bytes, with padding or transparency)?
Looking at it give:
image1 : JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, baseline, precision 8, 449x361, components 3
image2 : PNG image data, 617 x 353, 8-bit/color RGBA, non-interlaced
You may use the getDataType() method on the buffer to get the size of the color representation.

BufferedImage from 4-bit data buffer

Hello I have a problem with converting my 4-bit data buffer to WritableRaster.
Image resolution: 1024x768 (786432)
Here is description what I'm doing.
1) Create 4-bit BufferedImage
bit4Image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY, MY_BIT_4_COLOR_MODEL);
Graphics graphics = bit4Image.getGraphics();
graphics.drawImage(originalImage, 0, 0, null);
graphics.dispose();
//4-bit BufferedImage created. 4-bit BufferedImage is properly made cause it can be saved to hdd and looks good
2) Get byte array from DataBuffer from 4-bit
byte[] pixelData = ((DataBufferByte) bit4Image.getRaster().getDataBuffer()).getData();
// pixelData length is 393216
3) Now I want to create BufferedImage from this byte array pixelData
BufferedImage dest = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY, MY_BIT_4_COLOR_MODEL);
DataBufferByte buffer = new DataBufferByte(pixelData, pixelData.length);
WritableRaster raster = Raster.createInterleavedRaster(buffer, width, height, width, 1, new int[]{0}, new Point(0, 0));
dest.setData(raster);
Problem is when I call Raster.createInterleavedRaster. Exception:
java.awt.image.RasterFormatException: Data array too small (should be > 786431 )
I also tried something like this
BufferedImage dest = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY, MY_BIT_4_COLOR_MODEL);
dest.getRaster().setDataElements(0, 0, width, height, pixelData);
But this one gives me similar failure:
java.lang.ArrayIndexOutOfBoundsException: 393216
Could someone give me a hint or show the proper way of setting this 4-bit pixelData to WritableRaster?
Resolved.
I just had to create WritableRaster with giving it SampleModel:
SampleModel sm = MY_BIT_4_COLOR_MODEL.createCompatibleSampleModel(width, height);
WritableRaster wr = Raster.createWritableRaster(sm, buffer, new Point(0,0));
The initial code you had almost worked, the only problem is you tried to create an "interleaved" raster. For palette images (IndexColorModel) you typically have only one sample (the palette index) per pixel, so there's no samples to interleave.
Instead, your pixel data is 4 bit/pixel, stored as two pixels per byte. Storing more samples per storage unit, is often referred to as "packed". This means you need to create a "packed" raster, using one of the Raster.createPackedRaster methods.
Here's a full, runnable sample:
public static void main(String[] args) {
int width = 100;
int height = 100;
// Create initial 4 bit image
IndexColorModel icm = new IndexColorModel(4, 16, new int[16], 0, false, -1, DataBuffer.TYPE_BYTE);
BufferedImage bit4Image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY, icm);
// ...you probably do something in between here
// Get the pixel data
byte[] pixelData = ((DataBufferByte) bit4Image.getRaster().getDataBuffer()).getData();
// ...you probably do something in between here
// Create a data buffer around the array, wrap in raster
DataBufferByte buffer = new DataBufferByte(pixelData, pixelData.length);
WritableRaster raster = Raster.createPackedRaster(buffer, width, height, 4, null);
// Finally create a copy of the image, sharing pixel data
BufferedImage copy = new BufferedImage(icm, raster, icm.isAlphaPremultiplied(), null);
System.out.println("copy: " + copy);
}

getting a bufferedImage from a bytearray

I am trying to get back a bufferedImage from array of bytes, but I am getting an error saying bufferedimage is null. I actually tried several ways, everything ended up in the same way. Here goes my code:
1)
byte[] arr = Base64.decode(base64String);
BufferedImage bImageFromConvert =ImageIO.read(new ByteArrayInputStream(arr));
2)
InputStream in = new ByteArrayInputStream(arr);
BufferedImage bImageFromConvert = ImageIO.read(in);
I am pretty sure my byte array contains data and I think ImageIO.read() is where my code goes wrong.
The error is in your BufferedImage to Base64 encode method as you have posted in the comments.
You are never writing the BufferedImage to the ByteArrayOutputStream. Therefore the Base64 string is empty, and reading the empty string produces a null BufferedImage.
You should use this code to encode your image:
BufferedImage originalImage = ImageIO.read(new File("G:\\a.jpg"));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write( originalImage, "jpg", baos );
String base64String=Base64.encode(baos.toByteArray());
To decode the image use this code:
byte[] arr = Base64.decode(base64String);
BufferedImage bImageFromConvert =ImageIO.read(new ByteArrayInputStream(arr));
System.out.println(bImageFromConvert.getWidth());
Try this code.Maybe it works. It worked for me.
byte[] aByteArray = {};
int width = ;
int height = ;
DataBuffer buffer = new DataBufferByte(aByteArray, aByteArray.length);
WritableRaster raster = Raster.createInterleavedRaster(buffer, width, height, 3 * width, 3, new int[] {0, 1, 2}, (Point)null);
ColorModel cm = new ComponentColorModel(ColorModel.getRGBdefault().getColorSpace(), false, true, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
BufferedImage image = new BufferedImage(cm, raster, true, null);
Just add the byte, width and height to code and customize it.

Convert and display image from byte array

I'm making a program, which gets data about an image in byte array from a server. I'm converting this data into 24bit BMP format (whether its jpeg, png, bmp or 8-24-32bpp). First, I'm saving it to my HD, and then I'm loading it into a JLabel's Icon. Works perfectly, though there are some cases in which I get the following exception:
java.io.EOFException at
javax.imageio.stream.ImageInputStreamImpl.readFully(ImageInputStreamImpl.java:353) at
com.sun.imageio.plugins.bmp.BMPImageReader.read24Bit(BMPImageReader.java:1188) at
com.sun.imageio.plugins.bmp.BMPImageReader.read(BMPImageReader.java:843) at
javax.imageio.ImageIO.read(ImageIO.java:1448) at
javax.imageio.ImageIO.read(ImageIO.java:1308)
For this line (the second)
File imgFile = new File("d:/image.bmp");
BufferedImage image = ImageIO.read(imgFile);
In these cases:
the image does not load into the JLabel, but it can be found on my HD
the conversion is not proper, because something "slips"
the picture is like when you use italics in a word document
First, i thought maybe the bpp is the problem, then i thought that maybe the pictures are too large, but i have cases it works and cases it doesn't for both suggestions. I'm a little stuck here, and would be glad for ideas.
the picture is like .. when You use italics in a word document
Think I finally got what this bullet item meant now.. ;-)
Speculative answer, but here goes:
If the image you write looks "skewed", it's probably due to missing padding for each column as the BMP format specifies (or incorrect width field in the BMP header). I assume then, that the images you get EOF exceptions for, is where the width is not a multiple of 4.
Try to write the BMPs using ImageIO to see if that helps:
private static BufferedImage createRGBImage(byte[] bytes, int width, int height) {
DataBufferByte buffer = new DataBufferByte(bytes, bytes.length);
ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[]{8, 8, 8}, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
return new BufferedImage(cm, Raster.createInterleavedRaster(buffer, width, height, width * 3, 3, new int[]{0, 1, 2}, null), false, null);
}
...
byte[] bytes = ...; // Your image bytes
OutputStream stream = ...; // Your output
BufferedImage image = createRGBImage(bytes, width, height);
try {
ImageIO.write(image, "BMP", stream);
}
finally {
stream.close();
}
Call it by class name, liek ClassName.byteArrayToImage(byte):
public static BufferedImage byteArrayToImage(byte[] bytes){
BufferedImage bufferedImage=null;
try {
InputStream inputStream = new ByteArrayInputStream(bytes);
bufferedImage = ImageIO.read(inputStream);
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
return bufferedImage;
}
You can use this code to convert the output image to a byte Array
Blob b = rs.getBlob(2);
byte barr[] = new byte[(int)b.length()]; //create empty array
barr = b.getBytes(1,(int)b.length());
FileOutputStream fout = new FileOutputStream("D:\\sonoo.jpg");
fout.write(barr);

Problem converting bytes from a Bing Map request into a BufferedImage

I have very little experience with Java IO and images, and I've been unsuccessful at converting an aerial image saved as a byte array into a BufferedImage.
Here's my code:
int width = scaledImage.getWidth();
int height = scaledImage.getHeight();
DataBuffer buffer = new DataBufferByte(scaledImage.getImage(), scaledImage.getImage().length, 0);
SampleModel sampleModel = new SinglePixelPackedSampleModel(DataBuffer.TYPE_BYTE, width, height, new int[]{(byte)0xf});
WritableRaster raster = Raster.createWritableRaster(sampleModel, buffer, null);
ColorModel colorModel = imageManager.generateColorModel();
BufferedImage image = new BufferedImage(colorModel, raster, false, null);
Most of this code is borrowed from http://www.exampledepot.com/egs/java.awt.image/Mandelbrot2.html.
This code throws the following exception
java.awt.image.RasterFormatException: Data array too small (should be 122499 )
the actual length of the data array is 52341.
The dimensions are 350px X 350px
Here is the line that is killing you:
DataBuffer buffer = new DataBufferByte(scaledImage.getImage(), scaledImage.getImage().length, 0);
The example you show does width * height instead of scaledImage.getImage().length. In the model you've chosen, you need a byte per pixel, which is 350x350 or 122500.

Categories