在看这篇文章之前,我建议先看相机开发基础
针对这个功能需要做自定义相机,根据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(500350);
            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.this200),
                        dip2px(MyCameraDemo.this200));
                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(00, 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, 00null);
            canvas.drawBitmap(foreground, (bgWidth - fgWidth) / 2,
                    (bgHeight - fgHeight) / 2null);
            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(00, 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, 00, 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, 00, 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" /> 

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

  1. android 竖屏拍照旋转90度,三星等机型上拍照后图片被旋转90度的解决方案

    考虑到Android7.0以后拍照修改了调用和返回方式,找到了一个看起来还不错的第三方库,实际可能并非如此. -TakePhoto 在三星Note3和S6上测试,发现竖屏拍照后返回的照片是横屏的,在其 ...

  2. Android进阶之路 - 解决部分手机拍照之后图片被旋转的问题

    这几天犯了一个错误,初期想着甩锅给后台的- 但还好及时发现了是自身的问题~ 关联文章 Android基础进阶 - 调用拍照.获取图片(基础) Android基础进阶 - 获取.调用相册内图片(基础) ...

  3. android上传图片被旋转,解决android有的手机拍照后上传图片被旋转的问题

    需求:做仿新浪发微博的项目,能够上传图片还有两外一个项目用到手机拍摄图片,这两个都需要把图片上传到服务器 遇到问题:有的手机拍摄的图片旋转90度,有的图片旋转了180度,有的手机是正常的,服务器要求的 ...

  4. android拍照保存到系统相册,调用系统相机拍照,并且保存到系统相册的一般套路...

    最近遇到也一个需求:调用系统相机拍照,并且照片可以在系统相册显示. 关于照片显示在系统相册这个问题,因为安卓机型太多了,各大厂商都对原生系统进行了不同程度的定制,所以在一般情况下,有的手机会把图片直接 ...

  5. Android开发之拍照后图片旋转的问题

    经过测试,国产手机拍照无问题,国外手机拍照后自动选装90度了看图:主要有Google手机和三星手机都会有这个问题 解决办法也很简单说下思路: 首先获取图片被旋转的角度然后通过matrix.postRo ...

  6. 解决android有的手机拍照后上传图片被旋转的问题

    需求:做仿新浪发微博的项目,能够上传图片还有两外一个项目用到手机拍摄图片,这两个都需要把图片上传到服务器 遇到问题:有的手机拍摄的图片旋转90度,有的图片旋转了180度,有的手机是正常的,服务器要求的 ...

  7. Java 处理 iphone拍照后 图片EXIF属性翻转90度的方法

    http://blog.csdn.net/z69183787/article/details/50320821 Java获取照片EXIF信息 http://blog.csdn.net/ghsau/ar ...

  8. 三星手机拍照后 图片翻转

    今天遇到一个奇怪的现象  就是三星Note3 7508v型号的手机 拍照后 会自动的进行翻转. 1   代码中处理 int degree = CommonUtils.getBitmapDegree(a ...

  9. android 相册 uri空,android拍照获得图片URI为空的处理方法

    在拍照的时候,获得图片URI为空, 发起intent请求: private void getBitmapFromTakePictrue() { Intent intent = new Intent(M ...

最新文章

  1. 推荐一位二本毕业1年,上海买房的大佬,牛逼!
  2. centos安装ffmpeg php,lnmp下安装ffmpeg和ffmpeg-php教程
  3. 《中国大数据产业白皮书及百强榜单》:一览中国大数据产业发展全局
  4. Android 面试 - 动画
  5. Android 利用jsoup解析 html
  6. jquery的ajax查询数据库,用Jquery和Ajax查询Django数据库
  7. cf1553C. Penalty
  8. java多线程笔记补充之线程的生命周期
  9. qq传输文件的软件测试点,超强新功能 QQ传文件夹测试版抢先试用
  10. 学习ASP.NET Core Razor 编程系列三——创建数据表及创建项目基本页面
  11. 黑马程序员_Java学习日记num8
  12. 红外测距模块 51单片机_红外通信原理
  13. 【每日新闻】Gartner:区块链热度高但实际部署较少且面临挑战 | 阿里巴巴宣布研制出全球最强量子电路模拟器“太章”...
  14. Stack栈后进先出
  15. linux 终止一个前台进程,Linux中前台起动的进程怎么结束?
  16. 使用jqdata和hikyuu平台进行C /python混合策略编写的方法
  17. 一山不容二虎?双动力同步驱动技术与模型分享
  18. 【视频】主成分分析PCA降维方法和R语言分析葡萄酒可视化实例|数据分享
  19. 三、Cypher的使用(知识图谱构建射雕人物关系)
  20. Windows2008硬盘安装OpenSuse11.2

热门文章

  1. 排球分组循环交叉编排_巍山县举办气排球赛,看谁技高一筹!
  2. c# 通过读取Json文件生成HTML页并在浏览器显示
  3. ant design vue 实现手机号 身份证 中文校验 邮箱校验
  4. 第6周作业2-IF语句大显身手之成绩判断(网络131黄宇倩)
  5. Flutter for ble 之set_notification_error, could not locate CCCD descriptor for characteristic分析(原生角度)
  6. K近邻算法python实现并显示决策边界
  7. 2022年PC推荐-组装机及品牌机 2022年8月16日(持续更新)
  8. 苹果手机直播怎么投屏 苹果手机投影电脑屏幕
  9. amCharts 5.1.12 Crack
  10. 如何实现手机远程控制电源开关