Reputation: 5223
This is my code that I use to save the image to a Bitmap
. This piece of code is based on the code from CyanogenMod's camera app so I would assume it would work properly but nope. The most important thing about this issue is that when tested on a Nexus 4 the Bitmap
was being created properly for pictures taken with the back facing camera but using the front facing camera resulted in what you can see below.
The code that I'm using to create the Bitmap
:
private class XyzPictureCallback implements Camera.PictureCallback {
@Override
public void onPictureTaken (byte [] data, Camera camera) {
Options options = new Options();
options.inDither = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap image = BitmapFactory.decodeByteArray(data, 0, data.length, options);
}
}
I tried using different Options
(and none at all) but it did not help. It might be something with the pixel format returned by the two different cameras but when I ran getSupportedPictureFormats()
they both returned ImageFormat.JPEG
...
I'm running out of ideas...
I should probably also mention that saving the data
directly using a FileOutputStream
was creating a proper JPEG image. So the problem must be with the BitmapFactory
and the way I create the Bitmap
.
This is the bitmap that this code produces:
EDIT (24.03.2013):
After spending multiple hours trying to fix this I still have no real solution to this.
All i've found out is that the problem only occurs when I set the picture size (using Camera.Parameters.setPictureSize(int width, int height)
) to the highest possible resolution that is available to the front facing camera which I've obtained by calling Camera.Parameters.getSupportedPictureSizes()
.
The resolution that is causing the problem is 1280x960. As I've mentioned earlier it's the highest resolution. The second highest is 1280x720 and when I use this one the output picture is fine. I did check the format that the camera spits out and it's ImageFormat.JPEG all the time so i don't think the pixel format is the issue here...
EDIT (08.03.2013): Call to takePicture:
private class XyzAutoFocusCallback implements Camera.AutoFocusCallback {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (takingPicture) {
camera.takePicture(null, null, myPictureCallback);
} else {
...
}
}
Upvotes: 14
Views: 7794
Reputation: 15
This is my code, that i use to take pictures, and save them in a database, without changing its quality.
First you need this variables:
private static final int CAMERA_PIC_REQUEST = 2500;
private Rect Padding = new Rect(-1,-1,-1,-1);
private Matrix matrix = new Matrix();
private Bitmap rotatedBitmap = null;
private Bitmap bm = null;
private Bitmap scaledBitmap= null;
private ExifInterface exif ;
private int rotation=0;
private final BitmapFactory.Options options = new BitmapFactory.Options();
Then set the request, from a button, activity or fragment, depending on your app (Mine uses a button)
btn_camera.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);
}
}
);
Now as I am requesting the CAMERA _PIC_REQUEST from a Fragment i implement this code on the OnActivityResult()
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_PIC_REQUEST)
if (data != null) {
imageuri = data.getData();
//Bitmap image = (Bitmap) data.getExtras().get("data");
try {
options.inSampleSize = 2;
exif = new ExifInterface(getRealPathFromURI(imageuri));
rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
rotation = exifToDegrees(rotation);
bm = BitmapFactory.decodeStream(
getActivity().getContentResolver().openInputStream(imageuri),Padding,options);
scaledBitmap = Bitmap.createScaledBitmap(bm, 400,400, true);
if (rotation != 0)
{matrix.postRotate(rotation);}
//matrix.postRotate(180);
rotatedBitmap = Bitmap.createBitmap(scaledBitmap , 0, 0, scaledBitmap .getWidth(), scaledBitmap .getHeight(), matrix, true);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mIvFoto.setImageBitmap(rotatedBitmap);
}
}
The rotation and the matrix are for scaling the pic taken, to an ImageView, so i can take a preview of the photo, before saving it. That doesn't affect the quality of the pic. It's just for the preview bitmap. So in the ScaledBitmap variable as you can see, when CreatingScaledBitmap, i place the dimensions of the pic, to 400,400 you can place the dimensions of the pic you want you get, be sure to rotate the bitmap, so you can get the picture right, even if you take the photo in portrait mode.
Finally the methods for rotating and getting the picture from the Path that the camera saves it.
private static int exifToDegrees(int exifOrientation) {
if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) { return 90; }
else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) { return 180; }
else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) { return 270; }
return 0;
}
private String getRealPathFromURI(Uri contentURI) {
String result;
Cursor cursor =getActivity().getContentResolver().query(contentURI, null, null, null, null);
if (cursor == null) { // Source is Dropbox or other similar local file path
result = contentURI.getPath();
} else {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
result = cursor.getString(idx);
cursor.close();
}
return result;
}
I hope this may help you.
Upvotes: 0
Reputation: 29436
I should probably also mention that saving the data directly using a FileOutputStream was creating a proper JPEG image. So the problem must be with the BitmapFactory and the way I create the Bitmap.
Camera outputs fully processed JPEG data (hopefully), and you can write it to disk. Now what you should try:
BitmapFactory
process the original file and file saved by Image editor, see if you get a bad bitmap in both. If image is valid JPEG and BitmapFactory
still produces wrong Bitmap, the problem is with BitmapFactory
(less likely), if file output by Camera is invalid JPEG, problem is with Camera (more likely).
Upvotes: 0
Reputation: 16255
Are you setting the parameters from the back camera to the front camera? Another thing to test is for the front camera, first try not setting any parameter, just use the default settings to see if it will work. I ran into similar problems on Samsung devices but that was for back camera. Also you may need to rotate the images taken with front camera(for Samsung devices back camera needs that too)
public static Bitmap rotate(Bitmap bitmap, int degree) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix mtx = new Matrix();
mtx.postRotate(degree);
return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
}
Upvotes: 0
Reputation: 2821
I would suggest not setting the picture size in code and let the camera return the best picture it can capture. Check the code given in the answer here. https://stackoverflow.com/a/9745780/2107118
Upvotes: 0
Reputation: 4751
The height and width aren't supported for that camera. That's why it looks like that and why the 1280x720 setting works. It's the same as if you set your starcraft to run at a resolution not supported by your monitor.
Upvotes: 3
Reputation: 7156
Did you try to put null at your Options? Try that:
@Override
public void onPictureTaken(final byte[] data, Camera camera) {
Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length, null);
try {
FileOutputStream out = new FileOutputStream(Environment.getExternalStorageDirectory().getAbsolutePath()+"/image.jpg");
bm.compress(Bitmap.CompressFormat.JPEG, 95, out);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Upvotes: 0
Reputation: 446
Try this
Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
imv.setImageBitmap(bmp);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bmp.compress(CompressFormat.JPEG, 70, bos);
Upvotes: 0