Fixing @ccomangee's solution.
Some static webp images would be detected as animated and can cause issue in the application.
I had extracted webp frames and saved as webp images and tried to identify by checking VP8X signature and it exists in given position although It is static image. So if there is VP8X it does not mean that the image would be animated having more than one frames.
I tried few images with my solution and the result is below:
riff webp vp8* anim
OK(anim-trans).webp: [ RIFF | WEBP | VP8X | ANIM ]
Cuppy(static-trans).webp: [ RIFF | WEBP | VP8L | NA? ]
glass(anim-solid).webp: [ RIFF | WEBP | VP8X | ANIM ]
sunset(anim-trans).webp: [ RIFF | WEBP | VP8X | ANIM ]
atom(anim_solid).webp: [ RIFF | WEBP | VP8X | ANIM ]
spread(anim-trans).webp: [ RIFF | WEBP | VP8X | ANIM ]
heart(static-trans).webp: [ RIFF | WEBP | VP8X | NA? ]
ludo(static-trans).webp: [ RIFF | WEBP | VP8X | NA? ]
scene(static_solid).webp: [ RIFF | WEBP | VP8 | NA? ]
Here all images are named according to its type.
anim-trans: animated image contains transparency (alpha channel support)
anim-solid: animated image having no transparency
static-trans and static-solid are static images.
VP8L is loseless webp and VP8X contains extended features.
VP8 is surely static image.
If VP8X exists it could be static or animated most images would be animated.
The solution is
Read 4 bytes -> 'RIFF'
Skip 4 bytes
Read 4 bytes -> 'WEBP'
Read 4 bytes -> 'VP8X' / 'VP8L' / 'VP8'
skip 14 bytes
Read 4 bytes -> 'ANIM'
Java Code:
public static boolean check(File file) {
boolean riff = false;
boolean webp = false;
boolean vp8x = false;
boolean anim = false;
try (InputStream in = new FileInputStream(file)) {
byte[] buf = new byte[4];
int i = in.read(buf); // 4
if(buf[0] == 0x52 && buf[1] == 0x49 && buf[2]==0x46 && buf[3] == buf[2] )
riff = true;
in.skip(4); // ???? (8+)
i = in.read(buf); // (12+)
if(buf[0] == 0x57 && buf[1] == 0x45 && buf[2]==0x42 && buf[3] == 0x50 )
webp = true ;
i = in.read(buf); // (16+)
if(buf[0] == 0x41 && buf[1] == 0x4e && buf[2]==0x49 && buf[3] == 0x4d );
vp8x = true;
in.skip(14); // then next 4 should contain ANIM - 41 4e 49 4d
i = in.read(buf);
if(buf[0] == 0x41 && buf[1] == 0x4e && buf[2]==0x49 && buf[3] == 0x4d )
anim = true;
} catch (Exception e) {
System.out.println("errrrrr "+e.getMessage());
}
return riff && webp && anim;
}
you can directly read WEBP by skipping 8 bytes then count and skipp all chunks before ANIM and read that position if ANIM exist then its animated webp image else static.
File layout of webp images
https://developers.google.com/speed/webp/docs/riff_container#example_file_layouts
Ref: Google WEBP specification https://developers.google.com/speed/webp/docs/riff_container