Android開發(fā)仿掃一掃實(shí)現(xiàn)拍攝框內(nèi)的照片功能
就是仿照現(xiàn)在掃一掃的形式,周圍是半透明的遮擋,然后中間是全透明的,拍攝后只截取框內(nèi)的內(nèi)容
查了很多博客,實(shí)現(xiàn)起來真的太復(fù)雜了,本人比較怕麻煩所以在很多地方偷懶了
先上效果圖:



第一步:設(shè)置照相機(jī)預(yù)覽以及拍照
這是所有步驟的前提,沒有預(yù)覽,用戶怎么知道自己拍的什么呢。預(yù)覽用的是SurfaceView
這篇博文寫得已經(jīng)十分詳細(xì)了,打開照相機(jī),然后拍照,而且十分簡潔!不想別的博客一下就幾百行代碼不知所云。這篇代碼可以復(fù)制下去當(dāng)相機(jī)模版使用。
這里遇到一個問題,就是預(yù)覽的效果是左轉(zhuǎn)90度的,拍出來也是左轉(zhuǎn)90度的,查了很多資料,大家統(tǒng)一的做法就是。在相機(jī)預(yù)覽那里設(shè)置右旋90度,拍下的照片再右旋90度,具體的做法我會貼代碼
第二步:設(shè)置半透明邊框
很多博客的做法是繪圖呀什么的,太過負(fù)責(zé)。
其實(shí)如果考慮簡單點(diǎn)的話,只要在surfaceView上面疊加一層圖片就好了,用Framelayout布局
就是背景半透明,中間扣掉

