標籤:圖片 動畫 bitmap uri
問題來源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 的顯示處理,所以可以顯示動畫。