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
Related
I capture image from my cam and create bitmap and pass the path to ExifInterface to determine the rotation, since the cam captured image is rotated 90 degrees all the time. But this below code always shows value 0 which corresponds to ORIENTATION_UNDEFINED rotation type.
It is any other way to determine rotation or I am doing something wrong here ?
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File photoFile = null;
try {
photoFile = Utils.createImageFile(getContext());
String authorities = context.getPackageName() + ".fileprovider";
uriForFile = FileProvider.getUriForFile(context, authorities, photoFile);
} catch (IOException e) {
e.printStackTrace();
}
Log.d(TAG, "handleCaptureImage: " + uriForFile);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uriForFile);
startActivityForResult(intent, CAPTURE_IMAGE);
if (requestCode == CAPTURE_IMAGE) {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), uriForFile);
saveBitmap(bitmap);
}
public static File saveBitmap(Bitmap bitmap) {
File file = null;
String imageFileName = "JPEG_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + ".jpg";
String path = App.getAppContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath() + imageFileName;
if (bitmap != null) {
file = new File(path);
try {
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(path);
//this bitmap is rotated when I observe in debug mode.
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
ExifInterface exifInterface = new ExifInterface(path);
//still always returns 0 I expect 6 which is for 90 degrees
Log.d(TAG, "saveBitmap: "+exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL));
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
return file;
}
I capture image from my cam
I am going to guess that this is from ACTION_IMAGE_CAPTURE, given that your code references a requestCode.
In that case, what you have:
Reads in the image from a file
Saves the image again to another file, wiping out the EXIF headers along the way
You don't need any of that.
You know where the image is, as you (presumably) supplied a location via EXTRA_OUTPUT in your ACTION_IMAGE_CAPTURE request. So, use ExifInterface to read from that location. Get rid of the bitmap stuff, in particular writing the bitmap back out. A JPEG file may have EXIF headers. A Bitmap does not, and a JPEG file created from a Bitmap does not (unless you add them yourself).
in my app I take a picture and save it in specified way. My phone is Nexus 4 and the camera is very strong and every picture is about 2.31MB how can I save picture for example in 60KB?
Can I do it with code? and how?
File newdir = new File(dir);
if(!newdir.exists()){
newdir.mkdirs();
}
picturesCount++;
String file = dir+picturesCount+".jpg";
imagePath = file;
File newfile = new File(file);
try {
newfile.createNewFile();
} catch (IOException e) {}
Uri outputFileUri = Uri.fromFile(newfile);
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cameraIntent, TAKE_PHOTO_CODE);
When you are using camera and picture is taken, you can perform the task in the method below to reduce the quality of the image and type like JPEG or PNG (PNG takes more space than JPEG) so just play with the value (60 current out of 100) and see the difference in size.
#Override
public void onPictureTaken(byte[] data, Camera camera) {
InputStream in = new ByteArrayInputStream(data);
BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap preview_bitmap = BitmapFactory.decodeStream(in, null, options);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
preview_bitmap.compress(Bitmap.CompressFormat.JPEG, 60, stream);
byte[] byteArray = stream.toByteArray();
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(new File(
Environment.getExternalStorageDirectory(), "Image1.jpg"));
outStream.write(byteArray);
outStream.close();
} catch (FileNotFoundException e) {
Log.d("CAMERA", e.getMessage());
} catch (IOException e) {
Log.d("CAMERA", e.getMessage());
}
}
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.
When I take a picture with my Android camera, there is an image (imageview3) on my screen that I want to save with my picture.
Here is my onPictureTaken method
public void onPictureTaken(byte[] data, Camera camera) {
File imagesFolder = new File(Environment.getExternalStorageDirectory(), "/Ker");
imagesFolder.mkdirs();
String fileName = "Ker_.jpg";
output = new File(imagesFolder, fileName);
ImageView view = (ImageView) gameactivity.findViewById(R.id.imageView3);
view.setDrawingCacheEnabled(true);
Bitmap b = view.getDrawingCache();
FileOutputStream fos = null;
try {
fos = new FileOutputStream(output);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
b.compress(CompressFormat.JPEG, 95, fos);
try {
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
camera.stopPreview();
}
When I open the folder, the picture saved is only the imageview3 with a black background. Why has the real camera view not been saved?
EDIT
I'm trying something with canvas too:
output = new File(imagesFolder, fileName);
ImageView view = (ImageView) gameactivity.findViewById(R.id.imageView3);
view.setDrawingCacheEnabled(true);
Bitmap b = view.getDrawingCache();
FileOutputStream fos = null;
try {
fos = new FileOutputStream(output);
fos.write(data);
fos.close();
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
FileOutputStream fos2 = null;
b.compress(CompressFormat.JPEG, 95, fos2);
try {
Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fos.getFD());
Bitmap bitmap2 = BitmapFactory.decodeFileDescriptor(fos2.getFD());
Canvas canvas = new Canvas(bitmap);
canvas.drawBitmap(bitmap2, null, null);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Is that correct? How to save the canvas into a file on my sdcard (ie write data from canvas on fileoutputstream)
You're appending the JPEG of the imageview and the JPEG from the camera into a single file.
Create a separate file output stream for each file, and write the data from Bitmap.compress() and the onPictureTaken data array into their own streams.
If you want the two images to be combined into a single image, you'll need to decode the data array into a Bitmap, and then use a Canvas to draw the ImageView bitmap and the camera-captured Bitmap onto the canvas in the arrangement you want, and then save that out as a single jpeg.
You can't simply concatenate two compressed JPEG bitstreams together; the file format doesn't work that way.
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