Giter VIP home page Giter VIP logo

apng4android's Introduction

Animation Android

  • Support APNG & Animated Webp & Gif & AVIF in Android
  • Efficient decoder
  • Support Drawable usage and glide library module
  • Support animation play control
  • Support still image
  • Low memory usage

Usages

Add dependency in build.gradle

repositories {
    mavenCentral()
}

Animated WebP

dependencies {
    implementation 'com.github.penfeizhou.android.animation:awebp:${VERSION}'
}

APNG

dependencies {
    implementation 'com.github.penfeizhou.android.animation:apng:${VERSION}'
}

Gif

dependencies {
    implementation 'com.github.penfeizhou.android.animation:gif:${VERSION}'
}

AVIF

dependencies {
    implementation 'com.github.penfeizhou.android.animation:avif:${VERSION}'
}

Notice Before Use!

Don't put APNG resources in your drawable or mipmap directory! During the process of release building of an Android app, the aapt tool will zip & modify the frame info of the APNG file, which will lead to an abnormal behavior when playing it. Thus, please put the APNG resources in raw or assets folder instead.

Use

// Load from asset file
AssetStreamLoader assetLoader = new AssetStreamLoader(context, "wheel.png");


// Load form Resource
ResourceStreamLoader resourceLoader = new ResourceStreamLoader(context, R.drawable.sample);


// Load from file
FileStreamLoader fileLoader = new FileStreamLoader("/sdcard/Pictures/1.webp");


// Create APNG Drawable
APNGDrawable apngDrawable = new APNGDrawable(assetLoader);

//Create Animated webp drawable
WebPDrawable webpDrawable = new WebPDrawable(assetLoader);

//Create Animated avif drawable
AVIFDrawable avifDrawable = new AVIFDrawable(assetLoader);

// Auto play
imageView.setImageDrawable(apngDrawable);


// Not needed.default controlled by content
apngDrawable.setLoopLimit(10);


// Implement Animatable2Compat
drawable.registerAnimationCallback(new Animatable2Compat.AnimationCallback() {
    @Override
    public void onAnimationStart(Drawable drawable) {
        super.onAnimationStart(drawable);
    }
});

Glide support

Add dependency in build.gradle

repositories {
    ...
    mavenCentral()
}
dependencies {
    implementation 'com.github.penfeizhou.android.animation:glide-plugin:${VERSION}'
}

Direct use

Glide.with(imageView).load("https://misc.aotu.io/ONE-SUNDAY/SteamEngine.png").into(imageView);
Glide.with(imageView).load("https://isparta.github.io/compare-webp/image/gif_webp/webp/2.webp").into(imageView);

Welcome to join the talk

image

Star History

Star History Chart

apng4android's People

Contributors

huiung avatar insofan avatar jingpeng avatar nikclayton avatar penfeizhou avatar showmethe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

apng4android's Issues

How can I use it as full size?

I am using this library. And it is very cool compared to others...

However, the ratio seems fixed. is there any way to change it into match_parent/match_parent?

webp 支持透明动画吗

New Issue Checklist

  • I have searched for a similar issue in the project and found none

Issue Info

Info Value
Device Info e.g. Huawei Mate 30 pro
System Version e.g. 6.0
APNG4Android Library Version e.g. 1.0.0
Repro rate e.g. all the time (100%) / sometimes x% / only once
Repro with our demo project e.g. does it happen with our demo project?
Demo project link e.g. link to a demo project that highlights the issue

Issue Description and Steps

Please fill in the detailed description of the issue (full output of any stack trace, compiler error, ...) and the steps to reproduce the issue.

IllegalStateException

12-04 20:48:21.560 E/AndroidRuntime(10899): FATAL EXCEPTION: FrameDecoderExecutor-1 12-04 20:48:21.560 E/AndroidRuntime(10899): Process: com.xxx.xxx, PID: 10899 12-04 20:48:21.560 E/AndroidRuntime(10899): java.lang.IllegalStateException: copyPixelsFromBuffer called on recycled bitmap 12-04 20:48:21.560 E/AndroidRuntime(10899): at android.graphics.Bitmap.checkRecycled(Bitmap.java:383) 12-04 20:48:21.560 E/AndroidRuntime(10899): at android.graphics.Bitmap.copyPixelsFromBuffer(Bitmap.java:549) 12-04 20:48:21.560 E/AndroidRuntime(10899): at com.github.penfeizhou.animation.FrameAnimationDrawable.onRender(FrameAnimationDrawable.java:11) 12-04 20:48:21.560 E/AndroidRuntime(10899): at com.github.penfeizhou.animation.decode.FrameSeqDecoder$1.run(FrameSeqDecoder.java:7) 12-04 20:48:21.560 E/AndroidRuntime(10899): at android.os.Handler.handleCallback(Handler.java:751) 12-04 20:48:21.560 E/AndroidRuntime(10899): at android.os.Handler.dispatchMessage(Handler.java:95) 12-04 20:48:21.560 E/AndroidRuntime(10899): at android.os.Looper.loop(Looper.java:154) 12-04 20:48:21.560 E/AndroidRuntime(10899): at android.os.HandlerThread.run(HandlerThread.java:61)

