'How to identify whether webp image is static or animated?
I am working on a project where a user can upload webp
images. I know how to convert webp
images into jpg/png, but am stuck on how to identify whether the webp
image is static (non-animated) or animated.
I want to identify them because I use different commands for conversion:
Command for non-animated webp to jpg:
dwebp nonanimated.webp -o jpg.jpg
Command for animated webp to non-animated webp (takes 2nd frame):
webpmux -get frame 2 animated.webp -o nonanimated.webp
But I cannot find a single command that handle both cases.
I am using PHP on the server side, and HTML and Javascript for frontend.
Solution 1:[1]
After a lot of investigation i found that animated webp
images always conatins some string, when open in a text editor and non animated images doesn't. The strings are ANMF
and ANIM
. I checked these string in all webp images which i have. So this is perfect for me. Here are some solutions in PHP
, Javascript
and Shell Script
:
In PHP:
<?php
function isWebpAnimated($src){
$webpContents = file_get_contents($src);
$where = strpos($webpContents, "ANMF");
if ($where !== FALSE){
// animated
$isAnimated = true;
}
else{
// non animated
$isAnimated = false;
}
return $isAnimated;
}
?>
In Javascript:
function isAnimatedGif(src) {
var request = new XMLHttpRequest();
request.open('GET', src, true);
request.addEventListener('load', function () {
if(request.response.indexOf("ANMF") != -1){
// animated
alert(true);
}
else{
// non animated
alert(false);
}
});
request.send();
}
But In case of large images PHP
and Javascript
not working well, So best Solution is to use Shell Script
, If you have Ubuntu
.
In Shell Script:
echo $(grep -c "ANMF" ~/animated.webp)
return 0 if non animated, else non zero value for animated.
Solution 2:[2]
There are flags in Webp header, ANIMATION among others. Small function to check it:
function isWebpAnimated($fn){
$result = false;
$fh = fopen($fn, "rb");
fseek($fh, 12);
if(fread($fh, 4) === 'VP8X'){
fseek($fh, 16);
$myByte = fread($fh, 1);
$result = ((ord($myByte) >> 1) & 1)?true:false;
}
fclose($fh);
return $result;
}
ANIM and ANMF are from next chunk headers.
Solution 3:[3]
According Sven Liivak's isWebpAnimated()
... there is a small bug.
fseek($fh, 16);
should be:
fseek($fh, 20);
Because postion 16
is the chunk_size
position in VP8X
.
But we need the flag
position which is at 20
.
Fixed function:
function isWebpAnimated($fn){
$result = false;
$fh = fopen($fn, "rb");
fseek($fh, 12);
if(fread($fh, 4) === 'VP8X'){
fseek($fh, 20);
$myByte = fread($fh, 1);
$result = ((ord($myByte) >> 1) & 1)?true:false;
}
fclose($fh);
return $result;
}
Solution 4:[4]
This is my java code, it works for me.
static boolean isWebpAnimated(InputStream in) {
boolean result = false;
try {
in.skip(12);
byte[] buf = new byte[4];
int i = in.read(buf);
if ("VP8X".equals(new String(buf, 0, i))) {
in.skip(12);
result = (in.read(buf) == 4 && (buf[3] & 0x00000002) != 0);
}
} catch (Exception e) {
} finally {
try {
in.close();
} catch (Exception e) {
}
}
return result;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | HarisH Sharma |
Solution 2 | |
Solution 3 | Hans-Jürgen Petrich |
Solution 4 | ccomangee |