Skip to content

Commit

Permalink
Internal change
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 424362058
  • Loading branch information
sjudd authored and glide-copybara-robot committed Jan 26, 2022
1 parent 979459c commit f5e78ed
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 0 deletions.
@@ -0,0 +1,68 @@
package com.bumptech.glide.integration.avif;

import android.graphics.Bitmap;
import android.util.Log;
import com.bumptech.glide.load.Options;
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapResource;
import com.bumptech.glide.util.Preconditions;
import java.nio.ByteBuffer;
import javax.annotation.Nullable;
import org.aomedia.avif.android.AvifDecoder;
import org.aomedia.avif.android.AvifDecoder.Info;

/** A Glide {@link ResourceDecoder} capable of decoding Avif images. */
public final class AvifByteBufferBitmapDecoder implements ResourceDecoder<ByteBuffer, Bitmap> {
private static final String TAG = "AvifBitmapDecoder";

private final BitmapPool bitmapPool;

public AvifByteBufferBitmapDecoder(BitmapPool bitmapPool) {
this.bitmapPool = Preconditions.checkNotNull(bitmapPool);
}

private ByteBuffer maybeCopyBuffer(ByteBuffer source) {
// Native calls can only access ByteBuffer if isDirect() is true. Otherwise, we would have to
// make a copy into a direct ByteBuffer.
if (source.isDirect()) {
return source;
}
ByteBuffer sourceCopy = ByteBuffer.allocateDirect(source.remaining());
sourceCopy.put(source);
sourceCopy.flip();
return sourceCopy;
}

@Override
@Nullable
public Resource<Bitmap> decode(ByteBuffer source, int width, int height, Options options) {
ByteBuffer sourceCopy = maybeCopyBuffer(source);
Info info = new Info();
if (!AvifDecoder.getInfo(sourceCopy, sourceCopy.remaining(), info)) {
if (Log.isLoggable(TAG, Log.ERROR)) {
Log.e(TAG, "Requested to decode byte buffer which cannot be handled by AvifDecoder");
}
return null;
}
Bitmap bitmap =
bitmapPool.get(
info.width,
info.height,
(info.depth == 8) ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGBA_F16);
if (!AvifDecoder.decode(sourceCopy, sourceCopy.remaining(), bitmap)) {
if (Log.isLoggable(TAG, Log.ERROR)) {
Log.e(TAG, "Failed to decode ByteBuffer as Avif.");
}
bitmapPool.put(bitmap);
return null;
}
return BitmapResource.obtain(bitmap, bitmapPool);
}

@Override
public boolean handles(ByteBuffer source, Options options) {
return AvifDecoder.isAvifImage(maybeCopyBuffer(source));
}
}
@@ -0,0 +1,30 @@
package com.bumptech.glide.integration.avif;

import android.content.Context;
import android.graphics.Bitmap;
import androidx.annotation.NonNull;
import com.bumptech.glide.Glide;
import com.bumptech.glide.Registry;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.LibraryGlideModule;
import java.io.InputStream;
import java.nio.ByteBuffer;

/** Glide support for AVIF Images. */
@GlideModule
public final class AvifGlideModule extends LibraryGlideModule {

@Override
public void registerComponents(
@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
// Add the Avif ResourceDecoders before any of the available system decoders. This ensures that
// the integration will be preferred for Avif images.
AvifByteBufferBitmapDecoder byteBufferBitmapDecoder =
new AvifByteBufferBitmapDecoder(glide.getBitmapPool());
registry.prepend(ByteBuffer.class, Bitmap.class, byteBufferBitmapDecoder);
AvifStreamBitmapDecoder streamBitmapDecoder =
new AvifStreamBitmapDecoder(
registry.getImageHeaderParsers(), byteBufferBitmapDecoder, glide.getArrayPool());
registry.prepend(InputStream.class, Bitmap.class, streamBitmapDecoder);
}
}
@@ -0,0 +1,46 @@
package com.bumptech.glide.integration.avif;

import android.graphics.Bitmap;
import com.bumptech.glide.load.ImageHeaderParser;
import com.bumptech.glide.load.ImageHeaderParser.ImageType;
import com.bumptech.glide.load.ImageHeaderParserUtils;
import com.bumptech.glide.load.Options;
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.engine.bitmap_recycle.ArrayPool;
import com.bumptech.glide.util.ByteBufferUtil;
import com.bumptech.glide.util.Preconditions;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import javax.annotation.Nullable;

/** A Glide {@link ResourceDecoder} capable of decoding Avif Images. */
public final class AvifStreamBitmapDecoder implements ResourceDecoder<InputStream, Bitmap> {
private static final String TAG = "AvifStreamBitmapDecoder";

private final List<ImageHeaderParser> parsers;
private final AvifByteBufferBitmapDecoder avifByteBufferDecoder;
private final ArrayPool arrayPool;

public AvifStreamBitmapDecoder(
List<ImageHeaderParser> parsers,
AvifByteBufferBitmapDecoder avifByteBufferDecoder,
ArrayPool arrayPool) {
this.parsers = parsers;
this.avifByteBufferDecoder = Preconditions.checkNotNull(avifByteBufferDecoder);
this.arrayPool = Preconditions.checkNotNull(arrayPool);
}

@Override
@Nullable
public Resource<Bitmap> decode(InputStream source, int width, int height, Options options)
throws IOException {
return avifByteBufferDecoder.decode(ByteBufferUtil.fromStream(source), width, height, options);
}

@Override
public boolean handles(InputStream source, Options options) throws IOException {
return ImageType.AVIF.equals(ImageHeaderParserUtils.getType(parsers, source, arrayPool));
}
}

0 comments on commit f5e78ed

Please sign in to comment.