Android Camera pick image and upload - android

I have written code to capture photo and upload the captured image to the Facebook.It worked great for all the devices but when i try to run the app on Samsung galaxy s3,the app got crashed and given outofmemory error and when i compressed the image it showing Null-pointer exception.
Intent intent = new Intent(
MediaStore.ACTION_IMAGE_CAPTURE);
this.file = new File(
Environment
.getExternalStorageDirectory(),
"tmp_"
+ String.valueOf(System
.currentTimeMillis())
+ ".jpg");
ImageCaptureUri = Uri.fromFile(file);
try {
intent.putExtra(
android.provider.MediaStore.EXTRA_OUTPUT,
ImageCaptureUri);
intent.putExtra("return-data", true);
startActivityForResult(intent,
PICK_FROM_CAMERA);
} catch (Exception e) {
e.printStackTrace();
}
::onActivityResult
uploadBitmap= decodeFile(MainActivity.this.file);
int width = uploadBitmap.getWidth()/3;
int height = uploadBitmap.getHeight()/3;
// uploadBitmap=Bitmap.createScaledBitmap(uploadBitmap, 50, 50, false);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
uploadBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] byteArray = stream.toByteArray();
// Bitmap bitmap = BitmapFactory.decodeFile(path);
if (photoUrl != null) {
Bundle params = new Bundle();
params.putByteArray("photo", byteArray);
params.putString("caption",
MainActivity.locationData+" lat: "+MainActivity.latitude+" long:"+MainActivity.longitude);
String place ="\"location\""+": {"+
"\"latitude\""+":"+"\"12.9833\""+","+
"\"longitude\""+":"+"\"77.5833\""+
"}";
params.putString("place", placeid);
Utility.mAsyncRunner.request("me/photos", params, "POST",
new PhotoUploadListener(), null);
} else {
Toast.makeText(getApplicationContext(),
"Error capturing image",
Toast.LENGTH_SHORT).show();
}

try to decode as below
public static Bitmap decodeFile(File f,int WIDTH,int HIGHT){
try {
//Decode image size
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=WIDTH;
final int REQUIRED_HIGHT=HIGHT;
//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);
} catch (FileNotFoundException e) {}
return null;
}

Related

Android - Setting wallpaper from file path takes longer than expected

