日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android 图片操作

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

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

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

Android支持的圖片格式

目前在Android中支持的圖片文件格式如下。其中WebP格式是從Android4.0開始支持,但在Android4.0到Android4.2.1之間的Android系統(tǒng)不支持無損壓縮和有透明度的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文件中生成一個對應(yīng)的整數(shù)id,通過“R.drawable.文件名”來得到id值,然后通過Resource類的openRawResource()來得到該文件對應(yīng)的InputStream對象。代碼示例如下。

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

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

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

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

4、 通過Uri讀取圖片到InputStream?
Uri全寫是Universal Resource Identifier(通用資源標志符),Android系統(tǒng)中所有資源都可以用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()內(nèi)先判斷Uri的scheme類型,如果是resource類型,則先調(diào)用getResourceId()得到該Uri對應(yīng)的資源id,然后調(diào)用openRawResource()讀取文件到InputStream對象。如果是文件類型,則調(diào)用uri.getPath()得到文件路徑,然后調(diào)用FileInputStream()讀取文件到InputStream對象。對其他類型(即assets類型)則調(diào)用openAssetFileDescriptor()先得到一個AssetFileDescriptor對象,然后再得到一個InputStream對象。?
可以看到,通過Uri讀取圖片的流程和上述根據(jù)類型直接讀取大體是一樣的(assets類型稍有不同)。

將InputStream轉(zhuǎn)換為Bitmap

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

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

直接讀取圖片文件到Bitmap

上述流程是先將圖片文件讀取到InputStream中,然后將InputStream轉(zhuǎn)換為Bitmap對象,需要兩步。BitmapFactory提供了一些靜態(tài)類可以直接將圖片文件轉(zhuǎn)換為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,然后再調(diào)用BitmapFactory.decodeStream()來解析。由此可以看出,直接讀取圖片到Bitmap和先讀取圖片到InputStream,然后將InputStream轉(zhuǎn)換為Bitmap本質(zhì)上是一樣的,只是BitmapFactory將這兩步封裝在一起。因此,如果要將非assets中的圖片文件轉(zhuǎn)換為Bitmap,一般就直接使用BitmapFactory即可。

BitmapFactory.Options

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

圖片文件讀取注意事項

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

Options options = new BitmapFactory.Options();//設(shè)置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();

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。