Can't get the method to work - java

I have this method here, which converts an image to a byte array.
public byte[] imageToCompressedByteArray(Image image) throws IOException {
//load the image
String f = "C:\\Users\\mamed\\Documents\\NetBeansProjects\\Main\\src\\resources\\accept.png";
image = ImageIO.read(new FileInputStream(new File(f)));
// get image size
int width = image.getWidth(null);
int height = image.getHeight(null);
try {
int[] imageSource = new int[width * height];
PixelGrabber pg = new PixelGrabber(image, 0, 0, width, height, imageSource, 0, width);
pg.grabPixels();
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
GZIPOutputStream zippedStream = new GZIPOutputStream(byteStream);
ObjectOutputStream objectStream = new ObjectOutputStream(zippedStream);
objectStream.writeShort(width);
objectStream.writeShort(height);
objectStream.writeObject(imageSource);
objectStream.flush();
objectStream.close();
return byteStream.toByteArray();
}
catch (Exception e) {
throw new IOException("Error storing image in object: " + e);
}
}
However, i can't get this to work, i mean, it can't load the image and convert it, and i don't have an idea what the problem can be.

Are you sure the image path is correct and the loaded image is not corrupted image.
I not modified your code and I can see 1778416 byes its read from the image file.

I do not see anything wrong with the program. Maybe your image file is corrupted or image path is not correct.

Related

how to fill a raw file with an image buffer, using an alternative to ImageIO.write

