Android: taking photo in portrait mode and rotating it - android

I've been fighting with this problem for a while. My camera activity is locked to portrait mode and due to other features on it - it must be portrait mode. After I take photo with my Camera and displays it it appears rotated. I found solution to handle this problem but it takes too much memory of weaker devices so after clicking "take photo" button I have to wait around 8 sec till it goes to next activity (PREVIEW ACTIVITY) while on my own Nexus 4 it works without lags and starts instantly. My current code looks like that:
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile();
if (pictureFile == null){
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d("ABC", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("ABC", "Error accessing file: " + e.getMessage());
}
Bitmap bitmap = BitmapFactory.decodeFile(pictureFile.getAbsolutePath());
Matrix matrix = new Matrix();
if (currentCamera == BACK_CAMERA) {
matrix.postRotate(90);
} else {
matrix.postRotate(270);
matrix.preScale(1.0f, -1.0f);
}
Bitmap result = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
try {
FileOutputStream outStream = new FileOutputStream(pictureFile);
result.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
} catch (FileNotFoundException e) {
Log.d("ABC", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("ABC", "Error accessing file: " + e.getMessage());
}
takenPhotoURL= pictureFile.getAbsolutePath();
Intent intent = new Intent(CameraActivity.this, PreviewActivity.class);
intent.putExtra("PhotoURI",takenPhotoURL);
intent.putExtra("voteID",voteId);
CameraActivity.this.startActivity(intent);
}
getOutputMediaFile is a method that generates directory in my device where photo should be saved. (I'm not adding photo to gallery yet). When you analyse the code I've posted above you can see that im using FileOutputStream twice. First time I just save photo in phone memory, second time I open it again, write it on rotated matrix and flush it. I think using FileOutputStream, saving -> opening -> saving -> closing -> opening -> saving - closing is slowing weaker devices. I would like to modify this metod somehow to make it more efficient. Please help me with that.
What I have tried till now is trying to delete first FileOutputStream and make everything at once like that:
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile();
if (pictureFile == null){
return;
}
try {
FileOutputStream outStream = new FileOutputStream(pictureFile);
outStream.write(data);
Bitmap bitmap = BitmapFactory.decodeFile(pictureFile.getAbsolutePath());
Matrix matrix = new Matrix();
if (currentCamera == BACK_CAMERA) {
matrix.postRotate(90);
} else {
matrix.postRotate(270);
matrix.preScale(1.0f, -1.0f);
}
Bitmap result = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
result.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
} catch (FileNotFoundException e) {
Log.d("ABC", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("ABC", "Error accessing file: " + e.getMessage());
}
takenPhotoURL= pictureFile.getAbsolutePath();
Intent intent = new Intent(CameraActivity.this, PreviewActivity.class);
intent.putExtra("PhotoURI",takenPhotoURL);
intent.putExtra("voteID",voteId);
CameraActivity.this.startActivity(intent);
}
but it doesnt work. Photo is displayed without any changes (nothing happens). And I've tried also Exif but it didn't have effect. Please help me make it more efficient and faster.

Related

takePicture() landscape mode rotation android

I am taking an image from camera using:
mCamera.takePicture(null, null,
new PhotoHandler(getApplicationContext()));
But the image I am taking is landscape and I want it portrait, I tried converting the file into bitmap, rotate it and then save it again, here is my onPictureTaken() function and rotate() function inside PhotoHandler.class:
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFileDir = getDir();
if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {
Log.d("Error", "Can't create directory to save image.");
Toast.makeText(context, "Can't create directory to save image.",
Toast.LENGTH_LONG).show();
return;
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
String date = dateFormat.format(new Date());
String photoFile = "Picture_" + date + ".jpg";
String filename = pictureFileDir.getPath() + File.separator + photoFile;
pictureFile = new File(filename);
st1 = pictureFile.getAbsolutePath();
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
Toast.makeText(context, "New Image saved:" + photoFile,
Toast.LENGTH_LONG).show();
} catch (Exception error) {
Log.d("Error", "File" + filename + "not saved: "
+ error.getMessage());
Toast.makeText(context, "Image could not be saved.",
Toast.LENGTH_LONG).show();
}
Bitmap b = rotate(BitmapFactory.decodeFile(pictureFile.getAbsolutePath()),270);
FileOutputStream out = null;
try {
out = new FileOutputStream(pictureFile);
b.compress(Bitmap.CompressFormat.PNG, 100, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
CameraPreview.safeToTakePicture = true;
galleryAddPic();
}
public static Bitmap rotate(Bitmap bitmap, int degree) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix mtx = new Matrix();
mtx.setRotate(degree);
return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
}
Anyway, it takes too long, I tried using mCamera.setDisplayOrientation(90); but it changes only the preview of the camera, the picture taken is still the same, I also tried getting the parameters of the camera and changing it like here:
Camera.Parameters parameters = mCamera.getParameters();
parameters.set("orientation", "portrait");
mCamera.setParameters(parameters);
Without success, any help will be appreciated.
EDIT :
New code:
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFileDir = getDir();
if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {
Log.d("Error", "Can't create directory to save image.");
Toast.makeText(context, "Can't create directory to save image.",
Toast.LENGTH_LONG).show();
return;
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
String date = dateFormat.format(new Date());
String photoFile = "Picture_" + date + ".jpg";
String filename = pictureFileDir.getPath() + File.separator + photoFile;
pictureFile = new File(filename);
st1 = pictureFile.getAbsolutePath();
Bitmap b = rotate(BitmapFactory.decodeByteArray(data,0,data.length),270);
FileOutputStream out = null;
try {
out = new FileOutputStream(pictureFile);
b.compress(Bitmap.CompressFormat.PNG, 100, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
CameraPreview.safeToTakePicture = true;
galleryAddPic();
}
Anyway, it takes too long
Your current algorithm looks like this:
Start with the photo in memory
Save the photo to disk, which is slow
Read the photo back in from disk to memory, which is slow
Rotate the reloaded photo
A more efficient approach would be:
Start with the photo in memory
Rotate the photo
BitmapFactory has decodeByteArray() to get a Bitmap back for rotation purposes.

How to increase JPG file size in same resolution?

I can capturing, cropping, resizing and saving photos. Saving photos with same resolution (133x171). I need this resolution and greather than 20KB jpeg file size.
Sometimes it capture smaller than 20KB. I want to save all photos greather than 20KB.
JPEG Quality: 100
StartPreview Codes
public void surfaceCreated(SurfaceHolder holder) {
setWillNotDraw(false);
Log.d("Variable", "surfaceCreated");
try {
mCamera.setPreviewDisplay(holder);
Camera.Parameters parameters = mCamera.getParameters();
if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
parameters.set("orientation", "portrait");
mCamera.setDisplayOrientation(90);
}
parameters.set("jpeg-quality", 100);
mCamera.setParameters(parameters);
mCamera.startPreview();
} catch (IOException e) {
Log.d("Method.surfaceCreated", "Error setting camera preview: " + e.getMessage());
}
}
PictureTaken method:
#Override
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
/*Bitmap bitmapPicture = BitmapFactory.decodeByteArray(arg0, 0, arg0.length); */
File pictureFile = getOutputMediaFile();
if (pictureFile == null){
Log.d("Method.PictureCall", "Error creating media file, check storage permissions: ");
return;
}
data = cropImage(data);
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
Toast.makeText(c, "saved: " + pictureFile.toString(), Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
Log.d("Method.PictureCallBack", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("Method.PictureCallBack", "Error accessing file: " + e.getMessage());
}
camera.startPreview();
}
cropImage Method:
public byte[] cropImage (byte[] data) {
Point start_xy = getCaptureStartPoint();
Point cropRes = getCaptureResolution();
int stride = cropRes.x;
int[] pixels = new int[cropRes.x * cropRes.y];
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Bitmap bitmap = BitmapFactory.decodeByteArray(data , 0, data.length);
bitmap = rotateBitmap(bitmap, 90);
bitmap.getPixels(pixels, 0, stride, start_xy.x, start_xy.y, cropRes.x, cropRes.y);
bitmap = Bitmap.createBitmap(pixels, 0, stride, cropRes.x, cropRes.y, Config.ARGB_8888);
bitmap = Bitmap.createScaledBitmap(bitmap, efoto_x, efoto_y, false);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
return bos.toByteArray();
}
UPDATE #1:
Perhaps this isn't best way. But I tried. After write picture file to storage adding some EXIF data to image with this method.
private void addEXIFData(final File f) throws IOException {
ExifInterface exif = new ExifInterface(f.getAbsolutePath());
exif.setAttribute(ExifInterface.TAG_MAKE, "Photo Photo Photo Photo........ bla bla blaaaaa");
exif.setAttribute(ExifInterface.TAG_MODEL, "Photo Photo Photo Photo........ bla bla blaaaaa");
exif.setAttribute(ExifInterface.TAG_ORIENTATION, "90");
exif.setAttribute(ExifInterface.TAG_IMAGE_WIDTH, "150");
exif.saveAttributes();
}

Picture taken on portrait mode is saved rotated counter clockwise?

I'm building a camera app, I'm requesting the camera instance this way and the preview is shown in the right angle:
c = Camera.open();
c.setDisplayOrientation(90);
However after the user takes a photo and loading it into an imageView it's rotated 90 degrees counter clockwise. This is how I save the photo:
#Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
String filePath = folderPath + generateFileName();
FileOutputStream outStream = new FileOutputStream( filePath );
outStream.write(data);
outStream.close();
// Put into imageView
File file = new File(filePath);
if(file.exists()){
Bitmap myBitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
last_photo.setImageBitmap(myBitmap);
}
} catch (FileNotFoundException e) {
} catch (IOException e) {
} finally {
}
}
How can I save the image without it being rotated?
I think you want to use setRotation() instead, or in addition to, setDisplayOrientation(). That method is described here

Parse.com File saving Android not working

I modeled my code after their Mealspotting tutorial but for some reason, I can't see the file saved in the Data Browser. Why is that? Here is my code:
private void saveScaledPhoto(byte[] data) {
// Resize photo from camera byte array
Bitmap snypImage = BitmapFactory.decodeByteArray(data, 0, data.length);
Bitmap snypImageScaled = Bitmap.createScaledBitmap(snypImage, 200, 200
* snypImage.getHeight() / snypImage.getWidth(), false);
// Override Android default landscape orientation and save portrait
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotatedScaledMealImage = Bitmap.createBitmap(snypImageScaled, 0,
0, snypImageScaled.getWidth(), snypImageScaled.getHeight(),
matrix, true);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
rotatedScaledMealImage.compress(Bitmap.CompressFormat.JPEG, 100, bos);
byte[] scaledData = bos.toByteArray();
// Save the scaled image to Parse
photoFile = new ParseFile("snyp.jpg", scaledData);
photoFile.saveInBackground(new SaveCallback() {
public void done(ParseException e) {
if (e == null) {
ParseUser.getCurrentUser().put("photo",photoFile);
Log.d("save status",photoFile.getName() + " is saved!");
} else {
Toast.makeText(getActivity(),
"Error saving: " + e.getMessage(),
Toast.LENGTH_LONG).show();
}
}
});
}
You are just forgetting to save your User object: ParseUser.getCurrentUser().saveEventually();

Camera image is not saving in sdcard and does not display in imageview in front camera in android

I am using the front camera to take a picture and display it in image view, but the image is not captured using frontface camera in samsung galaxy tab. Can anybody tell what the problem is? Even I had given set picture format. I used getoptimalpreview size for preview size. Can anybody tell me if I missed anything? Preview is showing properly but clicking 'take picture' background is black
mCamera = Camera.open();
Parameters params = mCamera.getParameters();
params.set("camera-id", 2);
params.setPictureFormat(PixelFormat.JPEG);
saving and setting display in imageview
public void onPictureTaken(byte[] data, Camera camera)
{
Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
imv.setImageBitmap(bmp);
String filename = "vijaypicture.jpg";
File pictureFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + filename);
try
{
FileOutputStream pfos = new FileOutputStream(pictureFile);
bmp.compress(CompressFormat.JPEG, 75, pfos);
pfos.flush();
pfos.close();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
PictureCallback jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(String.format(
"/sdcard/test/%d.jpg", System.currentTimeMillis()));
outStream.write(data);
outStream.close();
Log.d("", "onPictureTaken - wrote bytes: " + data.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
Log.d("", "onPictureTaken - jpeg");
}
Hope that this helps, make manualy create a folder or use the mkdir command in your code to create the folder, and build a check if it already excists

Categories

Resources