Android 拍照后图片的旋转,合并,兼容性 相机开发

在看这篇文章之前,我建议先看 相机开发基础

针对这个功能需要做自定义相机,根据Camera相机类和SurfaceView类来实现自定义图形预览拍照功能。
但在实现过程中出现几个难点:
1.如何将自己产品图片(上图的台灯)和摄像头预览的图片结合成一张图片。
2.拍照的图片在有些手机上面出现旋转了90度的情况(Android兼容性问题)。
3.某些手机会出现在camera.setParameters(parameters)的调用时候出现设置失败的异常 java.lang.RuntimeException: setParameters failed
 
针对第一个问题:
     开始的考虑是在布局中SurfaceView上加一层ImageView来显示产品图片,然后通过截取View的方法截取SurfaceView和ImageView的父布局来实现,但截取view的时候发现只能截取静态的方法,对于像surfaceview之类的动态的view是不能够截取的(具体的截取方法请参考下面的源码),后来才有的是绘图的方式将预览图片的bitmap和产品图片的bitmap绘制到一张图片实现图片的合并(具体方法请参考下面源码)。
 
针对第二个问题:
    这个显然是android手机的兼容性问题,网上也有很大类似的网友提出此类问题,但给出的解决方法大都是先通过ExifInterface类来 读取bitmap的旋转角度,然后根据旋转角度旋转bitmap实现,我也用这个方法检验过,但实际上此方法并不靠谱,原因是读取bitmap的角度始终为0,即使我图片在拍照后出现的旋转了90度,也是读取不了的。 http://blog.csdn.net/qq_34850038/article/details/78761311 介绍了ExifInterface类在某些机型的有兼容性问题,并指出了问题产生的原因,我采用,拍照完成后,强制调用 setPictureDegreeZero方法(具体实现参考下面源码)来重新将图片的旋转角度设置为0,终于以次方解决了问题。终于松了口气,啊哈哈。
 
 
针对第三个问题:  
  某些机型出现了设置拍照参数失败,是因为某些参数设置对应该机型不支持,这里我需要做到的是需要确认哪些参数有兼容性问题的,经测试发现,
// parameters.setPreviewFrameRate(3);// 每秒3帧 每秒从摄像头里面获得3个画面, 此参数在小米2上面支持,在红米note2上面不支持,
// parameters . setPreviewSize ( PreviewWidth , PreviewHeight ); // 获得摄像区域的大小
// parameters.setPictureSize(PreviewWidth,PreviewHeight);// 获得保存图片的大小 ----这个两个参数也会有兼容性问题。
 
    目前发现这里3个参数有兼容性问题,其它若有发现在补充,同时如果网友们发现了其它参数存在兼容性问题也烦请指出,谢谢。