The problem is that ImageIO.write does not recognize the raw format, so the file does not fill it. I tried the same code with png and it created it correctly. Is there some alternative to ImageIO.write or some other way to create a raw, raw byte file? Is there some conversion alternative for an image in Fid format?
Fid Image to raw
Buffered image to raw
Here I create the file I have indicated the address:
private void RAWCompression(Fid.Fiv imagen) throws IOException{
JFileChooser fileChooser = new JFileChooser(System.getProperty("java.library.path"));
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fileChooser.setSelectedFile(new File("HuellaRaw.raw"));
fileChooser.showSaveDialog(null);
File dir = fileChooser.getSelectedFile();
File file = new File(dir.getAbsolutePath() + "/" + "HuellaRaw.raw");
System.out.println(file);
//Create file
try {
file.createNewFile();
} catch (IOException ex) {
Logger.getLogger(Capture.class.getName()).log(Level.SEVERE, null, ex);
}
I send the image to buferrtd:
BufferedImage imagenBuffered = new BufferedImage(imagen.getWidth(), imagen.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
imagenBuffered.getRaster().setDataElements(0, 0, imagen.getWidth(), imagen.getHeight(), imagen.getData());
I fill the file and convert it to bytes:
//convert BufferedImage to byte
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(imagenBuffered, "raw", baos);
byte[] bytes = baos.toByteArray();
//FileUtils.writeByteArrayToFile(file, bytes);
try (FileOutputStream os = new FileOutputStream(file)) {
os.write(bytes);
} catch (Exception e) {
System.err.print("imagen Error wri " + imagen.getImageData() + "\n");
}
This line does not fill the raw file:
(If I change raw to png then it does fill the file.)
ImageIO.write(imagenBuffered, "raw", baos);
This line of code with png is created correctly:
ImageIO.write(imagenBuffered, "png", baos);
You cannot use ImageIO to write raw. You could get the "raw bytes" of your image and write them to a file though.
If you already have your buffered image, you could try the inverse of this answer. https://stackoverflow.com/a/54578326/2067492
int[] rgb = imagenBuffered.getRGB(0, 0, width, height, null, width);
ByteBuffer bb = ByteBuffer.allocate( rgb.length*4 );
bb.asIntBuffer().put(rgb);
bytes = bb.array();
This would write all of the pixels to a byte[], no headers or information about the data, just 4 byte rgba as returned by getRGB.

Saving custom BufferedImage

I have raw grayscale image pixels represented by short[]. I would like to create BufferedImage from it and save it as PNG.
Since there is no TYPE_SHORT_GRAY defined for BufferedImage I'm creating one myself this way:
short[] myRawImageData;
// Create signed 16 bit data buffer, and compatible sample model
DataBuffer dataBuffer = new DataBufferShort(myRawImageData, w * h);
SampleModel sampleModel = new ComponentSampleModel(DataBuffer.TYPE_SHORT, w, h, 1, w, new int[] {0});
// Create a raster from sample model and data buffer
WritableRaster raster = Raster.createWritableRaster(sampleModel, dataBuffer, null);
// Create a 16 bit signed gray color model
ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);
ColorModel colorModel = new ComponentColorModel(colorSpace, false, false, Transparency.OPAQUE, DataBuffer.TYPE_SHORT);
// Finally create the signed 16 bit image
BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
try (FileOutputStream fos = new FileOutputStream("/tmp/tst.png")) {
ImageIO.write(image, "png", fos);// <--- Here goes the exception
} catch (Exception ex) {
ex.printStackTrace();
}
So far so good but when I'm trying to use ImageIO.write to save it as PNG I'm getting ArrayIndexOutOfBoundsException.
Your code works fine for me, the only way I got your error was when I changed the bandOffsets. Could you give us more of your code?
EDIT
If you have negative data in your dataset, you should probably be using ushort instead of short.
int h = 64, w = 64;
short[] myRawImageData = new short[4096];
for (int i = 0; i < 4096; i++){
//this rolls over into negative numbers
myRawImageData[i] = (short) (i * 14);
}
// Create signed 16 bit data buffer, and compatible sample model
DataBuffer dataBuffer = new DataBufferUShort(myRawImageData, w * h);
SampleModel sampleModel = new ComponentSampleModel(DataBuffer.TYPE_USHORT, w, h, 1, w, new int[] {0});
// Create a raster from sample model and data buffer
WritableRaster raster = Raster.createWritableRaster(sampleModel, dataBuffer, null);
// Create a 16 bit signed gray color model
ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);
ColorModel colorModel = new ComponentColorModel(colorSpace, false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
// Finally create the signed 16 bit image
BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
try (FileOutputStream fos = new FileOutputStream("/tmp/tst.png")) {
ImageIO.write(image, "png", fos);// <--- Here goes the exception
} catch (Exception ex) {
ex.printStackTrace();
}
This is assuming you expect negative values to be the brighter half of the gamut.

Java - Convert RAW to JPG/PNG

I have an image captured by a camera, in RAW BGRA format (byte array).
How can I save it to disk, as a JPG/PNG file?
I've tried with ImageIO.write from Java API, but I got error IllegalArgumentException (image = null)
CODE:
try
{
InputStream input = new ByteArrayInputStream(img);
BufferedImage bImageFromConvert = ImageIO.read(input);
String path = "D:/image.jpg";
ImageIO.write(bImageFromConvert, "jpg", new File(path));
}
catch(Exception ex)
{
System.out.println(ex.toString());
}
Note that "img" is the RAW byte array, and that is NOT null.
The problem is that ImageIO.read does not support raw RGB (or BGRA in your case) pixels. It expects a file format, like BMP, PNG or JPEG, etc.
In your code above, this causes bImageFromConvert to become null, and this is the reason for the error you see.
If you have a byte array in BGRA format, try this:
// You need to know width/height of the image
int width = ...;
int height = ...;
int samplesPerPixel = 4;
int[] bandOffsets = {2, 1, 0, 3}; // BGRA order
byte[] bgraPixelData = new byte[width * height * samplesPerPixel];
DataBuffer buffer = new DataBufferByte(bgraPixelData, bgraPixelData.length);
WritableRaster raster = Raster.createInterleavedRaster(buffer, width, height, samplesPerPixel * width, samplesPerPixel, bandOffsets, null);
ColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
System.out.println("image: " + image); // Should print: image: BufferedImage#<hash>: type = 0 ...
ImageIO.write(image, "PNG", new File(path));
Note that JPEG is not a good format for storing images with alpha channel. While it is possible, most software will not display it properly. So I suggest using PNG instead.
Alternatively, you could remove the alpha channel, and use JPEG.
With Matlab you can convert all types of images with 2 lines of code:
img=imread('example.CR2');
imwrite(img,'example.JPG');

How can I convert BufferedImage to byte[]?

public void actionPerformed(java.awt.event.ActionEvent evt) {
Connection cn = null;
Object source = evt.getSource();
JFileChooser filechooser= new JFileChooser();
filechooser.setDialogTitle("Choose Your File");
filechooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
int returnval=filechooser.showOpenDialog(this);
if(returnval==JFileChooser.APPROVE_OPTION)
{
File file = filechooser.getSelectedFile();
BufferedImage bi;
try
{
bi=ImageIO.read(file);
lbl_movieCover.setIcon(new ImageIcon(bi));
}
catch(IOException e)
{
}
//this.pack();
}
Above is my code for choosing the image and displaying the image to JLabel. My problem is that, I don't know how to convert it to byte[] so I could save it to my database. By the way, I'm using MySQL for my database. If you guys know how to do it, please let me know.
Use ImageIO.write to write the image through a ByteArrayOutputStream, for example
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
ImageIO.write(bi, "png", baos);
} finally {
try {
baos.close();
} catch (Exception e) {
}
}
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
You can then use the resulting byte[] array or ByteArrayInputStream and pass this to the setBlob method of a PreparedStatement
You could use a ByteArrayOutputStream and ImageIO to write an image to a byte array, like this:
static byte[] imageToByteArray(BufferedImage image) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
ImageIO.write(image, "png", stream);
} catch(IOException e) {
// This *shouldn't* happen with a ByteArrayOutputStream, but if it
// somehow does happen, then we don't want to just ignore it
throw new RuntimeException(e);
}
return stream.toByteArray();
// ByteArrayOutputStreams don't need to be closed (the documentation says so)
}
You can use this method-
/**
* #param userSpaceImage
* #return byte array of supplied image
*/
public byte[] getByteData(BufferedImage userSpaceImage) {
WritableRaster raster = userSpaceImage.getRaster();
DataBufferByte buffer = (DataBufferByte) raster.getDataBuffer();
return buffer.getData();
}
Use it like-
//file from filechooser
BufferedImage originalImage = ImageIO.read(file);
byte image[] = getByteData(originalImage);
Note that if image type is that of int e.g. BufferedImage.TYPE_INT_RGB then
you will get cast exception. Following method can be used to convert to suitable type-
/**
* this method convert supplied image to suitable type
* it is needed because we need bytes of array so TYPE_INT images must be
* converted to BYTE_BGR or so
* #param originalImage loaded from file-chooser
* #return
*/
public BufferedImage convertImage(BufferedImage originalImage) {
int newImageType = originalImage.getType();
/**
* Converting int to byte since byte array is needed later to modify
* the image
*/
if (newImageType == BufferedImage.TYPE_INT_RGB
|| newImageType == BufferedImage.TYPE_INT_BGR) {
newImageType = BufferedImage.TYPE_3BYTE_BGR;
} else if (newImageType == BufferedImage.TYPE_INT_ARGB) {
newImageType = BufferedImage.TYPE_4BYTE_ABGR;
} else if (newImageType == BufferedImage.TYPE_INT_ARGB_PRE) {
newImageType = BufferedImage.TYPE_4BYTE_ABGR_PRE;
}
BufferedImage newImage = new BufferedImage(originalImage.getWidth(),
originalImage.getHeight(), newImageType);
Graphics g = newImage.getGraphics();
g.drawImage(originalImage, 0, 0, null);
g.dispose();
return newImage;
}
While both #MadProgrammer's and #immibis' answers are technically correct and answers your question, you don't really want to copy an image file by decoding it, and re-encoding it. This is because it's slower, but more importantly, you will lose quality for certain image formats (most notably JPEG) and any metadata associated with the image will be lost (this last part could of course be intentional, but there are better ways to do this without ruining the image quality).
So, instead, do as #immibis seems to hint at in his comment, just open a FileInputStream and read the bytes directly from the file, and into the database. You should be able to open an OutputStream to the blob in your database as well, so you can save some memory (a good thing, if your files are large) by not reading the entire file contents into a byte array, before writing.
Something like:
File file = filechooser.getSelectedFile();
// ... show image in label as before (but please, handle the IOException)
InputStream input = new FileInputStream(file);
try {
Blob blob = ...; // Get from JDBC connection
OutputStream output = blob.setBinaryStream(0);
try {
FileUtils.copy(input, output);
}
finally {
output.close();
}
}
finally {
input.close();
}
FileUtils.copy can be implemented as:
public void copy(final InputStream in, final OutputStream out) {
byte[] buffer = new byte[1024];
int count;
while ((count = in.read(buffer)) != -1) {
out.write(buffer, 0, count);
}
// Flush out stream, to write any remaining buffered data
out.flush();
}

