I am making an app where in one of the activity i am fetching image from gallery and showing it in adapter like image below
I have to rotate that image and save it to sdcard. My code is doing fine but after saving it to sdcard i get very poor quality of image. my code is:
viewHolder.imgViewRotate.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
imagePosition = (Integer) v.getTag();
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
try {
FileOutputStream out = new FileOutputStream(new File(uriList.get(rotatePosition).toString()));
rotated.compress(Bitmap.CompressFormat.PNG, 100, out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
notifyDataSetChanged();
}
});
Any suggestions will be great help.
Try out below code to reduce image size without losing its quality:
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth)
{
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
}
EDITED:
Resize the image using BitmapFactory inSampleSize option and the image doesn't lose quality at all. Code:
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true;
Bitmap bm = BitmapFactory.decodeFile(tempDir+"/"+photo1_path , bmpFactoryOptions);
int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)600);
int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)800);
if (heightRatio > 1 || widthRatio > 1)
{
if (heightRatio > widthRatio){
bmpFactoryOptions.inSampleSize = heightRatio;
} else {
bmpFactoryOptions.inSampleSize = widthRatio;
}
}
bmpFactoryOptions.inJustDecodeBounds = false;
bm = BitmapFactory.decodeFile(tempDir+"/"+photo1_path, bmpFactoryOptions);
// recreate the new Bitmap
src = Bitmap.createBitmap(bm, 0, 0,bm.getWidth(), bm.getHeight(), matrix, true);
src.compress(Bitmap.CompressFormat.PNG, 100, out);
Related
Hello i have facebook image that i have to compress and put it in my imageview. I used below code to resize my image and compress it so that i can show it in my imageview but it gives file not found exception error
i do not find any way to compress file/image that located on server.
you can take bitmap from URL and the you suppose to re size.
For Getting Bitmap From URL.
URL url = new URL("http://....");
Bitmap image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
for resize you can use below code
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// "RECREATE" THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
}
How to use :-
place this code:-
private void showImage(final String URL) {
new Thread(new Runnable() {
#Override
public void run() {
URL url = new URL(URL);
Bitmap bm = BitmapFactory.decodeStream(url.openConnection()
.getInputStream());
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) YOUR_WIDTH) / width;
float scaleHeight = ((float) YOUR_HEIGHT) / height;
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// "RECREATE" THE NEW BITMAP
final Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width,
height, matrix, false);
runOnUiThread(new Runnable() {
#Override
public void run() {
your_imageView.setImageBitmap(resizedBitmap);
}
})
}
}).start();
}
thanks.
I'm doing an app which takes a photo with the camera and then rotates it and scales it.
I need to rotate the image because the camera returns a wrong rotated image and I need to scale it to reduce its size.
I first save in a temp directory the original image returned by camera, then I read it and make modifications, saving the new image to a new file.
I tried using matrix to rotate and scale the picture, but it loses quality.
Then I tried to scale it first with Bitmap.createScaledBitmap and then rotate it with matrix, but the result is even uglier than the one using only matrix.
Then I tried to rotate it first and then resize it using always Bitmap.createScaledBitmap. The image doesn't lose quality, but it's stretched as I scaled it after rotating it and width and height are inverted. Tried also to invert height and width according to the rotation made, but it loses quality again.
This is the last code I've written:
in= new FileInputStream(tempDir+"/"+photo1_path);
out = new FileOutputStream(file+"/picture.png");
Bitmap src = BitmapFactory.decodeStream(in);
int iwidth = src.getWidth();
int iheight = src.getHeight();
int newWidth = 0;
int newHeight = 0;
newWidth = 800;
newHeight = 600;
// calculate the scale - in this case = 0.4f
float scaleWidth = ((float) newWidth) / iwidth;
float scaleHeight = ((float) newHeight) / iheight;
// createa matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
//matrix.postScale(scaleWidth, scaleHeight);
int orientation = getOrientation(MyActivity.this,Uri.parse(tempDir+"/"+photo1_path));
switch(orientation) {
case 3:
orientation = 180;
break;
case 6:
orientation = 90;
break;
case 8:
orientation = 270;
break;
}
int rotate = 0;
switch(orientation) {
case 90:
rotate=90;
break;
case 180:
rotate=180;
break;
case 270:
rotate=270;
break;
}
// rotate the Bitmap
matrix.postRotate(rotate);
src =Bitmap.createScaledBitmap(src , newWidth, newHeight, false);
// recreate the new Bitmap
Bitmap new_bit = Bitmap.createBitmap(src, 0, 0,
src.getWidth(), src.getHeight(), matrix, true);
new_bit.compress(Bitmap.CompressFormat.PNG, 100, out);
Any advice?
EDIT: If I only rotate or only scale the image, it doesn't lose quality. It's when I do both that the image loses quality. Also, if I put the image in an ImageView after resizing it and scaling it, it doesn't lose quality, it's just when I save it to file that loses quality.
Solved!
I resize the image using BitmapFactory inSampleSize option and the image doesn't lose quality at all.
Code:
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true;
Bitmap bm = BitmapFactory.decodeFile(tempDir+"/"+photo1_path , bmpFactoryOptions);
int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)600);
int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)800);
if (heightRatio > 1 || widthRatio > 1)
{
if (heightRatio > widthRatio){
bmpFactoryOptions.inSampleSize = heightRatio;
} else {
bmpFactoryOptions.inSampleSize = widthRatio;
}
}
bmpFactoryOptions.inJustDecodeBounds = false;
bm = BitmapFactory.decodeFile(tempDir+"/"+photo1_path, bmpFactoryOptions);
//bm.compress(Bitmap.CompressFormat.PNG, 100, out);
/*Bitmap new_bit = Bitmap.createScaledBitmap(src , newWidth, newHeight, true);
new_bit.compress(Bitmap.CompressFormat.PNG, 100, out);*/
// recreate the new Bitmap
src = Bitmap.createBitmap(bm, 0, 0,bm.getWidth(), bm.getHeight(), matrix, true);
//Bitmap dest = Bitmap.createScaledBitmap(new_bit , newWidth, newHeight, true);
src.compress(Bitmap.CompressFormat.PNG, 100, out);
use this method to rotate the bitmap...
private Bitmap checkifImageRotated() {
ExifInterface exif;
try {
exif = new ExifInterface(file.getAbsolutePath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int rotate = 0;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270 :
rotate = -90;
break;
case ExifInterface.ORIENTATION_ROTATE_180 :
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90 :
rotate = 90;
break;
}
if (rotate != 0) {
Bitmap bitmap = BitmapFactory.decodeFile(getTempFile().getPath());
Matrix matrix = new Matrix();
matrix.setRotate(rotate);
Bitmap bmpRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
recycle(bitmap);
return bmpRotated;
}
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
Don't make the new bitmap just override
int angle=0; int valueangle=0; Bitmap bitmap;
#Override
public void onClick(View v) {
System.out.println("valueeeeeee " + angle);
if (bitmap != null) {
angle = valueangle + 90;
Matrix matrix = new Matrix();
matrix.postRotate(angle);
bitmap = Bitmap.createBitmap(
bitmap , 0, 0,
bitmap .getWidth(),
bitmap .getHeight(), matrix, true);
main_img.setImageBitmap(bitmap );
} else {
System.out.println(" bitmap is null");
}
}
I am using exifInterface for photo rotation issue code is below: Facing captured image orientation issue from camera.
Create a Bitmap from the file
Bitmap b = BitmapFactory.decodeFile(imagePath);
Resize the Bitmap by scaling it to appropriate level
int width = b.getWidth();
int height = b.getHeight();
int newWidth = 150;
int newHeight = 150;
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
// Bitmap resizedBitmap = Bitmap.createBitmap(b, 0, 0, width, height, matrix, true);
// resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 70, out);
Handle orientation of the image
ExifInterface exif = new ExifInterface(imagePath);
String orientation = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
if (orientation.equals(ExifInterface.ORIENTATION_NORMAL)) {
// Do nothing. The original image is fine.
} else if (orientation.equals(ExifInterface.ORIENTATION_ROTATE_90+"")) {
matrix.postRotate(90);
} else if (orientation.equals(ExifInterface.ORIENTATION_ROTATE_180+"")) {
matrix.postRotate(180);
} else if (orientation.equals(ExifInterface.ORIENTATION_ROTATE_270+"")) {
matrix.postRotate(270);
}
Save the new bitmap
out = new FileOutputStream(new File("some output file path"));
Bitmap resizedBitmap = Bitmap.createBitmap(b, 0, 0, width, height, matrix, true);
resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 70, out);
This code not working for resolve rotation issue, please give me guideline.
On Lg devices it's exifinterface always returning 0 orientation, Samsung devices returning 6 and 1.
How to fix this issue with all the devices like htc, Motorola, samsung , Sony and LG.
I am thankful to you all please help me.
You can use this function to do the same thing you require. Have this function in your activity or any util class and call it to get bitmap from file path.
I have been using this function in my application and my prime testing devices are LG.
public static Bitmap decodeFile(String path) {
int orientation;
try {
if (path == null) {
return null;
}
// decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
// Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE = 70;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 8;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE
|| height_tmp / 2 < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale++;
}
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
Bitmap bm = BitmapFactory.decodeFile(path, o2);
Bitmap bitmap = bm;
ExifInterface exif = new ExifInterface(path);
orientation = exif
.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
Log.e("orientation", "" + orientation);
Matrix m = new Matrix();
if ((orientation == 3)) {
m.postRotate(180);
m.postScale((float) bm.getWidth(), (float) bm.getHeight());
// if(m.preRotate(90)){
Log.e("in orientation", "" + orientation);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
return bitmap;
} else if (orientation == 6) {
m.postRotate(90);
Log.e("in orientation", "" + orientation);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
return bitmap;
}
else if (orientation == 8) {
m.postRotate(270);
Log.e("in orientation", "" + orientation);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
return bitmap;
}
return bitmap;
} catch (Exception e) {
}
return null;
}
I am creating an application and want to setup a gallery view. I do not want the images in the gallery view to be full size. How do I resize images in Android?
Try:
Bitmap yourBitmap;
Bitmap resized = Bitmap.createScaledBitmap(yourBitmap, newWidth, newHeight, true);
or:
resized = Bitmap.createScaledBitmap(yourBitmap,(int)(yourBitmap.getWidth()*0.8), (int)(yourBitmap.getHeight()*0.8), true);
public Bitmap resizeBitmap(String photoPath, int targetW, int targetH) {
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(photoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
int scaleFactor = 1;
if ((targetW > 0) || (targetH > 0)) {
scaleFactor = Math.min(photoW/targetW, photoH/targetH);
}
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true; //Deprecated API 21
return BitmapFactory.decodeFile(photoPath, bmOptions);
}
Capture the image and resize it.
Bitmap image2 = (Bitmap) data.getExtras().get("data");
img.setImageBitmap(image2);
String incident_ID = IncidentFormActivity.incident_id;
imagepath="/sdcard/RDMS/"+incident_ID+ x + ".PNG";
File file = new File(imagepath);
try {
double xFactor = 0;
double width = Double.valueOf(image2.getWidth());
Log.v("WIDTH", String.valueOf(width));
double height = Double.valueOf(image2.getHeight());
Log.v("height", String.valueOf(height));
if(width>height){
xFactor = 841/width;
}
else{
xFactor = 595/width;
}
Log.v("Nheight", String.valueOf(width*xFactor));
Log.v("Nweight", String.valueOf(height*xFactor));
int Nheight = (int) ((xFactor*height));
int NWidth =(int) (xFactor * width) ;
bm = Bitmap.createScaledBitmap( image2,NWidth, Nheight, true);
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bm.compress(CompressFormat.PNG, 100, ostream);
ostream.close();
You can use Matrix to resize your camera image ....
BitmapFactory.Options options=new BitmapFactory.Options();
InputStream is = getContentResolver().openInputStream(currImageURI);
bm = BitmapFactory.decodeStream(is,null,options);
int Height = bm.getHeight();
int Width = bm.getWidth();
int newHeight = 300;
int newWidth = 300;
float scaleWidth = ((float) newWidth) / Width;
float scaleHeight = ((float) newHeight) / Height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0,Width, Height, matrix, true);
BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);
//photo is bitmap image
Bitmap btm00 = Utils.getResizedBitmap(photo, 200, 200);
setimage.setImageBitmap(btm00);
And in Utils class :
public static Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// RECREATE THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
matrix, false);
return resizedBitmap;
}
bm = Bitmap.createScaledBitmap(bitmapSource, width, height, true);
:)
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize=2; //try to decrease decoded image
Bitmap bitmap=BitmapFactory.decodeStream(is, null, options);
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, fos); //compressed bitmap to file
Following is the function to resize bitmap by keeping the same Aspect Ratio. Here I have also written a detailed blog post on the topic to explain this method. Resize a Bitmap by Keeping the Same Aspect Ratio.
public static Bitmap resizeBitmap(Bitmap source, int maxLength) {
try {
if (source.getHeight() >= source.getWidth()) {
int targetHeight = maxLength;
if (source.getHeight() <= targetHeight) { // if image already smaller than the required height
return source;
}
double aspectRatio = (double) source.getWidth() / (double) source.getHeight();
int targetWidth = (int) (targetHeight * aspectRatio);
Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
if (result != source) {
}
return result;
} else {
int targetWidth = maxLength;
if (source.getWidth() <= targetWidth) { // if image already smaller than the required height
return source;
}
double aspectRatio = ((double) source.getHeight()) / ((double) source.getWidth());
int targetHeight = (int) (targetWidth * aspectRatio);
Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
if (result != source) {
}
return result;
}
}
catch (Exception e)
{
return source;
}
}
resized = Bitmap.createScaledBitmap(yourImageBitmap,(int)(yourImageBitmap.getWidth()*0.9), (int)(yourBitmap.getHeight()*0.9), true);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 10;
FixBitmap = BitmapFactory.decodeFile(ImagePath, options);
//FixBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.gv);
byteArrayOutputStream = new ByteArrayOutputStream();
FixBitmap.compress(Bitmap.CompressFormat.JPEG, 80, byteArrayOutputStream); //compress to 50% of original image quality
byteArray = byteArrayOutputStream.toByteArray();
ConvertImage = Base64.encodeToString(byteArray, Base64.DEFAULT);
i am saving a captured image in sdcard by using following code
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) {
Log.e("PictureDemo", "Exception in photoCallback", e);
}
return(null);
}
}
but i am getting the image of resolution 1024*768 how can i change the resoultion of that image.
i am calling SavePhotoTask like this
Camera.PictureCallback photoCallback=new Camera.PictureCallback(){
public void onPictureTaken(byte[] data, Camera camera){
bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
Bitmap mutableBitmap = bmp.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(mutableBitmap);
canvas.drawBitmap(itembmp,left,right,null);
image.setImageBitmap(mutableBitmap);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
mutableBitmap.compress(Bitmap.CompressFormat.PNG,100, stream);
byte[] byteArray = stream.toByteArray();
new SavePhotoTask().execute(byteArray);
Toast.makeText(PreviewDemo1.this,"Image Saved",Toast.LENGTH_LONG).show();
camera.startPreview();
inPreview=true;
}
};
thanks in advance
It is the jpeg passed to the doInBackground method that already has that resolution - you need to change whatever is calling this code.
If you can parse it to BitMap then you can use this:
private final int MAX_WIDTH = 400;
private final int MAX_HEIGHT = 400;
public Bitmap getResizedBitmap(Bitmap bm) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth;
float scaleHeight;
if (width < MAX_WIDTH && height < MAX_HEIGHT) {
return bm;
}
if (width > height) {
scaleWidth = ((float) MAX_WIDTH) / width;
scaleHeight = ((float) MAX_HEIGHT * height / width) / height;
} else {
scaleWidth = ((float) MAX_WIDTH * width / height) / width;
scaleHeight = ((float) MAX_HEIGHT) / height;
}
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
matrix, false);
return resizedBitmap;
}