|
10 | 10 | import static com.github.stickerifier.stickerify.media.MediaConstraints.MAX_VIDEO_FILE_SIZE; |
11 | 11 | import static com.github.stickerifier.stickerify.media.MediaConstraints.MAX_VIDEO_FRAMES; |
12 | 12 | import static com.github.stickerifier.stickerify.media.MediaConstraints.VP9_CODEC; |
| 13 | +import static java.nio.charset.StandardCharsets.ISO_8859_1; |
13 | 14 | import static java.nio.charset.StandardCharsets.UTF_8; |
14 | 15 |
|
15 | 16 | import com.github.stickerifier.stickerify.exception.CorruptedFileException; |
@@ -46,6 +47,12 @@ public final class MediaHelper { |
46 | 47 | private static final int IMAGE_KEEP_ASPECT_RATIO = -1; |
47 | 48 | private static final int VIDEO_KEEP_ASPECT_RATIO = -2; |
48 | 49 |
|
| 50 | + private static final int WEBP_CHUNK_TYPE_OFFSET = 12; |
| 51 | + private static final int WEBP_CHUNK_TYPE_LENGTH = 4; |
| 52 | + private static final int WEBP_FLAGS_BYTE_OFFSET = 20; |
| 53 | + private static final int WEBP_ANIMATION_BIT_MASK = 0x02; |
| 54 | + private static final String WEBP_EXTENDED_FILE_FORMAT = "VP8X"; |
| 55 | + |
49 | 56 | /** |
50 | 57 | * Based on the type of passed-in file, it converts it into the proper media. |
51 | 58 | * If no conversion was needed, {@code null} is returned. |
@@ -313,15 +320,16 @@ private static boolean isSupportedImage(File image, String mimeType) { |
313 | 320 | */ |
314 | 321 | private static boolean isAnimatedWebp(File file) { |
315 | 322 | try (var fileInputStream = new FileInputStream(file)) { |
316 | | - var header = new byte[256]; |
317 | | - int bytesRead = fileInputStream.read(header); |
318 | | - |
319 | | - if (bytesRead < 32) { |
| 323 | + var header = new byte[WEBP_FLAGS_BYTE_OFFSET + 1]; |
| 324 | + if (fileInputStream.read(header) < 21) { |
320 | 325 | return false; |
321 | 326 | } |
322 | 327 |
|
323 | | - var headerContent = new String(header, UTF_8); |
324 | | - return headerContent.contains("ANIM"); |
| 328 | + var chunkHeader = new String(header, WEBP_CHUNK_TYPE_OFFSET, WEBP_CHUNK_TYPE_LENGTH, ISO_8859_1); |
| 329 | + boolean isExtendedFormat = WEBP_EXTENDED_FILE_FORMAT.equals(chunkHeader); |
| 330 | + boolean hasAnimationFlag = (header[WEBP_FLAGS_BYTE_OFFSET] & WEBP_ANIMATION_BIT_MASK) != 0; |
| 331 | + |
| 332 | + return isExtendedFormat && hasAnimationFlag; |
325 | 333 | } catch (IOException e) { |
326 | 334 | LOGGER.atWarn().setCause(e).log("An error occurred checking if the file is an animated WebP"); |
327 | 335 | return false; |
|
0 commit comments