Loading include/android/imagedecoder.h +375 −9 Original line number Diff line number Diff line Loading @@ -109,7 +109,19 @@ enum { /** * AImageDecoder did not recognize the format. */ ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT = -9 ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT = -9, /** * The animation has reached the end. */ ANDROID_IMAGE_DECODER_FINISHED = -10, /** * This method cannot be called while the AImageDecoder is in its current * state. For example, various setters (like {@link AImageDecoder_setTargetSize}) * can only be called while the AImageDecoder is set to decode the first * frame of an animation. This ensures that any blending and/or restoring * prior frames works correctly. */ ANDROID_IMAGE_DECODER_INVALID_STATE = -11, }; struct AImageDecoder; Loading @@ -127,7 +139,7 @@ struct AImageDecoder; * After creation, {@link AImageDecoder_getHeaderInfo} can be used to retrieve * information about the encoded image. Other functions, like * {@link AImageDecoder_setTargetSize}, can be used to specify how to decode, and * {@link AImageDecoder_decode} will decode into client provided memory. * {@link AImageDecoder_decodeImage} will decode into client provided memory. * * {@link AImageDecoder} objects are NOT thread-safe, and should not be shared across * threads. Loading Loading @@ -240,6 +252,10 @@ void AImageDecoder_delete(AImageDecoder* _Nonnull decoder) __INTRODUCED_IN(30); /** * Choose the desired output format. * * If the encoded image represents an animation, this must be called while on * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or * after calling {@link AImageDecoder_rewind}). * * Available since API level 30. * * @param format {@link AndroidBitmapFormat} to use for the output. Loading @@ -255,6 +271,8 @@ void AImageDecoder_delete(AImageDecoder* _Nonnull decoder) __INTRODUCED_IN(30); * {@link AndroidBitmapFormat}. * - {@link ANDROID_IMAGE_DECODER_INVALID_CONVERSION}: The * {@link AndroidBitmapFormat} is incompatible with the image. * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on * the first frame. */ int AImageDecoder_setAndroidBitmapFormat(AImageDecoder* _Nonnull decoder, int32_t format) __INTRODUCED_IN(30); Loading @@ -266,6 +284,10 @@ int AImageDecoder_setAndroidBitmapFormat(AImageDecoder* _Nonnull decoder, * Pass true to this method to leave them unpremultiplied. This has no effect on an * opaque image. * * If the encoded image represents an animation, this must be called while on * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or * after calling {@link AImageDecoder_rewind}). * * Available since API level 30. * * @param unpremultipliedRequired Pass true to leave the pixels unpremultiplied. Loading @@ -278,6 +300,8 @@ int AImageDecoder_setAndroidBitmapFormat(AImageDecoder* _Nonnull decoder, * {@link AImageDecoder_setTargetSize}. * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The * {@link AImageDecoder} is null. * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on * the first frame. */ int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* _Nonnull decoder, bool unpremultipliedRequired) __INTRODUCED_IN(30); Loading @@ -288,6 +312,10 @@ int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* _Nonnull decoder, * Ignored by {@link ANDROID_BITMAP_FORMAT_A_8}, which does not support * an {@link ADataSpace}. * * If the encoded image represents an animation, this must be called while on * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or * after calling {@link AImageDecoder_rewind}). * * Available since API level 30. * * @param dataspace The {@link ADataSpace} to decode into. An ADataSpace Loading @@ -303,6 +331,8 @@ int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* _Nonnull decoder, * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The * {@link AImageDecoder} is null or |dataspace| does not correspond to an * {@link ADataSpace} value. * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on * the first frame. */ int AImageDecoder_setDataSpace(AImageDecoder* _Nonnull decoder, int32_t dataspace) __INTRODUCED_IN(30); Loading @@ -316,6 +346,10 @@ int AImageDecoder_setDataSpace(AImageDecoder* _Nonnull decoder, int32_t dataspac * specified by width and height, and the output image will be the size of the * crop rect. * * If the encoded image represents an animation, this must be called while on * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or * after calling {@link AImageDecoder_rewind}). * * Available since API level 30. * * @param width Width of the output (prior to cropping). Loading @@ -330,9 +364,11 @@ int AImageDecoder_setDataSpace(AImageDecoder* _Nonnull decoder, int32_t dataspac * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The * {@link AImageDecoder} is null. * - {@link ANDROID_IMAGE_DECODER_INVALID_SCALE}: |width| or |height| is <= 0, * the size is too big, any existing crop is not contained by the new image dimensions, * or the scale is incompatible with a previous call to * the size is too big, any existing crop is not contained by the new image * dimensions, or the scale is incompatible with a previous call to * {@link AImageDecoder_setUnpremultipliedRequired}(true). * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on * the first frame. */ int AImageDecoder_setTargetSize(AImageDecoder* _Nonnull decoder, int32_t width, int32_t height) __INTRODUCED_IN(30); Loading Loading @@ -374,6 +410,10 @@ int AImageDecoder_computeSampledSize(const AImageDecoder* _Nonnull decoder, int * the specified {@link ARect}. Clients will only need to allocate enough memory * for the cropped ARect. * * If the encoded image represents an animation, this must be called while on * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or * after calling {@link AImageDecoder_rewind}). * * Available since API level 30. * * @param crop Rectangle describing a crop of the decode. It must be contained inside of Loading @@ -389,8 +429,10 @@ int AImageDecoder_computeSampledSize(const AImageDecoder* _Nonnull decoder, int * * Errors: * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The * {@link AImageDecoder} is null or the crop is not contained by the * {@link AImageDecoder} is null, or the crop is not contained by the * (possibly scaled) image dimensions. * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on * the first frame. */ int AImageDecoder_setCrop(AImageDecoder* _Nonnull decoder, ARect crop) __INTRODUCED_IN(30); Loading Loading @@ -472,6 +514,10 @@ int32_t AImageDecoderHeaderInfo_getAndroidBitmapFormat( * {@link AImageDecoder_decodeImage} will premultiply pixels by default. * * Available since API level 30. * * Starting in API level 31, an AImageDecoder may contain multiple frames of an * animation, but this method still only reports whether the first frame has * alpha. */ int AImageDecoderHeaderInfo_getAlphaFlags( const AImageDecoderHeaderInfo* _Nonnull) __INTRODUCED_IN(30); Loading Loading @@ -518,8 +564,44 @@ size_t AImageDecoder_getMinimumStride(AImageDecoder* _Nonnull decoder) __INTRODU * Available since API level 30. * * Starting in API level 31, it can be used to decode all of the frames of an * animated image (i.e. GIF, WebP, HEIF) using new APIs (TODO (scroggo): list * and describe here). * animated image (i.e. GIF, WebP, HEIF) using new APIs. Internally, * AImageDecoder keeps track of its "current frame" - that is, the frame that * will be decoded by a call to AImageDecoder_decodeImage. At creation time, the * current frame is always the first frame, and multiple calls to this method * will each decode the first frame. {@link AImageDecoder_advanceFrame} advances * the current frame to the following frame, so that future calls to this method * will decode that frame. Some frames may update only part of the image. They * may only update a sub-rectangle (see {@link * AImageDecoderFrameInfo_getFrameRect}), or they may have alpha (see * {@link AImageDecoderFrameInfo_hasAlphaWithinBounds}). In these cases, this * method assumes that the prior frame is still residing in the |pixels| buffer, * decodes only the new portion, and blends it with the buffer. Frames that change * the entire |pixels| buffer are "independent", and do not require the prior * frame to remain in the buffer. The first frame is always independent. A * sophisticated client can use information from the {@link AImageDecoderFrameInfo} * to determine whether other frames are independent, or what frames they rely on. * * If the current frame is marked {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS}, * AImageDecoder_decodeImage will cache the |pixels| buffer prior to decoding * (note: this only happens for the first in a string of consecutive * ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS frames). After advancing to the * following frame, AImageDecoder_decodeImage will restore the cached buffer * prior to decoding that frame. * * Ignoring timing information, display, etc, a client wishing to decode all * frames of an animated image may conceptually use code like the following: * * while (true) { * int result = AImageDecoder_decodeImage(decoder, pixels, stride, size); * if (result != ANDROID_IMAGE_DECODER_SUCCESS) break; * * // Display or save the image in |pixels|, keeping the buffer intact for * // AImageDecoder to decode the next frame correctly. * Application_viewImage(pixels); * * result = AImageDecoder_advanceFrame(decoder); * if (result != ANDROID_IMAGE_DECODER_SUCCESS) break; * } * * @param decoder Opaque object representing the decoder. * @param pixels On success, will be filled with the result Loading Loading @@ -547,6 +629,10 @@ size_t AImageDecoder_getMinimumStride(AImageDecoder* _Nonnull decoder) __INTRODU * failed to seek. * - {@link ANDROID_IMAGE_DECODER_INTERNAL_ERROR}: Some other error, like a * failure to allocate memory. * - {@link ANDROID_IMAGE_DECODER_FINISHED}: The input contains no * more frames. No decoding occurred. The client must call * {@link AImageDecoder_rewind} before calling * {@link AImageDecoder_decodeImage} again. */ int AImageDecoder_decodeImage(AImageDecoder* _Nonnull decoder, void* _Nonnull pixels, size_t stride, Loading @@ -561,8 +647,8 @@ int AImageDecoder_decodeImage(AImageDecoder* _Nonnull decoder, * * Introduced in API 31. * * This may require seeking past the first frame to verify whether * there is a following frame (e.g. for GIF). * A single frame GIF is considered to *not* be animated. This may require * seeking past the first frame to verify whether there is a following frame. * * Errors: * - returns false if |decoder| is null. Loading Loading @@ -610,6 +696,286 @@ enum { int32_t AImageDecoder_getRepeatCount(AImageDecoder* _Nonnull decoder); __INTRODUCED_IN(31); /** * Advance to the next frame in the animation. * * Introduced in API 31. * * The AImageDecoder keeps track internally which frame it is ready to decode * (the "current frame"). Initially it is set to decode the first frame, and * each call to {@link AImageDecoder_decodeImage} will continue to decode * the same frame until this method (or {@link AImageDecoder_rewind}) * is called. * * Note that this can be used to skip a frame without decoding it. But * some frames depend on (i.e. blend with) prior frames, and * AImageDecoder_decodeImage assumes that the prior frame is in the * |pixels| buffer. In addition, AImageDecoder_decodeImage handles caching and * restoring frames (see {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS}), so * skipping frames in an image with such frames may not produce the correct * results. * * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value * indicating the reason for the failure. * * Errors: * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The AImageDecoder * represents an image that is not animated (see * {@link AImageDecoder_isAnimated}) or the AImageDecoder is null. * - {@link ANDROID_IMAGE_DECODER_INCOMPLETE}: The input appears * to be truncated. The client must call {@link AImageDecoder_rewind} * before calling {@link AImageDecoder_decodeImage} again. * - {@link ANDROID_IMAGE_DECODER_ERROR}: The input contains an error. * The client must call {@link AImageDecoder_rewind} before * calling {@link AImageDecoder_decodeImage} again. * - {@link ANDROID_IMAGE_DECODER_FINISHED}: The input contains no * more frames. The client must call {@link AImageDecoder_rewind} * before calling {@link AImageDecoder_decodeImage} again. */ int AImageDecoder_advanceFrame(AImageDecoder* _Nonnull decoder) __INTRODUCED_IN(31); /** * Return to the beginning of the animation. * * Introduced in API 31. * * After this call, the AImageDecoder will be ready to decode the * first frame of the animation. This can be called after reaching * the end of the animation or an error or in the middle of the * animation. * * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value * indicating the reason for the failure. * * Errors: * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The AImageDecoder * represents an image that is not animated (see * {@link AImageDecoder_isAnimated}) or the AImageDecoder is * null. * - {@link ANDROID_IMAGE_DECODER_SEEK_ERROR}: The asset or file * descriptor failed to seek. */ int AImageDecoder_rewind(AImageDecoder* _Nonnull decoder) __INTRODUCED_IN(31); #endif // __ANDROID_API__ >= 31 struct AImageDecoderFrameInfo; /** * Opaque handle to animation information about a single frame. * * Introduced in API 31 * * The duration (retrieved with {@link AImageDecoderFrameInfo_getDuration}) is * necessary for clients to display the animation at the proper speed. The other * information is helpful for a client that wants to determine what frames are * independent (or what frames they depend on), but is unnecessary for * a simple client that wants to sequentially display all frames. */ typedef struct AImageDecoderFrameInfo AImageDecoderFrameInfo; #if __ANDROID_API__ >= 31 /** * Create an uninitialized AImageDecoderFrameInfo. * * Introduced in API 31. * * This can be passed to {@link AImageDecoder_getFrameInfo} to fill * in information about the current frame. It may be reused. * * Must be deleted with {@link AImageDecoderFrameInfo_delete}. */ AImageDecoderFrameInfo* _Nullable AImageDecoderFrameInfo_create() __INTRODUCED_IN(31); /** * Delete an AImageDecoderFrameInfo. * * Introduced in API 31. */ void AImageDecoderFrameInfo_delete( AImageDecoderFrameInfo* _Nullable info) __INTRODUCED_IN(31); /** * Fill |info| with information about the current frame. * * Introduced in API 31. * * Initially, this will return information about the first frame. * {@link AImageDecoder_advanceFrame} and * {@link AImageDecoder_rewind} can be used to change which frame * is the current frame. * * If the image only has one frame, this will fill the {@link * AImageDecoderFrameInfo} with the encoded info, if any, or reasonable * defaults. * * @param decoder Opaque object representing the decoder. * @param info Opaque object to hold frame information. On success, will be * filled with information regarding the current frame. * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value * indicating the reason for the failure. * * Errors: * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: One of the parameters is null. * - {@link ANDROID_IMAGE_DECODER_FINISHED}: The input contains no * more frames. The client must call {@link AImageDecoder_rewind} to reset the * current frame to a valid frame (0). */ int AImageDecoder_getFrameInfo(AImageDecoder* _Nonnull decoder, AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31); /** * Report the number of nanoseconds to show the current frame. * * Introduced in API 31. * * Errors: * - returns 0 if |info| is null. */ int64_t AImageDecoderFrameInfo_getDuration( const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31); /** * The rectangle of the image (within 0, 0, * {@link AImageDecoder_getWidth}, {@link AImageDecoder_getHeight}) * updated by this frame. * * Introduced in API 31. * * Note that this is unaffected by calls to * {@link AImageDecoder_setTargetSize} or * {@link AImageDecoder_setCrop}. * * A frame may update only part of the image. This will always be * contained by the image’s dimensions. * * This, along with other information in AImageDecoderFrameInfo, * can be useful for determining whether a frame is independent, but * the decoder handles blending frames, so a simple * sequential client does not need this. * * Errors: * - returns an empty ARect if |info| is null. */ ARect AImageDecoderFrameInfo_getFrameRect( const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31); /** * Whether the new portion of this frame may contain alpha. * * Introduced in API 31. * * Note that this may differ from whether the composed frame has * alpha. If this frame does not fill the entire image dimensions * (see {@link AImageDecoderFrameInfo_getFrameRect}) or it blends * with an opaque frame, for example, the composed frame’s alpha * may not match. It is also conservative; for example, if a color * index-based frame has a color with alpha but does not use it, * this will still return true. * * This, along with other information in AImageDecoderFrameInfo, * can be useful for determining whether a frame is independent, but * the decoder handles blending frames, so a simple * sequential client does not need this. * * Errors: * - returns false if |info| is null. */ bool AImageDecoderFrameInfo_hasAlphaWithinBounds( const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31); #endif // __ANDROID_API__ >= 31 /** * How a frame is “disposed” before showing the next one. * * Introduced in API 31. * * This, along with other information in AImageDecoderFrameInfo, * can be useful for determining whether a frame is independent, but * the decoder handles disposing of frames, so a simple * sequential client does not need this. */ enum { // No disposal. The following frame will be drawn directly // on top of this one. ANDROID_IMAGE_DECODER_DISPOSE_OP_NONE = 1, // The frame’s rectangle is cleared (by AImageDecoder) before // decoding the next frame. ANDROID_IMAGE_DECODER_DISPOSE_OP_BACKGROUND = 2, // The frame’s rectangle is reverted (by AImageDecoder) to the // prior frame before decoding the next frame. ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS = 3, }; #if __ANDROID_API__ >= 31 /** * Return how this frame is “disposed” before showing the next one. * * Introduced in API 31. * * This, along with other information in AImageDecoderFrameInfo, * can be useful for determining whether a frame is independent, but * the decoder handles disposing of frames, so a simple * sequential client does not need this. * * @return one of: * - {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_NONE} * - {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_BACKGROUND} * - {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS} * Errors: * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} if |info| is null. */ int32_t AImageDecoderFrameInfo_getDisposeOp( const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31); #endif // __ANDROID_API__ >= 31 /** * How a frame is blended with the previous frame. * * Introduced in API 31. * * This, along with other information in AImageDecoderFrameInfo, * can be useful for determining whether a frame is independent, but * the decoder handles blending frames, so a simple * sequential client does not need this. */ enum { // This frame replaces existing content. This corresponds // to webp’s “do not blend”. ANDROID_IMAGE_DECODER_BLEND_OP_SRC = 1, // This frame blends with the previous frame. ANDROID_IMAGE_DECODER_BLEND_OP_SRC_OVER = 2, }; #if __ANDROID_API__ >= 31 /** * Return how this frame is blended with the previous frame. * * Introduced in API 31. * * This, along with other information in AImageDecoderFrameInfo, * can be useful for determining whether a frame is independent, but * the decoder handles blending frames, so a simple * sequential client does not need this. * * @return one of: * - {@link ANDROID_IMAGE_DECODER_BLEND_OP_SRC} * - {@link ANDROID_IMAGE_DECODER_BLEND_OP_SRC_OVER} * Errors: * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} if |info| is null. */ int32_t AImageDecoderFrameInfo_getBlendOp( const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31); #endif // __ANDROID_API__ >= 31 #ifdef __cplusplus Loading Loading
include/android/imagedecoder.h +375 −9 Original line number Diff line number Diff line Loading @@ -109,7 +109,19 @@ enum { /** * AImageDecoder did not recognize the format. */ ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT = -9 ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT = -9, /** * The animation has reached the end. */ ANDROID_IMAGE_DECODER_FINISHED = -10, /** * This method cannot be called while the AImageDecoder is in its current * state. For example, various setters (like {@link AImageDecoder_setTargetSize}) * can only be called while the AImageDecoder is set to decode the first * frame of an animation. This ensures that any blending and/or restoring * prior frames works correctly. */ ANDROID_IMAGE_DECODER_INVALID_STATE = -11, }; struct AImageDecoder; Loading @@ -127,7 +139,7 @@ struct AImageDecoder; * After creation, {@link AImageDecoder_getHeaderInfo} can be used to retrieve * information about the encoded image. Other functions, like * {@link AImageDecoder_setTargetSize}, can be used to specify how to decode, and * {@link AImageDecoder_decode} will decode into client provided memory. * {@link AImageDecoder_decodeImage} will decode into client provided memory. * * {@link AImageDecoder} objects are NOT thread-safe, and should not be shared across * threads. Loading Loading @@ -240,6 +252,10 @@ void AImageDecoder_delete(AImageDecoder* _Nonnull decoder) __INTRODUCED_IN(30); /** * Choose the desired output format. * * If the encoded image represents an animation, this must be called while on * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or * after calling {@link AImageDecoder_rewind}). * * Available since API level 30. * * @param format {@link AndroidBitmapFormat} to use for the output. Loading @@ -255,6 +271,8 @@ void AImageDecoder_delete(AImageDecoder* _Nonnull decoder) __INTRODUCED_IN(30); * {@link AndroidBitmapFormat}. * - {@link ANDROID_IMAGE_DECODER_INVALID_CONVERSION}: The * {@link AndroidBitmapFormat} is incompatible with the image. * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on * the first frame. */ int AImageDecoder_setAndroidBitmapFormat(AImageDecoder* _Nonnull decoder, int32_t format) __INTRODUCED_IN(30); Loading @@ -266,6 +284,10 @@ int AImageDecoder_setAndroidBitmapFormat(AImageDecoder* _Nonnull decoder, * Pass true to this method to leave them unpremultiplied. This has no effect on an * opaque image. * * If the encoded image represents an animation, this must be called while on * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or * after calling {@link AImageDecoder_rewind}). * * Available since API level 30. * * @param unpremultipliedRequired Pass true to leave the pixels unpremultiplied. Loading @@ -278,6 +300,8 @@ int AImageDecoder_setAndroidBitmapFormat(AImageDecoder* _Nonnull decoder, * {@link AImageDecoder_setTargetSize}. * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The * {@link AImageDecoder} is null. * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on * the first frame. */ int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* _Nonnull decoder, bool unpremultipliedRequired) __INTRODUCED_IN(30); Loading @@ -288,6 +312,10 @@ int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* _Nonnull decoder, * Ignored by {@link ANDROID_BITMAP_FORMAT_A_8}, which does not support * an {@link ADataSpace}. * * If the encoded image represents an animation, this must be called while on * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or * after calling {@link AImageDecoder_rewind}). * * Available since API level 30. * * @param dataspace The {@link ADataSpace} to decode into. An ADataSpace Loading @@ -303,6 +331,8 @@ int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* _Nonnull decoder, * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The * {@link AImageDecoder} is null or |dataspace| does not correspond to an * {@link ADataSpace} value. * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on * the first frame. */ int AImageDecoder_setDataSpace(AImageDecoder* _Nonnull decoder, int32_t dataspace) __INTRODUCED_IN(30); Loading @@ -316,6 +346,10 @@ int AImageDecoder_setDataSpace(AImageDecoder* _Nonnull decoder, int32_t dataspac * specified by width and height, and the output image will be the size of the * crop rect. * * If the encoded image represents an animation, this must be called while on * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or * after calling {@link AImageDecoder_rewind}). * * Available since API level 30. * * @param width Width of the output (prior to cropping). Loading @@ -330,9 +364,11 @@ int AImageDecoder_setDataSpace(AImageDecoder* _Nonnull decoder, int32_t dataspac * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The * {@link AImageDecoder} is null. * - {@link ANDROID_IMAGE_DECODER_INVALID_SCALE}: |width| or |height| is <= 0, * the size is too big, any existing crop is not contained by the new image dimensions, * or the scale is incompatible with a previous call to * the size is too big, any existing crop is not contained by the new image * dimensions, or the scale is incompatible with a previous call to * {@link AImageDecoder_setUnpremultipliedRequired}(true). * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on * the first frame. */ int AImageDecoder_setTargetSize(AImageDecoder* _Nonnull decoder, int32_t width, int32_t height) __INTRODUCED_IN(30); Loading Loading @@ -374,6 +410,10 @@ int AImageDecoder_computeSampledSize(const AImageDecoder* _Nonnull decoder, int * the specified {@link ARect}. Clients will only need to allocate enough memory * for the cropped ARect. * * If the encoded image represents an animation, this must be called while on * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or * after calling {@link AImageDecoder_rewind}). * * Available since API level 30. * * @param crop Rectangle describing a crop of the decode. It must be contained inside of Loading @@ -389,8 +429,10 @@ int AImageDecoder_computeSampledSize(const AImageDecoder* _Nonnull decoder, int * * Errors: * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The * {@link AImageDecoder} is null or the crop is not contained by the * {@link AImageDecoder} is null, or the crop is not contained by the * (possibly scaled) image dimensions. * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on * the first frame. */ int AImageDecoder_setCrop(AImageDecoder* _Nonnull decoder, ARect crop) __INTRODUCED_IN(30); Loading Loading @@ -472,6 +514,10 @@ int32_t AImageDecoderHeaderInfo_getAndroidBitmapFormat( * {@link AImageDecoder_decodeImage} will premultiply pixels by default. * * Available since API level 30. * * Starting in API level 31, an AImageDecoder may contain multiple frames of an * animation, but this method still only reports whether the first frame has * alpha. */ int AImageDecoderHeaderInfo_getAlphaFlags( const AImageDecoderHeaderInfo* _Nonnull) __INTRODUCED_IN(30); Loading Loading @@ -518,8 +564,44 @@ size_t AImageDecoder_getMinimumStride(AImageDecoder* _Nonnull decoder) __INTRODU * Available since API level 30. * * Starting in API level 31, it can be used to decode all of the frames of an * animated image (i.e. GIF, WebP, HEIF) using new APIs (TODO (scroggo): list * and describe here). * animated image (i.e. GIF, WebP, HEIF) using new APIs. Internally, * AImageDecoder keeps track of its "current frame" - that is, the frame that * will be decoded by a call to AImageDecoder_decodeImage. At creation time, the * current frame is always the first frame, and multiple calls to this method * will each decode the first frame. {@link AImageDecoder_advanceFrame} advances * the current frame to the following frame, so that future calls to this method * will decode that frame. Some frames may update only part of the image. They * may only update a sub-rectangle (see {@link * AImageDecoderFrameInfo_getFrameRect}), or they may have alpha (see * {@link AImageDecoderFrameInfo_hasAlphaWithinBounds}). In these cases, this * method assumes that the prior frame is still residing in the |pixels| buffer, * decodes only the new portion, and blends it with the buffer. Frames that change * the entire |pixels| buffer are "independent", and do not require the prior * frame to remain in the buffer. The first frame is always independent. A * sophisticated client can use information from the {@link AImageDecoderFrameInfo} * to determine whether other frames are independent, or what frames they rely on. * * If the current frame is marked {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS}, * AImageDecoder_decodeImage will cache the |pixels| buffer prior to decoding * (note: this only happens for the first in a string of consecutive * ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS frames). After advancing to the * following frame, AImageDecoder_decodeImage will restore the cached buffer * prior to decoding that frame. * * Ignoring timing information, display, etc, a client wishing to decode all * frames of an animated image may conceptually use code like the following: * * while (true) { * int result = AImageDecoder_decodeImage(decoder, pixels, stride, size); * if (result != ANDROID_IMAGE_DECODER_SUCCESS) break; * * // Display or save the image in |pixels|, keeping the buffer intact for * // AImageDecoder to decode the next frame correctly. * Application_viewImage(pixels); * * result = AImageDecoder_advanceFrame(decoder); * if (result != ANDROID_IMAGE_DECODER_SUCCESS) break; * } * * @param decoder Opaque object representing the decoder. * @param pixels On success, will be filled with the result Loading Loading @@ -547,6 +629,10 @@ size_t AImageDecoder_getMinimumStride(AImageDecoder* _Nonnull decoder) __INTRODU * failed to seek. * - {@link ANDROID_IMAGE_DECODER_INTERNAL_ERROR}: Some other error, like a * failure to allocate memory. * - {@link ANDROID_IMAGE_DECODER_FINISHED}: The input contains no * more frames. No decoding occurred. The client must call * {@link AImageDecoder_rewind} before calling * {@link AImageDecoder_decodeImage} again. */ int AImageDecoder_decodeImage(AImageDecoder* _Nonnull decoder, void* _Nonnull pixels, size_t stride, Loading @@ -561,8 +647,8 @@ int AImageDecoder_decodeImage(AImageDecoder* _Nonnull decoder, * * Introduced in API 31. * * This may require seeking past the first frame to verify whether * there is a following frame (e.g. for GIF). * A single frame GIF is considered to *not* be animated. This may require * seeking past the first frame to verify whether there is a following frame. * * Errors: * - returns false if |decoder| is null. Loading Loading @@ -610,6 +696,286 @@ enum { int32_t AImageDecoder_getRepeatCount(AImageDecoder* _Nonnull decoder); __INTRODUCED_IN(31); /** * Advance to the next frame in the animation. * * Introduced in API 31. * * The AImageDecoder keeps track internally which frame it is ready to decode * (the "current frame"). Initially it is set to decode the first frame, and * each call to {@link AImageDecoder_decodeImage} will continue to decode * the same frame until this method (or {@link AImageDecoder_rewind}) * is called. * * Note that this can be used to skip a frame without decoding it. But * some frames depend on (i.e. blend with) prior frames, and * AImageDecoder_decodeImage assumes that the prior frame is in the * |pixels| buffer. In addition, AImageDecoder_decodeImage handles caching and * restoring frames (see {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS}), so * skipping frames in an image with such frames may not produce the correct * results. * * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value * indicating the reason for the failure. * * Errors: * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The AImageDecoder * represents an image that is not animated (see * {@link AImageDecoder_isAnimated}) or the AImageDecoder is null. * - {@link ANDROID_IMAGE_DECODER_INCOMPLETE}: The input appears * to be truncated. The client must call {@link AImageDecoder_rewind} * before calling {@link AImageDecoder_decodeImage} again. * - {@link ANDROID_IMAGE_DECODER_ERROR}: The input contains an error. * The client must call {@link AImageDecoder_rewind} before * calling {@link AImageDecoder_decodeImage} again. * - {@link ANDROID_IMAGE_DECODER_FINISHED}: The input contains no * more frames. The client must call {@link AImageDecoder_rewind} * before calling {@link AImageDecoder_decodeImage} again. */ int AImageDecoder_advanceFrame(AImageDecoder* _Nonnull decoder) __INTRODUCED_IN(31); /** * Return to the beginning of the animation. * * Introduced in API 31. * * After this call, the AImageDecoder will be ready to decode the * first frame of the animation. This can be called after reaching * the end of the animation or an error or in the middle of the * animation. * * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value * indicating the reason for the failure. * * Errors: * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The AImageDecoder * represents an image that is not animated (see * {@link AImageDecoder_isAnimated}) or the AImageDecoder is * null. * - {@link ANDROID_IMAGE_DECODER_SEEK_ERROR}: The asset or file * descriptor failed to seek. */ int AImageDecoder_rewind(AImageDecoder* _Nonnull decoder) __INTRODUCED_IN(31); #endif // __ANDROID_API__ >= 31 struct AImageDecoderFrameInfo; /** * Opaque handle to animation information about a single frame. * * Introduced in API 31 * * The duration (retrieved with {@link AImageDecoderFrameInfo_getDuration}) is * necessary for clients to display the animation at the proper speed. The other * information is helpful for a client that wants to determine what frames are * independent (or what frames they depend on), but is unnecessary for * a simple client that wants to sequentially display all frames. */ typedef struct AImageDecoderFrameInfo AImageDecoderFrameInfo; #if __ANDROID_API__ >= 31 /** * Create an uninitialized AImageDecoderFrameInfo. * * Introduced in API 31. * * This can be passed to {@link AImageDecoder_getFrameInfo} to fill * in information about the current frame. It may be reused. * * Must be deleted with {@link AImageDecoderFrameInfo_delete}. */ AImageDecoderFrameInfo* _Nullable AImageDecoderFrameInfo_create() __INTRODUCED_IN(31); /** * Delete an AImageDecoderFrameInfo. * * Introduced in API 31. */ void AImageDecoderFrameInfo_delete( AImageDecoderFrameInfo* _Nullable info) __INTRODUCED_IN(31); /** * Fill |info| with information about the current frame. * * Introduced in API 31. * * Initially, this will return information about the first frame. * {@link AImageDecoder_advanceFrame} and * {@link AImageDecoder_rewind} can be used to change which frame * is the current frame. * * If the image only has one frame, this will fill the {@link * AImageDecoderFrameInfo} with the encoded info, if any, or reasonable * defaults. * * @param decoder Opaque object representing the decoder. * @param info Opaque object to hold frame information. On success, will be * filled with information regarding the current frame. * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value * indicating the reason for the failure. * * Errors: * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: One of the parameters is null. * - {@link ANDROID_IMAGE_DECODER_FINISHED}: The input contains no * more frames. The client must call {@link AImageDecoder_rewind} to reset the * current frame to a valid frame (0). */ int AImageDecoder_getFrameInfo(AImageDecoder* _Nonnull decoder, AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31); /** * Report the number of nanoseconds to show the current frame. * * Introduced in API 31. * * Errors: * - returns 0 if |info| is null. */ int64_t AImageDecoderFrameInfo_getDuration( const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31); /** * The rectangle of the image (within 0, 0, * {@link AImageDecoder_getWidth}, {@link AImageDecoder_getHeight}) * updated by this frame. * * Introduced in API 31. * * Note that this is unaffected by calls to * {@link AImageDecoder_setTargetSize} or * {@link AImageDecoder_setCrop}. * * A frame may update only part of the image. This will always be * contained by the image’s dimensions. * * This, along with other information in AImageDecoderFrameInfo, * can be useful for determining whether a frame is independent, but * the decoder handles blending frames, so a simple * sequential client does not need this. * * Errors: * - returns an empty ARect if |info| is null. */ ARect AImageDecoderFrameInfo_getFrameRect( const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31); /** * Whether the new portion of this frame may contain alpha. * * Introduced in API 31. * * Note that this may differ from whether the composed frame has * alpha. If this frame does not fill the entire image dimensions * (see {@link AImageDecoderFrameInfo_getFrameRect}) or it blends * with an opaque frame, for example, the composed frame’s alpha * may not match. It is also conservative; for example, if a color * index-based frame has a color with alpha but does not use it, * this will still return true. * * This, along with other information in AImageDecoderFrameInfo, * can be useful for determining whether a frame is independent, but * the decoder handles blending frames, so a simple * sequential client does not need this. * * Errors: * - returns false if |info| is null. */ bool AImageDecoderFrameInfo_hasAlphaWithinBounds( const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31); #endif // __ANDROID_API__ >= 31 /** * How a frame is “disposed” before showing the next one. * * Introduced in API 31. * * This, along with other information in AImageDecoderFrameInfo, * can be useful for determining whether a frame is independent, but * the decoder handles disposing of frames, so a simple * sequential client does not need this. */ enum { // No disposal. The following frame will be drawn directly // on top of this one. ANDROID_IMAGE_DECODER_DISPOSE_OP_NONE = 1, // The frame’s rectangle is cleared (by AImageDecoder) before // decoding the next frame. ANDROID_IMAGE_DECODER_DISPOSE_OP_BACKGROUND = 2, // The frame’s rectangle is reverted (by AImageDecoder) to the // prior frame before decoding the next frame. ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS = 3, }; #if __ANDROID_API__ >= 31 /** * Return how this frame is “disposed” before showing the next one. * * Introduced in API 31. * * This, along with other information in AImageDecoderFrameInfo, * can be useful for determining whether a frame is independent, but * the decoder handles disposing of frames, so a simple * sequential client does not need this. * * @return one of: * - {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_NONE} * - {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_BACKGROUND} * - {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS} * Errors: * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} if |info| is null. */ int32_t AImageDecoderFrameInfo_getDisposeOp( const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31); #endif // __ANDROID_API__ >= 31 /** * How a frame is blended with the previous frame. * * Introduced in API 31. * * This, along with other information in AImageDecoderFrameInfo, * can be useful for determining whether a frame is independent, but * the decoder handles blending frames, so a simple * sequential client does not need this. */ enum { // This frame replaces existing content. This corresponds // to webp’s “do not blend”. ANDROID_IMAGE_DECODER_BLEND_OP_SRC = 1, // This frame blends with the previous frame. ANDROID_IMAGE_DECODER_BLEND_OP_SRC_OVER = 2, }; #if __ANDROID_API__ >= 31 /** * Return how this frame is blended with the previous frame. * * Introduced in API 31. * * This, along with other information in AImageDecoderFrameInfo, * can be useful for determining whether a frame is independent, but * the decoder handles blending frames, so a simple * sequential client does not need this. * * @return one of: * - {@link ANDROID_IMAGE_DECODER_BLEND_OP_SRC} * - {@link ANDROID_IMAGE_DECODER_BLEND_OP_SRC_OVER} * Errors: * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} if |info| is null. */ int32_t AImageDecoderFrameInfo_getBlendOp( const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31); #endif // __ANDROID_API__ >= 31 #ifdef __cplusplus Loading