Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android 圖片解碼顯示流程

android 圖片解碼顯示流程

編輯:關於Android編程

問題來源

android 可以在 gallery 裡面顯示內部存儲的圖片,支持 jpeg,png,gif,bmp 等,甚至文件類型和圖片後綴名不一致,只要是圖片文件就能顯示,然後 git 只會顯示第一幀圖像,然而 android 其實是可以顯示 gif 動畫的,在浏覽器裡打開 gif 動畫,就能夠正常加載顯示。

Gallery 查看圖片

gallery 實現了 Gallery/src/com/android/camera/ViewImage.java
                        ImageViewTouchBase newView =
                                mSlideShowImageViews[mSlideShowImageCurrent];
                        newView.setVisibility(View.VISIBLE);
                        newView.setImageRotateBitmapResetBase(bitmap, true);
                        newView.bringToFront();

通過自己實現的 ImageViewTouchBase 裝載圖片並顯示
ImageViewTouchBase 繼承自 framework 的 ImageView
package com.android.camera;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.ImageView;

abstract class ImageViewTouchBase extends ImageView {

framework 處理圖片

ImageView 是 android 圖片框架實現通用圖片處理顯示類: 可以顯示 resource 裡面的圖片,
    public void setImageResource(int resId) {
        if (mUri != null || mResource != resId) {
            updateDrawable(null);
            mResource = resId;
            mUri = null;

            final int oldWidth = mDrawableWidth;
            final int oldHeight = mDrawableHeight;

            resolveUri();

            if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
                requestLayout();
            }
            invalidate();
        }
    }

我們在 gallery 裡面打開的圖片調用是通過 uri 傳過來的,
    public void setImageURI(Uri uri) {
        if (mResource != 0 ||
                (mUri != uri &&
                 (uri == null || mUri == null || !uri.equals(mUri)))) {
            updateDrawable(null);
            mResource = 0;
            mUri = uri;

            final int oldWidth = mDrawableWidth;
            final int oldHeight = mDrawableHeight;

            resolveUri();

            if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
                requestLayout();
            }
            invalidate();
        }
    }

android 會解析 uri 得到目標文件路徑
        } else if (mUri != null) {
            String scheme = mUri.getScheme();
            if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
                try {
                    // Load drawable through Resources, to get the source density information
                    ContentResolver.OpenResourceIdResult r =
                            mContext.getContentResolver().getResourceId(mUri);
                    d = r.r.getDrawable(r.id);
                } catch (Exception e) {
                    Log.w("ImageView", "Unable to open content: " + mUri, e);
                }
            } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)
                    || ContentResolver.SCHEME_FILE.equals(scheme)) {
                InputStream stream = null;
                try {
                    stream = mContext.getContentResolver().openInputStream(mUri);
                    d = Drawable.createFromStream(stream, null);
                } catch (Exception e) {
                    Log.w("ImageView", "Unable to open content: " + mUri, e);
                } finally {
                    if (stream != null) {
                        try {
                            stream.close();
                        } catch (IOException e) {
                            Log.w("ImageView", "Unable to close content: " + mUri, e);
                        }
                    }
                }
        } else {
                d = Drawable.createFromPath(mUri.toString());
            }

我們點擊 gallery 的圖片會產生包含 content 的 uri: I/ActivityManager( 1304): START u0 {dat=content://media/external/images/media/21 cmp=com.android.gallery/com.android.camera.ViewImage (has extras)} from pid 1706

然後通過 Drawable 從 inputstream 裡面解析創建 Drawable 對象
    public static Drawable createFromStream(InputStream is, String srcName) {
        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, srcName != null ? srcName : "Unknown drawable");
        try {
            return createFromResourceStream(null, null, is, srcName, null);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
        }
    }

後面的流程就是交給 skia 解析然後獲得一個 bitmap 並返回了。 skia 的 decode 可以自動識別 steam 裡面的數據流創建相應的 decoder。

問題答案

framework 是通用的圖片顯示處理,最後只返回了一個 bitmap ,所以 gif 只能處理第一幀圖像了,但是 browser 是從新實現了圖像顯示接口,有專門針對 gif 的顯示處理,所以可以顯示動畫。


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved