**【后注:】下載代碼的注意,我的手機是4.3寸的屏,華為U9200.如果不能運行的請修改參數。看[前文](http://blog.csdn.net/yanzi1225627/article/details/8577756)的第四條。Y的,省的說我傳的代碼不能用
**
最近一直在審視以前做過的東西,關于android攝像頭預覽,預覽界面上呈現矩形框,在前文(
### [Android開發 攝像頭SurfaceView預覽 背景帶矩形框 實現(原理:雙surfaceview,頂層畫矩形框,底層預覽視頻)](http://blog.csdn.net/yanzi1225627/article/details/7934710)
)----http://blog.csdn.net/yanzi1225627/article/details/7934710已經實現。最近發現上層繪制矩形框,用surfaceview有點大材小用了。SurfaceView繪制動畫更合適,只繪制個矩形框用ImageView足夠了。但有些時候必須要用SurfaceView來實現。比如360手機安全衛士掃描二維碼的實現應該就是通過上下兩層SurfaceView實現的(見下圖)。上層SurfaceView用于顯示那個可以旋轉的掃描示意框,底層SurfaceView預覽攝像頭視頻。

??? 廢話不說了,稍候幾天我會仿照上面360這個掃描二維碼的界面做一個工程(結合PreviewCallback),公開出來。這次先談用底層surfaceView+上層ImageView實現只拍攝矩形框中的圖像。新建一個類繼承ImageView,源碼如下:
~~~
package yan.guoqi.rectphoto;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.ImageView;
public class DrawImageView extends ImageView{
public DrawImageView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
Paint paint = new Paint();
{
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(2.5f);//設置線寬
paint.setAlpha(100);
};
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.drawRect(new Rect(100, 200, 400, 500), paint);//繪制矩形
}
}
~~~
布局文件里與前文http://blog.csdn.net/yanzi1225627/article/details/8577756這里一樣,只是在幀布局里加一個上面自定義的DrawImageView,整個布局文件示下:
~~~
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/BestWish"
tools:context=".RectPhoto" />
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<SurfaceView
android:id="@+id/previewSV"
android:layout_width="fill_parent"
android:layout_height="800px" />
<yan.guoqi.rectphoto.DrawImageView
android:id="@+id/drawIV"
android:layout_width="fill_parent"
android:layout_height="800px"
/>
</FrameLayout>
<ImageButton
android:id="@+id/photoImgBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/photo_img_btn"
android:layout_gravity="center" />
</LinearLayout>
~~~
???? 在主程序文件里,onCreate()函數里設置底層SurfaceView為底層且透明(如果不設也可以,默認就是如此):
mPreviewSV.setZOrderOnTop(false);
mySurfaceHolder.setFormat(PixelFormat.TRANSPARENT);//translucent半透明 transparent透明
??? 在主UI線程里的onCreate()函數里添加代碼:
?????? //繪制矩形的ImageView
??? ?mDrawIV = (yan.guoqi.rectphoto.DrawImageView)findViewById(R.id.drawIV);
??? ?mDrawIV.onDraw(new Canvas());
????? 看上面的DrawImageView的函數里的onDraw,畫的矩形是Rect(100, 200, 400, 500)。在onPictureTaken(byte[] data, Camera camera)函數里,先將圖片旋轉90度,大小成為寬×高(960×1280)。由于預覽surfaceview的大小是寬×高(540×800),所以在onPictureTaken函數里將960×1280的圖片縮放到540×800, 縮放相同大小后就可以用矩陣的坐標直接截取子圖了。核心函數就是這兩句:
???? //將960×1280縮放到540×800
**? ??? ??? ?Bitmap sizeBitmap = Bitmap.createScaledBitmap(rotaBitmap, 540, 800, true);
??? ??? ?Bitmap rectBitmap = Bitmap.createBitmap(sizeBitmap, 100, 200, 300, 300);//截取**
??? 注意這個截取的函數參數和矩陣的坐標關系,分別是x軸 y軸起始坐標及 x軸寬度 y軸寬度。截取出來的圖片大小應該是300×300. onPictureTaken()函數的源碼如下:
~~~
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
Log.i(tag, "myJpegCallback:onPictureTaken...");
if(null != data){
mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);//data是字節數據,將其解析成位圖
myCamera.stopPreview();
isPreview = false;
}
//設置FOCUS_MODE_CONTINUOUS_VIDEO)之后,myParam.set("rotation", 90)失效。圖片竟然不能旋轉了,故這里要旋轉下
Matrix matrix = new Matrix();
matrix.postRotate((float)90.0);
Bitmap rotaBitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), matrix, false);
//旋轉后rotaBitmap是960×1280.預覽surfaview的大小是540×800
//將960×1280縮放到540×800
Bitmap sizeBitmap = Bitmap.createScaledBitmap(rotaBitmap, 540, 800, true);
Bitmap rectBitmap = Bitmap.createBitmap(sizeBitmap, 100, 200, 300, 300);//截取
//保存圖片到sdcard
if(null != rectBitmap)
{
saveJpeg(rectBitmap);
}
//再次進入預覽
myCamera.startPreview();
isPreview = true;
}
~~~
涉及到的其他函數如saveJpeg()參見前文:
### [2013新春奉送:Android攝像頭開發完美demo---(循環聚焦,縮放大小,旋轉picture,查詢支持的picturesize, ImageButton按鍵效果)------------](http://blog.csdn.net/yanzi1225627/article/details/8577756)
http://blog.csdn.net/yanzi1225627/article/details/8577756?? 重復的東西我就不發了。
??? 效果圖如下所示:

