错误的像素化图像 - 自定义 android 相机
Bad pixelated image - custom android camera
我制作了自己的定制相机。这给了我糟糕的像素化图像,我不知道为什么。我可能使用质量为 100 的 JPEG 压缩。这是我得到的图像
Camera picture
这是我的代码:
public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Context mContext;
private Camera.Parameters parameters;
private byte[] mBuffer;
public CameraSurfaceView(Context context) {
super(context);
mContext = context;
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
if (CameraConfigurationUtils.mCameraInstance != null) {
CameraConfigurationUtils.mCameraInstance.setDisplayOrientation(90);
CameraConfigurationUtils.mCameraInstance.setPreviewDisplay(holder);
parameters = CameraConfigurationUtils.mCameraInstance.getParameters();
if (android.os.Build.VERSION.SDK_INT >= 14) {
CameraConfigurationUtils.setFocus(parameters, true, true, false);
} else {
CameraConfigurationUtils.setFocus(parameters, true, true, true);
}
WindowManager manager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
Point theScreenResolution = new Point();
theScreenResolution.set(display.getHeight(), display.getWidth());
CameraConfigurationUtils.findBestPreviewSizeValue(parameters, theScreenResolution);
CameraConfigurationUtils.mCameraInstance.setParameters(parameters);
updateBufferSize();
CameraConfigurationUtils.mCameraInstance.addCallbackBuffer(mBuffer);
CameraConfigurationUtils.mCameraInstance.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
public synchronized void onPreviewFrame(byte[] data, Camera c) {
if (CameraConfigurationUtils.mCameraInstance != null) {
CameraConfigurationUtils.mCameraInstance.addCallbackBuffer(mBuffer);
}
}
});
CameraConfigurationUtils.startPreview(mContext);
}
} catch (IOException e) {
e.printStackTrace();
CameraConfigurationUtils.releaseCamera();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
mHolder.removeCallback(this);
CameraConfigurationUtils.stopPreview();
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mHolder.getSurface() == null) {
return;
}
try {
CameraConfigurationUtils.mCameraInstance.setPreviewDisplay(mHolder);
CameraConfigurationUtils.startPreview(mContext);
} catch (Exception e) {
CameraConfigurationUtils.releaseCamera();
}
}
public byte[] getPic(int x, int y, int width, int height) {
System.gc();
Camera.Size s = parameters.getPreviewSize();
YuvImage yuvimage = new YuvImage(mBuffer, ImageFormat.NV21, s.width, s.height, null);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
yuvimage.compressToJpeg(new Rect(x, y, width, height), 100, outStream); // make JPG
yuvimage = null;
System.gc();
return outStream.toByteArray();
}
private void updateBufferSize() {
mBuffer = null;
System.gc();
// prepare a buffer for copying preview data to
int h = parameters.getPreviewSize().height;
int w = parameters.getPreviewSize().width;
int bitsPerPixel = ImageFormat.getBitsPerPixel(parameters.getPreviewFormat());
mBuffer = new byte[w * h * bitsPerPixel / 8];
//Log.i("surfaceCreated", "buffer length is " + mBuffer.length + " bytes");
}
}
我做错了什么?
您的图片示例看起来就像来自相机的常规低分辨率预览图像,但我可以看到在高分辨率屏幕上它会显示像素化。我相信你的问题在于这部分代码:
CameraConfigurationUtils.findBestPreviewSizeValue(parameters, theScreenResolution);
CameraConfigurationUtils.mCameraInstance.setParameters(parameters);
您似乎只是在计算最佳预览尺寸,该尺寸已返回给您,但您并未将其设置为实际预览尺寸。像这样尝试:
Point bestPreviewSize = CameraConfigurationUtils.findBestPreviewSizeValue(parameters, theScreenResolution);
parameters.setPreviewSize(bestPreviewSize.x, bestPreviewSize.y);
CameraConfigurationUtils.mCameraInstance.setParameters(parameters);
另一件事是,如果您打算拍摄高分辨率照片,则不应使用 getPic()
方法,因为它只是获取 jpeg 格式的预览帧,这是较低分辨率的图像.为此,您应该查看 Camera#takePicture method。
我制作了自己的定制相机。这给了我糟糕的像素化图像,我不知道为什么。我可能使用质量为 100 的 JPEG 压缩。这是我得到的图像 Camera picture
这是我的代码:
public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Context mContext;
private Camera.Parameters parameters;
private byte[] mBuffer;
public CameraSurfaceView(Context context) {
super(context);
mContext = context;
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
if (CameraConfigurationUtils.mCameraInstance != null) {
CameraConfigurationUtils.mCameraInstance.setDisplayOrientation(90);
CameraConfigurationUtils.mCameraInstance.setPreviewDisplay(holder);
parameters = CameraConfigurationUtils.mCameraInstance.getParameters();
if (android.os.Build.VERSION.SDK_INT >= 14) {
CameraConfigurationUtils.setFocus(parameters, true, true, false);
} else {
CameraConfigurationUtils.setFocus(parameters, true, true, true);
}
WindowManager manager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
Point theScreenResolution = new Point();
theScreenResolution.set(display.getHeight(), display.getWidth());
CameraConfigurationUtils.findBestPreviewSizeValue(parameters, theScreenResolution);
CameraConfigurationUtils.mCameraInstance.setParameters(parameters);
updateBufferSize();
CameraConfigurationUtils.mCameraInstance.addCallbackBuffer(mBuffer);
CameraConfigurationUtils.mCameraInstance.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
public synchronized void onPreviewFrame(byte[] data, Camera c) {
if (CameraConfigurationUtils.mCameraInstance != null) {
CameraConfigurationUtils.mCameraInstance.addCallbackBuffer(mBuffer);
}
}
});
CameraConfigurationUtils.startPreview(mContext);
}
} catch (IOException e) {
e.printStackTrace();
CameraConfigurationUtils.releaseCamera();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
mHolder.removeCallback(this);
CameraConfigurationUtils.stopPreview();
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mHolder.getSurface() == null) {
return;
}
try {
CameraConfigurationUtils.mCameraInstance.setPreviewDisplay(mHolder);
CameraConfigurationUtils.startPreview(mContext);
} catch (Exception e) {
CameraConfigurationUtils.releaseCamera();
}
}
public byte[] getPic(int x, int y, int width, int height) {
System.gc();
Camera.Size s = parameters.getPreviewSize();
YuvImage yuvimage = new YuvImage(mBuffer, ImageFormat.NV21, s.width, s.height, null);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
yuvimage.compressToJpeg(new Rect(x, y, width, height), 100, outStream); // make JPG
yuvimage = null;
System.gc();
return outStream.toByteArray();
}
private void updateBufferSize() {
mBuffer = null;
System.gc();
// prepare a buffer for copying preview data to
int h = parameters.getPreviewSize().height;
int w = parameters.getPreviewSize().width;
int bitsPerPixel = ImageFormat.getBitsPerPixel(parameters.getPreviewFormat());
mBuffer = new byte[w * h * bitsPerPixel / 8];
//Log.i("surfaceCreated", "buffer length is " + mBuffer.length + " bytes");
}
}
我做错了什么?
您的图片示例看起来就像来自相机的常规低分辨率预览图像,但我可以看到在高分辨率屏幕上它会显示像素化。我相信你的问题在于这部分代码:
CameraConfigurationUtils.findBestPreviewSizeValue(parameters, theScreenResolution);
CameraConfigurationUtils.mCameraInstance.setParameters(parameters);
您似乎只是在计算最佳预览尺寸,该尺寸已返回给您,但您并未将其设置为实际预览尺寸。像这样尝试:
Point bestPreviewSize = CameraConfigurationUtils.findBestPreviewSizeValue(parameters, theScreenResolution);
parameters.setPreviewSize(bestPreviewSize.x, bestPreviewSize.y);
CameraConfigurationUtils.mCameraInstance.setParameters(parameters);
另一件事是,如果您打算拍摄高分辨率照片,则不应使用 getPic()
方法,因为它只是获取 jpeg 格式的预览帧,这是较低分辨率的图像.为此,您应该查看 Camera#takePicture method。