实现GIF图片的缩放

图片选择器中提到gif文件是使用了普通的ImageView来实现的,如果需要实现gif图片的缩放那么就需要自定义SSIV

首先需要GIF解码器,可以选择使用glide的gif decoder,也可以使用原版的https://gist.github.com/devunwired/4479231

改造SSIV主要修改的地方是setImage方法,最后是使用了BitmapLoadTask加载图片文件,改为使用自定义的GifBitmapLoadTask进行加载,加载完成后先显示第一帧图片,如果帧数为1那么应该是静态图,不再进行下面的操作,如果不为1,则开启线程读取下一帧的图片并显示,然后一直循环读取并显示。

初始化decorder并开始加载

    public final void setImage(@NonNull ImageSource imageSource, ImageSource previewSource, ImageViewState state) {
         …………
                if (mDecoder == null) {
                    mDecoder = new GifDecoder();
                }
                //mDecoder.setDefaultBitmapConfig(Bitmap.Config.RGB_565);
                // Load gif bitmap
                GifImageLoadTask task = new GifImageLoadTask(this, getContext(), uri, false, mDecoder);
                execute(task);
}
GifImageLoadTask代码和BitmapImageLoadTask类似,不过这里是加载第一帧图片
private static class GifImageLoadTask extends AsyncTask<Void, Void, Integer> {
        private final WeakReference<GifSubsamplingScaleImageView> viewRef;
        private final Uri uri;
        private final boolean preview;
        private final GifDecoder gifDecoder;
        private Bitmap bitmap;
        private Exception exception;

        public GifImageLoadTask(GifSubsamplingScaleImageView gifSubsamplingScaleImageView, Context context, Uri uri, boolean preview, GifDecoder gifDecoder) {
            this.viewRef = new WeakReference<>(gifSubsamplingScaleImageView);
            this.uri = uri;
            this.preview = preview;
            this.gifDecoder = gifDecoder;
        }

        @Override
        public Integer doInBackground(Void... voidArr) {
            InputStream inputStream = null;
            try {
                try {
                    if (uri.getPath() != null) inputStream = new FileInputStream(uri.getPath());
                } catch (FileNotFoundException e) {
                    exception = e;
                }
                if (inputStream == null) {
                    return null;
                }
                gifDecoder.read(inputStream, inputStream.available());
                gifDecoder.advance();
                bitmap = gifDecoder.getNextFrame();
                if (bitmap != null) {
                    return 0;
                } else {
                    exception = new FileNotFoundException();
                    return null;
                }
            } catch (Exception ex) {
                this.exception = ex;
            } catch (OutOfMemoryError error) {
                this.exception = new RuntimeException(error);
            }
            return null;
        }

        @Override
        public void onPostExecute(Integer num) {
            GifSubsamplingScaleImageView view = viewRef.get();
            if (view == null) {
                return;
            }
            if (num != null) {
                if (preview) {
                    view.onPreviewLoaded(bitmap);
                } else {
                    view.onImageLoaded(bitmap, num, false);
                }
            } else if (exception != null && view.onImageEventListener != null) {
                if (preview) {
                    view.onImageEventListener.onPreviewLoadError(exception);
                } else {
                    view.onImageEventListener.onImageLoadError(exception);
                }
            }
        }
    }

加载完成后再进行下一步的判断

    public synchronized void onImageLoaded(Bitmap bitmap, int sOrientation, boolean bitmapIsCached) {
        debug("onImageLoaded");
        // If actual dimensions don't match the declared size, reset everything.
        if (this.sWidth > 0 && this.sHeight > 0 && (this.sWidth != bitmap.getWidth() || this.sHeight != bitmap.getHeight())) {
            reset(false);
        }
        if (this.bitmap != null && !this.bitmapIsCached) {
            this.bitmap.recycle();
        }

        if (this.bitmap != null && this.bitmapIsCached && onImageEventListener != null) {
            onImageEventListener.onPreviewReleased();
        }
        this.bitmapIsCached = bitmapIsCached;
        this.sOrientation = sOrientation;
        loadImage(bitmap, true);
        if (mDecoder != null && mDecoder.getFrameCount() > 1) {
            this.drawThread = new DrawThread();
            this.drawThread.start();
        }
    }

开启DrawThread进行循环的读取下一帧图片。

public class DrawThread extends Thread {

        public DrawThread() {
        }

        public void run() {
            if (mDecoder != null) {
                mIsRun = true;
                while (mIsRun) {
                    if (!waitIfPaused() && mDecoder != null) {
                        long startTime = SystemClock.elapsedRealtime();
                        mDecoder.advance();
                        Bitmap bitmap = mDecoder.getNextFrame();
                        if (bitmap != null) {
                            if (checkReady() || checkImageLoaded()) {
                                Message msg = Message.obtain();
                                msg.obj = bitmap;
                                msg.what = 0;
                                mHandler.sendMessage(msg);
                            }
                            long f = ((long) mDecoder.getNextDelay()) - (SystemClock.elapsedRealtime() - startTime);
                            if (f <= 0 ) {
                                f = 0;
                            }
                            SystemClock.sleep(f);
                        }
                    } else {
                        return;
                    }
                }
                mDecoder.release();
                mDecoder = null;
            }
        }
    }

这样基本实现了gif图片的显示和缩放,源码地址

发布了53 篇原创文章 · 获赞 17 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/jklwan/article/details/100866049
今日推荐