I am implementing an android program that allows users to upload photos from their device gallery to an ImageView. saving it in the cloud. My code works fine with small photos, but bigger photos caused the application to stop. I'm getting this error:
Bitmap too large to be uploaded into a texture (4128x2322, max=4096x4096)
I tried to resize the uploaded photo before displaying it using suggestions from previous questions, but they didn't work. I am not sure what the problem with my code is.
Any help would be appreciated. Here is the code from my last attempt:
{
// omitted code segment from onCreate...
browseButton = ((Button) findViewById(R.id.browse_button));
browseButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,"Select Picture"), SELECT_PICTURE);
}
}
);
}
//end on create
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (resultCode == RESULT_OK)
{
if (requestCode == SELECT_PICTURE)
{
Uri selectedImageUri = data.getData();
selectedImagePath = getPath(selectedImageUri);
System.out.println("Image Path : " + selectedImagePath);
Bitmap bitmap = BitmapFactory.decodeFile(selectedImagePath);
// Convert it to byte
ByteArrayOutputStream stream = new ByteArrayOutputStream();
// Compress image to lower quality scale 1 - 100
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
image = stream.toByteArray();
bitmap = BitmapFactory.decodeByteArray(image, 0, image.length);
Bitmap toyImageScaled = Bitmap.createScaledBitmap(bitmap, 200, 200
* bitmap.getHeight() / bitmap.getWidth(), false);
// Override Android default landscape orientation and save portrait
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotatedScaledToyImage = Bitmap.createBitmap(toyImageScaled, 0,
0, toyImageScaled.getWidth(), toyImageScaled.getHeight(),
matrix, true);
toyPreview.setImageBitmap(bitmap);
}
}
}
public String getPath(Uri uri)
{
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
You're still showing the big image at:
toyPreview.setImageBitmap(bitmap);
You should be showing the scaled image, toyImageScaled or rotatedScaledToyImage.
I think you should use the examples of the documentation, and use InSampleSize.
see this : http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
From DOCS:
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) {
// Calculate ratios of height and width to requested height and width
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
Related
I have an android app in which I give the possibility to whether take a photo or choose it from library. The problem is that taking a photo with the camera works pretty well, however, when I select a photo from the library the app bugs. After checking the size of the photos I find that the size of the selected photos (thumbnails) is very very big that's why the application slows and crashes after a while when I try to store the photo in my database. For example, the size of a photo taken with camera in my app is 129600 bytes, but when I try a second time to load this same photo from library into my app I find that its size is now 8294400 (much bigger) !! which is pretty bizarre !
I am wondering if my way of handling the case of photo selection (case when requestCode == 2) is correct, and if there is an error in my code ?
Here is my full code:
private void selectImage() {
final CharSequence[] options = { "Take Photo", "Choose from Gallery","Cancel" };
AlertDialog.Builder builder = new AlertDialog.Builder(ScrollingActivity.this);
builder.setTitle("Add Photo!");
builder.setItems(options, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int item) {
if (options[item].equals("Take Photo"))
{
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 1);
}
else if (options[item].equals("Choose from Gallery"))
{
Intent intent = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, 2);
}
else if (options[item].equals("Cancel")) {
dialog.dismiss();
}
}
});
builder.show();
}
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == 1) {
thumbnail = (Bitmap) data.getExtras().get("data");
System.out.println("Image Byte Count: " + thumbnail.getByteCount()); // prints 129600 Bytes.
} else if (requestCode == 2) {
Uri selectedImage = data.getData();
String[] filePath = { MediaStore.Images.Media.DATA };
Cursor c = getContentResolver().query(selectedImage,filePath, null, null, null);
c.moveToFirst();
int columnIndex = c.getColumnIndex(filePath[0]);
String picturePath = c.getString(columnIndex);
c.close();
thumbnail = (BitmapFactory.decodeFile(picturePath));
System.out.println("Image Byte Count: " + thumbnail.getByteCount()); // prints 8294400 bytes!!!
}
renderImage();
}
}
Thank you in advance for your help !
I faced the same problem last week and discovered on this forum that there is an option to check the image size without loading it into memory. Have a look at BitmapFactory.options The code below is cut from Stackoverflow.
Resources res = mContext.getResources();
int allowedwidth= res.getDimensionPixelSize(R.dimen.albumart_image_width);
int allowedheight= res.getDimensionPixelSize(R.dimen.albumart_image_height);
holder.improfile.setImageBitmap(
decodeSampledBitmapFromFile(circlepicture, allowedwidth, allowedheight));
} catch (Exception e) {
e.printStackTrace();
}
public static Bitmap decodeSampledBitmapFromFile(String circlepicture,int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(circlepicture, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(circlepicture, options);
}
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;
}
I want to post a bitmap to server by decoding base64. But after decoding I can display just a part of image(some top of image). How can I solve this problem?
I won't write codes for posting because they are work succesfully. In bitmapToString function I can get base64 strings and I try to display them, but I can see only a part of images.
Codes:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode==GALLERY_REQUEST) && resultCode == RESULT_OK) {
Uri selectedImage = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
Bitmap bitmap = scaleBitmap(BitmapFactory.decodeFile(filePath), 512,512,360);
bitMapToString(bitmap); //this function logs the base64 strings
}
}
}
public String bitmapToString(Bitmap bitmap){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] imageBytes = baos.toByteArray();
String result = Base64.encodeToString(imageBytes, Base64.DEFAULT);
Log.d("BitmapToString",result); //here I get base64 strings
return result;
}
public Bitmap scaleBitmap(Bitmap bm, int maxWidth, int maxHeight, int ifSquareMaxValue) {
int width = bm.getWidth();
int height = bm.getHeight();
if(maxWidth>width && maxHeight>height)
return bm;
if (width > height) {
float ratio = (float) width / maxHeight;
width = maxHeight;
height = (int)(height / ratio);
} else if (height > width) {
float ratio = (float) height / maxWidth;
height = maxWidth;
width = (int)(width / ratio);
} else {
height = ifSquareMaxValue;
width = ifSquareMaxValue;
}
return Bitmap.createScaledBitmap(bm, width, height, true);
}
for example, a base64 string of an image is this: (from bitmapToString function line: Log.d("BitmapToString",result);)
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
when I use use in img tag display like this:
http://kombers.org/a.html
My App have an activity with a ImageView where i pick a picture from phone gallery and set in this ImageView as user's profile picture.
My problem is that some pictures when picked make app stop cause is too big, i want to know if someone can look my code and help me how can i resize this picked picture, so after set in this image view, how can user cut this picture before set, here below is my code where i pic the picture. i will be so greatful if someone do the needed changes and give me the code cause i dont know so much about developing. thank you.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && null != data) {
Uri selectedImage = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
PreferenceManager.getDefaultSharedPreferences(this).edit().putString("picturePath", picturePath).commit();
cursor.close();
ImageView imageView = (ImageView) findViewById(R.id.User);
imageView.setImageBitmap(BitmapFactory.decodeFile(picturePath));
}
}
Try this is image compression like whtsapp I have used in my application https://www.built.io/blog/2013/03/improving-image-compression-what-weve-learned-from-whatsapp/
You can use Picasso library. Get it from here.
The syntax looks like this:
Picasso.with(getContext()).load(imagePath).into(imageView);
Not gonna rewrite your code but this could be useful
Bitmap bitmap = BitmapFactory.decodeFile(foto.getFotoOrderFilePath());
Double height = (double)bitmap.getHeight();
Double scalingFactor = (960.0/height);
int tempWidht = bitmap.getWidth();
Double Dwidth = (tempWidht*scalingFactor);
int width = Dwidth.intValue();
Log.v("bitmap dimensions: ", String.valueOf(height) + " + " +String.valueOf(width) + " + " + String.valueOf(scalingFactor));
bitmap = Utilities.scaleBitmap(bitmap, width, 960);
An excerpt from code I use to scale a bitmap down. It sets the hight to 960 and get the scaling to change the width accordingly.
edit:
the ScaleBitmap method.
public static Bitmap scaleBitmap(Bitmap bitmap, int wantedWidth, int wantedHeight) {
Bitmap output = Bitmap.createBitmap(wantedWidth, wantedHeight, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
Matrix m = new Matrix();
m.setScale((float) wantedWidth / bitmap.getWidth(), (float) wantedHeight / bitmap.getHeight());
canvas.drawBitmap(bitmap, m, new Paint());
return output;
}
sorry for the late response
You can try this code to resize image as per your requirement
public Bitmap decodeSampledBitmapFromResource(String Filepath,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(Filepath, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(Filepath, options);
}
public int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
int inSampleSize = 1;
final int height = options.outHeight;
final int width = options.outWidth;
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;
}
check here
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
I have look at many different methods of creating a reduced size bitmap of an image, but none of them work properly / I need something different.
This is a little difficult to explain :-)
What I need is a bitmap that keeps the ratio of the picture, but is less than a certain size - eg 1mb or the equivalent in pixel dimensions (As this bitmap needs to added as a putExtra() for an intent).
Problems I'm having so far:
Most of the methods that I've looked at create a scaled version of the bitmap. So: Image -> Bitmap1 (unscaled) -> Bitmap2 (scaled). But if the resolution of the image is very high, it is not scaled down enough. I think the solution would be to create a bitmap of an exact size so that any resolution can be reduced enough.
However, the side effect of this method would be that images already less than the required size will be resized up (or the resizing won't work?). So there needs to be an "if" to check if the image can be converted to a bitmap without resizing.
I have no idea how to go about doing this so any help is very much appreciated! :-)
This is what I'm using at the moment (It does NOT do I want it to do):
// This is called when an image is picked from the gallery
#Override
public void onActivityResult(int requestCode, int resultCode,
Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
switch (requestCode) {
case 0:
if (resultCode == Activity.RESULT_OK) {
selectedImage = imageReturnedIntent.getData();
viewImage = imageReturnedIntent.getData();
try {
decodeUri(selectedImage);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
iv_preview.setImageBitmap(mImageBitmap);
}
break; // The rest is unnecessary
This is the part which is currently scaling the size:
private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true; //
BitmapFactory.decodeStream(getActivity().getContentResolver()
.openInputStream(selectedImage), null, o);
// The new size we want to scale to
final int REQUIRED_SIZE = 260; // Is this kilobites? 306
// Find the correct scale value. It should be the power of 2.
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE) {
break;
}
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
o2.inScaled = false; // Better quality?
mImageBitmap = BitmapFactory.decodeStream(getActivity()
.getContentResolver().openInputStream(selectedImage), null, o2);
return BitmapFactory.decodeStream(getActivity().getContentResolver()
.openInputStream(selectedImage), null, o2);
}
If anything needs to be explained more please say.
Thank you
How to call:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Uri selectedImage = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
pho1.setImageBitmap(decodeSampledBitmapFromResource(picturePath,
80, 60));
Methods:
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) {
// Calculate ratios of height and width to requested height and
// width
final int heightRatio = Math.round((float) height
/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will
// guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
public static Bitmap decodeSampledBitmapFromResource(String path,
int reqWidth, int reqHeight) {
Log.d("path", path);
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, options);
}
I'm using the following code to set marker with user's own image in his/her gallery. But I get out of memory error all the time so I guess my implementation is wrong. Another interesting behavior I found is that if the marker isn't in the view, the error doesn't occur immediately. But once I move the camera to where that marker is the error appears again. (In short, I never get a chance to see my image)
Codes I use:
//on button click, send user to gallery to choose image he/she wants to use
changeAvatarButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, 1);
}
});
//use the selected image for marker icon
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1 && resultCode == RESULT_OK && null != data) {
Uri selectedImage = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
// BitmapDescriptorFactory
myIcon.setIcon(BitmapDescriptorFactory
.fromPath(picturePath));
}
}
logcat error: E/dalvikvm-heap(5809): Out of memory on a 16777232-byte allocation.
When debugging I change picturePath to a known path such as "/mnt/sdcard/DCIM/Camera/IMG_20121214.jpg" but the error is the same.
Thanks in advance :)
decode and scale image before loaded into memory,just change landscape and portrait to the size you actually want
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
if(imageWidth > imageHeight) {
options.inSampleSize = calculateInSampleSize(options,512,256);//if landscape
} else{
options.inSampleSize = calculateInSampleSize(options,256,512);//if portrait
}
options.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeFile(path,options);
method for calculating size
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) {
// Calculate ratios of height and width to requested height and width
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
You are trying to put 4 Mpix image as a marker icon. That doesn't seem like a good idea.
Load it as a Bitmap, scaling it down to reasonable size.