解釋:
專業(yè)領(lǐng)域包括網(wǎng)站建設(shè)、做網(wǎng)站、商城開發(fā)、微信營銷、系統(tǒng)平臺開發(fā), 與其他網(wǎng)站設(shè)計及系統(tǒng)開發(fā)公司不同,成都創(chuàng)新互聯(lián)的整合解決方案結(jié)合了幫做網(wǎng)絡(luò)品牌建設(shè)經(jīng)驗和互聯(lián)網(wǎng)整合營銷的理念,并將策略和執(zhí)行緊密結(jié)合,為客戶提供全網(wǎng)互聯(lián)網(wǎng)整合方案。
1、首先創(chuàng)建一個Bitmap圖片,并指定大??;
2、在該圖片上創(chuàng)建一個新的畫布Canvas,然后在畫布上繪制,并保存即可;
3、需要保存的目錄File,注意如果寫的目錄如“/sdcard/akai/”如果不存在的話,要先創(chuàng)建(file.mkdirs()),否則FileOutputStream會報錯No found;
4、需要添加權(quán)限:uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/
什么是畫布呢 其實通過字面意思的理解就是用來繪畫的地方,那么android里的畫布是神馬樣子的呢?
在自定義畫布中常用到下面3個類
Canvas
這些繪圖方法中的每一個都需要指定一個Paint對象來渲染它
Paint
Paint也稱為"刷子",Paint可以指定如何將基本圖形繪制到位圖上。
Paint類相當(dāng)于一個筆刷和調(diào)色板。它可以選擇如何使用上面描述的draw方法來渲染繪 制在畫布上的基本圖形。通過修改Paint對象,可以在繪圖的時候控制顏色、樣式、字體和特殊效果。最簡單地,setColor可以讓你選擇一個Paint的顏色,而Paint對象的樣式(使用setStyle控制)則可以決定是繪制繪圖對象的輪廓(STROKE),還是只填充每一部 分(FILL),或者是兩者都做(STROKE_AND_FILL)除了這些簡單的控制之外,Paint類還支持透明度,另外,它也可以通過使用各種各樣的陰影、過濾器和效果進行修改,從而提供由更豐富的、復(fù)雜的畫筆和顏料組成的調(diào)色板。
從繼承View類(或其子類)開始,并定義onDraw()回調(diào)方法。系統(tǒng)會調(diào)用該方法來完 成View對象自己的繪制請求。這也是通過Canvas對象來執(zhí)行所有的圖形繪制調(diào)用的地方,這個Canvas對象是由onDraw()回調(diào)方法傳入的。
Android框架只在必要的時候才會調(diào)用onDraw()方法,每次請求應(yīng)用程序準(zhǔn)備完成圖形 繪制任務(wù)時,必須通過調(diào)用invalidate()方法讓該View對象失效。這表明可以在該View 對象上進行圖形繪制處理了,然后Android系統(tǒng)會調(diào)用該View對象的onDraw()方(盡 管不保證該回調(diào)方法會立即被調(diào)用)。
在定制的View組件的onDraw()方法內(nèi)部,使用給定的Canvas對象來完成所有的圖形繪制處理(如Canvas.draw…()方法或把該Canvas對象作為參數(shù)傳遞給其他類的draw() 方法)。一旦onDraw()方法被執(zhí)行完成,Android框架就會使用這個Canvas對象來繪制一個有系統(tǒng)處理的Bitmap對象。
下面是Paint一些常用方法:
Bitmap
Bitmap繪圖的表面也稱位圖(這里詳細說哈位圖的功能)。
從資源中獲取位圖:
通過Resource的函數(shù):InputStream openRawResource(int id)獲取得到資源文件的數(shù)據(jù)流后,可以通過2種方式獲得bitmap
使用BitmapDrawable :
使用BitmapDrawable(InputStream is)構(gòu)造一個BitmapDrawable;
使用BitmapDrawable類的getBitmap()獲取得到位圖;
使用BitmapFactory使用BitmapFactory類decodeStream(InputStream is)解碼位 圖資源,獲取位圖BitmapFactory的所有函數(shù)都是static,這個輔助類可以通過資 源ID、路徑、文件、數(shù)據(jù)流等方式來獲取位圖。
獲取位圖的信息
一般獲取位圖信息包括:位圖大小、透明度、顏色格式等等,這些信息呢可以通過 三-一方法獲取得到Bitmap就迎刃而解了,Android SDK中對Bitmap有詳細說明,大家可以去詳細了解哈。
顯示位圖
顯示位圖需要使用核心類Canvas,可以直接通過Canvas類的drawBirmap()顯示位圖,或者借助于BitmapDrawable來將Bitmap繪制到Canvas,下面的實例中會詳細列舉到
位圖的縮放
位圖的縮放,在Android SDK中提供了2種方法:
1:將一個位圖按照需求重畫一遍,畫后的位圖就是我們需要的了,與位圖的顯示幾乎 一樣:
drawBitmap(Bitmap bitmap, Rect src, Rectdst, Paint paint)
2:在原有位圖的基礎(chǔ)上,縮放原位圖,創(chuàng)建一個新的位圖:
createBitmap(Bitmap source, int x, int y,int width, int height, Matrix m, boolean filter)
位圖旋轉(zhuǎn)
位圖的旋轉(zhuǎn),離不開Matrix。Android SDK提供了Matrix類,可以通過各種接口來設(shè)置 矩陣
android 處理圖片工具
截取視頻幀并轉(zhuǎn)化為Bitmap
這里只介紹按下“保存”后如何將一個Bitmap對象保存為圖片文件的執(zhí)行步驟,對圖片的下載,圖片到Bitmap對象的轉(zhuǎn)換,Bitmap對象的格式轉(zhuǎn)換和壓縮,以及界面設(shè)計部分全部都忽略了。
確定存儲路徑
獲取外部存儲權(quán)限
確定外部存儲狀態(tài)
確定文件名
保存到文件中
發(fā)送廣播,通知系統(tǒng)掃描保存后的文件
確定存儲路徑
在Android中文件存儲路徑包括內(nèi)部存儲和外部存儲兩種類型。
對內(nèi)部存儲,當(dāng)一個app被安裝到手機后,Android系統(tǒng)會在內(nèi)部存儲的/data/data/目錄下創(chuàng)建一個以包名稱命名的文件夾。例如/data/data/com.sohu.inputmethod.sogou/。一個應(yīng)用對內(nèi)部存儲的所有訪問都被限制在這個文件夾中,也就是說Android應(yīng)用只能在該目錄中讀取,創(chuàng)建,修改文件。對該目錄之外的其他內(nèi)部存儲中的目錄都沒有任何操作的權(quán)限。因此,如果將圖片保存在內(nèi)部存儲中,只能被應(yīng)用自身讀取,其他應(yīng)用均無法讀取。如果需要讓系統(tǒng)圖庫,相冊或其他應(yīng)用能夠找到保存的圖片,必須將圖片保存到外部存儲中。
對外部存儲,當(dāng)一個app被安裝到手機后,Android系統(tǒng)會在外部存儲的/Android/data/目錄下創(chuàng)建一個以包名命名的文件夾(這里第一個/不是根路徑,而是相對外部存儲所掛載路徑的相對路徑)。例如/storage/emulated/0/Android/data/com.sohu.inputmethod/。這個路徑同樣只能被應(yīng)用自身讀取,其他應(yīng)用不能訪問。因此,也不能將圖片保存在這個目錄中。
除外部存儲的/Android目錄之外的其他目錄一般都是可以被其他應(yīng)用訪問的。目前,大多數(shù)應(yīng)用都會在外部存儲的根路徑下建立一個類似包名的多層目錄,以存儲需要共享的文件。例如/storage/emulated/0/sogou/image/。還需要注意的是,很多查看圖片的應(yīng)用都支持按照文件夾來查看圖片。如果將圖片所在的文件夾取名為image,photo之類的,就無法和其他文件夾區(qū)分開,用戶也不能識別該文件夾的用途。因此最好取一個有區(qū)分度的文件夾名字,例如百度貼吧就保存在/tieba目錄,微信是保存在/tencent/MicroMsg/WeiXin目錄。
由于Android系統(tǒng)的碎片化問題,不同設(shè)備上外部存儲的路徑很可能會不同,因此,不能直接使用/storage/emulated/0/作為外部存儲的根路徑。
Android SDK中 Environment類 提供了getExternalStorageDirectory()方法來獲取外部存儲的根路徑。示例如下:
[java]?view plain?copy
String?dir?=?Environment.getExternalStorageDirectory().getAbsolutePath()?+?"/tencent/MicroMsg/WeiXin/"
需要注意的是Environment.getExternalStorageDirectory()返回的路徑中最后一個字符不是/,如果需要創(chuàng)建子目錄,需要在子目錄的前后都加上/。
獲取外部存儲權(quán)限
由于需要在外部存儲中寫文件,需要在AndroidManifest.xml中增加如下的權(quán)限聲明。
[java]?view plain?copy
uses-permission?android:name="android.permission.WRITE_EXTERNAL_STORAGE"/
確定外部存儲狀態(tài)
由于外部存儲需要被掛載,也可以被卸載,在寫入文件之前,需要先判斷外部存儲的狀態(tài)是否正常。只有狀態(tài)正常情況下才可以執(zhí)行保存文件的操作。獲取外部存儲狀態(tài)同樣是通過Environment類,通過Environment.getExternalStorageState()可以得到一個字符串,來表示外部存儲的狀態(tài)。同時在Environment類中定義了一系列的String常量表示不同的狀態(tài)。在所有的狀態(tài)中只有內(nèi)部存儲處于Environment.MEDIA_MOUNTED狀態(tài)時才可以讀寫文件,因此,需要將獲取到的狀態(tài)和Environment.MEDIA_MOUNTED做比較,如果不是Environment.MEDIA_MOUNTED狀態(tài),就返回保存失敗。示例如下。
[java]?view plain?copy
//獲取內(nèi)部存儲狀態(tài)
String?state?=?Environment.getExternalStorageState();
//如果狀態(tài)不是mounted,無法讀寫
if?(!state.equals(Environment.MEDIA_MOUNTED))?{
return;
}
確定文件名
保存的圖片文件名可以由應(yīng)用根據(jù)自身需要自行確定,一般來說需要有一個命名規(guī)則,然后根據(jù)命名規(guī)則計算得到文件名。
這里列舉幾種常見的命名規(guī)則。
隨機命名
這種命名規(guī)則是隨機生成一個字符串或一組數(shù)字來對圖片命名。
字符串可以通過UUID來生成,數(shù)字可以通過Random()類來生成,例如:
[java]?view plain?copy
//通過UUID生成字符串文件名
String?fileName1?=?UUID.randomUUID().toString();
//通過Random()類生成數(shù)組命名
Random?random?=?new?Random();
String?fileName2?=?String.valueOf(random.nextInt(Integer.MAX_VALUE));
這種命名規(guī)則是按照數(shù)字從小到大的順序來對圖片命名。
在程序啟動時先獲取圖片文件名中當(dāng)前最大數(shù)字的文件名,之后每保存一張圖片就將數(shù)字加1即可。
時間命名
這種命名規(guī)則是根據(jù)保存圖片的當(dāng)前系統(tǒng)時間來對圖片命名。
系統(tǒng)時間可以通過System.currentTimeMillis()來獲取,不過System.currentTimeMillis()獲取到的時間是一個long型的整數(shù),如果用它做文件名,無法通過文件名直接看出文件的具體保存時間??梢酝ㄟ^SimpleDateFormat先對當(dāng)前時間做格式化,然后再將其作為文件名來使用。例如:
[java]?view plain?copy
使用這種命名規(guī)則來命名需要注意的是同一秒鐘可能會有多張圖片需要保存,在得到當(dāng)前系統(tǒng)時間對應(yīng)的文件名后,需要判斷該文件是否存在。如果文件已經(jīng)存在,需要重新生成文件名。重新生成的文件名可以在之前的文件名后加上一個隨機數(shù)后綴,或者是用毫秒數(shù)做后綴。
Calendar?now?=?new?GregorianCalendar();
SimpleDateFormat?simpleDate?=?new?SimpleDateFormat("yyyyMMddHHmmss",?Locale.getDefault());
String?fileName?=?simpleDate.format(now.getTime());
文件URL命名
每張網(wǎng)絡(luò)圖片都有一個對應(yīng)的圖片URL,可以根據(jù)圖片的URL來對圖片命名。
不過URL中會包含一些不能用作文件名的特殊字符,此外直接用URL來命名可能會帶來安全問題。為了避免這兩個問題,可以將圖片URL的MD5值作為文件名來使用。由于MD5是不可逆的,也就無法通過MD5值反向得到圖片URL,同時MD5值對應(yīng)的字符串只包含[0-9A-Z],不包含特殊字符,可是作為文件名使用。
由于每張圖片的URL是唯一的,其對應(yīng)的文件名也就是唯一的。如果需要每張網(wǎng)絡(luò)圖片只能生成一個文件,不允許保存為多份拷貝,可以用這種命名規(guī)則。在得到URL對應(yīng)的文件名后,先判斷文件是否已經(jīng)存在,如果已經(jīng)存在,直接覆蓋或不處理。
保存到文件中
保存圖片文件時,通過Bitmap的compress()方法將Bitmap對象壓縮到一個文件輸出流中,然后flush()即可。示例如下。
[java]?view plain?copy
try?{
File?file?=?new?File(dir?+?fileName?+?".jpg");
FileOutputStream?out?=?new?FileOutputStream(file);
mBitmap.compress(Bitmap.CompressFormat.JPEG,?100,?out);
out.flush();
out.close();
}?catch?(Exception?e)?{
e.printStackTrace();
}
發(fā)送廣播,通知系統(tǒng)掃描保存后的文件
至此,已經(jīng)實現(xiàn)將Bitmap對象保存成外部存儲中的一個jpg格式的文件。但此時該文件只是保存在外部存儲的一個目錄中,必須進入其所在的目錄中才可以看到。在系統(tǒng)圖庫,相冊和其他應(yīng)用中無法看到新建的圖片文件。為了讓其他應(yīng)用能夠知道圖片文件被創(chuàng)建,必須通知MediaProvider服務(wù)將新建的文件添加到圖片數(shù)據(jù)庫中。
Android系統(tǒng)中常駐一個MediaProvider服務(wù),對應(yīng)的進程名為android.process.media,此服務(wù)用來管理本機上的媒體文件,提供媒體管理服務(wù)。在系統(tǒng)開機或者收到外部存儲的掛載消息后,MediaProvider會調(diào)用MediaScanner,MediaScanner會掃描外部存儲中的所有文件,根據(jù)文件類型的后綴將文件信息保存到對應(yīng)的數(shù)據(jù)庫中,供其他APP使用。
MediaScannerReceiver是一個廣播接收者,當(dāng)它接收到特定的廣播請求后,就會去掃描指定的文件,并根據(jù)文件信息將其添加到數(shù)據(jù)庫中。當(dāng)圖片文件被創(chuàng)建后,就可以發(fā)送廣播給MediaScannerReceiver,通知其掃描新建的圖片文件。示例如下。
[java]?view plain?copy
try?{
File?file?=?new?File(dir?+?fileName?+?".jpg");
FileOutputStream?out?=?new?FileOutputStream(file);
mBitmap.compress(Bitmap.CompressFormat.JPEG,?100,?out);
out.flush();
out.close();
//保存圖片后發(fā)送廣播通知更新數(shù)據(jù)庫
Uri?uri?=?Uri.fromFile(file);
sendBroadcast(new?Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,?uri));
}?catch?(Exception?e)?{
e.printStackTrace();
}
圖片的異步保存
保存圖片文件時,如果圖片很大,或需要同時保存多張圖片時,就需要較多的時間。為了避免阻塞UI線程,出現(xiàn)幀率下降或ANR,通常需要將圖片保存操作放到線程中去執(zhí)行。當(dāng)圖片保存完畢后通過sendMessage()方法通知UI線程保存結(jié)果。
將圖片保存放到后臺線程去執(zhí)行需要增加一些同步機制避免一些多線程問題。例如有兩張圖片需要保存,分別放到兩個線程中去執(zhí)行,保存圖片時文件名以數(shù)字順序增加。第一個線程選中文件名為125.jpg,但此時文件還未創(chuàng)建,第二個線程判斷125.jpg不存在,于是也選取125.jpg作為文件名,兩張圖片就保存到同一個文件中了。
很簡單,使用下面的程序就可以了: package com.savemybitmap; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import android.graphics.Bitmap; import android.os.Environment; import android.util.Log; /** * 保存圖片的類 * * @author Administrator * */ public class SaveBitmap { private final static String CACHE = "/Caochen"; /** * 保存圖片的方法 * 保存到sdcard * @throws IOException */ public void savePic(Bitmap b, String strFileName) { String filePath = isExistsFilePath(); FileOutputStream fos = null; GetImageName getName = new GetImageName(); String imageName = getName.getImageName(strFileName); File file = new File(filePath, imageName); if (file.exists()) { Log.i(imageName, "is Exist!!!"); } else { try { fos = new FileOutputStream(file); if (null != fos) { b.compress(Bitmap.CompressFormat.PNG, 90, fos); fos.flush(); fos.close(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } /** * 獲取sd卡的緩存路徑, * 一般在卡中sdCard就是這個目錄 * * @return SDPath */ public static String getSDPath() { File sdDir = null; boolean sdCardExist = Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED); // 判斷sd卡是否存在 if (sdCardExist) { sdDir = Environment.getExternalStorageDirectory();// 獲取根目錄 } else { Log.e("ERROR", "沒有內(nèi)存卡"); } return sdDir.toString(); } /** * 獲取緩存文件夾目錄 如果不存在創(chuàng)建 否則則創(chuàng)建文件夾 * * @return filePath */ private String isExistsFilePath() { String filePath = getSDPath() + CACHE; File file = new File(filePath); if (!file.exists()) { file.mkdirs(); } return filePath; } }
滿意請采納
就我個人所知道的安卓系統(tǒng)的話,它的所有照片都存儲在一個叫做。DC im的一個文件夾里面。這個文件講的話,你可以通過幾種方式找到一般安卓手機的話,他都會有一個文件管理的圖標(biāo)。
你點擊進去,以后。然后選擇一個手機的選項,然后在內(nèi)部存儲里你就可以找到這個文件夾。
現(xiàn)在的安卓系統(tǒng)比較高級,他都會在后面?zhèn)渥⒁粋€相冊的選項。然后最后在這個選項里面基本上所有的圖片都在你的。這個文件夾里面包括你使用照相機照的圖片,甚至是你的截圖都是保存在這個文件夾里面的。
而且現(xiàn)在這個文件夾真的是比較人性化了。安卓系統(tǒng)人性化的方面就是你可以獲得這方面的權(quán)限,可以直接的方便的查看而蘋果手機不行就只有安卓手機可以。