When i capture photo in portrait mode, it is landscaped and I use this function to rotate image
private Bitmap rotateImage(String mCurrentPhotoPath, String rotationAngle){
//Set hardCode size imageView 300dp
int targetW = CommonUtils.ConvertDpTPpx(mContext, 300);
int targetH = CommonUtils.ConvertDpTPpx(mContext, 300);
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
int scaleFactor = Math.min(photoW / targetW, photoH / targetH);
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
Matrix matrix = new Matrix();
matrix.setRotate(Float.parseFloat(rotationAngle), (float) bitmap.getWidth() / 2, (float) bitmap.getHeight() / 2);
return Bitmap.createBitmap(bitmap, 0, 0, photoW/2, photoH/2, matrix, true);
}
When I build on device on S4, it runs right, but when it run on Sony Docomo (SO-04E) and LG LTE2, after capture photo and app crash. A bug is x + width (image) < bitmap.width. And then i edit photoW/4 and photoH/4 so Sony and LG run right but S4 image is cropped. So, at the return line, how i should fix the width and height to run right on all device.
Related
I am using this line of code for getting the full sized image, i am not setting this image on any view, still this line when executed takes a lot of ram, around 110-120m, any solutions ? I even tried running this code in Backgroung thread using Async Task. The picture resolution is 4008*5344.
Bitmap image = MediaStore.Images.Media.getBitmap(getContentResolver(),Uri.parse(mCurrentPhotoPath));
And the below method given in developers site, gives me Null bitmap.
private void setPic() {
// Get the dimensions of the View
int targetW = mImageView.getWidth();
int targetH = mImageView.getHeight();
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
mImageView.setImageBitmap(bitmap);
}
I need to make an icon on Home screen from image. I use the standart code for this:
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imagePath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
final int scaleFactor = (int) Math.max(photoW/app_icon_size, photoH/app_icon_size);
// Decode the image file into a Bitmap sized to fill needed sizes
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
Bitmap bitmap = BitmapFactory.decodeFile(imagePath, bmOptions);
return bitmap;
But because of using integer rather than float for inSampleSize i have to downscale bitmap a little more to fit it exactly to sizes i need:
final float aspectRatio = (float) bitmap.getWidth()/bitmap.getHeight();
final int finalW = (aspectRatio < 1 ? (int) (app_icon_size*aspectRatio) : app_icon_size);
final int finalH = (aspectRatio > 1 ? (int) (app_icon_size/aspectRatio) : app_icon_size);
bitmap = Bitmap.createScaledBitmap(bitmap, finalW, finalH, false);
Everything is nice exept it is scaled from its 0,0 point. So i tried to use createBitmap with Matrix instead of createScaledBitmap:
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale((float) finalW/bitmap.getWidth(), (float) finalH/bitmap.getHeight(), (float) bitmap.getWidth()/2, (float) bitmap.getHeight()/2);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), scaleMatrix, false);
But nothing changed, it still scales from 0,0. This is banal question i guess, but most solutions on Stack and other resources concern Canvas and View but i need to scale Bitmap itslef.
I want to show 4 images in 2 x 2 grid format on the screen. Images are sourced from google image search and images are square of 200 X 200
This is my approach to scale them. RelativeLayout with 4 nested RelativeLayout and each layout has imageView in it. and this is how I get screen width to scale images. Setting internal layoutparams height and width to screenWidth/2 and then scaling images.
this is what I am doing to get the image height and width for particular screen. e.g if screen width is 550 then my image size would be 275 x 275.
public static int getOptionWidth(Context context) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return metrics.widthPixels;
}
optionWidth = (getOptionWidth(context) / 2)
This is for unscaled bitmap
public static Bitmap resourceDecoder(byte[] imgBytes, int destWidth, int destHeight) {
Options options = new Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(imgBytes, 0, imgBytes.length, options);
options.inJustDecodeBounds = false;
float srcAspect = (float) srcWidth / (float) srcHeight;
float dstAspect = (float) dstWidth / (float) dstHeight;
if (srcAspect > dstAspect) {
options.inSampleSize = srcHeight / dstHeight;
} else {
options.inSampleSize = srcWidth / dstWidth;
}
Bitmap unscaledBitmap = BitmapFactory.decodeByteArray(imgBytes, 0, imgBytes.length, options);
return unscaledBitmap;
}
This will be my destination width and height because I need images in square. I have implemented basic method to get source rectangle (getSrcRect) and get destination rectangle (getDstRect)
Rect srcRect = getSrcRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(), dstWidth, dstHeight);
Rect dstRect = getDstRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(), dstWidth, dstHeight);
Bitmap scaledBitmap = Bitmap.createBitmap(dstRect.width(), dstRect.height(), Config.ARGB_8888);
Canvas canvas = new Canvas(scaledBitmap);
canvas.drawBitmap(unscaledBitmap, srcRect, dstRect, new Paint(Paint.FILTER_BITMAP_FLAG));
return scaledBitmap;
This is working fine and results are coming as expected (tested on hdpi, xhdpi and mdpi). But now I am confused as I am no using dxtopx or pxTodX conversion. Am I missing something? though results are as expected I am little worried about the approach. I don't know should I use pxToDx or vice-versa. If I do how does it affect my result and how should I use these.
You don't have to use PX to DP conversion for this, because you already set all of your size variables relative to screen width by using getOptionWidth(context).
I have very large bitmap image. My source
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
// The new size we want to scale to
final int REQUIRED_WIDTH = 1000;
final int REQUIRED_HIGHT = 500;
// Find the correct scale value. It should be the power of 2.
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_WIDTH
&& o.outHeight / scale / 2 >= REQUIRED_HIGHT)
scale *= 2;
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
i want to resize image correctly, i need resize image to maximum available size
for example
i downloaded image size 4000x4000 px and my phone supported 2000x1500 px size
i need anderstend how size suported my phone?
then i resize image to 2000x1500 (for example)
Here you have good to resize bitmap to maximum avaliabe size :
public void onClick() //for example
{
/*
Getting screen diemesions
*/
WindowManager w = getWindowManager();
Display d = w.getDefaultDisplay();
int width = d.getWidth();
int height = d.getHeight();
// "bigging" bitmap
Bitmap nowa = getResizedBitmap(yourbitmap, width, height);
}
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;
}
I hope I helped
Not So Perfect But here is My solution to Do That,
fun setScaleImageWithConstraint(bitmap: Bitmap): Bitmap {
val maxWidth = 500 //max Height Constraint
val maxHeight = 500 //max Width Constraint
var width = bitmap.width
var height = bitmap.height
if (width > maxWidth || height > maxHeight) {
//If Image is still Large than allowed W/H Half the Size
val quarterWidth = ((width / 2).toFloat() + (width / 3).toFloat()).toInt()
val quarterHeight = ((height / 2).toFloat() + (height / 3).toFloat()).toInt()
val scaledBitmap = Bitmap.createScaledBitmap(bitmap, quarterWidth, quarterHeight, false)
//Recursive Call to Resize and return Resized One
return setScaleImageWithConstraint(scaledBitmap)
} else {
//This will be executed when Image is not violating the Constraints
return bitmap
}
}
Reduce Bitmap 1 Quarter Size Recursively Until the Allowed With And Height is reached.
I've tested this code snippet on about 25 devices and it works great on all of them except a Samsung Galaxy Nexus that I'm trying to test with now.
Here is the method and I apologize for not trimming it down to find the exact spot that's throwing the exception, but eclipse's debugging is doodoo.
private void setupImageView() {
imageLocation = currentPhotoPath;
// Get the dimensions of the View
Display display = getWindowManager().getDefaultDisplay();
Point size = getDisplaySize(display);
int targetW = size.x;
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imageLocation, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW / targetW, photoH / targetW);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(imageLocation, bmOptions);
//int rotationForImage = getRotationForImage(imageLocation);
int rotationForImage = (whichCamera == 0 ? 90 : 270);
if (rotationForImage != 0) {
int targetWidth = rotationForImage == 90 || rotationForImage == 270 ? bitmap.getHeight() : bitmap.getWidth();
int targetHeight = rotationForImage == 90 || rotationForImage == 270 ? bitmap.getWidth() : bitmap.getHeight();
Bitmap rotatedBitmap = Bitmap.createBitmap(targetWidth, targetHeight, bitmap.getConfig());
Canvas canvas = new Canvas(rotatedBitmap);
Matrix matrix = new Matrix();
matrix.setRotate(rotationForImage, bitmap.getWidth() / 2, bitmap.getHeight() / 2);
canvas.drawBitmap(bitmap, matrix, new Paint());
bitmap.recycle();
bitmap = rotatedBitmap;
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 40, bytes);
try
{
File f = new File(imageLocation);
f.createNewFile();
//write the bytes in file
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
fo.close();
}
catch(java.io.IOException e){}
}
imageView.setImageBitmap(bitmap);
}
anyone know what Samsung does differently with the nexus that would cause this to throw an exception? It works fine on a Galaxy S III
It looks like something in the if block you mention is throwing an NPE - that's the real bug here. Don't worry about the Activity/ResultInfo stuff, that is downstream and triggered by the NPE. Go line by line and look for the null reference :-)
Regarding Eclipse - sadly I don't have much experience there. For Android I personally use IntelliJ and the debugging works well. Are you able to debug other Java code (even a simple Hello, World)?