File not found exception should stop the animation

I noticed when cleaning the cache a bunch of warning:

2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at java.io.FileInputStream.open0(Native Method)
2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at java.io.FileInputStream.open(FileInputStream.java:231)
2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at java.io.FileInputStream.<init>(FileInputStream.java:165)
2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at com.github.penfeizhou.animation.io.FileReader.reset(FileReader.java:24)
2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at com.github.penfeizhou.animation.io.FilterReader.reset(FilterReader.java:30)
2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at com.github.penfeizhou.animation.apng.decode.APNGFrame.encode(APNGFrame.java:89)
2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at com.github.penfeizhou.animation.apng.decode.APNGFrame.draw(APNGFrame.java:126)
2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at com.github.penfeizhou.animation.apng.decode.APNGFrame.draw(APNGFrame.java:22)
2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at com.github.penfeizhou.animation.apng.decode.APNGDecoder.renderFrame(APNGDecoder.java:190)
2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at com.github.penfeizhou.animation.decode.FrameSeqDecoder.step(FrameSeqDecoder.java:463)
2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at com.github.penfeizhou.animation.decode.FrameSeqDecoder.access$200(FrameSeqDecoder.java:35)
2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at com.github.penfeizhou.animation.decode.FrameSeqDecoder$1.run(FrameSeqDecoder.java:56)
2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:458)
2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at java.util.concurrent.ThreadPoolExecutor.processTask(ThreadPoolExecutor.java:1187)
2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152)
2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
2019-08-24 12:18:14.988 17833-18021/app.fedilab.android W/System.err:     at java.lang.Thread.run(Thread.java:784)
2019-08-24 12:18:14.995 17833-18040/app.fedilab.android W/System.err: java.io.FileNotFoundException: /data/user/0/app.fedilab.android/cache/image_manager_disk_cache/5b6ee9e893a2dd423458d69fea72ef028141b23897100f97af8dd83ca2b2e2e5.0 (No such file or directory)

The error is handled in APNGFrame.java

Would it be possible to stop the animation especially for the FileNotFoundException

引入工程会导致工程无法编译

会报 class file for androidx.core.view.NestedScrollingChild3 not found 错误
这是个啥?

compileSdkVersion = 29
buildToolsVersion = "29.0.2"
com.android.tools.build:gradle:4.0.1
androidx.recyclerview:recyclerview:1.1.0
androidx.appcompat:appcompat:1.1.0
androidx.viewpager2:viewpager2:1.0.0

ResourceStreamLoader for any drawable

Currently it's possible to use ResourceStreamLoader from a drawable:

// Load form Resource
ResourceStreamLoader resourceLoader = new ResourceStreamLoader(context, R.drawable.sample);

Would it be possible to use it with any drawable?

The idea is to use the lib with Glide without the plugin:

 Glide.with(context)
                        .asDrawable()
                        .load(emoji.getUrl())
                       
                        .into(new SimpleTarget<Drawable>() {
                            @Override
                            public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                                ResourceStreamLoader resourceLoader = new ResourceStreamLoader(context, resource);
                            }
                        });

Currently I use File instead of Drawable to make it work with Glide.

FrameAnimationDrawable onRender

这边遇到了一种情况
有时FrameAnimationDrawable的onRender方法调用时frameSeqDecoder.getSampleSize()返回的是1
接着frameSeqDecoder的setDesiredSize调用,然后sampleSize就变成2了
再往后的onRender方法里,给过来的byteBuffer就小了,但是bitmap已经创建了,还是原来的大小所以
if (byteBuffer.remaining() < this.bitmap.getByteCount()) {
Log.e(TAG, "onRender:Buffer not large enough for pixels");
return;
}
这个条件就一直是true了,就一直报这个错误了

Originally posted by @ffts in #55 (comment)

E/FrameSeqDecoder: Processing,wait for finish at INITIALIZING

I have an issue with animated emoji in a GridView using ArrayAdapter. It's lagging and I got a lot of messages: E/FrameSeqDecoder: Processing,wait for finish at INITIALIZING

Here is my adapter:

public class CustomEmojiAdapter extends ArrayAdapter<Emojis> {


    private Context context;
    private List<Emojis> emojis;

    public CustomEmojiAdapter(@NonNull Context context, int resource, List<Emojis> emojis) {
        super(context, resource, resource);
        this.context = context;
        this.emojis = emojis;
    }

    @Override
    public int getCount() {
        return emojis.size();
    }

