Getting nullpointerexception for bitmap.getWidth() when reading image from sdcard - android

I read an image from sd card with BitmapFactory:
String myJpgPath = "/sdcard/yourdollar/img001.jpg";
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
Bitmap bm = BitmapFactory.decodeFile(myJpgPath, options);
If I write:
Log.i("width and height: ", bm.getWidth() + " " + bm.getHeight());
I get a nullpointer exception. I tried to scale with Bitmap.createScaledBitmap() but I get the same error. After it I am processing the bitmap so I would like to have a bitmap in the end that has any width or height, because it seems like I didn't give parameters for the bitmap. But I cannot scale it, so how can I get this image as a bitmap with a width of 500 and a height of 500?
***UPDATE
buttonClick = (Button) findViewById(R.id.buttonClick);
buttonClick.setOnClickListener(new OnClickListener() {
public void onClick(View v) { // <5>
preview.camera.takePicture(shutterCallback, rawCallback, jpegCallback);
Intent intentstart = new Intent(CameraActivity.this, Intent2.class);
startActivity(intentstart);
}
});
Okay here is the thing. This button takes a picture with the camera then change activity. If I do this way, the app does not have time to create the so when I use it in my second activity to read it, it throws nullpointerexception. So I got tricky (and wrong as well) and put:
preview.camera.takePicture(shutterCallback, rawCallback, jpegCallback);
try {
Thread.sleep(1200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Intent intentstart = new Intent(CameraActivity.this, Intent2.class);
startActivity(intentstart);
So it has 1.2 seconds to create the file, then change activity. Is there any way to check if the file created or not? Of course if its true then it should change activity.
Any suggestion?

First just check whether your image in your required directory /sdcard/yourdollar/img001.jpg And, Just try like this -
String myJpgPath = "/sdcard/yourdollar/img001.jpg";
Bitmap bm = BitmapFactory.decodeFile(myJpgPath);
and get image height & width in your Logcat
Log.i("width and height: ", bm.getWidth() + " " + bm.getHeight());

Related

the image is smaller than its respective imageView with a deforming rotation

I have specified an area for the imageView in the layout, in which I should display an image by referring to its path. Now, I got the image displayed on its respective imageview but
(1) the image is smaller than the allotted are for the imageView. And I want the imgae
to fit exactly the imageView
(2) the image is rotated 90 degrees anticlockwise. I want it to be
displayed normally without rotation?
Please help me to achieve the aforementioned points
Last Update
Java_Code:
private void displayMeetinPointImageInsideImageView(DataBaseRow dataBaseRow, ImageView imgSpaceIv) {
// TODO Auto-generated method stub
if (dataBaseRow == null) {
Log.w(TAG, "#displayMeetinPointImageInsideImageView(): The Object Of The DataBaseRow Class Is NULL, Maybe "
+ "It Was Not Instantiated.");
return;
} else if (imgSpaceIv == null) {
Log.w(TAG, "#displayMeetinPointImageInsideImageView(): The Variable Of Type ImageView Is NULL, Maybe It Was "
+ "Not Instantiated.");
return;
} else if (dataBaseRow.getImgPath().isEmpty()) {
Log.w(TAG, "#displayMeetinPointImageInsideImageView(): dataBaseRow.getImgPath() Is Empty");
return;
} else {
String imgPathString = dataBaseRow.getImgPath();
Options options = new Options();
options.inSampleSize = 3;
Bitmap bitmap = BitmapFactory.decodeFile(imgPathString);
Bitmap imgbitmap = BitmapFactory.decodeFile(imgPathString, options);
imgSpaceIv.setImageBitmap(imgbitmap);
}
}
Look at your logs:
dataBaseRow.getImgPath()= /storage/emulated/0/DCIM/MPL/5th guy hinging.jpeg
There is space in your filename.

Memory/Allocation errors when setting ImageButton from Camera Photo

I am trying to take a photo from the phones camera and place in it in a ImageButton as part of a Profile activity including all users details, and then save the image as shared pref.
If I use the following code the ImageButton simply does not update:
protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
// method checks data returned form camera via startActivityForResult
super.onActivityResult(requestCode, resultCode, data);
Runnable runnable = new Runnable(){#Override
public void run() {
handler.post(new Runnable(){
#Override
public void run() {
Bundle extras = data.getExtras();
photo = (Bitmap) extras.get("data");
takeAndSetPhoto.setImageBitmap(photo);
Toast.makeText(getBaseContext(), "Image set to profile!",
Toast.LENGTH_SHORT).show();
}//edn inner run
});//end new runnab;e
}
};
new Thread(runnable).start();
}//end if result OK
}// end onActivity
Alternatively the image DOES load if I use this method but I get erros:
Allocation fail for scaled Bitmap
Out Of Memory 01-03 10:13:06.645: E/AndroidRuntime(30163):
android.view.InflateException: Binary XML file line #18: Error
inflating class
The code is using Uro for phot taken:
public void run() {
Bundle extras = data.getExtras();
Uri photoShot = data.getData(); view
takeAndSetPhoto.setImageURI(photoShot);
Toast.makeText(getBaseContext(), "Image set to profile!",
Toast.LENGTH_SHORT).show();
}//edn inner run
All suggestions appreciated.
Cheers
Ciaran
Resizing Image:
When resizing the image:
Bitmap photoBitmap = Bitmap.createScaledBitmap(photo, 100, 100, false);
It works fine on the emulator with SD card activated, but crashes on a real device (a tablet 8inch)
Problem was I was not resizing image when taken form device phone, passed image to this method before setting to the image view:
public Bitmap reSizeImage(Bitmap bitmapImage) {
// resize bitmap image passed and rerun new one
Bitmap resizedImage = null;
float factorH = h / (float) bitmapImage.getHeight();
float factorW = w / (float) bitmapImage.getWidth();
float factorToUse = (factorH > factorW) ? factorW : factorH;
try {
resizedImage = Bitmap.createScaledBitmap(bitmapImage,
(int) (bitmapImage.getWidth() * factorToUse),
(int) (bitmapImage.getHeight() * factorToUse), false);
} catch (IllegalArgumentException e) {
Log.d(TAG, "Problem resizing Image #Line 510+");
e.printStackTrace();
}
Log.d(TAG,
"in resixed, value of resized image: "
+ resizedImage.toString());
return resizedImage;
}// end reSize