Reducing Image Size and Saving it in MySQL DB with Java

I know that we can save image in mysql using BLOB Data Type and The Code i have used it as follows,
JFileChooser fc = new JFileChooser();
fc.setFileFilter(new JPEGImageFileFilter());
int res = fc.showOpenDialog(null);
try {
if (res == JFileChooser.APPROVE_OPTION) {
File image = new File(fc.getSelectedFile().getPath());
FileInputStream fis = new FileInputStream ( image );
String sql="insert into imgtst (username,image) values (?, ?)";
pst=con.prepareStatement(sql);
pst.setString(1, user);
pst.setBinaryStream (2, fis, (int) file.length() );
} else {
JOptionPane.showMessageDialog(null, "you must select image",
"Abortin", JOptionPane.WARNING_MESSAGE);
}
} catch (Exception ioException) {
e.printStackTrace();
}
Now What do i need to make sure the file size which is saving into the database should not be more than 100 KB if its more than that size i need some method to compress the size of an image to be 100 KB.Kindly give your valuable suggestions.
Try this
public static BufferedImage resizeImage(Image image, int width, int height) {
final BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
final Graphics2D graphics2D = bufferedImage.createGraphics();
graphics2D.setComposite(AlphaComposite.Src);
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2D.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
graphics2D.drawImage(image, 0, 0, width, height, null);
graphics2D.dispose();
return bufferedImage;
}
maybe you can try compress the image first before insert it into database.
this is the example i got for compressing the image :
File imageFile = new File("myimage.jpg");
File compressedImageFile = new File("myimage_compressed.jpg");
InputStream is = new FileInputStream(imageFile);
OutputStream os = new FileOutputStream(compressedImageFile);
float quality = 0.5f;
// create a BufferedImage as the result of decoding the supplied InputStream
BufferedImage image = ImageIO.read(is);
// get all image writers for JPG format
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
if (!writers.hasNext())
throw new IllegalStateException("No writers found");
ImageWriter writer = (ImageWriter) writers.next();
ImageOutputStream ios = ImageIO.createImageOutputStream(os);
writer.setOutput(ios);
ImageWriteParam param = writer.getDefaultWriteParam();
// compress to a given quality
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(quality);
// appends a complete image stream containing a single image and
//associated stream and image metadata and thumbnails to the output
writer.write(null, new IIOImage(image, null, null), param);
// close all streams
is.close();
os.close();
ios.close();
writer.dispose();

Categories

Resources