    @Override
    public Emojis getItem(int position) {
        return emojis.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @NonNull
    public View getView(final int position, View convertView, @NonNull ViewGroup parent) {
        final ImageView imageView;
        Emojis emoji = emojis.get(position);
        if (convertView == null) {
            LayoutInflater layoutInflater = LayoutInflater.from(context);
            convertView = layoutInflater.inflate(R.layout.drawer_emoji_picker, parent, false);
            imageView = convertView.findViewById(R.id.img_custom_emoji);
        } else {
            imageView = (ImageView) convertView;
        }

        SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
        boolean disableAnimatedEmoji = sharedpreferences.getBoolean(Helper.SET_DISABLE_ANIMATED_EMOJI, false);

        Glide.with(context)
                .asFile()
                .load(emoji.getUrl())
                .listener(new RequestListener<File>()  {
                    @Override
                    public boolean onResourceReady(File resource, Object model, Target<File> target, DataSource dataSource, boolean isFirstResource) {
                        return false;
                    }

                    @Override
                    public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
                        return false;
                    }
                })
                .into(new SimpleTarget<File>() {
                    @Override
                    public void onResourceReady(@NonNull File resourceFile, @Nullable Transition<? super File> transition) {
                        Drawable resource;
                        if(GifParser.isGif(resourceFile.getAbsolutePath())){
                            resource = GifDrawable.fromFile(resourceFile.getAbsolutePath());
                        }else{
                            resource = APNGDrawable.fromFile(resourceFile.getAbsolutePath());
                        }

                        if( !disableAnimatedEmoji) {
                            resource.setVisible(true, true);
                            imageView.setImageDrawable(resource);

                        }else{
                            Bitmap bitmap = drawableToBitmap(resource.getCurrent());
                            imageView.setImageBitmap(bitmap);
                        }
                    }
                });
        return convertView;
    }

}

I can't use the plugin for Glide but it worked perfectly simply with:

 Glide.with(context)
                .load(emoji.getUrl())
                .into(imageView);

Thanks for helping

加载网络apng动画资源只显示静态图不能播放动画,加载本地资源没有问题

New Issue Checklist

  • I have searched for a similar issue in the project and found none

Issue Info

Info Value
Device Info e.g. Huawei Mate 20
System Version e.g. 9.0
APNG4Android Library Version e.g. 1.3.1
Repro rate e.g. all the time (100%) / sometimes x% / only once
Repro with our demo project e.g. does it happen with our demo project?
Demo project link e.g. link to a demo project that highlights the issue

Issue Description and Steps

Please fill in the detailed description of the issue (full output of any stack trace, compiler error, ...) and the steps to reproduce the issue.
加载网络apng动画资源只显示静态图不能播放动画,加载本地资源没有问题

Loading APNG with Glide plugin - not working

Issue Info

Loading APNG doesn't show an animated image.

Trying to load APNG into an ImageView using the following code

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        Glide
            .with(this)
            .load("https://misc.aotu.io/ONE-SUNDAY/SteamEngine.png")
            .into(img)
    }
}

With the following dependencies

implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
implementation 'com.github.penfeizhou.android.animation:glide-plugin:2.0.0'

Image is loaded but it is not moving, I tried the one with WebP https://isparta.github.io/compare-webp/image/gif_webp/webp/2.webp and it is working perfectly.

Device tested on:
Emulator: Nexus 5 API 28
minSdkVersion: 26
targetSdkVersion: 30

Also used this Image, still same result
chilled_koala

I would be happy to support more info

Any idea why is this happening?

How to register callback with Glide plugin?

dependency

com.github.penfeizhou.android.animation:glide-plugin:1.0.0

code

Glide.with(imageView)
    .load("https://misc.aotu.io/ONE-SUNDAY/SteamEngine.png")
    .into(imageView);

question

How can I register the Animatable2Compat.AnimationCallback to Glide?
I want to get the callback on animation start and end.

加载网络apng动画资源只显示静态图不能播放动画,加载本地资源没有问题

New Issue Checklist

  • I have searched for a similar issue in the project and found none

Issue Info

Info Value
Device Info e.g. Huawei Mate 30 pro
System Version e.g. 6.0
APNG4Android Library Version e.g. 1.0.0
Repro rate e.g. all the time (100%) / sometimes x% / only once
Repro with our demo project e.g. does it happen with our demo project?
Demo project link e.g. link to a demo project that highlights the issue

Issue Description and Steps

Please fill in the detailed description of the issue (full output of any stack trace, compiler error, ...) and the steps to reproduce the issue.

Issue with Recyclerview

I implemented a function that allows to load GIF if requested but when scrolling down, I have a lot of messages : E/FrameSeqDecoder: Processing,wait for finish at FINISHING and the app freezes.
I simply use that method:

