拍照并修正图片显示方向

记录:拍照需要实现前后置摄头双拍,然后合成一张图片,上传到服务器

注注注注意的点:因为安卓手机机型比较多,每个手机拍出来获取图片资源方向都会不一样,因此需要先修正图片然后再合成图片,不然合成图片的方向就会不可控制,如下图一。由于每个手机拍出来的图片显示方向都会不一样。修正后就正常显示,如下图二。拍照完成后小图片可在大图片范围内任意拖拽,拖拽超出大图则回弹到大图边缘,如下图三。

/**

* 缩放前摄像头的图片 小图 屏幕宽高的0.32倍

*

* @return

*/

private Bitmap zoomBitmapImg(Bitmap bitmapWH) {

double imgWidth = Double.valueOf(DensityUtil.getScreenWidth(this)) * 0.32; //image 宽

double imgHeight = Double.valueOf(DensityUtil.getScreenHeight4_3(this)) * 0.32; //image 高

int width = bitmapWH.getWidth(); //bitmap 宽

int height = bitmapWH.getHeight(); //bitmap 高

//得到想要的大小

float scaleWidth = (float) (imgWidth / width); //宽的缩放比 scaleW = 想要得到的宽 / bitmap宽

float scaleHeight = (float) (imgHeight / height); //高的缩放比 scaleH = 想要得到的高 / bitmap高

Matrix matrix = new Matrix();

matrix.postScale(scaleWidth, scaleHeight);

Bitmap newBm = Bitmap.createBitmap(bitmapWH, 0, 0, width, height, matrix, true);

if (bitmapWH != null && !bitmapWH.isRecycled()) {

bitmapWH.recycle();

}

return newBm;

}

/**

* 把大图变成4:3 为背景图

*

* @return

*/

private Bitmap zoBitmapImg(Bitmap bitmapWH) {

double imgWidth = Double.valueOf(DensityUtil.getScreenWidth(this)); //image 宽

double imgHeight = Double.valueOf(DensityUtil.getScreenHeight4_3(this)); //image 高

int width = bitmapWH.getWidth(); //bitmap 宽

int height = bitmapWH.getHeight(); //bitmap 高

//得到想要的大小

float scaleWidth = (float) (imgWidth / width); //宽的缩放比

float scaleHeight = (float) (imgHeight / height); //高的缩放比

Matrix matrix = new Matrix();

matrix.postScale(scaleWidth, scaleHeight);

Bitmap newBm = Bitmap.createBitmap(bitmapWH, 0, 0, width, height, matrix, true);

if (bitmapWH != null && !bitmapWH.isRecycled()) {

bitmapWH.recycle();

}

return newBm;

}

/**

* 为 Bitmap 设置切割圆角

*

* @param source 原图

* @return

*/

private Bitmap getRoundBitmap(Bitmap source, float radius) {

Bitmap bitmap_bg = getBitmapByColor(source.getWidth() + DensityUtil.dip2px(this, 2) * 2,

source.getHeight() + DensityUtil.dip2px(this, 2) * 2);

Bitmap result = composeBitmap(getRoundCornerBitmap(bitmap_bg, DensityUtil.dip2px(this, 22)), getRoundCornerBitmap(source, radius));

return result;

}

/**

* 裁剪圆角

*

* @param source

* @param radius

* @return

*/

private Bitmap getRoundCornerBitmap(Bitmap source, float radius) {

Bitmap dstBitmap = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);

final Paint paint = new Paint();

paint.setAntiAlias(true);

final Rect dst = new Rect(0, 0, source.getWidth(), source.getHeight());

final RectF rectF = new RectF(dst);

Canvas canvas = new Canvas(dstBitmap);

canvas.drawARGB(0, 0, 0, 0);

canvas.drawRoundRect(rectF, radius, radius, paint);

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

canvas.drawBitmap(source, null, dst, paint);

if (source != null && !source.isRecycled()) {

source.recycle();

}

return dstBitmap;

}

/**

* 构建背景,用于设置圆角,本质是一大一小两个圆角bitmap 合并

*

* @param width

* @param height

* @return

*/

private Bitmap getBitmapByColor(int width, int height) {

Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

int[] pixels = new int[width * height];

for (int i = 0; i < height; i++) {

for (int j = 0; j < width; j++) {

pixels[i * width + j] = Color.BLACK;

}

}

bitmap.setPixels(pixels, 0, width, 0, 0, width, height);

return bitmap;

}

/**

* 合并图片

*

* @param bitmap1

* @param bitmap2

* @return

*/

