Java ImageIO.write to classpath? - java

I am trying to use the ImageIO class to save an image and then get the resource using an input stream. My problem is that I keep getting a NullPointerException whenever I try to create the input stream. If I simply go and put an image file in the class path, it works. Here is my code:
ImageIO.write(image, "png", new File("temp.png"));
InputStream imgIs = AptCap.class.getResourceAsStream("temp.png");
byte[] imgData = new byte[imgIs.available()]; // I get null here.
I have also tried specifying direct locations to files on the C drive for both of them, but I still get a null pointer exception. I would rather not do that anyway, but just keep it in the classpath (for purposes of multi OS support).

ByteArrayOutputStream baos = new ByteArrayOutputStream(); // create OutputStream
ImageIO.write(image, "png", baos); // write to OS
InputStream imgIs = new ByteArrayInputStream(baos.toByteArray()); // grab bytes from OS
//..

Related

Set ImageWriter output to ObjectOutputStream

I'm trying to compress images with this method: Setting jpg compression level with ImageIO in Java.
The solution works fine, but I use ObjectOutputStream instead of FileImageOutputStream, when I set the ObjectOutputStream as the writer output I get an java.lang.IllegalArgumentException: Illegal output type! exception. I need to use ObjectOutputStream.
This works perfectly ImageIO.write(img, "jpg", outstream);.
When you call ImageIO.write(img, "jpg", outstream);, the method will invoke ImageIO.createImageOutputStream(outstream) and pass the result to the ImageWriter. When you call setOutput directly, you must do that yourself.
ImageWriter w = ImageIO.getImageWritersByFormatName("jpg").next();
w.setOutput(ImageIO.createImageOutputStream(outputStream));
w.write(image);

How to get data blockwise from an outputstream in java?

I want to serialize a big object structure to store it to a sql database.
Object tree = getTree();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(tree);
String objectString = Base64.getEncoder().encodeToString(baos.toByteArray());
The problem is that the generated byte array by baos.toByteArray() is to large. It throws java.lang.OutOfMemoryError and it is to big to transfer it to the database at once. I'm looking for an option to get the generated byte array block by block from outputstream to work it off in a loop step by step.
Write the initial OutputStream to a temporary file (using FileOutputStream). also, make sure you close the ObjectOutputStream or it will be a malformed stream. Lastly, open your temp file as a FileInputStream and use that to stream into your database.
Forget about the base64-encoding and write the object directly to the Blob's output stream.

Inserting 1 MB image in neo4j returns a different size (536 KB) when retrieved

I am trying to insert a 1 MB image inside neo4j using the following code:
File fnew = new File("C:\\Users\\myimage.jpg");
BufferedImage originalImage = ImageIO.read(fnew);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.flus();
ImageIO.write(originalImage, "jpg", baos);
return baos.toByteArray();
Then I insert this byte array using:
user.setProperty("photo", photo);
This all goes fine. When I try to select the photo, using the following method, it writes it on my hard drive disk as 536KB instead of the 1 MB original size.
byte[] imageInByte = (byte[]) user.getProperty("photo");
InputStream in = new ByteArrayInputStream(imageInByte);
BufferedImage bImageFromConvert = ImageIO.read(in);
ImageIO.write(bImageFromConvert, "jpg", new File("C:\\newimage.jpg"));
Now the weird part: I can see the image, open it, same resolution, I don't see any difference in terms of quality though. Looks like it is compressed.
Why is this happening?
Saving a jpg image through ImageIO results in lossy compression of the jpg (I believe the quality defaults to 70%). You can a) Change the the quality of the image when you write to file (see Setting jpg compression level with ImageIO in Java ) or b) if you don't actually need the BufferedImage, just read/write the bytes from file to database.

Fastest way to read/write Images from a File into a BufferedImage?