Decoded bitmap results in larger size

I am trying to store a bitmap (that i have previously read from a file) after decoding it in a preferable size using BitmapFactory.Options.inSampleSize. The problem is that the file size of the stored bitmap is at least double the size of the original file. I have searched a lot and could not find how i can deal with this, since i don't want it to happen for memmory efficiency (later i reuse the stored bitmap). Here is my method that does what i describe:
private Bitmap decodeFileToPreferredSize(File f) {
Bitmap b = null;
try {
// Decode image size
Log.i("Bitmap", "Imported image size: " + f.length() + " bytes");
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(f.getAbsolutePath(), o);
//Check if the user has defined custom image size
int scale = 1;
if(pref_height != -1 && pref_width != -1) {
if (o.outHeight > pref_height || o.outWidth > pref_width) {
scale = (int) Math.pow(
2,
(int) Math.round(Math.log(pref_width
/ (double) Math.max(o.outHeight, o.outWidth))
/ Math.log(0.5)));
}
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
b = BitmapFactory.decodeFile(f.getAbsolutePath(), o2);
String name = "Image_" + System.currentTimeMillis() + ".jpg";
File file = new File(Environment.getExternalStorageDirectory(), name);
FileOutputStream out = new FileOutputStream(file);
b.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.close();
Log.i("Bitmap", "Exported image size: " + file.length() + " bytes");
} catch (Exception e) {
b = null;
}
return b;
}
UPDATE I saw the densities on the two image files. The one that came from camera intent has 72 dpi density for width and height. The image file created from my above method has 96 dpi density for width and height. This explains why a 0.5 MByte image that came form the camera is resized in approximatelly 2.5 MByte with my above method since the rescale factor is (96/72) * 2 ~= 2.5. For some reason, the bitmap i create does not take the density of the image that came from the camera. I tried to set the density with all variation of BitmapFactory.Options.inDensity but no luck. Also i tried to change the bitmap density with bitmap.setDensity(int dpi); but still no effect. So, my new question is if there is a way to define the density of the bitmap when the image is stored.
Thanks in advance.
I had a similar issue. When I downloaded images from web they used more space on the SD than they did when downloaded to my PC from browser. I think the issue is simply that BitmapFactory saves the images in a non optimzed format of some sort.
My workaround was to use following instead of the bitmapfactory:
try {
try {
is = yourinputstream;
// Consider reading stream twice and return the bitmap.
os = youroutputstream;
byte data[] = new byte[4096];
int count;
while ((count = is.read(data)) != -1) {
os.write(data, 0, count);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(is != null) {
is.close();
}
if(os != null) {
os.close();
}
}
} catch (IOException e) {
e.printStackTrace();
}
You are correct that the problem is in a density change.
This thread revealed a solution: BitmapFactory returns bigger image than source
Before decoding also disable inScaled:
options.inSampleSize = 2; //or however you desire, power of 2
options.inScaled = false;
This will keep the density from changing and you will see the decrease in size you were looking for.
When BitmapFactory.Options.inSampleSize = 0.5, it does 100% / 0.5 = 200%.
What you want I think is BitmapFactory.Options.inSampleSize = 2, it does 100% / 2 = 50%

Android : Scrolling and No scrolling wallpaper issue

I'm little confused about setting up wallpaper,
In my galaxy s if i set wallapaper through code then it's not scrolling by default but If galary sets the wallpaper then its scrolling
Avoid a wallpaper to stretch across 5 screens
It depends on Home luncher app but how can i manage scrolling enabled disabled in my code
// the content of our screen.
setContentView(R.layout.wallpaper_2);
final WallpaperManager wallpaperManager = WallpaperManager
.getInstance(this);
final Drawable wallpaperDrawable = wallpaperManager.getDrawable();
final ImageView imageView = (ImageView) findViewById(R.id.imageview);
imageView.setDrawingCacheEnabled(true);
imageView.setImageDrawable(wallpaperDrawable);
Button randomize = (Button) findViewById(R.id.randomize);
randomize.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
int mColor = (int) Math.floor(Math.random() * mColors.length);
wallpaperDrawable.setColorFilter(mColors[mColor],
PorterDuff.Mode.MULTIPLY);
imageView.setImageDrawable(wallpaperDrawable);
imageView.invalidate();
}
});
Button setWallpaper = (Button) findViewById(R.id.setwallpaper);
setWallpaper.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
try {
wallpaperManager.setBitmap(imageView.getDrawingCache());
finish();
} catch (IOException e) {
e.printStackTrace();
}
}
});
wallpaperwizardrii application support scrolling and not scrolling features, It means it is possible at place but after investing so much time i failed to get solution.
I tried to set wallpaperManager.setWallpaperOffsetSteps(xStep, yStep); but can not get result of it
Am I missing any api which i am not aware
Help me Thanks in advance...
EDIT:I am setting one wallpaper in my phone from below code its result is ok because im having ICS in my phone but in emulator its stretched.
WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.dashboard);
Bitmap useThisBitmap = Bitmap.createScaledBitmap(bitmap,
wallpaperManager.getDesiredMinimumWidth(),
wallpaperManager.getDesiredMinimumHeight(), true);
bitmap.recycle();
try {
wallpaperManager.setBitmap(useThisBitmap);
} catch (IOException e) {
e.printStackTrace();
}
Log.e("", "Width : " + wallpaperManager.getDesiredMinimumWidth());
Log.e("", "Height : " + wallpaperManager.getDesiredMinimumHeight());
Is there any relation with offset??