private Bitmap composeBitmap(Bitmap bitmap1, Bitmap bitmap2) {

int bgWidth = bitmap1.getWidth();

int bgHeight = bitmap1.getHeight();

Bitmap newBitmap = Bitmap.createBitmap(bgWidth, bgHeight, Bitmap.Config.ARGB_8888);

Canvas canvas = new Canvas(newBitmap);

canvas.drawBitmap(bitmap1, 0, 0, null);

canvas.drawBitmap(bitmap2, (bgWidth - bitmap2.getWidth()) >> 1, (bgHeight - bitmap2.getHeight()) >> 1, null);

canvas.save();

canvas.restore();

return newBitmap;

}

注:没有修正图片之前

/**

* 读取照片旋转角度

*

* @param path 照片路径

* @return 角度

*/

public Bitmap readPictureDegree(String path) {

Bitmap bitmap = BitmapUtil.fileToBitmap(path);

try {

Matrix matrix = new Matrix();

ExifInterface exifInterface = new ExifInterface(path);

int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);

switch (orientation) {

case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:

//ok

matrix.postScale(-1f, 1f);

break;

case ExifInterface.ORIENTATION_ROTATE_180:

matrix.setRotate(180f);

break;

case ExifInterface.ORIENTATION_FLIP_VERTICAL:

matrix.postScale(1f, -1f);

break;

case ExifInterface.ORIENTATION_TRANSPOSE:

matrix.setRotate(90f);

matrix.postScale(-1f, 1f);

break;

case ExifInterface.ORIENTATION_ROTATE_90:

//ok

matrix.setRotate(90f);

break;

case ExifInterface.ORIENTATION_TRANSVERSE:

//ok

matrix.setRotate(270);

matrix.postScale(-1f, 1f);

break;

case ExifInterface.ORIENTATION_ROTATE_270:

matrix.setRotate(-90f);

break;

}

Bitmap bm = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);

if (bitmap != bm) {

bitmap.recycle();

bitmap = bm;

}

} catch (IOException e) {

e.printStackTrace();

}

return bitmap;

}

/**

* 两张图片合成一张图片 前后摄像头两张图片 旋转图片

*

* @param backImgUrl //后摄像头图片

* @param frontImgUrl //前摄像头图片

* @return

*/

private Bitmap newCombineBitMap(String backImgUrl, String frontImgUrl, float centrePointX, float centrePointY) {

try {

Bitmap backImg = zoBitmapImg(readPictureDegree(backImgUrl)); //大图

Bitmap frontImg = getRoundBitmap(zoomBitmapImg(readPictureDegree(frontImgUrl)), DensityUtil.dip2px(this, 20)); //小图

Bitmap bitmap = Bitmap.createBitmap(backImg.getWidth(), backImg.getHeight(), backImg.getConfig());

Canvas canvas = new Canvas(bitmap);

canvas.drawBitmap(backImg, new Matrix(), null);

// 通过中心点比例显示 X,Y 轴

float mPointX = backImg.getWidth() * centrePointX - (frontImg.getWidth() / 2);

float mPointY = backImg.getHeight() * centrePointY - (frontImg.getHeight() / 2);

// LogUtils.d("中心点是什么==============:", mPointX, mPointY);

canvas.drawBitmap(frontImg, mPointX, mPointY, null);

return bitmap;

} catch (Exception e) {

e.printStackTrace();

return null;

}

}

注:修正图片之后

添加点击拖拽事件:

//滑动事件

mCoverPreviewFront.setOnTouchListener(new OnTouchListener() {

@Override

public boolean onTouch(View view, MotionEvent motionEvent) {

float x = motionEvent.getX();

float y = motionEvent.getY();

if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { //按下

isMove = false;

mDownX = x;

mDownY = y;

// 记录第一次在屏幕上坐标,用于计算初始位置

mFirstX = (int) motionEvent.getRawX();

mFirstY = (int) motionEvent.getRawY();

} else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {//移动

mDragY = motionEvent.getY(); //拖拽时记录Y轴变化

mDragX = motionEvent.getX(); //拖拽时记录X轴变化

view.offsetTopAndBottom((int) (y - mDownY));

view.offsetLeftAndRight((int) (x - mDownX));

//记录移动位置大于一定程度才算滑动事件

int offs = 3;

if (mDragX > mDownX + offs || mDragX < mDownX - offs || mDragY > mDownY + offs || mDragY < mDownY - offs) {

isMove = true;

}

} else if (motionEvent.getAction() == MotionEvent.ACTION_UP) { //抬起

if (isMove) {

adsorptionBorder(view, mImagePreview);

} else {

switchImage();

}

}

return view.onTouchEvent(motionEvent);

}

});

}

