标签:
走的思路是,添加一个ImageView控件。将预览的数据,在onPreviewFrame()里变换后,显示在ImageView控件中,再保存ImageView里的图片。
需要的话,再将ImageView控件覆盖在预览界面之上。
(也可以直接处理预览界面,但之前做的时候总是出现问题。就先再试试这个方向。)
1 package com.example.mycamerafinal; 2 3 import java.io.FileNotFoundException; 4 import java.io.IOException; 5 import java.io.OutputStream; 6 import java.util.Iterator; 7 import java.util.List; 8 9 10 import android.app.Activity; 11 import android.content.ContentValues; 12 import android.content.res.Configuration; 13 import android.graphics.Bitmap; 14 import android.graphics.Canvas; 15 import android.graphics.ColorMatrix; 16 import android.graphics.ColorMatrixColorFilter; 17 import android.graphics.Matrix; 18 import android.graphics.Paint; 19 import android.graphics.Bitmap.Config; 20 import android.hardware.Camera; 21 import android.hardware.Camera.PreviewCallback; 22 import android.net.Uri; 23 import android.os.Bundle; 24 import android.os.Message; 25 import android.provider.MediaStore.Images.Media; 26 import android.util.Log; 27 import android.view.SurfaceHolder; 28 import android.view.SurfaceView; 29 import android.view.View; 30 import android.view.View.OnClickListener; 31 import android.widget.Button; 32 import android.widget.ImageView; 33 import android.widget.Toast; 34 35 public class MainActivity extends Activity implements OnClickListener, 36 SurfaceHolder.Callback, Camera.PictureCallback,Camera.PreviewCallback 37 { 38 SurfaceView cameraView; 39 SurfaceHolder surfaceHolder; 40 Camera camera; 41 ImageView imgView; 42 Button bt_takePicture; 43 String TAG = "Camera"; 44 45 @Override 46 public void onCreate(Bundle savedInstanceState) 47 { 48 super.onCreate(savedInstanceState); 49 setContentView(R.layout.activity_main); 50 51 imgView = (ImageView) findViewById(R.id.ImageView); 52 cameraView = (SurfaceView) findViewById(R.id.CameraView); 53 bt_takePicture = (Button) findViewById(R.id.takePicture); 54 bt_takePicture.setOnClickListener(this); 55 surfaceHolder = cameraView.getHolder(); 56 surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 57 surfaceHolder.addCallback(this); 58 cameraView.setFocusable(true); 59 cameraView.setFocusableInTouchMode(true); 60 //cameraView.setClickable(true); 61 //cameraView.setOnClickListener(this); 62 } 63 64 public void onClick(View v) 65 { 66 camera.takePicture(null, null, this); 67 } 68 69 public void onPictureTaken(byte[] data, Camera camera) 70 { 71 Uri imageFileUri = getContentResolver() 72 .insert(Media.EXTERNAL_CONTENT_URI, new ContentValues()); 73 74 try { 75 OutputStream imageFileOS = getContentResolver() 76 .openOutputStream(imageFileUri); 77 imageFileOS.write(data); 78 imageFileOS.flush(); 79 imageFileOS.close(); 80 } 81 catch (FileNotFoundException e) 82 { 83 Toast t = Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT); 84 t.show(); 85 } 86 catch (IOException e) 87 { 88 Toast t = Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT); 89 t.show(); 90 } 91 92 camera.startPreview(); 93 } 94 // ... 95 public static Bitmap toGrayscale(Bitmap bmpOriginal) { 96 int width, height; 97 height = bmpOriginal.getHeight(); 98 width = bmpOriginal.getWidth(); 99 100 Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); 101 Canvas c = new Canvas(bmpGrayscale); 102 Paint paint = new Paint(); 103 ColorMatrix cm = new ColorMatrix(); 104 cm.setSaturation(0); 105 ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm); 106 paint.setColorFilter(f); 107 c.drawBitmap(bmpOriginal, 0, 0, paint); 108 return bmpGrayscale; 109 } 110 111 /** 112 * 解码 113 * 114 * @param rgb 115 * @param yuv420sp 116 * @param width 117 * @param height 118 */ 119 static public void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width, int height) { 120 final int frameSize = width * height; 121 122 for (int j = 0, yp = 0; j < height; j++) { 123 int uvp = frameSize + (j >> 1) * width, u = 0, v = 0; 124 for (int i = 0; i < width; i++, yp++) { 125 int y = (0xff & ((int) yuv420sp[yp])) - 16; 126 if (y < 0) 127 y = 0; 128 if ((i & 1) == 0) { 129 v = (0xff & yuv420sp[uvp++]) - 128; 130 u = (0xff & yuv420sp[uvp++]) - 128; 131 } 132 133 int y1192 = 1192 * y; 134 int r = (y1192 + 1634 * v); 135 int g = (y1192 - 833 * v - 400 * u); 136 int b = (y1192 + 2066 * u); 137 138 if (r < 0) 139 r = 0; 140 else if (r > 262143) 141 r = 262143; 142 if (g < 0) 143 g = 0; 144 else if (g > 262143) 145 g = 262143; 146 if (b < 0) 147 b = 0; 148 else if (b > 262143) 149 b = 262143; 150 151 rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); 152 } 153 } 154 } 155 156 157 public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) 158 { 159 Toast.makeText(this, "surfaceChanged", Toast.LENGTH_SHORT).show(); 160 161 } 162 163 public void surfaceCreated(SurfaceHolder holder) 164 { 165 Toast.makeText(this, "surfaceCreated", Toast.LENGTH_SHORT).show(); 166 camera = Camera.open(); 167 try { 168 camera.setPreviewDisplay(holder); 169 Camera.Parameters parameters = camera.getParameters(); 170 if (this.getResources().getConfiguration().orientation 171 != Configuration.ORIENTATION_LANDSCAPE) 172 { 173 parameters.set("orientation", "portrait"); 174 175 // Android 2.2 及以上版本 176 camera.setDisplayOrientation(90); 177 178 // Android 2.0 及以上版本 179 parameters.setRotation(90); 180 } 181 182 // 效果, 用于Android 2.0 及以上版本 183 List<String> colorEffects = parameters.getSupportedColorEffects(); 184 Iterator<String> cei = colorEffects.iterator(); 185 186 while (cei.hasNext()) { 187 String currentEffect = cei.next(); 188 if (currentEffect.equals(Camera.Parameters.EFFECT_SOLARIZE)) 189 { 190 parameters.setColorEffect(Camera.Parameters.EFFECT_SOLARIZE); 191 break; 192 } 193 }// End 效果, 用于Android 2.0 及以上版本 194 195 camera.setParameters(parameters); 196 camera.startPreview(); 197 camera.setPreviewCallback(this); 198 199 } 200 catch (IOException exception) 201 { 202 camera.release(); 203 } 204 } 205 206 public void surfaceDestroyed(SurfaceHolder holder) 207 { 208 camera.stopPreview(); 209 camera.release(); 210 Toast.makeText(this, "surfaceDestroyed", Toast.LENGTH_SHORT).show(); 211 } 212 213 @Override 214 public void onPreviewFrame(byte[] data, Camera arg1) { 215 // TODO Auto-generated method stub 216 217 if (data != null) { 218 int imageWidth = arg1.getParameters().getPreviewSize().width; 219 int imageHeight = arg1.getParameters().getPreviewSize().height; 220 int RGBData[] = new int[imageWidth * imageHeight]; 221 decodeYUV420SP(RGBData, data, imageWidth, imageHeight); // 解码 222 Bitmap bm = null; 223 try{ 224 bm = Bitmap.createBitmap(RGBData, imageWidth, imageHeight, Config.ARGB_8888); 225 } 226 catch(OutOfMemoryError e){ 227 Log.e(TAG,"OOE1"); 228 } 229 bm = toGrayscale(bm);// 实时滤镜效果 这时把图片变成黑白 230 // 显示图片 231 Matrix mt = new Matrix(); 232 mt.setRotate(90); 233 Bitmap bm2 = null; 234 try{ 235 bm2 = Bitmap.createBitmap(bm,0,0,imageWidth,imageHeight,mt,true); 236 }catch(OutOfMemoryError e){ 237 Log.e(TAG,"OOE2"); 238 } 239 imgView.setImageBitmap(bm2); 240 Log.w(TAG,"to img"); 241 //bm.recycle();bitmap内存管理 242 } 243 } 244 } // End the Activity
与原先的区别在于:
在onPreviewFrame()里,对data转换编码方式(不知为什么?)后,生成bm。对bm添加效果(暂用变成黑白),再配合Matrix旋转后,生成bm2。再把bm2显示在ImageView中。
问题:这里bitmap的内存管理可能会有问题。如果在每次onPreviewFrame()的最后加上bm2.recycle(),ImageView中就会是空白(虽然明明是setImageBitmap()之后才recycle()的?),并且退出程序后会报错。就把那句注释了。
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:orientation="vertical" 4 android:layout_width="fill_parent" 5 android:layout_height="fill_parent" > 6 7 <SurfaceView android:id="@+id/CameraView" 8 android:layout_width="fill_parent" 9 android:layout_height="0dp" 10 android:layout_weight="1" 11 > 12 </SurfaceView> 13 <ImageView 14 android:id="@+id/ImageView" 15 android:layout_width="match_parent" 16 android:layout_height="0dp" 17 android:layout_weight="1" 18 /> 19 <Button 20 android:id="@+id/takePicture" 21 android:layout_width="match_parent" 22 android:layout_height="wrap_content" 23 android:text="takePicture" 24 /> 25 </LinearLayout>
与原先的区别在于:
添加了ImageView控件。
标签:
原文地址:http://www.cnblogs.com/kiwi-bird/p/4449038.html