Catching OutOfMemoryError in decoding Bitmap

Is it a good practice to catch OutOfMemoryError even you have tried some ways to reduce memory usage? Or should we just not catching the exception? Which one is better practice?
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
bitmap = BitmapFactory.decodeFile(file, options);
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
Thanks
It's good practice to catch it once and give decodeFile another chance. Catch it and call System.gc() and try decoding again. There is a high probability that it will work after calling System.gc().
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
bitmap = BitmapFactory.decodeFile(file, options);
} catch (OutOfMemoryError e) {
e.printStackTrace();
System.gc();
try {
bitmap = BitmapFactory.decodeFile(file);
} catch (OutOfMemoryError e2) {
e2.printStackTrace();
// handle gracefully.
}
}
I did something like this: I catch the error only for try to scale down the image until it works. Eventually it can not work at all; then returns null; otherwise, in success, returns the bitmap.
Outside I decide what to do with the bitmap whether it's null or not.
// Let w and h the width and height of the ImageView where we will place the Bitmap. Then:
// Get the dimensions of the original bitmap
BitmapFactory.Options bmOptions= new BitmapFactory.Options();
bmOptions.inJustDecodeBounds= true;
BitmapFactory.decodeFile(path, bmOptions);
int photoW= bmOptions.outWidth;
int photoH= bmOptions.outHeight;
// Determine how much to scale down the image.
int scaleFactor= (int) Math.max(1.0, Math.min((double) photoW / (double)w, (double)photoH / (double)h)); //1, 2, 3, 4, 5, 6, ...
scaleFactor= (int) Math.pow(2.0, Math.floor(Math.log((double) scaleFactor) / Math.log(2.0))); //1, 2, 4, 8, ...
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds= false;
bmOptions.inSampleSize= scaleFactor;
bmOptions.inPurgeable= true;
do
{
try
{
Log.d("tag", "scaleFactor: " + scaleFactor);
scaleFactor*= 2;
bitmap= BitmapFactory.decodeFile(path, bmOptions);
}
catch(OutOfMemoryError e)
{
bmOptions.inSampleSize= scaleFactor;
Log.d("tag", "OutOfMemoryError: " + e.toString());
}
}
while(bitmap == null && scaleFactor <= 256);
if(bitmap == null)
return null;
For example, with an image of 3264x2448, the loop iterates 2 times on my phone, and then it works.
You'd want to catch it if you want to display either a smaller image / different image / show a custom error message to the user.
Your image access wrapper can catch these errors and return some custom error codes defined within your code; your activity that uses this code can decide what to do with the error code - warn user, force him to exit with a better error message than the one the android system would provide, etc.
Btw, you are not using the options variable in your sample code.
Though it might not be a good idea to catch OutOfMemoryError using try-catch. But, sometimes you have no choice, because all of us hate app crashes.
So, what you can do is
Catch OutOfMemoryError using try-catch
Since, after this error your activity may become unstable, restart it.
You may disable animations so that user doesn't know that activity is restarted.
You may put some extra data in intent to know that app was crashed during previous run.
How I did is:
try {
//code that causes OutOfMemoryError
} catch (Exception e) {
// in case of exception handle it
e.printStackTrace();
} catch (OutOfMemoryError oome)
{
//restart this activity
Intent i=this.getIntent();
i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); //disable animation
//EXTRA_ABNORMAL_SHUTDOWN is user defined
i.putExtra(this.EXTRA_ABNORMAL_SHUTDOWN, true);
//put extra data into intent if you like
finish(); //and finish the activity
overridePendingTransition(0, 0);
startActivity(i); //then start it(there is also restart method in newer API)
return false;
}
And then on onCreate of Activity you can resume(something like this):
boolean abnormalShutdown=getIntent().getBooleanExtra(this.EXTRA_ABNORMAL_SHUTDOWN, false);
if (abnormalShutdown)
{
//Alert user for any error
//get any extra data you put befor restarting.
}
This approach saved my app.
Hope it helps you too!!

Categories

Resources