I'm trying to set wallpaper from file path. However it takes more than 10 seconds and causes my app to freeze.
Here's the code I'm using:
public void SET_WALLPAPER_FROM_FILE_PATH (String file_path)
{
Bitmap image_bitmap;
File image_file;
FileInputStream fis;
try {
WallpaperManager wallpaper_manager = WallpaperManager.getInstance(m_context);
image_file = new File(file_path);
fis = new FileInputStream(image_file);
image_bitmap = BitmapFactory.decodeStream(fis);
wallpaper_manager.setBitmap(image_bitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
I have tried to use:
wallpaper_manager.setStream(fis)
instead of:
wallpaper_manager.setBitmap(image_bitmap);
as suggested in this answer but couldn't load the wallpaper.
Can anyone guide me?
Thanks
Try to use AsyncTask,
in doInBackground method write something like this
public static Bitmap decodeFile(File f,int WIDTH,int HIGHT){
try {
//Decode image size
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=WIDTH;
final int REQUIRED_HIGHT=HIGHT;
//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);
}
catch (FileNotFoundException e) {}
return null;
}

Saving bitmap to SdCard Android

I am writng a code to convert a png file back to bmp and save it on the sdcard. This is my current code.
FileInputStream in;
BufferedInputStream buf;
try {
in = new FileInputStream("File_Path_to_Read.png");
buf = new BufferedInputStream(in);
byte[] bMapArray= new byte[buf.available()];
buf.read(bMapArray);
Bitmap bMap = BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length);
//Code segment to save on file
int numBytesByRow = bMap.getRowBytes() * bMap.getHeight();
ByteBuffer byteBuffer = ByteBuffer.allocate(numBytesByRow);
bMap.copyPixelsToBuffer(byteBuffer);
byte[] bytes = byteBuffer.array();
FileOutputStream fileOuputStream = new FileOutputStream("File_Path_To_Save.bmp");
fileOuputStream.write(bytes);
fileOuputStream.close();
if (in != null) {
in.close();
}
if (buf != null) {
buf.close();
}
} catch (Exception e) {
}
I am having problem in saving the bMap to the Sdcard. All the examples I found use bMap.compress(). Using this method I can't save as bmp. Can someone give an example on how to save the bitmap on the Sdcard?
Edit:
I can now save the file as .bmp to sdcard. However it won't get to the original size. Any sugguestions on converting the PNG to BMP?
File root = new File(Environment.getExternalStorageDirectory()
+ File.separator + "My_Folder" + File.separator);
root.mkdirs();
File myFile = new File(root, "ABC.jpg");
Bitmap bitmap = decodeFile(myFile, 800, 600);
OutputStream out = null;
File file = new File(mediaStorageDir.getAbsoluteFile() + "/DEF.jpg");
try {
out = new FileOutputStream(file);
bitmap .compress(Bitmap.CompressFormat.JPEG, 80, out);
out.flush();
out.close();
bitmap.recycle();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
public static Bitmap decodeFile(File f, int WIDTH, int HIGHT) {
try {
// Decode image size
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 = WIDTH;
final int REQUIRED_HIGHT = HIGHT;
// Find the correct scale value. It should be the power of 2.
int scale = 2;
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);
} catch (FileNotFoundException e) {
}
return null;
}

Camera Preview Out of Memory Error

Objective of the program: the user is able to place one picture on the top of camera preview and move it freely (image is big 1920x1080 pixels) and can store this two layers (picture and camera preview) pressing the photo button. So far he is only able to save one picture of this kind because when he takes the second one the out of memory error problem appears.
Solution It seems that the problem can be solved if you use recycle bitmap function when you dont need to use bitmaps anymore. Or you can resize them (didn't want to)... Are these good ideas?
Code:
private PictureCallback mPicture = new PictureCallback()
{
#Override
public void onPictureTaken(byte[] data, Camera camera)
{
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
mPreview.setDrawingCacheEnabled(true);
mPreview.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_AUTO);
Bitmap bitmap = mPreview.getDrawingCache();
bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
combination = overlay(bmp, bitmap);
if(pictureFile == null)
{
return;
}
try
{
FileOutputStream fos = new FileOutputStream(pictureFile);
combination.compress(CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://"+ mediaStorageDir)));
}
catch(FileNotFoundException e)
{
Log.d(TAG, "File not found: "+e.getMessage());
}
catch(IOException e)
{
Log.d(TAG, "Error accessing file: "+e.getMessage());
}
}
};
public static Bitmap overlay(Bitmap bmp1, Bitmap bmp2)
{
Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(),bmp1.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(bmp1, new Matrix(), null);
canvas.drawBitmap(bmp2, null, new Rect(0,0,bmp1.getWidth(), bmp1.getHeight()), null);
return bmOverlay;
}
private static File getOutputMediaFile(int type)
{
File mediaFile = null;
if(isSdPresent() == false)
{
Log.d(TAG, "There is no Sd card. Cannot use the camera");
}
else
{
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "World Cup Camera");
if(!mediaStorageDir.exists())
{
if(!mediaStorageDir.mkdirs())
{
Log.d("WorldCupApp", "failed to create directory");
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
if (type == MEDIA_TYPE_IMAGE)
{
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg");
}
else
{
return null;
}
}
return mediaFile;
}
I heard about this code should I use?
private Bitmap decodeFile(File f)
{
try
{
//Decode image size
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_SIZE=70;
//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.decodeStream(new FileInputStream(f), null, o2);
}
catch (FileNotFoundException e) {}
return null;
}
You can use android:largeHeap="true" inside the application tag on AndroidManifest when you're having outofmemory errors.

Cant start new activity from onActivityResult method in main activity

I have used following method to get image after calling photo gallery intent. I want to start another activity by passing the bitmap of that image and show that image in the second activity. But, nothing will happen after a photo is picked from photo gallery.
protected void onActivityResult(int requestCode, int resultCode, Intent
data) {
final String path;
if (requestCode == GALLERY_REQUEST) {
if (resultCode == Activity.RESULT_OK) {
Uri imageFileUri = data.getData();
if (imageFileUri != null) {
try {
path = getPath(imageFileUri);
BitmapFactory.Options load_option = new BitmapFactory.Options();
load_option.inPurgeable = true;
load_option.inDensity = 0;
load_option.inTargetDensity = 0;
load_option.inDensity = 0;
load_option.inScaled = false;
bmp_main = BitmapFactory.decodeFile(path, load_option);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp_main.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
Intent intentPhoto = new Intent(MainActivity.this, SecondActivity.class);
intentPhoto.putExtra("image",byteArray);
startActivity(intentPhoto);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
Can anybody tell what's the problem?
N.B.: 1.I have added the activity in the manifest
2. There is no logcat error or exception regarding this
3. I have done debugging, it goes upto startActivity line correctly, but after that nothing happen
Use below code...
if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK
&& null != data) {
Uri contentUri = data.getData();
startActivity(new Intent(this, ViewGallery_Photo.class)
.setData(contentUri));
}
So in onActivityResult there are 2 logic
1) if you are loading images from gallery then it will take you to other activity
2) if you are capturing image from camera then it will take you to other activity not the same activity which is calling by gallery ...
Call this out of your if condition:
Intent intentPhoto = new Intent(MainActivity.this, SecondActivity.class);
intentPhoto.putExtra("image",byteArray);
startActivity(intentPhoto);
Try this:
try {
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();
String fullPath = Environment.getExternalStorageDirectory()
.getAbsolutePath();
try {
File dir = new File(fullPath);
if (!dir.exists()) {
dir.mkdirs();
}
OutputStream fOut = null;
File file = new File(fullPath, "userImage" + ".png");
if (file.exists())
file.delete();
file.createNewFile();
fOut = new FileOutputStream(file);
fOut.flush();
fOut.close();
Log.v("Image saved", "in" + file);
} catch (Exception e) {
Log.e("saveToExternalStorage()", e.getMessage());
}
decodeFile(picturePath);
/*
* iv_display.setImageBitmap(mPhoto); Bitmap useThisBitmap =
* Bitmap.createScaledBitmap(mPhoto, mPhoto.getWidth(),
* mPhoto.getHeight(), true);
*/
ByteArrayOutputStream baos = new ByteArrayOutputStream();
myBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
bytepicture = baos.toByteArray();
Intent newdata = new Intent(MainMenu.this, SecondActivity.class);
newdata.putExtra("picture", bytepicture);
startActivity(newdata);
} catch (Exception e) {
// TODO: handle exception
Log.v("TAG", "No Image Selected:");
}
For decode file :
public void decodeFile(String filePath) {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, o);
// The new size we want to scale to
final int REQUIRED_SIZE = 1024;
// Find the correct scale value. It should be the power of 2.
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 3;
while (true) {
if (width_tmp < REQUIRED_SIZE && height_tmp < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
mPhoto = BitmapFactory.decodeFile(filePath, o2);
myBitmap = ExifUtils.rotateBitmap(filePath, mPhoto);
// image.setImageBitmap(bitmap);
}

Android OutOfMemoryException taking a picture with camera

I'm trying to take a picture and add an overlay on top of it. Here is my code (only the callback) :
private PictureCallback mPicture = new PictureCallback() {
#Override
public void onPictureTaken(final byte[] data, Camera camera) {
if(!dirFile.exists()){
dirFile.mkdirs();
}
try {
String name = new SimpleDateFormat("ddMMyyyy_HHmmss").format(new Date()) + ".jpg";
picturePath = new File(dirFile, name);
new AsyncTask<Void, Void, Void>(){
FileOutputStream fos = new FileOutputStream(picturePath);
Bitmap photo;
#Override
protected Void doInBackground(Void... params) {
photo = BitmapFactory.decodeByteArray(data, 0, data.length).copy(Config.ARGB_8888, true);
Bitmap cadre = BitmapFactory.decodeResource(getResources(), R.drawable.cadre16001200);
Canvas canvas = new Canvas(photo);
canvas.drawBitmap(cadre, new Matrix(), null);
cadre.recycle();
photo.compress(CompressFormat.JPEG, 100, fos);
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
geotag(picturePath.toString());
return null;
}
protected void onPostExecute(Void result) {
dialog.dismiss();
mCamera.startPreview();
//Affiche la nouvelle photo
picture.setImageBitmap(photo);
};
}.execute();
} catch (FileNotFoundException e) {
Log.d("PhotoActivity", "File not found: " + e.getMessage());
}
}
};
I get the following error on my Samsung Galaxy S3 (android 4.1.2) , with an OutOfMemoryException
07-04 10:01:24.076: E/dalvikvm-heap(2980): Out of memory on a 7680016-byte allocation.
Weird thing is that it works perfectly on the Samsung Gio (android 2.2.1) with the same resolution of 1600x1200.
I googled a lot, and I can't use the main solution of downsizing the picture. It is a memory issue, but I don't know how I can reduce the memory usage.
EDIT : I found this, seems it was the real matter : https://stackoverflow.com/a/12377158/1343969
you should decode the bitmap before proccessing it to the UI, here's a code example
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream stream1=new FileInputStream(f);
BitmapFactory.decodeStream(stream1,null,o);
stream1.close();
//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=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;
FileInputStream stream2=new FileInputStream(f);
Bitmap bitmap=BitmapFactory.decodeStream(stream2, null, o2);
stream2.close();
return bitmap;
} catch (FileNotFoundException e) {
}
catch (IOException e) {
e.printStackTrace();
}
return null;
}
You should simply call the empty constructor of Canvas and draw the photo on it. This would remove the copy() call and reduce the memory usage.
photo = BitmapFactory.decodeByteArray(data, 0, data.length);
Bitmap cadre = BitmapFactory.decodeResource(getResources(), R.drawable.cadre16001200);
Canvas canvas = new Canvas();
canvas.drawBitmap(photo, 0, 0, null);
canvas.drawBitmap(cadre, new Matrix(), null);
cadre.recycle();
photo.compress(CompressFormat.JPEG, 100, fos);

Categories

Resources