點擊拍照,查看保存后的圖片如下:

? ? 反思:
1,SurfaceView為啥 無論translucent半透明還是 transparent透明基本沒啥區別?而且surfaceview的setAlpha函數不能用。?
2,在這里surfaceview一定要在底層(默認如此),如果設成頂層會看不到紅色矩形框。可以自己測試下。
3,最糾結的一點,第一副圖片里的360掃描二維碼的界面,底層的預覽surfaceview是半透明的,底色是灰色的,只有中間的掃描矩形框是透明的,亮色。這一塊究竟是怎么實現的??下午實驗了n種方法愣是無濟于事。我擦。。。如果有高人,希望能不吝指點下。 不過說實話,人家已經設計出來的產品界面看著就是好,不得不服阿。以后要多多模仿鉆研這些成型產品的設計。
源碼下載:[http://download.csdn.net/detail/yanzi1225627/5063105](http://download.csdn.net/detail/yanzi1225627/5063105)???????????????????????????????????????????
歡迎android愛好者加群248217350,備注:yanzi
????????????????????????????????????????????????????????????????????----------------------------------------本文系原創,轉載請注明作者:yanzi1225627
???
- 前言
- Linux下使用QT調用opencv讀取攝像頭視頻 調試心得
- Android開發 攝像頭SurfaceView預覽 背景帶矩形框 實現(原理:雙surfaceview,頂層畫矩形框,底層預覽視頻)
- Android開發:安裝NDK,移植OpenCV2.3.1,JNI調用OpenCV全過程
- 2013新春奉送:Android攝像頭開發完美demo---(循環聚焦,縮放大小,旋轉picture,查詢支持的picturesize, ImageButton按鍵效果)
- 如何設置ImageButton按鍵按下去后的 特效----(如類似風車旋轉的動畫特效)
- Android攝像頭:只拍攝SurfaceView預覽界面特定區域內容(矩形框)---完整實現(原理:底層SurfaceView+上層繪制ImageView)
- Android開發:SurfaceView上新建線程繪制旋轉圖片 及 刷新特定區域(臟矩形)
- Android開發:ImageView上繪制旋轉圓環(透明度不同的旋轉圓環,利用canvas.drawArc實現)
- Android上掌紋識別第一步:基于OpenCV的6種膚色分割 源碼和效果圖
- Android開發:實時處理攝像頭預覽幀視頻------淺析PreviewCallback,onPreviewFrame,AsyncTask的綜合應用
- Android攝像頭開發:拍照后添加相框,融合相框和圖片為一副 圖片
- Android(OpenCV) NDK開發: 0xdeadbaad(code=1)錯誤 及 關閉armeabi和libnative_camera_r2.2.2.so的生成
- Android攝像頭開發:實時攝像頭視頻預覽幀的編碼問題(二)
- setContentView切換頁面(無需每次都findViewById)-----二
- Android開發:setContentView切換界面,自定義帶CheckBox的ListView顯示SQlite條目-----實現