针对不兼容性问题,尽量避免去设置它,
对应setPreviewSize和setPictureSize可以通过以下方式取得合适的预览尺寸进行设置,具体方法请参考下面源代码。
// 选择合适的预览尺寸 List < Camera . Size > sizeList = parameters . getSupportedPreviewSizes ();
 
 
具体实现代码:
  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    package  com.example.eclipsetest;
     
    import  java.io.BufferedOutputStream;
    import  java.io.File;
    import  java.io.FileOutputStream;
    import  java.io.IOException;
    import  java.lang.reflect.Method;
    import  java.util.Iterator;
    import  java.util.List;
     
    import  android.app.Activity;
    import  android.content.Context;
    import  android.graphics.Bitmap;
    import  android.graphics.Bitmap.Config;
    import  android.graphics.BitmapFactory;
    import  android.graphics.Canvas;
    import  android.graphics.Matrix;
    import  android.graphics.PixelFormat;
    import  android.graphics.drawable.Drawable;
    import  android.hardware.Camera;
    import  android.hardware.Camera.AutoFocusCallback;
    import  android.hardware.Camera.Parameters;
    import  android.hardware.Camera.PictureCallback;
    import  android.hardware.Camera.ShutterCallback;
    import  android.hardware.Camera.Size;
    import  android.media.ExifInterface;
    import  android.os.Build;
    import  android.os.Bundle;
    import  android.os.Environment;
    import  android.util.DisplayMetrics;
    import  android.util.Log;
    import  android.view.Display;
    import  android.view.Gravity;
    import  android.view.SurfaceHolder;
    import  android.view.SurfaceView;
    import  android.view.View;
    import  android.view.View.MeasureSpec;
    import  android.view.View.OnClickListener;
    import  android.view.WindowManager;
    import  android.widget.Button;
    import  android.widget.FrameLayout;
    import  android.widget.ImageView;
    import  android.widget.ImageView.ScaleType;
    import  android.widget.Toast;
     
    /**
      * 自定义拍照,将特定图片添加到预览图片中保存起来
      *
      * @ClassName: MyCameraDemo
      * @Description:
      * @author xiaoxiao
      * @date modify by 2015-9-8 下午2:09:16
      *
      */
    public  class  MyCameraDemo  extends  Activity {
         private  SurfaceView surface =  null ;
         private  Button but =  null ;
         private  SurfaceHolder holder =  null ;
         private  Camera cam =  null ;
         private  boolean  previewRunning =  true ;
         private  Button but2;
         private  ImageView iv_img;
         private  FrameLayout flay_view;
     
         @Override
         public  void  onCreate(Bundle savedInstanceState) {
             super .onCreate(savedInstanceState);
             super .setContentView(R.layout.main);
             this .but = (Button)  super .findViewById(R.id.but);
             this .but2 = (Button)  super .findViewById(R.id.but2);
             this .surface = (SurfaceView)  super .findViewById(R.id.surface);
             iv_img = (ImageView) findViewById(R.id.iv_img);
             flay_view = (FrameLayout) findViewById(R.id.flay_view);
             this .holder =  this .surface.getHolder();
             this .holder.addCallback( new  MySurfaceViewCallback());
             this .holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
             this .holder.setFixedSize( 500 350 );
             this .but.setOnClickListener( new  OnClickListenerImpl());
             but2.setOnClickListener( new  OnClickListener() {
     
                 @Override
                 public  void  onClick(View v) {
                     iv_img.setVisibility(View.VISIBLE);
                     iv_img.setImageResource(R.drawable.taideng);
                 }
             });
         }
     
         private  class  OnClickListenerImpl  implements  OnClickListener {
     
             @Override
             public  void  onClick(View v) {
                 if  (cam !=  null ) {
                     cam.autoFocus( new  AutoFocusCallbackImpl());
                 }
             }
     
         }
     
         private  class  MySurfaceViewCallback  implements  SurfaceHolder.Callback {
     
             @Override
             public  void  surfaceChanged(SurfaceHolder holder,  int  format,  int  width,
                     int  height) {
     
             }
     
             @Override
             public  void  surfaceCreated(SurfaceHolder holder) {
                 if  (cam !=  null ) {
                     cam.stopPreview(); // 停掉原来摄像头的预览
                     cam.release(); // 释放资源
                     cam =  null ; // 取消原来摄像头
                 }
                 try  {
                     cam = Camera.open( 0 );  // 取得第一个摄像头
                 catch  (Exception e) {
                     // TODO: handle exception
                     Toast.makeText(MyCameraDemo. this "摄像头打开失败" 0 ).show();
                     return ;
                 }
                 cam = deal2(cam);
             }
     
             @Override
             public  void  surfaceDestroyed(SurfaceHolder holder) {
                 if  (cam !=  null ) {
                     if  (MyCameraDemo. this .previewRunning) {
                         cam.stopPreview();  // 停止预览
                         MyCameraDemo. this .previewRunning =  false ;
                     }
                     cam.stopPreview();
                     cam.release();
                     cam =  null ;
                 }
             }
     
         }
     
         private  class  AutoFocusCallbackImpl  implements  AutoFocusCallback {
     
             @Override
             public  void  onAutoFocus( boolean  success, Camera camera) {
                 if  (success) {  // 成功
                     cam.takePicture(sc, pc, jpgcall);
                 }
             }
     
         }
     
         private  PictureCallback jpgcall =  new  PictureCallback() {
     
             @Override
             public  void  onPictureTaken( byte [] data, Camera camera) {  // 保存图片的操作
                 Bitmap bmp = BitmapFactory.decodeByteArray(data,  0 , data.length);
                 // Bitmap bmp2 = new BitmapDrawable(iv_img).getDrawable();
                 // Bitmap bmp2 = BitmapFactory.decodeResource(getResources(),
                 // R.drawable.taideng);
                 // Bitmap bmp2 = drawableToBitamp(iv_img.getDrawable());
                 String fileName =  "test_"  + System.currentTimeMillis() +  ".jpg" ;
                 String filePath = Environment.getExternalStorageDirectory()
                         .toString()
                         + File.separator
                         "xiao"
                         + File.separator
                         + fileName;
                 bmp = rotateBitmapByDegree(bmp,  90 );
     
                 save(bmp, filePath, fileName);
                 bmp = loadBitmap(filePath,  true );
                 setPictureDegreeZero(filePath);
     
                 Bitmap bmp2 = getSmallBitmap(MyCameraDemo. this ,
                         R.drawable.taideng, dip2px(MyCameraDemo. this 200 ),
                         dip2px(MyCameraDemo. this 200 ));
                 Bitmap bmp3 = combineBitmap(bmp, bmp2);
                 save(bmp3, filePath, fileName);
                 cam.stopPreview();
                 cam.startPreview();
             }
     
         };
     
         private  ShutterCallback sc =  new  ShutterCallback() {
             @Override
             public  void  onShutter() {
                 // 按下快门之后进行的操作
             }
         };
         private  PictureCallback pc =  new  PictureCallback() {
     
             @Override
             public  void  onPictureTaken( byte [] data, Camera camera) {
     
             }
     
         };
     
         /**
          * 开始考虑用剪切的方法,但是截取只适合静态界面,这里surfaceView是动态的(在不断重绘)不能剪切,后来考虑用绘图的方式将两个bitmap合在一起。
          *
          * @param view
          * @return
          */
         private  Bitmap cropView(View view) {
             view.measure(MeasureSpec.makeMeasureSpec( 100 , MeasureSpec.UNSPECIFIED),
                     MeasureSpec.makeMeasureSpec( 100 , MeasureSpec.UNSPECIFIED));
             view.layout( 0 0 , view.getMeasuredWidth(), view.getMeasuredHeight());
             view.buildDrawingCache();
             Bitmap bitmap = view.getDrawingCache();
             return  bitmap;
         }
     
         
         /**
          * 合并两张bitmap为一张
          *
          * @param background
          * @param foreground
          * @return Bitmap
          */
         public  static  Bitmap combineBitmap(Bitmap background, Bitmap foreground) {
             if  (background ==  null ) {
                 return  null ;
             }
             int  bgWidth = background.getWidth();
             int  bgHeight = background.getHeight();
             int  fgWidth = foreground.getWidth();
             int  fgHeight = foreground.getHeight();
             Bitmap newmap = Bitmap
                     .createBitmap(bgWidth, bgHeight, Config.ARGB_8888);
             Canvas canvas =  new  Canvas(newmap);
             canvas.drawBitmap(background,  0 0 null );
             canvas.drawBitmap(foreground, (bgWidth - fgWidth) /  2 ,
                     (bgHeight - fgHeight) /  2 null );
             canvas.save(Canvas.ALL_SAVE_FLAG);
             canvas.restore();
             return  newmap;
         }
     
         private  void  save(Bitmap bitmap, String filePath, String fileName) {
             File file =  new  File(filePath);
             if  (!file.getParentFile().exists()) {
                 file.getParentFile().mkdirs();  // 创建文件夹
             }
             try  {
                 BufferedOutputStream bos =  new  BufferedOutputStream(
                         new  FileOutputStream(file));
                 bitmap.compress(Bitmap.CompressFormat.JPEG,  80 , bos);  // 向缓冲区之中压缩图片
                 bos.flush();
                 bos.close();
                 Toast.makeText(MyCameraDemo. this ,
                         "拍照成功,照片已保存在"  + fileName +  "文件之中!" , Toast.LENGTH_SHORT)
                         .show();
             catch  (Exception e) {
                 Toast.makeText(MyCameraDemo. this "拍照失败!" , Toast.LENGTH_SHORT)
                         .show();
             }
         }
     
         private  Bitmap bitmap;
     
         private  Bitmap drawableToBitamp(Drawable drawable) {
             int  w = drawable.getIntrinsicWidth();
             int  h = drawable.getIntrinsicHeight();
             System.out.println( "Drawable转Bitmap" );
             Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
                     : Bitmap.Config.RGB_565;
             bitmap = Bitmap.createBitmap(w, h, config);
             // 注意,下面三行代码要用到,否在在View或者surfaceview里的canvas.drawBitmap会看不到图
             Canvas canvas =  new  Canvas(bitmap);
             drawable.setBounds( 0 0 , w, h);
             drawable.draw(canvas);
             return  bitmap;
         }
     
         /**
          * 读取图片的旋转的角度, 某些机型此方法无效
          *
          * @param path
          *            图片绝对路径
          * @return 图片的旋转角度
          */
         private  int  getBitmapDegree(String path) {
             int  degree =  0 ;
             try  {
                 // 从指定路径下读取图片,并获取其EXIF信息
                 ExifInterface exifInterface =  new  ExifInterface(path);
                 // 获取图片的旋转信息
                 int  orientation = exifInterface.getAttributeInt(
                         ExifInterface.TAG_ORIENTATION,
                         ExifInterface.ORIENTATION_NORMAL);
                 switch  (orientation) {
                 case  ExifInterface.ORIENTATION_ROTATE_90:
                     degree =  90 ;
                     break ;
                 case  ExifInterface.ORIENTATION_ROTATE_180:
                     degree =  180 ;
                     break ;
                 case  ExifInterface.ORIENTATION_ROTATE_270:
                     degree =  270 ;
                     break ;
                 }
             catch  (IOException e) {
                 e.printStackTrace();
             }
             return  degree;
         }
     
         /**
          * 将图片按照某个角度进行旋转
          *
          * @param bm
          *            需要旋转的图片
          * @param degree
          *            旋转角度
          * @return 旋转后的图片
          */
         public  static  Bitmap rotateBitmapByDegree(Bitmap bm,  int  degree) {
             Bitmap returnBm =  null ;
     
             // 根据旋转角度,生成旋转矩阵
             Matrix matrix =  new  Matrix();
             matrix.postRotate(degree);
             try  {
                 // 将原始图片按照旋转矩阵进行旋转,并得到新的图片
                 returnBm = Bitmap.createBitmap(bm,  0 0 , bm.getWidth(),
                         bm.getHeight(), matrix,  true );
             catch  (OutOfMemoryError e) {
             }
             if  (returnBm ==  null ) {
                 returnBm = bm;
             }
             if  (bm != returnBm) {
                 bm.recycle();
             }
             return  returnBm;
         }
     
         // 控制图像的正确显示方向
         private  void  setDispaly(Camera.Parameters parameters, Camera camera) {
             if  (Integer.parseInt(Build.VERSION.SDK) >=  8 ) {
                 setDisplayOrientation(camera,  90 );
             else  {
                 parameters.setRotation( 90 );
             }
     
         }
     
         // 实现的图像的正确显示
         private  void  setDisplayOrientation(Camera camera,  int  i) {
             Method downPolymorphic;
             try  {
                 downPolymorphic = camera.getClass().getMethod(
                         "setDisplayOrientation" new  Class[] {  int . class  });
                 if  (downPolymorphic !=  null ) {
                     downPolymorphic.invoke(camera,  new  Object[] { i });
                 }
             catch  (Exception e) {
                 Log.e( "Came_e" "图像出错" );
             }
         }
     
         private  Camera deal2(Camera mCamera) {
             // 设置camera预览的角度,因为默认图片是倾斜90度的
             // mCamera.setDisplayOrientation(90);
     
             int  PreviewWidth =  0 ;
             int  PreviewHeight =  0 ;
             WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); // 获取窗口的管理器
             Display display = wm.getDefaultDisplay(); // 获得窗口里面的屏幕
             Camera.Parameters parameters = mCamera.getParameters();
             // parameters.setFlashMode(Parameters.FLASH_MODE_TORCH); //开启闪光灯,支持
             setDispaly(parameters, mCamera);
             // parameters.setRotation(90);
             // parameters.setPreviewFrameRate(3);// 每秒3帧 每秒从摄像头里面获得3个画面,
             // 某些机型(红米note2)不支持
             parameters.setPictureFormat(PixelFormat.JPEG); // 设置照片输出的格式
             parameters.set( "jpeg-quality" 100 ); // 设置照片质量
             try  {
                 // 选择合适的预览尺寸
                 List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();
                 // 如果sizeList只有一个我们也没有必要做什么了,因为就他一个别无选择
                 if  (sizeList.size() >  1 ) {
                     Iterator<Camera.Size> itor = sizeList.iterator();
                     while  (itor.hasNext()) {
                         Camera.Size cur = itor.next();
                         if  (cur.width >= PreviewWidth
                                 && cur.height >= PreviewHeight) {
                             PreviewWidth = cur.width;
                             PreviewHeight = cur.height;
                             break ;
                         }
                     }
                 }
                 parameters.setPreviewSize(PreviewWidth, PreviewHeight);  // 获得摄像区域的大小
                 parameters.setPictureSize(PreviewWidth, PreviewHeight);  // 获得保存图片的大小
                 // parameters.setPreviewSize(display.getWidth(),
                 // display.getWidth()); // 获得摄像区域的大小
                 // parameters.setPictureSize(display.getWidth(),
                 // display.getWidth());// 设置拍出来的屏幕大小
     
             catch  (Exception e) {
                 Log.e( "MyCameraDemo" , e.toString());
             }
             try  {
                 cam.setPreviewDisplay(MyCameraDemo. this .holder);
             catch  (IOException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }
             mCamera.setParameters(parameters); // 把上面的设置 赋给摄像头
             mCamera.startPreview(); // 开始预览
             mCamera.cancelAutoFocus(); // 2如果要实现连续的自动对焦,这一句必须加上
             previewRunning =  true ;
             return  mCamera;
         }
     
         /** 从给定路径加载图片 */
         public  Bitmap loadBitmap(String imgpath) {
             return  BitmapFactory.decodeFile(imgpath);
         }
     
         /** 从给定的路径加载图片,并指定是否自动旋转方向 */
         public  Bitmap loadBitmap(String imgpath,  boolean  adjustOritation) {
             if  (!adjustOritation) {
                 return  loadBitmap(imgpath);
             else  {
                 Bitmap bm = loadBitmap(imgpath);
                 int  digree =  0 ;
                 ExifInterface exif =  null ;
                 try  {
                     exif =  new  ExifInterface(imgpath);
                 catch  (IOException e) {
                     e.printStackTrace();
                     exif =  null ;
                 }
                 if  (exif !=  null ) {
                     // 读取图片中相机方向信息
                     // int ori = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                     // ExifInterface.ORIENTATION_NORMAL);
                     int  ori = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                             ExifInterface.ORIENTATION_FLIP_VERTICAL);
                     // 计算旋转角度
                     switch  (ori) {
                     case  ExifInterface.ORIENTATION_ROTATE_90:
                         digree =  90 ;
                         break ;
                     case  ExifInterface.ORIENTATION_ROTATE_180:
                         digree =  180 ;
                         break ;
                     case  ExifInterface.ORIENTATION_ROTATE_270:
                         digree =  270 ;
                         break ;
                     default :
                         digree =  0 ;
                         break ;
                     }
                 }
                 if  (digree !=  0 ) {
                     // 旋转图片
                     Matrix m =  new  Matrix();
                     m.postRotate(digree);
                     bm = Bitmap.createBitmap(bm,  0 0 , bm.getWidth(),
                             bm.getHeight(), m,  true );
                 }
                 return  bm;
             }
         }
     
         /**
          * 将图片的旋转角度置为0  ,此方法可以解决某些机型拍照后图像,出现了旋转情况
          *
          * @Title: setPictureDegreeZero
          * @param path
          * @return void
          * @date 2012-12-10 上午10:54:46
          */
         private  void  setPictureDegreeZero(String path) {
             try  {
                 ExifInterface exifInterface =  new  ExifInterface(path);
                 // 修正图片的旋转角度,设置其不旋转。这里也可以设置其旋转的角度,可以传值过去,
                 // 例如旋转90度,传值ExifInterface.ORIENTATION_ROTATE_90,需要将这个值转换为String类型的
                 exifInterface.setAttribute(ExifInterface.TAG_ORIENTATION,  "no" );
                 exifInterface.saveAttributes();
             catch  (IOException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }
     
         }
     
         /**
          * 根据路径获取图片并压缩返回bitmap用于显示
          *
          * @param context
          * @param id
          * @return
          */
     
         private   Bitmap getSmallBitmap(Context context,  int  id, int  width, int  height) {
             final  BitmapFactory.Options options =  new  BitmapFactory.Options();
             options.inJustDecodeBounds =  true ;
             BitmapFactory.decodeResource(context.getResources(), id, options);
             // 计算 缩略图大小为原始图片大小的几分之一 inSampleSize:缩略图大小为原始图片大小的几分之一
             options.inSampleSize = calculateInSampleSize(options, width, height);
             options.inJustDecodeBounds =  false ;
     
             return  BitmapFactory.decodeResource(context.getResources(), id, options);
         }
         
         /**
          * 计算图片的缩放值
          *
          * @param options
          * @param reqWidth
          * @param reqHeight
          * @return
          */
         private   int  calculateInSampleSize(BitmapFactory.Options options,  int  reqWidth,  int  reqHeight) {
             // Raw height and width of image
             final  int  height = options.outHeight;
             final  int  width = options.outWidth;
             int  inSampleSize =  1 ;
     
             if  (height > reqHeight || width > reqWidth) {
                 final  int  heightRatio = Math.round(( float ) height / ( float ) reqHeight);
                 final  int  widthRatio = Math.round(( float ) width / ( float ) reqWidth);
                 inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
     
             }
             return  inSampleSize;
     
         }
         /**
          * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
          */
         public  static  int  dip2px(Context context,  float  dpValue) {
             final  float  scale = context.getResources().getDisplayMetrics().density;
             return  ( int ) (dpValue * scale +  0 .5f);
         }
     
         /**
          * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
          */
         public  static  int  px2dip(Context context,  float  pxValue) {
             final  float  scale = context.getResources().getDisplayMetrics().density;
             return  ( int ) (pxValue / scale +  0 .5f);
         }
    }

      


 
布局文件:
  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    <?xml version= "1.0"  encoding= "utf-8" ?>
    <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android"
         android:layout_width= "fill_parent"
         android:layout_height= "fill_parent"
         android:orientation= "vertical"  >
         <FrameLayout
             android:id= "@+id/flay_view"
             android:layout_width= "fill_parent"
             android:layout_height= "fill_parent"
             android:layout_weight= "1000"  >
             <SurfaceView
                 android:id= "@+id/surface"
                 android:layout_width= "fill_parent"
                 android:layout_height= "fill_parent"
                 android:layout_weight= "1000"  />
             <ImageView
                 android:id= "@+id/iv_img"
                 android:layout_width= "200dp"
                 android:layout_height= "200dp"
                 android:layout_gravity= "center"
                 android:visibility= "gone"
                 android:src= "@drawable/taideng"
                 android:scaleType= "fitCenter" />
         </FrameLayout>
         <LinearLayout
             android:layout_width= "match_parent"
             android:layout_height= "wrap_content"
             android:layout_weight= "1"
             android:orientation= "horizontal"  >
             <Button
                 android:id= "@+id/but"
                 android:layout_width= "wrap_content"
                 android:layout_height= "wrap_content"
                 android:layout_weight= "1"
                 android:text= "照相"  />
             <Button
                 android:id= "@+id/but2"
                 android:layout_width= "wrap_content"
                 android:layout_height= "wrap_content"
                 android:layout_weight= "1"
                 android:text= "添加图片"  />
         </LinearLayout>
    </LinearLayout> 

      

 
最后不要忘了权限:
    
  1. <uses-feature android:name="android.hardware.camera" />
        <uses-feature android:name="android.hardware.camera.autofocus" />
        <uses-permission android:name="android.permission.CAMERA" />
        <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值