我捕捉图像是为了把它转换成一定大小的正方形。当我使用不同的手机捕捉图像时,在其中一些手机中捕捉到的图像与预览中显示的图像相同,但在一些手机中,捕捉到的图像是旋转的。
下面是代码:
按钮点击:
bGetImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
final Bitmap[] bitmap = {null};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
imageCapture.takePicture(getMainExecutor(),new ImageCapture.OnImageCapturedCallback() {
@Override
public void onCaptureSuccess(@NonNull ImageProxy image) {
super.onCaptureSuccess(image);
Log.d(TAG, "onCaptureSuccess: testview.innerRectangle " + testview.innerRectangle.width());
Log.d(TAG, "onCaptureSuccess: testview.innerRectangle " + testview.innerRectangle.height());
OutputTransform source = previewView.getOutputTransform();
// imageProxy is the output of the ImageCapture.
OutputTransform target = new ImageProxyTransformFactory().getOutputTransform(image);
//print size of target
Log.d(TAG, "onCaptureSuccess: target " + target.getMatrix().toString());
// Build the transform from ImageAnalysis to PreviewView
CoordinateTransform coordinateTransform = new CoordinateTransform(source, target);
// The variable box here is your bounding box in PreviewView
coordinateTransform.mapRect(testview.innerRectangle);
Log.d(TAG, "onCaptureSuccess: testview.innerRectangle " + testview.innerRectangle.width());
Log.d(TAG, "onCaptureSuccess: testview.innerRectangle " + testview.innerRectangle.height());
bitmap[0] = imageProxytoBitmap(image);
Log.d(TAG, "onCaptureSuccess: bitmap[0] " + bitmap[0].getWidth());
Log.d(TAG, "onCaptureSuccess: bitmap[0] " + bitmap[0].getHeight());
// bitmap[0] = Bitmap.createBitmap(bitmap[0],(int)testview.innerRectangle.left,(int)testview.innerRectangle.top,(int)testview.innerRectangle.width(),(int)testview.innerRectangle.height());
try {
Uri uri = getUri(bitmap[0], getContentResolver());
Log.d(TAG, "onCaptureSuccess: bitmap[0] " + bitmap[0].getWidth());
Log.d(TAG, "onCaptureSuccess: bitmap[0] " + bitmap[0].getHeight());
String path = uri.toString();
moveToScanActivity(path);
} catch (IOException e) {
Log.e(TAG, "onCaptureSuccess: ",e);
}
}
});
}
}
});
摄像头提供程序初始化:
cameraProviderFuture.addListener(() -> {
try {
ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
CameraSelector selector = CameraSelector.DEFAULT_BACK_CAMERA;
cameraProvider.unbindAll();
// Camera camera = cameraProvider.bindToLifecycle(this, selector);
bindPreview(cameraProvider);
} catch (ExecutionException | InterruptedException e) {
// No errors need to be handled for this Future.
// This should never be reached.
}
}, ContextCompat.getMainExecutor(this));
我正在使用的其他功能:
void bindPreview(@NonNull ProcessCameraProvider cameraProvider) {
Log.d(TAG, "bindPreview: width " + width);
Log.d(TAG, "bindPreview: height " + height);
Preview preview = new Preview.Builder()
.setTargetResolution(new Size(width, height))
.setTargetRotation(ROTATION_0)
.build();
previewView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(
View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
Size newViewFinderDimens = new Size(right - left, bottom - top);
updateTransform(0, MainActivity.bufferDimens, newViewFinderDimens);
}
});
imageCapture =
new ImageCapture.Builder()
.setTargetResolution(new Size(width, height))
.setTargetRotation(ROTATION_0)
.build();
CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build();
preview.setSurfaceProvider(previewView.getSurfaceProvider());
UseCaseGroup useCaseGroup = new UseCaseGroup.Builder()
.addUseCase(preview)
.addUseCase(imageCapture)
.build();
cameraProvider.bindToLifecycle((LifecycleOwner)this, cameraSelector, useCaseGroup);
previewHeight = previewView.getHeight();
previewWidth = previewView.getWidth();
}
private Uri getUri(Bitmap bitmap, ContentResolver contentResolver) throws FileNotFoundException {
File file = new File(getApplicationContext().getExternalMediaDirs()[0].getAbsolutePath(),"Mytittle_" + System.currentTimeMillis() + ".png");
bitmap.compress(Bitmap.CompressFormat.PNG, 100, new FileOutputStream(file));
Log.d(TAG, "getUri: path " + file.getAbsolutePath());
return Uri.parse(file.getAbsolutePath());
}
private Bitmap rotateImage(Bitmap img, int degree)
{
Matrix matrix = new Matrix();
matrix.postRotate(degree);
return Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, false);
}
public void updateTransform(int rotation, Size newBufferDimens, Size newViewFinderDimens) {
if (rotation == viewFinderRotation &&
newBufferDimens == bufferDimens &&
newViewFinderDimens == viewFinderDimens) {
// Nothing has changed, no need to transform output again
//Log.d("AK", "nothing has changed, no need to transform output again");
return;
}
if (newBufferDimens.getWidth() == 0 || newBufferDimens.getHeight() == 0) {
// Invalid buffer dimens - wait for valid inputs before setting matrix
//Log.d("AK", "returning from here newbufferdimens");
return;
} else {
// Update internal field with new inputs
bufferDimens = newBufferDimens;
}
if (newViewFinderDimens.getWidth() == 0 || newViewFinderDimens.getHeight() == 0) {
// Invalid view finder dimens - wait for valid inputs before setting matrix
//Log.d("AK", "returning from here newViewfinder");
return;
} else {
// Update internal field with new inputs
viewFinderDimens = newViewFinderDimens;
}
Matrix matrix = new Matrix();
Log.d(TAG, "Applying output transformation.\n" +
"View finder size: " + viewFinderDimens + "\n" +
"Preview output size: " + bufferDimens + "\n" +
"View finder rotation: " + viewFinderRotation + "\n" +
"Preview output rotation: " + 0);
float centerX = previewView.getWidth() / 2f;
float centerY = previewView.getHeight() / 2f;
// Correct preview output to account for display rotation
float rotationDegrees;
switch (previewView.getDisplay().getRotation()) {
case Surface.ROTATION_0:
rotationDegrees = 0f;
break;
case Surface.ROTATION_90:
rotationDegrees = 90f;
break;
case Surface.ROTATION_180:
rotationDegrees = 180f;
break;
case Surface.ROTATION_270:
rotationDegrees = 270f;
break;
default:
return;
}
matrix.postRotate(-rotationDegrees, centerX, centerY);
float bufferRatio = bufferDimens.getHeight() / (float) bufferDimens.getWidth();
int scaledWidth;
int scaledHeight;
if (previewView.getWidth() > previewView.getHeight()) {
scaledHeight = viewFinderDimens.getWidth();
scaledWidth = round(viewFinderDimens.getWidth() * bufferRatio);
} else {
scaledHeight = viewFinderDimens.getHeight();
scaledWidth = round(viewFinderDimens.getHeight() * bufferRatio);
}
Canvas canvas = new Canvas();
float xScale = scaledWidth / (float) viewFinderDimens.getWidth();
float yScale = scaledHeight / (float) viewFinderDimens.getHeight();
//Log.d("AK", "scale x y" + xScale + " " + yScale);
matrix.preScale(xScale, yScale, centerX, centerY);
}
private Bitmap imageProxytoBitmap(ImageProxy image) {
ByteBuffer buffer =image.getPlanes()[0].getBuffer();
buffer.rewind();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
byte[] cloneBytes = bytes.clone();
return BitmapFactory.decodeByteArray(cloneBytes, 0, cloneBytes.length);
}
我希望捕获的图像与预览完全相同(未旋转的图像)
1条答案
按热度按时间rxztt3cl1#
如果你在谷歌照片应用程序中打开旋转后的图像,它们还在旋转吗?如果不是,那么这意味着你没有使用EXIF信息。
基本上,当一张照片被捕获时,它可能会旋转,也可能不会旋转,这取决于OEM。当它没有旋转时,CameraX会将旋转信息保存在
TAG_ORIENTATION
标签中。您需要读取该信息并自己将其应用到位图上。类似于:未测试代码。在旋转过程中可能需要交换宽度/高度。