/* * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.facebook.animated.webp; import javax.annotation.concurrent.ThreadSafe; import java.nio.ByteBuffer; import com.facebook.common.internal.DoNotStrip; import com.facebook.common.internal.Preconditions; import com.facebook.imagepipeline.animated.base.AnimatedDrawableFrameInfo; import com.facebook.imagepipeline.animated.base.AnimatedDrawableFrameInfo.BlendOperation; import com.facebook.imagepipeline.animated.base.AnimatedDrawableFrameInfo.DisposalMethod; import com.facebook.imagepipeline.animated.base.AnimatedImage; import com.facebook.imagepipeline.animated.factory.AnimatedImageDecoder; import static com.facebook.imagepipeline.nativecode.StaticWebpNativeLoader.ensure; /** * A representation of a WebP image. An instance of this class will hold a copy of the encoded * data in memory along with the parsed header data. Frames are decoded on demand via * {@link WebPFrame}. */ @ThreadSafe @DoNotStrip public class WebPImage implements AnimatedImage, AnimatedImageDecoder { // Accessed by native methods @SuppressWarnings("unused") @DoNotStrip private long mNativeContext; @DoNotStrip public WebPImage() { } /** * Constructs the image with the native pointer. This is called by native code. * * @param nativeContext the native pointer */ @DoNotStrip WebPImage(long nativeContext) { mNativeContext = nativeContext; } @Override protected void finalize() { nativeFinalize(); } @Override public void dispose() { nativeDispose(); } /** * Creates a {@link WebPImage} from the specified encoded data. This will throw if it fails * to create. This is meant to be called on a worker thread. * * @param source the data to the image (a copy will be made) */ public static WebPImage create(byte[] source) { ensure(); Preconditions.checkNotNull(source); ByteBuffer byteBuffer = ByteBuffer.allocateDirect(source.length); byteBuffer.put(source); byteBuffer.rewind(); return nativeCreateFromDirectByteBuffer(byteBuffer); } public static WebPImage create(long nativePtr, int sizeInBytes) { ensure(); Preconditions.checkArgument(nativePtr != 0); return nativeCreateFromNativeMemory(nativePtr, sizeInBytes); } @Override public AnimatedImage decode(long nativePtr, int sizeInBytes) { return WebPImage.create(nativePtr, sizeInBytes); } @Override public int getWidth() { return nativeGetWidth(); } @Override public int getHeight() { return nativeGetHeight(); } @Override public int getFrameCount() { return nativeGetFrameCount(); } @Override public int getDuration() { return nativeGetDuration(); } @Override public int[] getFrameDurations() { return nativeGetFrameDurations(); } @Override public int getLoopCount() { return nativeGetLoopCount(); } @Override public WebPFrame getFrame(int frameNumber) { return nativeGetFrame(frameNumber); } @Override public int getSizeInBytes() { return nativeGetSizeInBytes(); } @Override public boolean doesRenderSupportScaling() { return true; } @Override public AnimatedDrawableFrameInfo getFrameInfo(int frameNumber) { WebPFrame frame = getFrame(frameNumber); try { return new AnimatedDrawableFrameInfo( frameNumber, frame.getXOffset(), frame.getYOffset(), frame.getWidth(), frame.getHeight(), frame.isBlendWithPreviousFrame() ? BlendOperation.BLEND_WITH_PREVIOUS : BlendOperation.NO_BLEND, frame.shouldDisposeToBackgroundColor() ? DisposalMethod.DISPOSE_TO_BACKGROUND : DisposalMethod.DISPOSE_DO_NOT); } finally { frame.dispose(); } } private static native WebPImage nativeCreateFromDirectByteBuffer(ByteBuffer buffer); private static native WebPImage nativeCreateFromNativeMemory(long nativePtr, int sizeInBytes); private native int nativeGetWidth(); private native int nativeGetHeight(); private native int nativeGetDuration(); private native int nativeGetFrameCount(); private native int[] nativeGetFrameDurations(); private native int nativeGetLoopCount(); private native WebPFrame nativeGetFrame(int frameNumber); private native int nativeGetSizeInBytes(); private native void nativeDispose(); private native void nativeFinalize(); }