问题
First Method
When I set
javasetRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
or java setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
Camera2 is running fine and save image from imageavailablelistener.
Second Method
When I set java setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
or java setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
It will exit from the app and cannot save image
Conversion Credit
YUV Image to Bitmap method is credit to link
Caller
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
final Image image = reader.acquireLatestImage();
if (image == null)
return;
BitmapFunctions bitmapFunctions = new BitmapFunctions();
// QrDecoder qrDecoder = new QrDecoder();
//Convert YUV to RGB and return bitmap
Bitmap bitmap = bitmapFunctions.mediaImageToBitmap(image, activity);
Actual Conversion Functions
public class BitmapFunctions {
private Allocation allocationYuv;
private Allocation allocationRgb;
private RenderScript rs;
public Bitmap mediaImageToBitmap(Image image, Context context) {
final ByteBuffer yuvBytes = imageToByteBuffer(image);
// Convert YUV to RGB
rs = RenderScript.create(context);
Bitmap bitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
allocationRgb = Allocation.createFromBitmap(rs, bitmap);
allocationYuv = Allocation.createSized(rs, Element.U8(rs), yuvBytes.array().length);
allocationYuv.copyFrom(yuvBytes.array());
ScriptIntrinsicYuvToRGB scriptYuvToRgb = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
scriptYuvToRgb.setInput(allocationYuv);
scriptYuvToRgb.forEach(allocationRgb);
allocationRgb.copyTo(bitmap);
return bitmap;
}
public void release() {
allocationYuv.destroy();
allocationRgb.destroy();
rs.destroy();
}
private ByteBuffer imageToByteBuffer(final Image image) {
final Rect crop = image.getCropRect();
final int width = crop.width();
final int height = crop.height();
final Image.Plane[] planes = image.getPlanes();
final byte[] rowData = new byte[planes[0].getRowStride()];
final int bufferSize = width * height * ImageFormat.getBitsPerPixel(ImageFormat.YUV_420_888) / 8;
final ByteBuffer output = ByteBuffer.allocateDirect(bufferSize);
int channelOffset = 0;
int outputStride = 0;
for (int planeIndex = 0; planeIndex < 3; planeIndex++) {
if (planeIndex == 0) {
channelOffset = 0;
outputStride = 1;
} else if (planeIndex == 1) {
channelOffset = width * height + 1;
outputStride = 2;
} else if (planeIndex == 2) {
channelOffset = width * height;
outputStride = 2;
}
final ByteBuffer buffer = planes[planeIndex].getBuffer();
final int rowStride = planes[planeIndex].getRowStride();
final int pixelStride = planes[planeIndex].getPixelStride();
final int shift = (planeIndex == 0) ? 0 : 1;
final int widthShifted = width >> shift;
final int heightShifted = height >> shift;
buffer.position(rowStride * (crop.top >> shift) + pixelStride * (crop.left >> shift));
for (int row = 0; row < heightShifted; row++) {
final int length;
if (pixelStride == 1 && outputStride == 1) {
length = widthShifted;
buffer.get(output.array(), channelOffset, length);
channelOffset += length;
} else {
length = (widthShifted - 1) * pixelStride + 1;
buffer.get(rowData, 0, length);
for (int col = 0; col < widthShifted; col++) {
output.array()[channelOffset] = rowData[col * pixelStride];
channelOffset += outputStride;
}
}
if (row < heightShifted - 1) {
buffer.position(buffer.position() + rowStride - length);
}
}
}
return output;
}
Error
2019-06-19 17:04:47.551 23356-23423/com.dsonic.datasonicscanner E/AndroidRuntime: FATAL EXCEPTION: CameraBackground
Process: com.dsonic.datasonicscanner, PID: 23356
java.lang.IllegalStateException: buffer is inaccessible
at java.nio.DirectByteBuffer.get(DirectByteBuffer.java:219)
at com.dsonic.dsoniccamera2lib.Camera2.BitmapFunctions.imageToByteBuffer(BitmapFunctions.java:105)
at com.dsonic.dsoniccamera2lib.Camera2.BitmapFunctions.mediaImageToBitmap(BitmapFunctions.java:36)
at com.dsonic.dsoniccamera2lib.Camera2.Camera2Manager$4.onImageAvailable(Camera2Manager.java:302)
at android.media.ImageReader$ListenerHandler.handleMessage(ImageReader.java:812)
at android.os.Handler.dispatchMessage(Handler.java:108)
at android.os.Looper.loop(Looper.java:166)
at android.os.HandlerThread.run(HandlerThread.java:65)
ctrl+f
to find the error line
BitmapFunctions.java:105 is channelOffset += outputStride;
BitmapFunctions.java:36 is Bitmap bitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
Camera2Manager.java:302 is Bitmap bitmap = bitmapFunctions.mediaImageToBitmap(image, activity);
Update 20/6/2019
Everything run fine now, same code nothing change. Using same cable but phone is restarted this morning and added Log.e("Image Size", "Width = " + image.getWidth() + " Height = " + image.getHeight());
.
After I comment it out it auto exit on me again. Now I remove the comment, it can't work again. WTF?
Can anyone explain to me?
回答1:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR)
instead of setting this.
Change it to force orientation in Manifest. Don't know why this work
Hope someone can explain to me.
来源:https://stackoverflow.com/questions/56664653/how-to-convert-yuv-to-bitmap-in-landscape-orientation