I have an issue when saving images in my application. I am using Android camera api 1 (pre api 21) on android version 4.4.4. Device is a OnePlus One.
When I take a picture my in-built camera in my app in seems to save the images in poor quality and also rotated 90 degrees counter-clockwise (-90).
Here is an example with images.
Portrait view with default android camera app (saved image):
Portrait view with in-built app camera:
Picture when saved with in-built app camera (saved image):
First problem, rotation orientation
Now the rotation I am guessing is due to this (if I don't change the setDisplayOrientation the camera is skewed in my app):
public void refreshCamera(Camera camera) {
if (holder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
camera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
int rotation = ((WindowManager)activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
int degrees = 0;
// specifically for back facing camera
switch (rotation) {
case Surface.ROTATION_0:
degrees = 90;
break;
case Surface.ROTATION_90:
degrees = 0;
break;
case Surface.ROTATION_180:
degrees = 270;
break;
case Surface.ROTATION_270:
degrees = 180;
break;
}
camera.setDisplayOrientation(degrees);
setCamera(camera);
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
} catch (Exception e) {
Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
}
}
To fix this I guess I could rotate the images when I have saved the image, seems like a waste of code writing such a method though.
Second problem, the quality
This I am clueless as to why the quality is so bad, I'm guessing it has to do with this:
private PictureCallback getPictureCallback() {
return new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// save picture on seperate thread so camera can refresh quicker
new Thread(new SavePicThread(data)).start();
// refresh camera to continue preview
cameraPreview.refreshCamera(camera);
}
};
}
public class SavePicThread implements Runnable {
byte[] data;
public SavePicThread(byte[] data) {
this.data = data;
}
public void run() {
// make a new picture file
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
return;
}
try {
// write to the file
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.flush();
fos.close();
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Toast toast = Toast.makeText(getActivity(), "Picture saved", Toast.LENGTH_SHORT);
toast.show();
}
});
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// make the picture visible to the rest of the device
galleryAddPic(pictureFile);
}
}
// make picture and save to a folder
private File getOutputMediaFile() {
// make a new file directory inside the "sdcard" folder
// File mediaStorageDir = new File("/sdcard/", "fela"); // private pic for app
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "fela");
// if the directory does not exist
if (!mediaStorageDir.exists()) {
// if you cannot make this directory return
if (!mediaStorageDir.mkdirs()) {
return null;
}
}
// take the current timeStamp
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
// and make a media file:
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
return mediaFile;
}
/**
* makes the image visible for the device (gallery)
* @param pic file
*/
private void galleryAddPic(File file) {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(file);
mediaScanIntent.setData(contentUri);
getActivity().sendBroadcast(mediaScanIntent);
}
Been looking at tutorials, this is pretty much what they cover!