I want exactly the functionality of Camera (Like Single and Batch(Multiple Photos at a time)) in the following app:
https://play.google.com/store/apps/details?id=com.thegrizzlylabs.geniusscan.free&hl=en
I have implemented Successfully this. But, my question is, I have implemented this functionality with SurfaceView. When I capture photos from camera, its blurred when compared to the Genius Scan App.
Could anyone please let me know how exactly i can achieve this functionality without getting blurred.
NOTE: Capturing Multiple Photos
private void takeImage() {
camera.takePicture(null, null, new PictureCallback() {
private File imageFile;
#Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
// convert byte array into bitmap
Bitmap loadedImage = null;
Bitmap rotatedBitmap = null;
loadedImage = BitmapFactory.decodeByteArray(data, 0,
data.length);
// rotate Image
Matrix rotateMatrix = new Matrix();
rotateMatrix.postRotate(rotation);
rotatedBitmap = Bitmap.createBitmap(loadedImage, 0, 0,
loadedImage.getWidth(), loadedImage.getHeight(),
rotateMatrix, false);
String state = Environment.getExternalStorageState();
File folder = null;
if (state.contains(Environment.MEDIA_MOUNTED)) {
folder = new File(Environment
.getExternalStorageDirectory() + "/Demo");
} else {
folder = new File(Environment
.getExternalStorageDirectory() + "/Demo");
}
boolean success = true;
if (!folder.exists()) {
success = folder.mkdirs();
}
if (success) {
java.util.Date date = new java.util.Date();
imageFile = new File(folder.getAbsolutePath()
+ File.separator
+ new Timestamp(date.getTime()).toString()
+ "Image.jpg");
imageFile.createNewFile();
} else {
Toast.makeText(getBaseContext(), "Image Not saved",
Toast.LENGTH_SHORT).show();
return;
}
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
// save image into gallery
rotatedBitmap.compress(CompressFormat.JPEG, 100, ostream);
FileOutputStream fout = new FileOutputStream(imageFile);
fout.write(ostream.toByteArray());
fout.close();
ContentValues values = new ContentValues();
values.put(Images.Media.DATE_TAKEN,
System.currentTimeMillis());
values.put(Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.MediaColumns.DATA,
imageFile.getAbsolutePath());
CameraDemoActivity.this.getContentResolver().insert(
Images.Media.EXTERNAL_CONTENT_URI, values);
if (mSingleView.getVisibility() == View.VISIBLE) {
btnDoneClicked();
} else {
}
mArrayUri.add(Uri.fromFile(imageFile));
if (mBatchView.getVisibility() == View.VISIBLE) {
batchClickCount++;
mtxtCapturedClicks.setText(String.valueOf(batchClickCount));
} else {
batchClickCount = 0;
mtxtCapturedClicks.setText("");
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public static Bitmap scaleBitmap(Bitmap bitmap, int newWidth, int newHeight) {
Bitmap scaledBitmap = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);
float scaleX = newWidth / (float) bitmap.getWidth();
float scaleY = newHeight / (float) bitmap.getHeight();
float pivotX = 0;
float pivotY = 0;
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(scaleX, scaleY, pivotX, pivotY);
Canvas canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bitmap, 0, 0, new Paint(Paint.FILTER_BITMAP_FLAG));
return scaledBitmap;
}
Try this function to improve the image quality
Related
I am using Camera in my app to take pictures of ID cards, I have a rectangular overlay to which image will be cropped. issue is that the image quality is reduced once the image is captured.
I am unable to figure out where exactly it is happening. In cutImage method, I am cutting the image but I don't think I am doing anything to the resolution of the image there.
Can any one suggest where the quality might be going down.
takePicture is called when the user clicks to take the picture.
Once the picture is taken there is a button 'use picture' that is when usePicture is called.
cutImage method is used to crop the image based on the preview.
any suggestions on how to stop the resolution from going down will be very very helpful
protected void takePicture() {
Log.e(TAG, "takePicture started");
if(null == cameraDevice) {
Log.e(TAG, "cameraDevice is null");
return;
}
try {
ImageReader reader = ImageReader.newInstance(textureViewWidth, textureViewHeight, ImageFormat.JPEG, 1);
List<Surface> outputSurfaces = new ArrayList<Surface>(2);
outputSurfaces.add(reader.getSurface());
outputSurfaces.add(new Surface(textureView.getSurfaceTexture()));
final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(reader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
// Orientation
int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
Image image = null;
try {
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
takenPictureBytes = bytes;
Log.d(TAG, "takenPictureBytes length - " + takenPictureBytes.length);
} catch (Exception e) {
Log.d(TAG, " onImageAvailable exception ");
e.printStackTrace();
} finally {
if (image != null) {
Log.d(TAG, " image closing");
image.close();
}
}
}
};
reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);
final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Log.d(TAG, "takePicture - camera capture session");
switchPanels(true);
progress.setVisibility(View.GONE);
}
};
cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(CameraCaptureSession session) {
try {
session.capture(captureBuilder.build(), captureListener, mBackgroundHandler);
} catch (CameraAccessException e) {
Log.d(TAG, "takePicture - onConfigured- camera access exception ");
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(CameraCaptureSession session) {
Log.d(TAG, "takePicture - onConfigureFailed");
}
}, mBackgroundHandler);
} catch (CameraAccessException e) {
Log.d(TAG, "takePicture - CameraAccessException ");
e.printStackTrace();
}
}
private void usePicture() {
Log.d(TAG, "usePicture - started ");
if(null != takenPictureBytes ){
try{
String imagePath = null;
Bitmap bitmap = BitmapFactory.decodeByteArray(takenPictureBytes, 0, takenPictureBytes.length);
int bitmapByteCountUsePic = byteSizeOf(bitmap);
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
if (isFrameMode) {
float withRatio = (float) rotatedBitmap.getWidth() / (float) textureViewWidth;
float heightRatio = (float) rotatedBitmap.getHeight() / (float) textureViewHeight;
Bitmap newImage = cutImage(rotatedBitmap, (int) (photoFrameView.getWidth() * withRatio), (int) (photoFrameView.getHeight() * heightRatio), withRatio);
int bitmapByteCountNewImage = byteSizeOf(newImage);
imagePath = saveBitmap(newImage);
} else {
imagePath = saveBitmap(rotatedBitmap);
}
TakePhotoFragment.TakePhotoFragmentEvent takePhotoFragmentEvent = new TakePhotoFragment.TakePhotoFragmentEvent();
takePhotoFragmentEvent.setImagePath(imagePath);
// send rxjava
//pop backstack
RxBus.getInstance().post(takePhotoFragmentEvent);
getActivity().getSupportFragmentManager().popBackStack();
}catch (Exception e){
Log.d(TAG, "usePicture - exception ");
e.printStackTrace();
}
}else{
Log.d(TAG, "usePicture - takenPictureBytes is null");
DialogUtil.showErrorSnackBar(getView(), R.string.retake_photo );
}
}
public Bitmap cutImage(final Bitmap bitmap, final int pixepWidth, final int pixelsHeight, float widthRatio) {
int bitmapByteCountCutImage = byteSizeOf(bitmap);
Bitmap output = createBitmap(pixepWidth, pixelsHeight, Bitmap.Config.ARGB_8888);
Bitmap original = bitmap;
final Paint paint = new Paint();
Canvas canvas = new Canvas(output);
int padding = (int) ((float) getResources().getDimensionPixelSize(R.dimen.double_padding) * widthRatio);
Rect rect = new Rect(padding, (original.getHeight() - pixelsHeight) / 2, padding + pixepWidth, original.getHeight() - (original.getHeight() - pixelsHeight) / 2);
final RectF cutedRect = new RectF(0, 0, pixepWidth, pixelsHeight);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
canvas.drawBitmap(original, rect, cutedRect, paint);
return output;
}
private String saveBitmap(Bitmap bitmap) {
File pictureFileDir = getDir();
if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {
Toast.makeText(getActivity(), "Can't create directory to save image.", Toast.LENGTH_LONG).show();
return null;
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmssSSS");
String date = dateFormat.format(new Date());
String photoFile = "Picture_" + date + ".jpg";
String filename = pictureFileDir.getPath() + File.separator + photoFile;
File pictureFile = new File(filename);
try {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(stream.toByteArray());
fos.close();
return pictureFile.getAbsolutePath();
} catch (Exception error) {
Log.d(TAG, "File" + filename + "not saved: " + error.getMessage());
}
return null;
}
You are changing the bitmap size/resolution in this code:
float withRatio = (float) rotatedBitmap.getWidth() / (float) textureViewWidth;
float heightRatio = (float) rotatedBitmap.getHeight() / (float) textureViewHeight;
Bitmap newImage = cutImage(rotatedBitmap, (int) (photoFrameView.getWidth() * withRatio), (int) (photoFrameView.getHeight() * heightRatio), withRatio);
int bitmapByteCountNewImage = byteSizeOf(newImage);
imagePath = saveBitmap(newImage);
Put in a breakpoint and see what the new heightRatio and widthRatio are, and what the photoFrameView.getWidth() * withRatio value comes out to. I think you will find it is small compared to the original image. I'm not sure why you are calculating the Ratios with the textureViewWidth/Height, you shouldn't have to do that. Whatever you are displaying the image in should be able to 'Fill' without having to change the size of the underlying bitmap, and thus losing resolution.
You might check out this method:
rawBitmap = ((BitmapDrawable)imageToLoad.getDrawable()).getBitmap();
theBitmap = Bitmap.createScaledBitmap(rawBitmap, 285, 313, false);
Hello i am resizing the image after capturing from native camera.. image resizing is working fine but i have only one problem and that is the image is getting skewed after resizing.
here is the code that i am using to resize the image.
File f = new File(Environment.getExternalStorageDirectory() + File.separator + "Bavel/" + imageName);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(f);
if (orientation == ExifInterface.ORIENTATION_UNDEFINED) {
saveByteArray(fos, getBytesFromBitmap(loadedImage));
} else {
saveByteArrayWithOrientation(fos, getBytesFromBitmap(loadedImage), orientation);
}
} catch (FileNotFoundException e) {
Log.e("Error", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.e("Error", "File write failure: " + e.getMessage());
}
private void saveByteArray(FileOutputStream fos, byte[] data) throws IOException {
long time = System.currentTimeMillis();
fos.write(data);
Log.e("saveByteArray: %1dms", "" + (System.currentTimeMillis() - time));
}
private void saveByteArrayWithOrientation(FileOutputStream fos, byte[] data, int orientation) {
long totalTime = System.currentTimeMillis();
long time = System.currentTimeMillis();
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Log.e("decodeByteArray: %1dms", "" + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
if (orientation != 0 && bitmap.getWidth() > bitmap.getHeight()) {
Matrix matrix = new Matrix();
matrix.postRotate(orientation);
int newWidth;
int newHeight;
if (bitmap.getWidth() > bitmap.getHeight()) {
newHeight = Helper.BITMAP_HEIGHT;
newWidth = Helper.BITMAP_HEIGHT * bitmap.getWidth() / bitmap.getHeight();
} else {
newWidth = Helper.BITMAP_HEIGHT;
newHeight = Helper.BITMAP_HEIGHT * bitmap.getHeight() / bitmap.getWidth();
}
bitmap = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, false);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
time = System.currentTimeMillis();
bitmap.compress(Bitmap.CompressFormat.JPEG, Helper.COMPRESS_QUALITY, fos);
Log.d("compress: %1dms", "" + (System.currentTimeMillis() - time));
Log.d("bitmap height ", "" + bitmap.getHeight());
Log.d("bitmap witdh ", "" + bitmap.getWidth());
bitmap.recycle();
Log.d("saveByte: %1dms", "" + (System.currentTimeMillis() - totalTime));
}
public byte[] getBytesFromBitmap(Bitmap bitmap) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, Helper.COMPRESS_QUALITY, stream);
return stream.toByteArray();
}
Here is the output after resizing the image
But i want the out put like this
Please help and thank for help in advance.
I have solved this by using below code. i am adding the answer so it might be helpful to someone else.
ExifInterface exif = new ExifInterface(imagePath);
final int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
File root = new File(Environment.getExternalStorageDirectory(), "/Bavel/");
if (!root.exists()) {
root.mkdirs();
}
File f = new File(Environment.getExternalStorageDirectory()
+ File.separator + "Bavel/" + imageName);
resizeNewImage(loadedImage, f, orientation);
private void resizeNewImage(Bitmap bm, File file, int orientation) {
try {
if (bm.getWidth() > bm.getHeight()) {
int newWidth;
int newHeight;
if (bm.getWidth() > bm.getHeight()) {
newHeight = Helper.BITMAP_HEIGHT;
newWidth = Helper.BITMAP_HEIGHT * bm.getWidth() / bm.getHeight();
} else {
newWidth = Helper.BITMAP_HEIGHT;
newHeight = Helper.BITMAP_HEIGHT * bm.getHeight() / bm.getWidth();
}
Matrix matrix = new Matrix();
switch (orientation) {
case ExifInterface.ORIENTATION_NORMAL:
matrix.postRotate(90);
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
matrix.setScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.setRotate(180);
break;
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
matrix.setRotate(180);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_TRANSPOSE:
matrix.setRotate(90);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.setRotate(90);
break;
case ExifInterface.ORIENTATION_TRANSVERSE:
matrix.setRotate(-90);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.setRotate(-90);
break;
default:
matrix.postRotate(90);
}
bm = Bitmap.createScaledBitmap(bm, newWidth, newHeight, true);
bm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
// file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.JPEG, Helper.COMPRESS_QUALITY, ostream);
ostream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Hello I am working on one android app where I need to capture the image using camera intent and set the bitmap in the imageview but here bitmap is rotated by 90 degree. I have checked many threads of stackoverflow like Photo rotate 90 degree while capture in some phones but did not work for me.
Here when I am executing this exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1); then it is returning 0 ORIENTATION_UNDEFINED and in my getImage function no condition is satisfying.
Intent cameraIntent = new Intent(
android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
capturedPhotoName = System.currentTimeMillis() + ".png";
File photo = new File(Environment.getExternalStorageDirectory(),
capturedPhotoName);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
imageUri = Uri.fromFile(photo);
startActivityForResult(cameraIntent, CAMERA_INTENT_REQUEST);
onActivityResult
Uri selectedImage = imageUri;
getContentResolver().notifyChange(selectedImage, null);
ContentResolver cr = getContentResolver();
Bitmap bitmap;
try {
bitmap = android.provider.MediaStore.Images.Media.getBitmap(cr,
selectedImage);
bitmap = Util.getImage(bitmap, selectedImage.toString());
mPictureImageView.setImageBitmap(bitmap);
} catch (Exception e) {
Log.e("New Issue Activity", e.toString());
}
/**
* Get the image orientation
*
* #param imagePath
* #return orietation angle
* #throws IOException
*/
public static Bitmap getImage(Bitmap bitmap, String path) throws IOException {
Matrix m = new Matrix();
ExifInterface exif = new ExifInterface(path);
int orientation = exif
.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
if ((orientation == ExifInterface.ORIENTATION_ROTATE_180)) {
m.postRotate(180);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), m, true);
return bitmap;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
m.postRotate(90);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), m, true);
return bitmap;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
m.postRotate(270);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), m, true);
return bitmap;
}
return bitmap;
}
I implemented one photo take activity which you can take the photo and set the orientation of the photo. It is supported by every device I tested including Samsung galaxy series, tablets, sony xperia series, tablets.
You can check out my accepted answer about rotation of images on this topic:
Camera capture orientation on samsung devices in android
If you also need to save and use that image that you have rotated, saving and using the photo functions additional to my answer I gave above:
savePhoto function:
public void savePhoto(Bitmap bmp) {
imageFileFolder = new File(Environment.getExternalStorageDirectory(),
cc.getDirectoryName());
imageFileFolder.mkdir();
FileOutputStream out = null;
Calendar c = Calendar.getInstance();
String date = fromInt(c.get(Calendar.MONTH))
+ fromInt(c.get(Calendar.DAY_OF_MONTH))
+ fromInt(c.get(Calendar.YEAR))
+ fromInt(c.get(Calendar.HOUR_OF_DAY))
+ fromInt(c.get(Calendar.MINUTE))
+ fromInt(c.get(Calendar.SECOND));
imageFileName = new File(imageFileFolder, date.toString() + ".jpg");
try {
out = new FileOutputStream(imageFileName);
bmp.compress(Bitmap.CompressFormat.JPEG, 70, out);
out.flush();
out.close();
scanPhoto(imageFileName.toString());
out = null;
} catch (Exception e) {
e.printStackTrace();
}
}
scanPhoto function:
public void scanPhoto(final String imageFileName) {
geniusPath = imageFileName;
msConn = new MediaScannerConnection(MyClass.this,
new MediaScannerConnectionClient() {
public void onMediaScannerConnected() {
msConn.scanFile(imageFileName, null);
}
#Override
public void onScanCompleted(String path, Uri uri) {
msConn.disconnect();
}
});
msConn.connect();
}
SavePhotoTask class:
class SavePhotoTask extends AsyncTask<byte[], String, String> {
#Override
protected String doInBackground(byte[]... jpeg) {
File photo = new File(Environment.getExternalStorageDirectory(),
"photo.jpg");
if (photo.exists()) {
photo.delete();
}
try {
FileOutputStream fos = new FileOutputStream(photo.getPath());
fos.write(jpeg[0]);
fos.close();
} catch (java.io.IOException e) {
}
return (null);
}
}
Try below code:-
Uri selectedImageURI = data.getData();
imageFile = new File(getRealPathFromURI(selectedImageURI));
ExifInterface exif = new ExifInterface(imageFile.toString());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
Bitmap bitmap = Utility.getOrientationFromExif(new Utility().compressImage1(imageFile.toString(),((Activity)context)),orientation);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG , 50 , bos);
Utility.java
public class Utility
{
public Bitmap compressImage1(String imageUri, Activity act)
{
String filePath = getRealPathFromURI(imageUri, act);
BitmapFactory.Options options = new BitmapFactory.Options();
// by setting this field as true, the actual bitmap pixels are not
// loaded in the memory. Just the bounds are loaded. If
// you try the use the bitmap here, you will get null.
options.inJustDecodeBounds = true;
// Bitmap bmp = decodeBitmap(Uri.parse(imageUri), 612, 816, act);
Bitmap bmp = BitmapFactory.decodeFile(filePath, options);
// setting inSampleSize value allows to load a scaled down version of
// the original image
options.inSampleSize = calculateInSampleSize(options, 612, 816);
// inJustDecodeBounds set to false to load the actual bitmap
options.inJustDecodeBounds = false;
// this options allow android to claim the bitmap memory if it runs low
// on memory
options.inPurgeable = true;
options.inInputShareable = true;
options.inTempStorage = new byte[16 * 1024];
// load the bitmap from its path
bmp = BitmapFactory.decodeFile(filePath, options);
return bmp;
}
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight)
{
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth)
{
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and
// keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth)
{
inSampleSize *= 2;
}
}
return inSampleSize;
}
public static Bitmap getOrientationFromExif(Bitmap bitmap, int orientation)
{
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int newWidth = 612;
int newHeight = 816;
// calculate the scale - in this case = 0.4f
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
switch (orientation)
{
case ExifInterface.ORIENTATION_NORMAL:
return bitmap;
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
// matrix.setScale(-1, 1);
matrix.postScale(scaleWidth, scaleHeight);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.setRotate(180);
break;
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
matrix.setRotate(180);
// matrix.postScale(-1, 1);
matrix.postScale(scaleWidth, scaleHeight);
break;
case ExifInterface.ORIENTATION_TRANSPOSE:
matrix.setRotate(90);
// matrix.postScale(-1, 1);
matrix.postScale(scaleWidth, scaleHeight);
break;
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.setRotate(90);
break;
case ExifInterface.ORIENTATION_TRANSVERSE:
matrix.setRotate(-90);
// matrix.postScale(-1, 1);
matrix.postScale(scaleWidth, scaleHeight);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.setRotate(-90);
break;
default:
return bitmap;
}
try
{
Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
bitmap.recycle();
return bmRotated;
}
catch (OutOfMemoryError e)
{
e.printStackTrace();
return null;
}
}
}
This function worked for me, try your luck.
public static Bitmap rotateImage(Bitmap bmp, String imageUrl) {
if (bmp != null) {
ExifInterface ei;
int orientation = 0;
try {
ei = new ExifInterface(imageUrl);
orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
} catch (IOException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
}
int bmpWidth = bmp.getWidth();
int bmpHeight = bmp.getHeight();
Matrix matrix = new Matrix();
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.postRotate(90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.postRotate(180);
break;
default:
break;
// etc.
}
Bitmap resizedBitmap = Bitmap.createBitmap(bmp, 0, 0, bmpWidth,
bmpHeight, matrix, true);
return resizedBitmap;
} else {
return bmp;
}
}
I'm developing an application that can display a photo from the camera using the camera intent using the extra crop option. The code is working fine in most of the devices but when i tried to test it in my brand new Galaxy Note3 it crashes and didn't run properly, Also the image taken is still huge in size "Almost 4 MB" which is so large to be displayed in the imageview. Can anyone point me if there is anyway to avoid this?
Hereunder my code :
Intent intent = new Intent(
"android.media.action.IMAGE_CAPTURE");
file = getOutputMediaFile();
intent.putExtra("crop", "true");
intent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(file));
intent.putExtra("outputFormat",
Bitmap.CompressFormat.JPEG
.toString());
intent.putExtra(
MediaStore.EXTRA_SCREEN_ORIENTATION,
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
startActivityForResult(intent,
ACTION_REQUEST_CAMERA);
and for activityforresult
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch (requestCode) {
case ACTION_REQUEST_CAMERA:
if (data != null) {
try {
int inWidth = 0;
int inHeight = 0;
InputStream in = new FileInputStream(
file.getAbsolutePath());
// decode image size (decode metadata only, not the
// whole image)
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, options);
in.close();
in = null;
// save width and height
inWidth = options.outWidth;
inHeight = options.outHeight;
// decode full image pre-resized
in = new FileInputStream(file.getAbsolutePath());
options = new BitmapFactory.Options();
// calc rought re-size (this is no exact resize)
options.inSampleSize = Math.max(inWidth / 350,
inHeight / 550);
// decode full image
Bitmap roughBitmap = BitmapFactory.decodeStream(in,
null, options);
// calc exact destination size
Matrix m = new Matrix();
RectF inRect = new RectF(0, 0, roughBitmap.getWidth(),
roughBitmap.getHeight());
RectF outRect = new RectF(0, 0, 700, 800);
m.setRectToRect(inRect, outRect,
Matrix.ScaleToFit.CENTER);
float[] values = new float[9];
m.getValues(values);
// resize bitmap
Bitmap resizedBitmap = Bitmap.createScaledBitmap(
roughBitmap,
(int) (roughBitmap.getWidth() * values[0]),
(int) (roughBitmap.getHeight() * values[4]),
true);
// save image
try {
FileOutputStream out = new FileOutputStream(
file.getAbsolutePath());
resizedBitmap.compress(Bitmap.CompressFormat.JPEG,
90, out);
fullphoto = resizedBitmap;
setPic(file.getAbsolutePath(), camera);
} catch (Exception e) {
Log.e("Image", e.getMessage(), e);
}
} catch (IOException e) {
Log.e("Image", e.getMessage(), e);
}
}
// fullphoto = BitmapFactory.decodeFile(file.getAbsolutePath());
// photo = decodeSampledBitmapFromFile(file.getAbsolutePath(),
// 100, 100);
// camera.setImageBitmap(imghelper.getRoundedCornerBitmap(
// fullphoto, 10));
iscamera = "Yes";
firsttime = false;
break;
}
Is it possible to save a photo taken with a camera in color mode as black and white or must the camera paramaters be changed so the viewfinder sees black and white when the picture is taken? Here is the code I am using to save an image in color, I want to save it as black and white to save space.
PictureCallback jpegCallback = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
Log.e("Pic Taken","Callback");
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
options.inDither = false; // Disable Dithering mode
options.inPurgeable = true; // Tell to gc that whether it needs free
// memory, the Bitmap can be cleared
options.inInputShareable = true; // Which kind of reference will be
// used to recover the Bitmap
// data after being clear, when
// it will be used in the future
options.inTempStorage = new byte[32 * 1024];
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bMap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
int orientation;
// others devices
if(bMap.getHeight() < bMap.getWidth()){
orientation = 90;
} else {
orientation = 0;
}
Bitmap bMapRotate;
if (orientation != 0) {
Matrix matrix = new Matrix();
matrix.postRotate(orientation);
bMapRotate = Bitmap.createBitmap(bMap, 0, 0, bMap.getWidth(),
bMap.getHeight(), matrix, true);
} else
bMapRotate = Bitmap.createScaledBitmap(bMap, bMap.getWidth(),
bMap.getHeight(), true);
FileOutputStream out;
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
try {
Log.e("Saving","Pic");
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "/" + System.currentTimeMillis() + ".jpg";
out = new FileOutputStream(baseDir + fileName);
bMapRotate.compress(Bitmap.CompressFormat.JPEG, 25, out);
if (bMapRotate != null) {
bMapRotate.recycle();
bMapRotate = null;
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
You can convert Bitmap:
public Bitmap convertToGrayScale(Bitmap original) {
Bitmap result = Bitmap.createBitmap(original.getWidth(), original.getHeight(), Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
ColorMatrix matrix = new ColorMatrix();
matrix.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(matrix);
paint.setColorFilter(f);
canvas.drawBitmap(original, 0, 0, paint);
return result;
}
You can convert an existing photo into Black and White. After:
else
bMapRotate = Bitmap.createScaledBitmap(bMap, bMap.getWidth(),
bMap.getHeight(), true);
Add this:
Bitmap newBitmap = Bitmap.createBitmap(bMapRotate.getWidth(), bMapRotate.getHeight(), Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(newBitmap);
Paint paint = new Paint();
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.setSaturation(0);
ColorMatrixColorFilter cmFilter = new ColorMatrixColorFilter(colorMatrix);
paint.setColorFilter(cmFilter);
canvas.drawBitmap(bMapRotate, 0, 0, paint);
And don't forget to call .recycle() on bMapRotate.
It should be available in the Camera.parameters.
Depending on if the device's camera supports it, you could use it.
Use this code to retrieve them:
Camera.Parameters params = cam.getParameters();
try {
for (String e : params.getSupportedColorEffects()) {
Log.d(TAG, "Effect: " + e);
}
}
catch (NullPointerException npe) {
Log.d(TAG, "No color effects supported by this camera.");
}
And read the documentation:
http://developer.android.com/reference/android/hardware/Camera.Parameters.html