What is the fastest way to read Images from a File into a BufferedImage in Java/Grails?
What is the fastest way to write Images from a BufferedImage into a File in Java/Grails?
my variant (read):
byte [] imageByteArray = new File(basePath+imageSource).readBytes()
InputStream inStream = new ByteArrayInputStream(imageByteArray)
BufferedImage bufferedImage = ImageIO.read(inStream)
my variant (write):
BufferedImage bufferedImage = // some image
def fullPath = // image page + file name
byte [] currentImage
try{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write( bufferedImage, "jpg", baos );
baos.flush();
currentImage = baos.toByteArray();
baos.close();
}catch(IOException e){
System.out.println(e.getMessage());
}
}
def newFile = new FileOutputStream(fullPath)
newFile.write(currentImage)
newFile.close()
Your solution to read is basically reading the bytes twice, once from the file and once from the ByteArrayInputStream. Don't do that
With Java 7 to read
BufferedImage bufferedImage = ImageIO.read(Files.newInputStream(Paths.get(basePath + imageSource)));
With Java 7 to write
ImageIO.write(bufferedImage, "jpg", Files.newOutputStream(Paths.get(fullPath)));
The call to Files.newInputStream will return a ChannelInputStream which (AFAIK) is not buffered. You'll want to wrap it
new BufferedInputStream(Files.newInputStream(...));
So that there are less IO calls to disk, depending on how you use it.
I'm late to the party, but anyway...
Actually, using:
ImageIO.read(new File(basePath + imageSource));
and
ImageIO.write(bufferedImage, "jpeg", new File(fullPath));
...might prove faster (try it, using a profiler, to make sure).
This is because these variants use RandomAccessFile-backed ImageInputStream/ImageOutputStream implementations behind the scenes, while the InputStream/OutputStream-based versions will by default use a disk-backed seekable stream implementation. The disk-backing involves writing the entire contents of the stream to a temporary file and possibly reading back from it (this is because image I/O often benefits from non-linear data access).
If you want to avoid extra I/O with the stream based versions, at the cost of using more memory, it is possible to call the ambiguously named ImageIO.setUseCache(false), to disable disk caching of the seekable input streams. This is obviously not a good idea if you are dealing with very large images.
You are almost good for writing. Just don't use the intermediate ByteArrayOutputStream. It is a giant bottleneck in your code. Instead wrap the FileOutputStream in a BufferedOutputStream and do the same.
Same goes indeed for your reading. Remove the Itermediate ByteArrayInputStream.

Not able to delete image file after image conversion from PNG to TIF

I am creating .PNG file using BufferedImage with some test. Now after creating image I am trying to convert .PNG image to .TIF, which is working fine. Now once I create TIF image, I want to delete PNG image. But because of some reason, I am not able to do this. There is no any exception for this.
Here is my code
File pngFile = null;
FileOutputStream fOut = null;
try {
pngFile = new File("C:\\Test.PNG");
fOut = new FileOutputStream ("C:\\Test.TIF");
RenderedOp src = JAI.create("fileload", "C:\\Test.PNG");
TIFFImageEncoder encoder = new TIFFImageEncoder (fOut, null);
encoder.encode (src);
}catch(Exception e) {
}finally {
fOut.close();
System.out.println(pngFile.delete());
}
Well there's definitely no exception since your catch block is empty.
Something may be still holding a handle to the file, not allowing it to be deleted.
I would examine JAI.create, RenderedOp and the TiffEncoder.
Instead of providing the file path as string you can provide input stream and in finally first close the input stream and then delete the file. This may work.
I was facing same problem sometime before. The best way to do it in this is to first dispose the resources using the image object you have create, like below-
var image = Image.FromFile(pngTarget); // here pngTarget is my PNG file's name along with complete path.
// your code to convert png to tiff
.
.
.
at the end of the method you can write below -
image.Dispose(); // the image object I have created above
File.Delete(pngTarget); // delete the file
Also, don't forget to flush/close the memory stream, if using any.
Thanks.

Categories