日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

android 图片操作

發布時間:2025/4/5 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 图片操作 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Android中圖片的讀取,修改,顯示和保存涉及到的類大致如圖所示。

在讀取圖片文件時,先將圖片文件轉換為InputStream對象,然后通過BitmapFactory將其轉換為Bitmap對象。?
在圖片保存時,先將Bitmap對象轉換為OutputStream對象,然后再將OutputStream輸出到文件中。?
如果要對圖片進行修改,可以通過將Bitmap對象轉換為顏色數組(int[])來修改,也可以通過Canvas來修改。此外Bitmap類提供了一個createBitmap的靜態方法,可以對Bitmap對象做一些轉換。?
顯示圖片時,可以將Bitmap對象轉換為Drawable對象,然后設置給ImageView。?
本文介紹圖片文件的讀取。

Android支持的圖片格式

目前在Android中支持的圖片文件格式如下。其中WebP格式是從Android4.0開始支持,但在Android4.0到Android4.2.1之間的Android系統不支持無損壓縮和有透明度的WebP格式圖片,Android4.2.1之后才開始支持所有的WebP格式圖片。?
下圖截取自http://developer.android.com/guide/appendix/media-formats.html?

讀取圖片文件到InputStream

1、讀取SD卡中的圖片到InputStream?
對SD卡中的文件,獲取到文件的路徑之后便可以通過FileInputStream類來生成InputStream。FileInputStream類是InputStream類的派生類。代碼示例如下。

FileInputStream stream = new FileInputStream(fileName);
  • 1
  • 1

2、讀取resource中的圖片到InputStream?
對resource/drawable目錄下的圖片,每個文件都會在R文件中生成一個對應的整數id,通過“R.drawable.文件名”來得到id值,然后通過Resource類的openRawResource()來得到該文件對應的InputStream對象。代碼示例如下。

InputStream strem = getResources().openRawResource(R.drawable.name);
  • 1
  • 1

3、讀取assets中的圖片到InputStream?
對assets目錄中的圖片,先通過getAssets()得到AssetManager對象,然后通過AssetManager對象的open方法來打開文件,得到該文件對應的InputStream對象。代碼示例如下。

InputStream strem = getAssets().open("apple.png");
  • 1
  • 1

注意:如果圖片在assets根目錄,讀取時只需要加圖片文件名,不需要加/assets/,圖片文件名需要包含擴展名。如果圖片在assets的子目錄中,需要加上子目錄的路徑,例如apple.png在/assert/fruit/spring/目錄中,則open參數為”/fruit/spring/apple.png”。

4、 通過Uri讀取圖片到InputStream?
Uri全寫是Universal Resource Identifier(通用資源標志符),Android系統中所有資源都可以用Uri來表示。在獲取到資源的Uri后可以通過ContentResolver將其解析成InputStream對象。代碼示例如下。

InputStream strem = getContentResolver().openInputStream(uri);
  • 1
  • 1

openInputStream()核心代碼如下。

String scheme = uri.getScheme(); if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {OpenResourceIdResult r = getResourceId(uri);InputStream stream = r.r.openRawResource(r.id);return stream; } else if (SCHEME_FILE.equals(scheme)) {return new FileInputStream(uri.getPath()); } else {AssetFileDescriptor fd = openAssetFileDescriptor(uri, "r", null);return fd.createInputStream(); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

這里openInputStream()內先判斷Uri的scheme類型,如果是resource類型,則先調用getResourceId()得到該Uri對應的資源id,然后調用openRawResource()讀取文件到InputStream對象。如果是文件類型,則調用uri.getPath()得到文件路徑,然后調用FileInputStream()讀取文件到InputStream對象。對其他類型(即assets類型)則調用openAssetFileDescriptor()先得到一個AssetFileDescriptor對象,然后再得到一個InputStream對象。?
可以看到,通過Uri讀取圖片的流程和上述根據類型直接讀取大體是一樣的(assets類型稍有不同)。

將InputStream轉換為Bitmap

通過BitmapFactory的decodeStream()方法可以將InputStream轉換為Bitmap對象。代碼示例如下。

Bitmap bitmap = BitmapFactory.decodeStream(stream);
  • 1
  • 1

直接讀取圖片文件到Bitmap

上述流程是先將圖片文件讀取到InputStream中,然后將InputStream轉換為Bitmap對象,需要兩步。BitmapFactory提供了一些靜態類可以直接將圖片文件轉換為Bitmap對象。?
直接讀取SD卡中的圖片到Bitmap示例代碼如下。

Bitmap bitmap = BitmapFactory.decodeFile(fileName);
  • 1
  • 1

直接讀取resource中的圖片到Bitmap示例代碼如下。

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), id);
  • 1
  • 1

BitmapFactory并沒有提供直接讀取assets中圖片的api。?
查看BitmapFactory源碼可以看到,BitmapFactory.decodeFile()和BitmapFactory.decodeResource()兩個api都是先將SD卡或resource中的圖片讀取到InputStream,然后再調用BitmapFactory.decodeStream()來解析。由此可以看出,直接讀取圖片到Bitmap和先讀取圖片到InputStream,然后將InputStream轉換為Bitmap本質上是一樣的,只是BitmapFactory將這兩步封裝在一起。因此,如果要將非assets中的圖片文件轉換為Bitmap,一般就直接使用BitmapFactory即可。