public static void loadGiF(final Context context, String url, final ImageView imageView){
        SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
        boolean disableGif = sharedpreferences.getBoolean(SET_DISABLE_GIF, false);
        Glide.with(imageView.getContext())
                .asDrawable()
                .thumbnail(0.1f)
                .load(url)
                .into(new SimpleTarget<Drawable>() {
                    @Override
                    public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                        if( !disableGif) {
                            resource.setVisible(true, true);
                            imageView.setImageDrawable(resource);
                        }else{
                            resource.setVisible(true, true);
                            Bitmap bitmap = drawableToBitmap(resource.getCurrent());
                            imageView.setImageBitmap(bitmap);
                        }
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                            imageView.setClipToOutline(true);
                        }
                        imageView.setBackgroundResource(R.drawable.rounded_corner_10);
                    }
                });
    }

and in my adapter:

loadGiF(context, account.getAvatar(), holder.status_account_profile);

我用一个有透明边框的webp动画测试,发现透明边框显示成了白色,能帮忙看下这个问题吗

New Issue Checklist

  • I have searched for a similar issue in the project and found none

Issue Info

Info Value
Device Info e.g. Huawei Mate 30 pro
System Version e.g. 6.0
APNG4Android Library Version e.g. 1.0.0
Repro rate e.g. all the time (100%) / sometimes x% / only once
Repro with our demo project e.g. does it happen with our demo project?
Demo project link e.g. link to a demo project that highlights the issue

Issue Description and Steps

Please fill in the detailed description of the issue (full output of any stack trace, compiler error, ...) and the steps to reproduce the issue.

How does it happen? Buffer not large enough for pixels

How does it happen?

我看了一下最近1.3.3 change log,增加了一条 Avoid buffer size smaller than the target bitmap。
想确认一下这个是在什么情况下出现的,因为修复的代码只是做了一个防止错误的出现而已,是否彻底解决了问题?

Issue Info

Info Value
Device Info VIVO V3
System Version Android 5.1.1,level 22
APNG4Android Library Version 1.3.2
Repro rate Per thousand
Repro with our demo project no
Demo project link e.g. link to a demo project that highlights the issue

DISABLE_ANIMATION_GIF_DECODER默认值问题

public static final Option<Boolean> DISABLE_ANIMATION_GIF_DECODER = Option.memory( "com.github.penfeizhou.animation.glide.AnimationDecoderOption.DISABLE_ANIMATION_GIF_DECODER", false);
注释里面默认值是true,但是代码里面是false
现在使用glide加载图片,得到的GifDrawable是这个库的,不是glide默认的。

IOException: mark/reset not supported when using custom StreamLoader

New Issue Checklist

  • I have searched for a similar issue in the project and found none

Issue Info

Info Value
Device Info (1) Huawei Honor 8X + (2) Android emu API29
System Version (1) 9.0 + (2) 10.0
APNG4Android Library Version 1.3.3
Repro rate all the time (100%)
Repro with our demo project not tried
Demo project link N/A

Issue Description and Steps

When trying to use the library's FileLoader, my images wouldn't be displayed when passing absolute paths located on the SD card. I guess that is because APNG4Android relies on File only, and not on SAF.

To fix that, I implemented a custom StreamLoader that fetches the proper InputStream (see below).

The problem is, APNG4Android seems to call InputStream's reset method without intercepting the IOException, resulting in an empty image.

NB : The problem does not come from the test image I use, because it is properly displayed and animated when located in the phone's memory (the area where new FileInputStream(file) works fine).

//                FileLoader loader = new FileLoader(absolutePath):  <-- doesn't work when absolutePath points to a location on the SD card
ImgLoader loader = new ImgLoader(absolutePath);
APNGDrawable apngDrawable = new APNGDrawable(loader);
imgView.setImageDrawable(apngDrawable);
// Load the image using an InputStream whatever the location of the path (phone memory or SD card)
static class ImgLoader extends StreamLoader {

        private String path;

        ImgLoader(String path) {
            this.path= path;
        }

        @Override
        protected InputStream getInputStream() throws IOException {
            DocumentFile file = FileHelper.getDocumentFile(new File(path), false); // Helper to get a DocumentFile out of the given File
            if (null == file || !file.exists()) return null; // Not triggered

            return App.getInstance().getContentResolver().openInputStream(file.getUri());
        }
    }

Suggestions
a. Catch the reported exception (see below) and continue loading the image properly
and/or
b. Use ContentResolver.openInputStream inside FileReader to support resources located on SAF area.

