Android : How to iterate through webp frames using android's ImageDecoder - java

I want to convert the animated webp into gif and I have gif encoder+decoder and webp ecnoder and it is working fine with gifs only. I want to process the animated webp as well so I need to decode the animated webp first and get bitamps for each frames. I could not get any animated webp decoder and later found that android.graphic has Image decoder which support animated webp image but it shown example for drawable and it has start() method for animated webp.
How can I iterate through each frames to convert them into bitmap or some data type like byte[], base64, streams, etc so that i can convet that into bitmap.
File file = new File(...);
ImageDecoder.Source source = ImageDecoder.createSource(file);
Drawable drawable = ImageDecoder.decodeDrawable(source);

As alternative for achieving same goal I have solved this by using Glide and APNG4 library along with some encoder decoder available on git.
You can do both encode decode and and other stuff alone with APNG4.
https://github.com/penfeizhou/APNG4Android

Here is how we can extract frames from animated webp file without using any third party library.
According to Google's Container Specification for WebP image format,
We need to read the image in specific way and you can do that with almost any language you like.
In Java you can create InputStream of animated webp file and read data in 4 bytes in sequence.
There is library android-webp-encoder for encoding webp image and written in pure java.
Although you can use it for decoding the image as well. Need to modify the the library. I have modified it but not published yet. Soon I will upload it on github as I fix the bugs.
But I can explain how to modify that library to decode frames or write your own codes to decode.
First create inputstream of image
Read data in 4 bytes chunks till the end of file.
Reading:
Read 4 bytes and check if it is 'RIFF' characters.
Then read next 4 bytes. This is file size.
After file size next 4 bytes must be 'WEBP' characters
Next 4 bytes will give 'VP8X' characters. Our actual image data and parameters starts from here.
Next 4 bytes must should contain value 10 as after that we need to read 10 bytes in specific manner stated in the google's container specification.
After VP8X, ANIM and other optional chunks we have to read ANMF followed by ALPH (optional) data, VP8/VP8L data. these are the actual image data we need to extract and create bitmaps out of it.
Each ANMF occurrence will signal us about each frames.
You can write static webp image data to ByteArrayOutputStream and create
bitmap using BitmapFactory.decodeByteArray(stream). This will return bitmap image of that frame.

Related

Extract TIFF images from PDF without decoding

With the help of iText 5 I would like to extract all TIFF images from given PDF file and save them as TIFF files.
Examples and other posts (1, 2) use the following method:
Create PdfImageObject from PDF stream which in line 189 decodes the image stream (if corresponding filter implementation is present).
Call PdfImageObject#getImageAsBytes() which returns JPEG (original), PNG (re-encoded) or TIFF (in case of 8 bits per pixel).
As a result TIFF image with 1 bit color depth is converted to PNG, which is not what I need.
Another approach would be to call PdfImageObject#getBufferedImage() which will decode the image in step (2) into raster and afterwards encode it again as TIFF using ImageIO.write(bufferedImage, "tiff", file).
As one can see this is not efficient. Another solution shown in this post demonstrates how to save encoded TIFF image stream to file by prepending it a TIFF header – that is the solution I am looking for.
Can iText help here?
PDF images are not TIFF images.
PDFs however can contain images that use compression techniques that are also used in TIFF, e.g. Flate, CCITT, LZW, JPEG.

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.

Decode SVG image file (encoded as base64) in java

I have SVG file encoded as base64, and I want to show the image with ImageView.
This is what I tried:
// imageBase64 is string that represents the SVG image encoded as base64
byte[] decodedString = Base64.decode(imageBase64, Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
but decodedByte always returned null.
PS:
This code works with jpeg images.
If the base64 string contains the base64 prefix
("data:image/svg+xml;base64," or "data:image/jpeg;base64,) the decodedByte always returned null too
The base64 string is correct (its works good in HTML and other base64
online tools)
(This is based on Robert Longson's insightful comments.)
Your problem is not related to the base64 encoding. It is more fundamental than that.
The approach you are currently taking won't work because BitmapFactory will only decode bitmap file formats. The Bitmap class will only represent PNG, JPG and GIF formats; see the javadoc. (SVG is a vector graphic format not a bitmap format.)
The second issue is that Android does not currently have native support for SVG in ImageView. So you have two alternatives:
Display the SVG graphics using an embedded browser window. Android 3+ default browsers support SVG. (Android 2 browsers don't, though there are possible workarounds.)
Use a 3rd-party SVG library. There are examples that use a Picture object and others that use a subclass of ImageView. Investigate the options and choose the one that best meets your requirements.
For more details of the alternatives, read the various answers to:
SVG support on Android

Working with JPEG images in Java

I am using the BufferedImage class to read in an image as pixels which I then use bit shifting to get their appropriate components into separate int arrays. This works OK.
I have used this reference site to manually perform DCT functions with the pixel arrays.
Methods used: forwardDCT(), quantitizeMatrix(), dequantitzeMatrax(), inverseDCT()
which then are fed back into a resultant image array to reconstruct the JPEG file, which I then use BufferedImage's write() method to write the pixel data back out as the image.
This works perfectly, and I can view the image. (Even better the value I use to compress visually works).
My question is, is there a way to write the quantitize coefficients as the compressed values as a JPEG?
Because the BufferedImage write() method is used to input pixel data, rather than coefficient data?
Hope this is clear.
Thanks
Ultimately the DCT calculation is just one step in the whole JPEG encoding process. A complete implementation also has to deal with quantization, Huffman encoding, and conforming with the JPEG standard.
Java effectively just gives you an interface to a JPEG encoder that lets you do useful things like save images.
The ImageWriter that ImageIO.write() uses for JPEG images depends on your system. The default ImageWriter for JPEGs will only let you change some settings that affect the quantization and encoding using the JPEGImageWriteParam class (http://docs.oracle.com/javase/6/docs/api/javax/imageio/ImageWriteParam.html).
Getting your hand-crafted DCT coefficients into a JPEG file could potentially involve writing an entire JPEG library. If you don't want to do all that work, then you could modify the source of an existing library so that it uses your DCT coefficients.
Before the DCT . . .
While JPEG has no knowledge of colors, it is normal for JPEG file formats to use the YCbCr color space. If you are thinking about writing a JPEG file, you would need to do this conversion first.
After the Quantization . . .
The coefficients are run length encoded. That's a step you'd have to add. That's the most complex part of JPEG encoding.

How to get a better understanding of a png representation on java?

I want to dive in the low level of how a png file is represented on memory in java, so that i can iterate over its pixels, change them, create a modified png file using existing one, etc.
Where do i begin?
You could begin by reading it into a BufferedImage with ImageIO.read(file) .
The getRGB(...) methods can help you to obtain information about the individual pixels, and the corresponding setRGB(...) methods help you to change them.
The representation of an image in memory in Java, is essentially unrelated to the format of the file: be it PNG, JPEG, GIF or whatever, those are standards for encoding an image as a (language independent) stream of bytes. But when you are manipulating the pixels of an image in memory, you have already decoded it, and so you've "forgotten" from which format (PNG, JPEG...) it came from.
The most common way of manipulating an image in Java is using the BufferedImage class, included in the java.awt.image.* package. But that's not a requisite. For instance, I've worked on a low level PNG coder/encoder (PNGJ) that does not use BufferedImage, but instead gives you each image line as an int[] array.

Categories