I am trying to set the background for an ImageView using a saved path. However the following code crashes.
selectSavedImagefromGallery(imagePath);
Here imagePath = "/storage/sdcard0/Downloads/image.jpg" which is a valid path. It works when I set the image choosing it from the gallery. But I would like to save the path so it can be used at anytime.
private void selectSavedImagefromGallery(String savedImagePath) {
Bitmap bm;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(savedImagePath, options);
final int REQUIRED_SIZE = 200;
int scale = 1;
while (options.outWidth / scale / 2 >= REQUIRED_SIZE
&& options.outHeight / scale / 2 >= REQUIRED_SIZE)
scale *= 2;
options.inSampleSize = scale;
options.inJustDecodeBounds = false;
bm = BitmapFactory.decodeFile(savedImagePath, options);
profile_pic.setImageBitmap(bm);
}
The error is being caused by this the last line:
profile_pic.setImageBitmap(bm);
What can I do to make it work?
Thanks.
Related
This code is used to compress and resize image in my app Image is showing blurry and size is reducing to much. Can yo Explain how this code works and how can i improve quality of my image with this existing code.
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
final int REQUIRED_SIZE = 200;
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_SIZE
&& o.outHeight / scale / 2 >= REQUIRED_SIZE)
scale *= 2;
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
Bitmap bit1 = BitmapFactory.decodeStream(new FileInputStream(f),
null, o2);
Your code is just initializing the bitmap options to work with a decodedStream ( the input image or file you will work with) after that is setting a rule thats say the required size should be >= 200 width and height and after that is just creating a final bitmap with the required output of the stream
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
final int REQUIRED_SIZE = 200;
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_SIZE
&& o.outHeight / scale / 2 >= REQUIRED_SIZE)
scale *= 2;
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
Bitmap bit1 = BitmapFactory.decodeStream(new FileInputStream(f),
null, o2);
bit1.compress(Bitmap.CompressFormat.PNG, 100, out); //you can use this line and play with the value 100 in order to set quality of the image when its compresed
Since your image is scaled to a certain size ( which is >= 200 width and height) your image output dimension will depend on the input bitmap at first
if you want to check out the Dimensions of the bitmap you can do this
Log.e("Dimensions", bit1.getWidth()+" "+bit1.getHeight());
Bitmap.compress
compress(Bitmap.CompressFormat format, int quality, OutputStream
stream) Write a compressed version of the bitmap to the specified
outputstream.
EDIT: As Vladyslav Matviienko suggests you could increase your REQUIRED_SIZE to a bigger value, since like i wrote above, you are setting a fixed size at first
Here is a piece of code that I used to compress Bitmap:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
System.out.println("before: " + bmp.getByteCount());
bmp.compress(Bitmap.CompressFormat.JPEG, 80, baos);
System.out.println("baos: " + baos.toByteArray().length);
BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap b = BitmapFactory.decodeStream(new ByteArrayInputStream(baos.toByteArray()),
null, options);
System.out.println("after: " + b.getByteCount());
LogCat output:
12-29 11:45:52.638 18042-18042/com.xxx.yyy I/System.out: before: 653760
12-29 11:45:52.678 18042-18042/com.xxx.yyy I/System.out: baos: 13118
12-29 11:45:52.688 18042-18042/com.xxx.yyy I/System.out: after: 1307520
size of baos seems the size of Bitmap after compressing, but why b.getByteCount() return a larger size than bmp before compressing?
BitmapFactory.Options options = new BitmapFactory.Options();
/*
isSampleSize will reduce your bitmap size.
If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save
memory. The sample size is the number of pixels in either dimension that correspond to a single pixel in the
decoded bitmap. For example, inSampleSize == 4 returns an image that is 1/4 the width/height of the original
and 1/16 the number of pixels. Any value <= 1 is treated the same as 1. Note: the decoder uses a final value based
on powers of 2, any other value will be rounded down to the nearest power of 2.
*/
options.inSampleSize = 2;
Bitmap b = BitmapFactory.decodeStream(new ByteArrayInputStream(baos.toByteArray()), null, options);
System.out.println("after: " + b.getByteCount());
I had Same Problem but i solved using Some Method.i used this method in my Camera App after image Captured.i put my code here.Using it you will try.
My Methods :
public static Bitmap decodeSampledBitmapFromByte(Context context, byte[] bitmapBytes) {
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int reqWidth, reqHeight;
Point point = new Point();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
display.getSize(point);
reqWidth = point.x;
reqHeight = point.y;
} else {
reqWidth = display.getWidth();
reqHeight = display.getHeight();
}
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.inMutable = true;
options.inBitmap = BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.length, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Load & resize the image to be 1/inSampleSize dimensions
// Use when you do not want to scale the image with a inSampleSize that is a power of 2
options.inScaled = true;
options.inDensity = options.outWidth;
options.inTargetDensity = reqWidth * options.inSampleSize;
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false; // If set to true, the decoder will return null (no bitmap), but the out... fields will still be set, allowing the caller to query the bitmap without having to allocate the memory for its pixels.
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
return BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.length, options);
}
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
int initialInSampleSize = computeInitialSampleSize(options, reqWidth, reqHeight);
int roundedInSampleSize;
if (initialInSampleSize <= 8) {
roundedInSampleSize = 1;
while (roundedInSampleSize < initialInSampleSize) {
// Shift one bit to left
roundedInSampleSize <<= 1;
}
} else {
roundedInSampleSize = (initialInSampleSize + 7) / 8 * 8;
}
return roundedInSampleSize;
}
private static int computeInitialSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final double height = options.outHeight;
final double width = options.outWidth;
final long maxNumOfPixels = reqWidth * reqHeight;
final int minSideLength = Math.min(reqHeight, reqWidth);
int lowerBound = (maxNumOfPixels < 0) ? 1 :
(int) Math.ceil(Math.sqrt(width * height / maxNumOfPixels));
int upperBound = (minSideLength < 0) ? 128 :
(int) Math.min(Math.floor(width / minSideLength),
Math.floor(height / minSideLength));
if (upperBound < lowerBound) {
// return the larger one when there is no overlapping zone.
return lowerBound;
}
if (maxNumOfPixels < 0 && minSideLength < 0) {
return 1;
} else if (minSideLength < 0) {
return lowerBound;
} else {
return upperBound;
}
}
i think u need to Use My method decodeSampledBitmapFromByte() instead of your
method.you need to put all methods in your code.
Using this Code i get same size After compressing.i put my LogCat here.
Hope it will help You...Enjoy.(:
I have wrote a function that do reduce image size then upload it
everything works very well except original image will lost it quality
it should only reduce uploaded image size not the original one
this is my function
public void ReduceAndUpload(File file)
{
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
o.inSampleSize = 6;
BitmapFactory.decodeFile(file.getPath(), o);
int Scale = 1;
while (o.outWidth / Scale / 2 >= 75 && o.outHeight / Scale / 2 >= 75)
{
Scale *= 2;
}
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = Scale;
Bitmap SelectedBitmap = BitmapFactory.decodeFile(file.getPath(), o2);
ByteArrayOutputStream OutputStream = new ByteArrayOutputStream();
SelectedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, OutputStream);
String ImageEncode = Base64.encodeToString(OutputStream.toByteArray(), 0);
DoUpload(ImageEncode);
}
whats wrong ?
Full Code: http://paste.ubuntu.com/20529512/
What does BitmapFactory.Options in android.graphics.BitmapFactory.Options do?
There is no theoretical explanation in the android sdk reference manual about this class, it only contains the explanation about the methods of the class.
Bitmapfactory is mainly used for Scaling
Bitmap lBmp = BitmapFactory.decodeResource(getResources(), R.Drawable.ic_dolphin);
It gets the "dolpin" image and it will reduce the image size, if we dnt use bitmapfactory then it leads to insufficient memory allocations
It's used to pass options to the BitmapFactory - as you might expect :)
For example, you can use it to explicitly scale the Bitmap up or down from the source.
See this example
This method is used to create bitmap of given specific size which is stored in sdcard.
public Bitmap decodeFile(String path,int size) {
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, o);
// The new size we want to scale to
final int REQUIRED_SIZE = size;
// Find the correct scale value. It should be the power of 2.
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_SIZE && o.outHeight / scale / 2 >= REQUIRED_SIZE)
scale *= 2;
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeFile(path, o2);
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
Ok Someone help me figure this out. I am using the Bitmap.options as recommended by other threads and android tutorials to figure out the inSample size. The problem that the following code is resulting in null bitmap instead of scaled bitmap
private int determineCorrectScale(InputStream imageStream){
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(imageStream, null, o);
// The new size we want to scale to
final int REQUIRED_SIZE = 100;
// Find the correct scale value. It should be the power of 2.
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_SIZE && o.outHeight / scale / 2 >= REQUIRED_SIZE) {
scale *= 2;
}
return scale;
}
private String saveScaledBitmapToPhone(Uri imagUri){
InputStream imageStream;
try {
imageStream = getContentResolver().openInputStream(imagUri);
int scale= determineCorrectScale(imageStream);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = scale;
Bitmap yourSelectedImage = BitmapFactory.decodeStream(imageStream, null, options );
.
.
.
.
} catch (Exception e) {
return imagUri.toString(); //default
}
}
The problem that yourSelectedImage is null. However if I comment out the line
int scale= determineCorrectScale(imageStream);
and set the insampleSize to 8 or 16 or any other fixed manual number then everything works fine. Can any one explain this behaviour or how to fix it? My feeling says it is due to creating two Options objects of static class but that's just a guess. I still can't fix it :(
PLEASE HELP
You're reusing the same data stream. Either reset it, cache the data in a byte array, or open a new stream.