2020-02-23 22:30:02.900 7395-7559/app.debug W/System.err: java.io.IOException: mark/reset not supported
2020-02-23 22:30:02.900 7395-7559/app.debug W/System.err:     at java.io.InputStream.reset(InputStream.java:348)
2020-02-23 22:30:02.900 7395-7559/app.debug W/System.err:     at java.io.FilterInputStream.reset(FilterInputStream.java:226)
2020-02-23 22:30:02.900 7395-7559/app.debug W/System.err:     at com.github.penfeizhou.animation.io.StreamReader.reset(StreamReader.java:39)
2020-02-23 22:30:02.900 7395-7559/app.debug W/System.err:     at com.github.penfeizhou.animation.io.FilterReader.reset(FilterReader.java:30)
2020-02-23 22:30:02.900 7395-7559/app.debug W/System.err:     at com.github.penfeizhou.animation.apng.decode.APNGFrame.encode(APNGFrame.java:89)
2020-02-23 22:30:02.900 7395-7559/app.debug W/System.err:     at com.github.penfeizhou.animation.apng.decode.APNGFrame.draw(APNGFrame.java:126)
2020-02-23 22:30:02.900 7395-7559/app.debug W/System.err:     at com.github.penfeizhou.animation.apng.decode.APNGFrame.draw(APNGFrame.java:22)
2020-02-23 22:30:02.900 7395-7559/app.debug W/System.err:     at com.github.penfeizhou.animation.apng.decode.APNGDecoder.renderFrame(APNGDecoder.java:190)
2020-02-23 22:30:02.900 7395-7559/app.debug W/System.err:     at com.github.penfeizhou.animation.decode.FrameSeqDecoder.step(FrameSeqDecoder.java:451)
2020-02-23 22:30:02.900 7395-7559/app.debug W/System.err:     at com.github.penfeizhou.animation.decode.FrameSeqDecoder.access$200(FrameSeqDecoder.java:34)
2020-02-23 22:30:02.900 7395-7559/app.debug W/System.err:     at com.github.penfeizhou.animation.decode.FrameSeqDecoder$1.run(FrameSeqDecoder.java:58)
2020-02-23 22:30:02.900 7395-7559/app.debug W/System.err:     at android.os.Handler.handleCallback(Handler.java:883)
2020-02-23 22:30:02.900 7395-7559/app.debug W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:100)
2020-02-23 22:30:02.900 7395-7559/app.debug W/System.err:     at android.os.Looper.loop(Looper.java:214)
2020-02-23 22:30:02.900 7395-7559/app.debug W/System.err:     at android.os.HandlerThread.run(HandlerThread.java:67)

NullPointerException

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Rect.width()' on a null object reference at com.github.penfeizhou.animation.FrameAnimationDrawable.getIntrinsicWidth(FrameAnimationDrawable.java:196) at android.widget.ImageView.invalidateDrawable(ImageView.java:293) at android.graphics.drawable.Drawable.invalidateSelf(Drawable.java:450) at android.graphics.drawable.Drawable.setVisible(Drawable.java:859) at com.github.penfeizhou.animation.FrameAnimationDrawable.setVisible(FrameAnimationDrawable.java:191) at android.widget.ImageView.updateDrawable(ImageView.java:1061) at android.widget.ImageView.setImageDrawable(ImageView.java:609) at com.bumptech.glide.request.target.DrawableImageViewTarget.setResource(DrawableImageViewTarget.java:28) at com.bumptech.glide.request.target.DrawableImageViewTarget.setResource(DrawableImageViewTarget.java:10) at com.bumptech.glide.request.target.ImageViewTarget.setResourceInternal(ImageViewTarget.java:127) at com.bumptech.glide.request.target.ImageViewTarget.onResourceReady(ImageViewTarget.java:104) at com.bumptech.glide.request.SingleRequest.onResourceReady(SingleRequest.java:582) at com.bumptech.glide.request.SingleRequest.onResourceReady(SingleRequest.java:544) at com.bumptech.glide.load.engine.EngineJob.callCallbackOnResourceReady(EngineJob.java:152) at com.bumptech.glide.load.engine.EngineJob$CallResourceReady.run(EngineJob.java:398)  at android.os.Handler.handleCallback(Handler.java:808)  at android.os.Handler.dispatchMessage(Handler.java:101)  at android.os.Looper.loop(Looper.java:166)  at android.app.ActivityThread.main(ActivityThread.java:7529)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921) 

Rendering webP image wrong.

hi,
I'm using APNG4Android source code with Glide, when testing ,apng and gif get nothing wrong, but webP seems to have some rendering problem.

  • When some webP image playing, i can see white rectangle area with some colorful pixels on it. Seems like something wrong with blending.
  • And some other webP image playing faster than the speed it playing on webpage.

Hope you can help me! Thanks.

NullPointerException

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Rect.width()' on a null object reference at com.github.penfeizhou.animation.FrameAnimationDrawable.getIntrinsicWidth(FrameAnimationDrawable.java:196) at android.widget.ImageView.invalidateDrawable(ImageView.java:293) at android.graphics.drawable.Drawable.invalidateSelf(Drawable.java:450) at android.graphics.drawable.Drawable.setVisible(Drawable.java:859) at com.github.penfeizhou.animation.FrameAnimationDrawable.setVisible(FrameAnimationDrawable.java:191) at android.widget.ImageView.updateDrawable(ImageView.java:1061) at android.widget.ImageView.setImageDrawable(ImageView.java:609) at com.bumptech.glide.request.target.DrawableImageViewTarget.setResource(DrawableImageViewTarget.java:28) at com.bumptech.glide.request.target.DrawableImageViewTarget.setResource(DrawableImageViewTarget.java:10) at com.bumptech.glide.request.target.ImageViewTarget.setResourceInternal(ImageViewTarget.java:127) at com.bumptech.glide.request.target.ImageViewTarget.onResourceReady(ImageViewTarget.java:104) at com.bumptech.glide.request.SingleRequest.onResourceReady(SingleRequest.java:582) at com.bumptech.glide.request.SingleRequest.onResourceReady(SingleRequest.java:544) at com.bumptech.glide.load.engine.EngineJob.callCallbackOnResourceReady(EngineJob.java:152) at com.bumptech.glide.load.engine.EngineJob$CallResourceReady.run(EngineJob.java:398)  at android.os.Handler.handleCallback(Handler.java:808)  at android.os.Handler.dispatchMessage(Handler.java:101)  at android.os.Looper.loop(Looper.java:166)  at android.app.ActivityThread.main(ActivityThread.java:7529)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921) 