边框吸顶:

/**

* 拖动超出父控件,吸边

*

* @param view

* @param parentView

*/

private void adsorptionBorder(View view, View parentView) {

// int padding = 32;

int padding = 40;

int endX = parentView.getWidth() - padding;

int endY = parentView.getHeight() - padding;

int x = 0;

int y = 0;

if ((view.getX()) < padding) {

x = padding;

// view.animate().setInterpolator(new DecelerateInterpolator()).setDuration(300).x(x).start();

} else if ((view.getX() + view.getWidth()) > endX) {

x = parentView.getWidth() - (view.getWidth() + padding);

// view.animate().setInterpolator(new DecelerateInterpolator()).setDuration(300).x(x).start();

} else {

x = (int) view.getX();

}

if (view.getY() < padding) {

y = padding;

// view.animate().setInterpolator(new DecelerateInterpolator()).setDuration(300).y(padding).start();

} else if (view.getY() + view.getHeight() > endY) {

y = endY - view.getHeight();

// view.animate().setInterpolator(new DecelerateInterpolator()).setDuration(300).y(y).start();

} else {

y = (int) view.getY();

}

FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) view.getLayoutParams();

layoutParams.leftMargin = x;

layoutParams.topMargin = y;

view.setLayoutParams(layoutParams);

}

/**

* 切换图片显示

*/

private void switchImage() {

mIsSwitch = !mIsSwitch;

Glide.with(getContext()).load(mIsSwitch ? mFrontBackImgUrl : mRearImgUrl).into(mImagePreview);

Glide.with(getContext()).load(mIsSwitch ? mRearImgUrl : mFrontBackImgUrl).into(mCoverPreviewFront);

}

中心点计算:(用于计算小图在大图上滑动的中心点,用于摆放位置记录)

// 通过 X,Y 轴 获取中心点比例

float mPointX = (mCoverPreviewFront.getX() + mCoverPreviewFront.getWidth() / 2) / mImagePreview.getWidth();

float mPointY = (mCoverPreviewFront.getY() + mCoverPreviewFront.getHeight() / 2) / mImagePreview.getHeight();

//中心点取前两位值

BigDecimal mBigPointX = BigDecimal.valueOf(centrePointX).setScale(2, BigDecimal.ROUND_HALF_UP);

BigDecimal mBigPointY = BigDecimal.valueOf(centrePointY).setScale(2, BigDecimal.ROUND_HALF_UP);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是可以使用的PyQt5代码: ```python import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * from PyQt5.QtMultimedia import * from PyQt5.QtMultimediaWidgets import * class CameraWidget(QWidget): def __init__(self, parent=None): super(CameraWidget, self).__init__(parent) # 创建Camera对象 self.camera = QCamera(self) # 创建显示相机画面的QCameraViewfinder对象 self.viewfinder = QCameraViewfinder(self) self.viewfinder.show() # 设置相机给QCameraViewfinder self.camera.setViewfinder(self.viewfinder) # 创建用于捕捉图像的QCameraImageCapture对象 self.imageCapture = QCameraImageCapture(self.camera) # 定义拍照按钮 self.captureButton = QPushButton("拍照") self.captureButton.clicked.connect(self.captureImage) # 创建水平布局 layout = QHBoxLayout() layout.addWidget(self.viewfinder) layout.addWidget(self.captureButton) self.setLayout(layout) def captureImage(self): # 定义用于保存照片的文件名 filename = QDateTime.currentDateTime().toString("yyyyMMddhhmmsszzz.jpg") # 定义照片保存路径 filepath = "./" + filename # 拍照并保存图片到指定路径 self.imageCapture.capture(filepath) # 显示拍摄的照片 image = QImage(filepath) pixmap = QPixmap.fromImage(image) scaledPixmap = pixmap.scaled(self.viewfinder.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation) self.viewfinder.setPixmap(scaledPixmap) if __name__ == '__main__': app = QApplication(sys.argv) widget = CameraWidget() widget.show() sys.exit(app.exec_()) ``` 这段代码将创建一个窗口,其中包括一个显示电脑摄像头拍摄的画面的区域、一个拍照按钮和一个用于保存拍照的照片的文件名的文件路径。当用户点击拍照按钮时,程序会拍摄照片并在窗口中显示该照片。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值