How can i convert a big bmp to a png? - java

I'm trying to convert a very big bmp file to a png.
I'm writing an app to make fractal image and I want to make a very high resolution image (like ultrahd).
I'll save bitmap pixel image directly into file with RandomAccessFile, so I will not allocate any Bitmap object into memory. The problem will be to convert the temporany bitmap to a png.
I found BitmapRegionDecoder but it is not usefull for my problem.
It is not easy to convert an image without a full data load. :(
I think a good solution could be a method look like: convertToPng(InputStream bitmapData, OutputStream pngStream).
My question is, how can i convert a very big bitmap to a png without have an OutOfMemoryException?

You can try the PNGJ library (disclaimer: I'm the author) which allows to read/write PNG images line by line.

Related

Extract image into a file from PDImageXObject without loading it into memory

This is related to How to extract image bytes out of PDF efficiently, but I'll try to restate the problem differently so it's less about PDF parsing and more about image processing.
I'm using PDFBox to extract images out of PDF files. There's an class PDImageXObject that represents the image inside the PDF, which contains image metadata (height, width, etc), and exposes two APIs to pull out the image are: BufferedImage getImage() and BufferedImage getImage(Rectangle rect, int subsampling);.
The current code is straightforward:
BufferedImage image = pdImage.getImage();
ImageIO.write(image, "jpg", baos);
However, for a large image, I'm having an issue with memory usage, as BufferedImage is storing uncompressed image data in memory, which is a lot bigger than the compressed result.
Is there a way to avoid loading the whole image into memory by breaking it up into tiles (e.g. 1024x1024) and iterating over them using the getImage signature that takes Rectangle? I'm seeing some promising information about JAI being able to use Tiles to output a compressed image without loading the uncompressed content into memory at once, but I don't understand how to tie it together with what I have from PDImageXObject. Or is there another way to do it? Is JAI still an active project?
By the way, the purpose of extracting the image is to feed it into the next component in the pipeline that can handle multiple image formats. So, if some format other than jpg, is more suited for tiled processing, that should be ok.
I'm aware of one possibility using something like BigBufferedImage. But I was thinking processing a Tile at a time looked promising.
OK, I found a libray: Commons Imaging. Class Imaging maybe can help you.
I think you can try createInputStream() method, find out the size of real data(bytes length).

How to compress an image up to 5kb?

How to write a Base64-encoded image to file?
I encoded an image to a string using Base64.
First, I read the file, then convert it to a byte array and then apply Base64 encoding to convert the image to a string.
Now my problem is how to compress image to 5kb.
Like Whatsapp Image Compression in Android.
If what you need is to store the image as "text" you can compress the Base64 string SO answer.
On the other hand you can reduce resolution of the image by lowering its size.
Not all the images can be compressed to 5kb without losing quality, but making proper resolution changes and compresing the image it can be achieved Another SO answer.

Modify image data in ByteBuffer

I would like to modify the per-pixel RGB color data of a PNG image that I have loaded as a ByteBuffer, preferably a simple, lightweight solution.
I currently load the data directly from the file into a ByteBuffer using a ReadableByteChannel, which does not decode the PNG data.
So the question is, how do I
Decode the ByteBuffer PNG data into something where I can modify the pixel data
Turn it back into a valid ByteBuffer ('valid' means that it would be accepted by an OpenGl shader)
The PNG image encoding includes (among other things) a ZLIB compression, you cannot access the pixel values directly. You need (practically speaking) to decode the image, for example reading it into a BufferedImage with ImageIO.read( )
If for some reason (huge image, memory constraints) you don't like to load the full image in memory in a BufferedImage you could use a progressive reader (eg PNGJ)

Converting Pixel Array to Image in Java

I have used this code to get Image into array of pixels.
convertTo2DWithoutUsingGetRGB method for reading image to pixel array
writeToFile method for pixel array to image
Now I would like to convert the array of pixels to Image. But when I convert it, I am losing image data.
Initial Image size: 80Kb JPG
Duplicate Image size: 71Kb JPG
I can clearly notice some difference between the both images, the Java produced image has some sort of white-noise.
I would like to reproduce the image without single pixel loss of data, how do I achieve in Java?
The jpg file format uses a lossy compression algorithm which means that the files it generates will have slight differences from the original. You can change the quality setting to compress more or less but you can't save the with its original size without any modifications.
This is why jpg isn't recommended for image editing. Use a lossless format instead, like PNG.

Read/write imag files by lines or by pixels using Java

I have a specific object with image data. And I want read/write images (in BMP, JPEG and PNG formats) to this object.
Of course, I can read/write image into/from BufferedImage and then copy/paste pixels into/from my object. But, I want to do it more faster without intermediate objects!
How can I perform it over standard Java library or throw other Java library?
P.S.:
I know pngj library that allow read PNG images by lines. Maybe you know same libraries for BMP, JPEG (or for all of them: BMP, JPEG, PNG)?
Why don't you just have the BufferedImage in your Object? BufferedImage isn't all that bad. Otherwise, you will need to use something like BufferedImage to convert the image file into pixels, and then read the BufferedImage into something like an int[] array of pixels, but it still requires BufferedImage in the middle, and this would slow things down by adding an extra loop to read over and store the pixels.
Is there a reason why BufferedImage isn't suitable for your purpose?
If you want to do all the reading by yourself, you can just open the file with a stream and read it into an array, but you would need to work your way through the whole structure of the file (headers etc...) if you are working with compressed formats you'd have to work on that too.
Best would be to use imageio to load/write your files and I don't believe there is a lot of overhead coming from the read/write of your images.
Also if you expect to do some heavy work on the images, know that BufferedImages can be hardware accelerated which will improve performance a lot.

Categories