版本:implementation 'com.github.penfeizhou.android.animation:glide-plugin:1.3.1

不是特定的APNG图片导致的崩溃,而是使用ViewPager切换Fragment,Fragment是一个APNG图片列表,在切换的过程中偶尔会出现的异常。

Min SDK version

Hey,
I wonder if the library could accept a lower minSdkVersion currently set to 19?

WebPEncoder doesn't work

Hello!
I saw your library and I really like it.
It is the only library I found that handles animated webp, but unfortunately I couldn't make it work.

I tried both:

final byte[] ret = WebPEncoder.fromGif(new AssetStreamLoader(context, "test.gif")).build();
File file = new File(context.getCacheDir(), "test.webp");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
fos.write(ret);
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}

and

WebPEncoder encoder = new WebPEncoder();

int duration = 0;
for (int i = 0; i < standardGifDecoder.getFrameCount(); i++) {
Bitmap bitmap = standardGifDecoder.getNextFrame();
encoder.addFrame(bitmap, 0,0, standardGifDecoder.getNextDelay());
}

But both gave me an invalid webp file (attaching it).
test1.zip

The original gif:
test

It would be amazing if you could help me, or even direct me to the bug so I can open a PR.
Thanks!

How to use the Glide plugin?

I try to use APNG4Android with Glide and ImageSpan for displaying animated png like this one

Animated emoji

As soon as I import the lib 'com.github.pengfeizhou.android.animation:glide-plugin:0.2.16', drawable are no longer displayed. I use this code:

  Glide.with(context)
	.asDrawable()
	.load(emoji.getUrl())
        .into(new SimpleTarget<Drawable>() {
        	@Override
                public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
 			resource.setBounds(0,0,(int) Helper.convertDpToPixel(20, context),(int) Helper.convertDpToPixel(20, context));
                        ImageSpan imageSpan = new ImageSpan(resource, ImageSpan.ALIGN_BASELINE);
                        contentSpan.setSpan(imageSpan, startPosition,endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
		}
  	});

I don't get errors so I guess I am not using it correctly.

部分宽度为533dp的pad设备播放apng会鬼畜

调用代码如下:
Glide.with(this)
.load("$rootDir/animPic/microphone.png")
.listener(object : RequestListener {
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, isFirstResource: Boolean): Boolean {
return false
}

                override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                    if (resource is APNGDrawable) {
                        resource.setLoopLimit(0)
                    }
                    return false
                }

            })
            .into(ivMicrophone)

microphone

【Crash】APNGParser$FormatException: APNG Format error

线上出现大量:

Caused by: com.github.penfeizhou.animation.apng.decode.APNGParser$FormatException: APNG Format error
    at com.github.penfeizhou.animation.apng.decode.APNGParser.parse(APNGParser.java)
    at com.github.penfeizhou.animation.apng.decode.APNGDecoder.read(APNGDecoder.java)
    at com.github.penfeizhou.animation.apng.decode.APNGDecoder.read(APNGDecoder.java)
    at com.github.penfeizhou.animation.decode.FrameSeqDecoder$2.call(FrameSeqDecoder.java)
    at com.github.penfeizhou.animation.decode.FrameSeqDecoder$2.call(FrameSeqDecoder.java)

Android版本均有分布,机型也均有分布。
我是使用OKhttp下载到本地后,使用此框架加载的。

你好大神,内存问题

1.很感谢你的库。
2.使用FileLoader加载apng文件,出现内存以0.2M/s的速度在增加,然后加载到一定大小又回回到原内存,请问这种情况是什么原因?是否正常?

Problem decoding into existing bitmap

EXCEPTION LOG:
java.lang.IllegalArgumentException: Problem decoding into existing bitmap
at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:670)
at com.github.penfeizhou.animation.webp.decode.AnimationFrame.draw(AnimationFrame.java:82)

Explicit termination method 'close' not called

Hey,

When I wanted to debug some crashes I noticed this bug. Is it something that I can fix on my end?

StrictMode policy violation: android.os.strictmode.LeakedClosableViolation: A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.

Here are the full logs