第三步:怎么只拍攝框內(nèi)的圖片
這個問題,很多博客都是長篇大論,什么矩陣運(yùn)算都用上了,雖然很強(qiáng),但是不想看下去。
拍攝框內(nèi)的圖片,就直接拍完整張照片之后,在照片里面摳圖就好了啊。
Bitmap.createBitmap(bitmap,50,250,650,500);
自己算一下透明框大概在什么位置,左上角的坐標(biāo)是什么,寬和高是什么。用上述函數(shù)就可以在原照片摳圖了。
第四步:完善一點(diǎn),加入點(diǎn)擊對焦
其實(shí)就是在點(diǎn)擊事件里面調(diào)用對焦函數(shù)就行
總的代碼:
public class MainActivity extends AppCompatActivity {
private SurfaceView surfaceview;
private Camera camera;
private Button take;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); // 沒有標(biāo)題 必須在設(shè)置布局之前找到調(diào)用
setContentView(R.layout.activity_main);
/*
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, // 設(shè)置全屏顯示
WindowManager.LayoutParams.FLAG_FULLSCREEN);
*/
take = (Button)findViewById(R.id.take);
surfaceview = (SurfaceView) findViewById(R.id.surfaceview);
SurfaceHolder holder = surfaceview.getHolder();
holder.setFixedSize(176, 155);// 設(shè)置分辨率
holder.setKeepScreenOn(true);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// SurfaceView只有當(dāng)activity顯示到了前臺,該控件才會被創(chuàng)建 因此需要監(jiān)聽surfaceview的創(chuàng)建
holder.addCallback(new MySurfaceCallback());
//拍照按鈕
take.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
takepicture();
}
});
}
//點(diǎn)擊事件
@Override
public boolean onTouchEvent(MotionEvent event) {
//對焦
camera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean b, Camera camera) {
camera.cancelAutoFocus();
}
});
return super.onTouchEvent(event);
}
/**
* 監(jiān)聽surfaceview的創(chuàng)建
* @author Administrator
* Surfaceview只有當(dāng)activity顯示到前臺,該空間才會被創(chuàng)建
*/
private final class MySurfaceCallback implements SurfaceHolder.Callback {
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
try {
// 當(dāng)surfaceview創(chuàng)建就去打開相機(jī)
camera = Camera.open();
Camera.Parameters params = camera.getParameters();
// Log.i("i", params.flatten());
params.setJpegQuality(80); // 設(shè)置照片的質(zhì)量
params.setPictureSize(1024, 768);
params.setPreviewFrameRate(5); // 預(yù)覽幀率
camera.setParameters(params); // 將參數(shù)設(shè)置給相機(jī)
//右旋90度,將預(yù)覽調(diào)正
camera.setDisplayOrientation(90);
// 設(shè)置預(yù)覽顯示
camera.setPreviewDisplay(surfaceview.getHolder());
// 開啟預(yù)覽
camera.startPreview();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
if(camera != null){
camera.release();
camera = null;
}
}
}
//拍照的函數(shù)
public void takepicture(){
/*
* shutter:快門被按下
* raw:相機(jī)所捕獲的原始數(shù)據(jù)
* jpeg:相機(jī)處理的數(shù)據(jù)
*/
camera.takePicture(null, null, new MyPictureCallback());
}
//byte轉(zhuǎn)Bitmap
public Bitmap Bytes2Bimap(byte[] b) {
if (b.length != 0) {
return BitmapFactory.decodeByteArray(b, 0, b.length);
} else {
return null;
}
}
//bitmap轉(zhuǎn)byte
public byte[] Bitmap2Bytes(Bitmap bm) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
return baos.toByteArray();
}
//照片回調(diào)函數(shù),其實(shí)是處理照片的
private final class MyPictureCallback implements Camera.PictureCallback {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
try {
Bitmap bitmap = Bytes2Bimap(data);
Matrix m = new Matrix(); int width = bitmap.getWidth(); int height = bitmap.getHeight(); m.setRotate(90);
//將照片右旋90度
bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, m,
true);
Log.d("TAG","width "+width);
Log.d("TAG","height "+height);
//截取透明框內(nèi)照片
bitmap = Bitmap.createBitmap(bitmap,50,250,650,500);
data = Bitmap2Bytes(bitmap);
File file = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".jpg");
FileOutputStream fos = new FileOutputStream(file);
fos.write(data);
// 在拍照的時候相機(jī)是被占用的,拍照之后需要重新預(yù)覽
camera.startPreview();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
以上所述是小編給大家介紹的Android開發(fā)仿掃一掃實(shí)現(xiàn)拍攝框內(nèi)的照片功能 ,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
Android?Studio實(shí)現(xiàn)音樂播放器的全過程(簡單易上手)
這篇文章主要給大家介紹了關(guān)于Android?Studio實(shí)現(xiàn)音樂播放器的相關(guān)資料,文中通過實(shí)例代碼以及圖文介紹的非常詳細(xì),對各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2022-02-02
Android視頻/音頻緩存框架AndroidVideoCache(Okhttp)詳解
這篇文章主要為大家詳細(xì)介紹了Android視頻、音頻緩存框架AndroidVideoCache,實(shí)現(xiàn)邊下邊播功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-07-07
Android上實(shí)現(xiàn)RTSP服務(wù)器的方法
在Android平臺實(shí)現(xiàn)RTSP服務(wù)器是一項(xiàng)挑戰(zhàn)性任務(wù),旨在無需部署獨(dú)立的RTSP/RTMP服務(wù),通過內(nèi)置輕量級RTSP服務(wù),實(shí)現(xiàn)本地音視頻數(shù)據(jù)的對外共享,本文介紹Android上實(shí)現(xiàn)RTSP服務(wù)器的方法,感興趣的朋友一起看看吧2024-11-11
Android Studio中通過CMake使用NDK并編譯自定義庫和添加預(yù)編譯庫
這篇文章是基于Android Studio 3.01版本的,NDK是R16。本文重點(diǎn)給大家介紹Android Studio中通過CMake使用NDK并編譯自定義庫和添加預(yù)編譯庫的相關(guān)知識,感興趣的朋友一起看看吧2018-01-01
Android如何實(shí)現(xiàn)設(shè)備的異顯功能詳解
這篇文章主要給大家介紹了關(guān)于Android如何實(shí)現(xiàn)設(shè)備的異顯功能的相關(guān)資料,這篇文章通過示例代碼介紹的非常詳細(xì),對各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2022-02-02
android-使用環(huán)信SDK開發(fā)即時通信功能(附源碼下載)
本篇文章主要介紹了android-使用環(huán)信SDK開發(fā)即時通信功能,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。2016-12-12