BitmapFactory.Options

BitmapFactory在decode時可以傳遞一個Options參數,用來設置轉換到Bitmap時的一些參數。?
BitmapFactory.Options中包含了一系列的public成員變量,每個成員變量代表一個轉換參數。這里列出了BitmapFactory.Options類中定義的全部public成員變量。在BitmapFactory.Options類的注釋中詳細的描述了每個成員變量的含義。這里只介紹幾個常用的成員變量的用法。

public static class Options {public Bitmap inBitmap;public boolean inMutable;public boolean inJustDecodeBounds;public int inSampleSize;public Bitmap.Config inPreferredConfig = Bitmap.Config.ARGB_8888;public boolean inPremultiplied;public boolean inDither;public int inDensity;public int inTargetDensity;public int inScreenDensity;public boolean inScaled;public boolean inPurgeable;public boolean inInputShareable;public boolean inPreferQualityOverSpeed;public int outWidth;public int outHeight;public String outMimeType;public byte[] inTempStorage;public boolean mCancel;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

inJustDecodeBounds:此變量默認為false。當此變量被設置為true時,表示只對圖片的Bound(圖片的范圍,也就是長寬包含的像素大小)進行解析,不生成Bitmap對象。在BitmapFactory.Options定義中可以看到有三個out開頭的成員變量,outWidth,outHeight和outMimeType。當inJustDecodeBounds設置為true時,會分別將圖片的寬度,高度和Mime類型保存到這三個成員變量中。?
inSampleSize:inSampleSize是一個整數,表示對圖片像素的取樣比例,即圖片中每inSampleSize個像素取樣后對應Bitmap中的一個像素。例如inSampleSize=2,表示圖片中每兩個像素對應Bitmap中的一個像素,轉換后Bitmap的寬和高包含的像素個數是原圖片的1/2,總像素個數是原圖的1/4。inSampleSize=4,表示圖片中每四個像素對應Bitmap中的一個像素,轉換后Bitmap的寬和高包含的像素個數是原圖片的1/4,總像素個數是原圖的1/16。如果它小于1等于1,則表示完全取樣,即圖片中每個像素都會被提取保存到Bitmap中,轉換后Bitmap的寬和高包含的像素個數和原圖片相等。圖片取樣時只能按照2的整數次冪來取樣,比如1,2,4,8,16……,如果inSampleSize不是2的整數次冪,則實際取樣時使用和inSampleSize最接近的2的整數次冪來取樣,比如inSampleSize= 10,和10最接近的2的整數次冪是8,因此會每8個像素取樣一次。?
inPreferredConfig:表示圖片中每個像素的保存方式。默認為Bitmap.Config.ARGB_8888,表示每個像素需要包含Alpha,R,G,B四個通道的信息,每個通道用8位來表示,也就是需要4個字節來保存一個像素。

圖片文件讀取注意事項

1、WebP圖片格式問題?
雖然Android官方描述是在4.0之后開始支持WebP格式,但在4.0到4.2.1不支持有透明度設置和無損壓縮的WebP格式圖片。所以如果簡單的判斷,圖片如果是WebP格式,且是4.0以上的系統,就通過BitmapFactory來解析,很可能會出現有些圖片能解析,有些又不能解析的情況。此外,還有一些特殊機型,例如NokiaXL雖然是Android4.1的系統,但并不支持WebP編解碼。因此,最好是從4.2系統開始用BitmapFactory來解析WebP格式的圖片。?
2、解析大圖時的OOM問題?
Android為每個應用分配的堆內存空間是有限的,如果應用請求的內存超過了限制,就會導致OOM。根據手機內存大小的不同,一般應用能夠使用的堆內存在幾十兆到兩三百兆之間。然后應用在讀取圖片文件時非常消耗內存的,一張手機相機拍出的照片都有3M左右,如果每張圖都直接讀取,即使不造成OOM,也會導致頻繁GC。還有些超大圖一張就有幾個G,如果直接讀取肯定會導致OOM。為了避免讀取大圖時造成的OOM問題,并減少內存消耗,一般在讀取圖片時都需要根據圖片尺寸來取樣。也就是設置BitmapFactory.Options的inSampleSize屬性。示例代碼如下。

Options options = new BitmapFactory.Options();//設置inJustDecodeBounds為true表示只獲取大小,不生成Btimapoptions.inJustDecodeBounds = true;//解析圖片大小InputStream stream = getContentResolver().openInputStream(uri);BitmapFactory.decodeStream(stream, null, options);stream.close();int width = options.outWidth;int height = options.outHeight;int ratio = 0;//如果寬度大于高度,交換寬度和高度if (width > height) {int temp = width;width = height;height = temp;}//計算取樣比例it sampleRatio = Math.max(width/900, height/1600);//定義圖片解碼選項Options options = new Options();options.inSampleSize = sampleRatio;//讀取圖片,并將圖片縮放到指定的目標大小InputStream stream = getContentResolver().openInputStream(uri);Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options);stream.close();

總結

以上是生活随笔為你收集整理的android 图片操作的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。