2019-08-17 09:22:43.099 16542-16551/app.fedilab.android D/StrictMode: StrictMode policy violation: android.os.strictmode.LeakedClosableViolation: A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.
        at android.os.StrictMode$AndroidCloseGuardReporter.report(StrictMode.java:1803)
        at dalvik.system.CloseGuard.warnIfOpen(CloseGuard.java:264)
        at java.io.FileInputStream.finalize(FileInputStream.java:487)
        at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:250)
        at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:237)
        at java.lang.Daemons$Daemon.run(Daemons.java:103)
        at java.lang.Thread.run(Thread.java:784)
     Caused by: java.lang.Throwable: Explicit termination method 'close' not called
        at dalvik.system.CloseGuard.open(CloseGuard.java:221)
        at java.io.FileInputStream.<init>(FileInputStream.java:168)
        at com.github.penfeizhou.animation.io.FileReader.reset(FileReader.java:24)
        at com.github.penfeizhou.animation.io.FilterReader.toInputStream(FilterReader.java:55)
        at com.github.penfeizhou.animation.io.FilterReader.toInputStream(FilterReader.java:56)
        at com.github.penfeizhou.animation.apng.decode.StillFrame.draw(StillFrame.java:35)
        at com.github.penfeizhou.animation.apng.decode.StillFrame.draw(StillFrame.java:19)
        at com.github.penfeizhou.animation.apng.decode.APNGDecoder.renderFrame(APNGDecoder.java:190)
        at com.github.penfeizhou.animation.decode.FrameSeqDecoder.step(FrameSeqDecoder.java:463)
        at com.github.penfeizhou.animation.decode.FrameSeqDecoder.access$200(FrameSeqDecoder.java:35)
        at com.github.penfeizhou.animation.decode.FrameSeqDecoder$1.run(FrameSeqDecoder.java:56)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:458)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:784) 

java.lang.NullPointerException in getDesiredSample

New Issue Checklist

Caused by: java.lang.NullPointerException: 
 
  at com.github.penfeizhou.animation.decode.FrameSeqDecoder.getDesiredSample (FrameSeqDecoder.java:407)
 
  at com.github.penfeizhou.animation.decode.FrameSeqDecoder.setDesiredSize (FrameSeqDecoder.java:381)
 
  at com.github.penfeizhou.animation.FrameAnimationDrawable.setBounds (FrameAnimationDrawable.java:128)
 
  at app.fedilab.android.client.Entities.Status$8.onResourceReady (Status.java:895)
 
  at app.fedilab.android.client.Entities.Status$8.onResourceReady (Status.java:885)
  • I have searched for a similar issue in the project and found none

Issue Description and Steps

I can't reproduce that on my end but I got several reports.

Glide support

Does the Glide support change the general behaviour (or is it a change in Glide 4.9.0)? I will explain my issue.

I was using Glide in that way for loading some profile pictures:

 Glide.with(imageView.getContext())
                        .load(url)
                        .apply(new RequestOptions().transforms(new CenterCrop(), new RoundedCorners(10)))
                        .into(imageView);

When it was a gif URL, that worked but now I get a message telling me it can't load a gif image as a bitmap.

My current fix is:

 if ( url.endsWith(".gif")) {
            try {
                Glide.with(imageView.getContext())
                        .asGif()
                        .load(url)
                        .apply(new RequestOptions().transforms(new CenterCrop(), new RoundedCorners(10)))
                        .into(imageView);
            } catch (Exception ignored) {
            }
        } else {
            try {
                Glide.with(context)
                        .asBitmap()
                        .apply(new RequestOptions().transforms(new CenterCrop(), new RoundedCorners(10)))
                        .load(urlStatic)
                        .into(imageView);
            } catch (Exception ignored) {
            }
        }

Crash

  • I have searched for a similar issue in the project and found none

Issue Info

Info Value
Device Info vivo Y66
System Version 6.0.1
APNG4Android Library Version 1.3.3

java.lang.IllegalArgumentException: Problem decoding into existing bitmap
at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:525)
at com.github.penfeizhou.animation.apng.decode.APNGFrame.draw(APNGFrame.java:133)
at com.github.penfeizhou.animation.apng.decode.APNGFrame.draw(APNGFrame.java:22)
at com.github.penfeizhou.animation.apng.decode.APNGDecoder.renderFrame(APNGDecoder.java:190)
at com.github.penfeizhou.animation.decode.FrameSeqDecoder.step(FrameSeqDecoder.java:451)
at com.github.penfeizhou.animation.decode.FrameSeqDecoder.access$200(FrameSeqDecoder.java:34)
at com.github.penfeizhou.animation.decode.FrameSeqDecoder$1.run(FrameSeqDecoder.java:58)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.os.HandlerThread.run(HandlerThread.java:61)

java.lang.OutOfMemoryError on ByteBufferWriter.reset

New Issue Checklist

  • I have searched for a similar issue in the project and found none

Issue Info

Info Value
Device Info Huawei P8 lite 2017 (HWPRA-H)
System Version Android 8.0
APNG4Android Library Version 1.3.3

Issue Description and Steps

I only see that error logs and I can't link the call from my project that throws them.

java.lang.OutOfMemoryError: 
 
  at java.nio.HeapByteBuffer.<init> (HeapByteBuffer.java:54)
 
  at java.nio.HeapByteBuffer.<init> (HeapByteBuffer.java:49)
 
  at java.nio.ByteBuffer.allocate (ByteBuffer.java:261)
 
  at com.github.penfeizhou.animation.io.ByteBufferWriter.reset (ByteBufferWriter.java:51)
 
  at com.github.penfeizhou.animation.apng.io.APNGWriter.reset (APNGWriter.java:33)
 
  at com.github.penfeizhou.animation.apng.decode.APNGFrame.encode (APNGFrame.java:70)
 
  at com.github.penfeizhou.animation.apng.decode.APNGFrame.draw (APNGFrame.java:126)
 
  at com.github.penfeizhou.animation.apng.decode.APNGFrame.draw (APNGFrame.java:22)
 
  at com.github.penfeizhou.animation.apng.decode.APNGDecoder.renderFrame (APNGDecoder.java:190)
 
  at com.github.penfeizhou.animation.decode.FrameSeqDecoder.step (FrameSeqDecoder.java:451)
 
  at com.github.penfeizhou.animation.decode.FrameSeqDecoder.access$200 (FrameSeqDecoder.java:34)
 
  at com.github.penfeizhou.animation.decode.FrameSeqDecoder$1.run (FrameSeqDecoder.java:58)
 
  at com.github.penfeizhou.animation.decode.FrameSeqDecoder.innerStart (FrameSeqDecoder.java:270)
 
  at com.github.penfeizhou.animation.decode.FrameSeqDecoder.access$900 (FrameSeqDecoder.java:34)
 
  at com.github.penfeizhou.animation.decode.FrameSeqDecoder$3.run (FrameSeqDecoder.java:240)
 
  at android.os.Handler.handleCallback (Handler.java:808)
 
  at android.os.Handler.dispatchMessage (Handler.java:101)
 
  at android.os.Looper.loop (Looper.java:166)
 
  at android.os.HandlerThread.run (HandlerThread.java:65)

调用stop方法会ANR

ANR Input dispatching timed out (Waiting to send non-key event because the touched window has not finished processing certain input events that were delivered to it over 500.0ms ago. Wait queue length: 22. Wait queue head age: 5506.6ms.)

How to get rid of these messages FrameSeqDecoder?

I have a lot of these messages in log. Is it a misconfiguration on my end?

2019-08-03 11:59:11.248 26871-26871/app.fedilab.android I/FrameSeqDecoder: No need to stop
2019-08-03 11:59:11.251 26871-27830/app.fedilab.android I/FrameSeqDecoder:  Set state to RUNNING,cost 3

I needed to change my code, now I use the lib like this:

 Glide.with(context)
                        .asFile()
                        .load(emoji.getUrl())
                        .into(new SimpleTarget<File>() {
                            @Override
                            public void onResourceReady(@NonNull File resourceFile, @Nullable Transition<? super File> transition) {
                                Drawable resource;
                                if( emoji.getUrl().endsWith(".gif")){
                                    resource = GifDrawable.fromFile(resourceFile.getAbsolutePath());
                                    ((GifDrawable) resource).start();
                                }else{
                                    resource = APNGDrawable.fromFile(resourceFile.getAbsolutePath());
                                }
                                final String targetedEmoji = ":" + emoji.getShortcode() + ":";
                                if (contentSpan != null && contentSpan.toString().contains(targetedEmoji)) {
                                    //emojis can be used several times so we have to loop
                                    for (int startPosition = -1; (startPosition = contentSpan.toString().indexOf(targetedEmoji, startPosition + 1)) != -1; startPosition++) {
                                        final int endPosition = startPosition + targetedEmoji.length();
                                        if( endPosition <= contentSpan.toString().length() && endPosition >= startPosition) {
                                            ImageSpan imageSpan;
                                            if( !disableAnimatedEmoji) {
                                                resource.setBounds(0, 0, (int) Helper.convertDpToPixel(20, context), (int) Helper.convertDpToPixel(20, context));
                                                resource.setVisible(true, true);
                                                imageSpan = new ImageSpan(resource);

                                            }else{
                                                resource.setVisible(true, true);
                                                Bitmap bitmap = drawableToBitmap(resource.getCurrent());
                                                imageSpan = new ImageSpan(context,
                                                        Bitmap.createScaledBitmap(bitmap, (int) Helper.convertDpToPixel(20, context),
                                                                (int) Helper.convertDpToPixel(20, context), false));
                                            }
                                            contentSpan.setSpan(
                                                    imageSpan, startPosition,
                                                    endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
                                        }
                                    }
                                }

                            }
                        });

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.