I am trying to make a simple image gallery through which I can set wallpaper; I am using the below code to fetch the files from download folder and display it in scroll view.
I am able to do that, but now I want to fetch the currently displayed image so that I can set that image as wallpaper.
Below is the code I have for my activity class:
public class MainActivity extends Activity {
LinearLayout myGallery;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myGallery = (LinearLayout)findViewById(R.id.mygallery);
String ExternalStorageDirectoryPath = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
.getAbsolutePath();
String targetPath = ExternalStorageDirectoryPath ;
Toast.makeText(getApplicationContext(), targetPath, Toast.LENGTH_LONG).show();
File targetDirector = new File(targetPath);
File[] files = targetDirector.listFiles();
for (File file : files){
myGallery.addView(insertPhoto(file.getAbsolutePath()));
}
}
View insertPhoto(String path){
Bitmap bm = decodeSampledBitmapFromUri(path, 520, 520);
LinearLayout layout = new LinearLayout(getApplicationContext());
layout.setLayoutParams(new LayoutParams(550, 550));//Size of view
layout.setGravity(Gravity.CENTER);
ImageView imageView = new ImageView(getApplicationContext());
imageView.setLayoutParams(new LayoutParams(520, 520));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setImageBitmap(bm);
layout.addView(imageView);
return layout;
}
public Bitmap decodeSampledBitmapFromUri(String path, int reqWidth, int reqHeight) {
Bitmap bm = null;
// 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;
bm = BitmapFactory.decodeFile(path, options);
return bm;
}
public 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) {
if (width > height) {
inSampleSize = Math.round((float)height / (float)reqHeight);
} else {
inSampleSize = Math.round((float)width / (float)reqWidth);
}
}
return inSampleSize;
}
}
Please tell me how I can fetch the image which is currently displayed in the scroll view.
Thanks
Aman
its been 5 months yet not answered, but i think i will try to answer it.
I think you need a custom view ie. with canvas. create a canvas and then create a bitmap in canvas. After that when you get a bitmap from linear layout in the form of URI, in your code a method decodeSampledBitmapFromUri you are getting a bitmap, simply assign the bitmap to the created bitmap on the canvas.
Related
Is it possible to add border to a image without showing the image to the user in android.
Like google photo scan app..Here a border is added to image with photoscan logo
You can use this this library
implementation 'com.github.siyamed:android-shape-imageview:0.9.+#aar'
in Xml File
<com.github.siyamed.shapeimageview.BubbleImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/neo"
app:siArrowPosition="right"
app:siSquare="true"/>
Designed a custom layout with a image view
Inflated it to a view object
Set the my image to that image view in layout
Drawn the view to a bitmap and saved it
Code for inflating and drawing
public Bitmap drawToBitmap(Context context, final int layoutResId,
final int width, final int height, String imageDescription) {
final Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bmp);
final LayoutInflater inflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View layout = inflater.inflate(layoutResId, null);
ImageView img = layout.findViewById(R.id.imgAnalysedBitmap);
img.setImageBitmap(croppedBitmap);
layout.setDrawingCacheEnabled(true);
layout.measure(
View.MeasureSpec.makeMeasureSpec(canvas.getWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(canvas.getHeight(), View.MeasureSpec.EXACTLY));
layout.layout(0, 0, layout.getMeasuredWidth(), layout.getMeasuredHeight());
canvas.drawBitmap(layout.getDrawingCache(), 0, 0, new Paint());
return bmp;
}
Usage:
final DisplayMetrics metrics = getResources().getDisplayMetrics();
Bitmap bmap = drawToBitmap(this, R.layout.layout_watermark, metrics.widthPixels, metrics.heightPixels, imageDescription);
In my app, I have it so that a button rotates a bitmap 90 degrees each time it is pressed. I have another button that does the same thing but rotates the bitmap -90 degrees.
My issues is that after I press the rotate buttons about 4-6 times, it varies per picture, in any order, I get the error:
`java.lang.NullPointerException`: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference.
Why is this error occurring when the rotation fxn works fine the first few times? I have noticed that the width and height of the bitmap increase each time the rotate button is pushed but that shouldn't crash the app if they are larger than the imageview. I've tried multiple other methods but they seem to crash or just shrink the image.
This is my code:
rotateClockWise.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
Bitmap bitmap = imageViewtoBitmap(imageView);
int width = bitmap.getWidth();
Log.i(TAG, Integer.toString(width));
int height = bitmap.getHeight();
Log.i(TAG, Integer.toString(height));
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
width, height, matrix, true );
imageView.setImageBitmap(rotatedBitmap);
}
});
rotateCCW.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
Bitmap bitmap = imageViewtoBitmap(imageView);
int width = bitmap.getWidth();
Log.i(TAG, Integer.toString(width));
int height = bitmap.getHeight();
Log.i(TAG, Integer.toString(height));
Matrix matrix = new Matrix();
matrix.postRotate(-90);
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
bitmap.getWidth(), bitmap.getHeight(), matrix, true );
imageView.setImageBitmap(rotatedBitmap);
}
});
public static Bitmap imageViewtoBitmap(ImageView imageView){
/**
* Args:
* imageview: an imageview
* Returns:
* the bitmap of the imageview
*/
//convert imageview to bitmap
imageView.setDrawingCacheEnabled(true);
// Without it the view will have a dimension of 0,0 and the bitmap will
be null
imageView.measure(View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED));
// hardcoded so i always know how big image is
imageView.layout(0, 0, imageView.getMeasuredWidth(),
imageView.getMeasuredHeight());
if (imageView == null){
Log.i(TAG, "nothing");
}
imageView.buildDrawingCache(true);
Bitmap bitmapImage = Bitmap.createBitmap(imageView.getDrawingCache());
imageView.setDrawingCacheEnabled(false); // clear drawing cache
return bitmapImage;
}
You should delay click.
Example
in onCreate()
rotateClockWise.setOnClickListener(this);
rotateCCW.setOnClickListener(this);
in method onClick
private long lastClick = 1;
void onClick(View view) {
if(SystemClock.elapsedRealtime() - lastClick < 500) return;
lastClick = SystemClock.elapsedRealtime();
switch (view.getId()) {
case R.id.rotateClockWise: // change id of rotateClockWise
break;
case R.id.rotateCCW: // change id of rotateCCW
break;
}
}
I have a ArrayList with two columns and I display a image with text below. I am using high quality images and need to display those images in the grid view with a decent quality for which I am using BitmapFactory.Options. I am using the same code from google but that still throws me an OutOfMemory error.
CODE :
BitmapFactory.Options obj = new BitmapFactory.Options();
obj.inPurgeable = true;
obj.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.drawable.car, obj);
BitmapFactory.decodeResource(getResources(), R.drawable.nature, obj);
obj.inSampleSize = 4;
obj.inJustDecodeBounds = false;
Bitmap homeIcon = BitmapFactory.decodeResource(getResources(), R.drawable.car,obj);
Bitmap userIcon = BitmapFactory.decodeResource(getResources(), R.drawable.nature,obj);
gridArray.add(new Item(homeIcon,"Home"));
gridArray.add(new Item(userIcon,"User"));
gridArray.add(new Item(homeIcon,"House"));
gridArray.add(new Item(userIcon,"Friend"));
gridArray.add(new Item(homeIcon,"Home"));
gridArray.add(new Item(userIcon,"Personal"));
gridArray.add(new Item(homeIcon,"Home"));
gridArray.add(new Item(userIcon,"User"));
gridArray.add(new Item(homeIcon,"Building"));
gridArray.add(new Item(userIcon,"User"));
gridArray.add(new Item(homeIcon,"Home"));
gridArray.add(new Item(userIcon,"xyz"));
UPDATE :
Item.java :
public class Item {
Bitmap image;
String title;
public Item(Bitmap image, String title) {
super();
this.image = image;
this.title = title;
}
public Bitmap getImage() {
return image;
}
public void setImage(Bitmap image) {
this.image = image;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
This is the code and I have another class name Item which has a constructor with arguments as Bitmap and String. While executing this, it throws me an OutOfMemoryError. I am not sure whether I should add any other extras in these code. Any help will be appreciated guys.
This Error occurs usually when loading large bitmaps. Are the drawables for you ImageButtons high resolution? If so, this is likely the error. You try downsampling them to their appropriate resolution, but for a quick-fix, adding android:largeHeap="true" under the <application> tag of your AndroidManifest.xml file can sometimes allow your application to load large images without an out of memory error.
The reason you use the same code from Google yet still receive the out of memory error is not just the high resolution of the bitmaps, but also the large amount you are loading at once.
Adding a small wait between them can spread the load and make a cute little animation depending on you layout, just an idea (But of course don't do it on the UI Thread).
Good Luck!
You can try to use android:largeHeap="true" inside the application tag on AndroidManifest to avoid some out of memory erros on your app. It will let your app to use more ram.
try removing first two decode statements made in fly which are causing the problem as your bitmaps are loaded there without sampling
you can modify below code according to your need.I hope it will help you.
Bitmap imageProcess(String path) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
imageBitmap = BitmapFactory.decodeFile(path, options);
options.inSampleSize = calculateInSampleSize(options,
displayMetrics.widthPixels,
(int) (displayMetrics.heightPixels * .75));
options.inJustDecodeBounds = false;
imageBitmap = BitmapFactory.decodeFile(path, options);
return imageBitmap;
}
public int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height
/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio > widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
I follow the example in this link :
Viewpager Example in android
its work fine but when i placed my own high resolution images (large in size ), it gave me exception :
java.lang.OutOfMemoryError: bitmap size exceeds VM budget.
i post an old question about that but it closed coz its duplicated for that reason , i tried and searched alot, finally i found the solution which is : scaling my images to avoid memory exception by following :
author advice and answers here in stackfllow and android development site , i ended with the bellow code , which also end with same exception, i think there is some wrong in my code coz im still learning java and android development , but that what i can end with , please any help or advice will be appreciated ,
thanks .
my code:
ViewPagerAdapter
public class ViewPagerAdapter extends PagerAdapter {
Activity activity;
int imageArray[];
public ViewPagerAdapter(Activity act, int[] imgArra) {
imageArray = imgArra;
activity = act;
}
public int getCount() {
return imageArray.length;
}
public Object instantiateItem(View collection, int position) {
ImageView view = new ImageView(activity);
view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
view.setScaleType(ScaleType.FIT_XY);
view.setBackgroundResource(imageArray[position]);
((ViewPager) collection).addView(view, 0);
return view;
}
#Override
public void destroyItem(View arg0, int arg1, Object arg2) {
((ViewPager) arg0).removeView((View) arg2);
}
#Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == ((View) arg1);
}
#Override
public Parcelable saveState() {
return null;
}
public static Bitmap decodeSampledBitmapFromResource(String imageArra,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imageArra, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(imageArra, 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) {
if (width > height) {
inSampleSize = Math.round((float)height / (float)reqHeight);
} else {
inSampleSize = Math.round((float)width / (float)reqWidth);
}
}
return inSampleSize;}}
PageIndicatorActivity:
public class PageIndicatorActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPagerAdapter adapter = new ViewPagerAdapter(this, imageArra);
ViewPager myPager = (ViewPager) findViewById(R.id.myfivepanelpager);
myPager.setAdapter(adapter);
myPager.setCurrentItem(0);
}
private int imageArra[] = { R.drawable.one, R.drawable.two,
R.drawable.three, R.drawable.four,
R.drawable.five, R.drawable.six,
R.drawable.seven, R.drawable.eight,R.drawable.nine,
R.drawable.ten }; }
logcat stack :
FATAL EXCEPTION: main
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:563)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:439)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
at android.content.res.Resources.loadDrawable(Resources.java:1709)
at android.content.res.Resources.getDrawable(Resources.java:581)
at android.view.View.setBackgroundResource(View.java:7586)
at com.horizontalscrollviewwithpageindicator.ViewPagerAdapter.instantiateItem
(ViewPagerAdapter.java:33)
at android.support.v4.view.PagerAdapter.instantiateItem(PagerAdapter.java:110)
at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:692)
at android.support.v4.view.ViewPager.populate(ViewPager.java:875)
at android.support.v4.view.ViewPager.populate(ViewPager.java:772)
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1234)
at android.view.View.measure(View.java:8366)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1017)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:386)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:309)
at android.view.View.measure(View.java:8366)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)
at android.view.View.measure(View.java:8366)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)
at android.view.View.measure(View.java:8366)
at android.view.ViewRoot.performTraversals(ViewRoot.java:844)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1865)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3687)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)
Try the following tips.
- Android works well with .png images, where the same size image in .jpg format creates a OutOfMemoryError.
See this link for the solution from official Android Developers Site:
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
You never use the method to scale the images, also your inSampleSize needs to be a power of two(i believe). These images are way too big (4.5 mb that you stated in your previous post). On top of a huge bitmap being stored, the view pager keeps 3 views in memory at any given time. Your memory allocated for your view pager is something like >13.5mb. Replace your instantiate view with the following:
ImageView myView = new ImageView(context);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
Bitmap bitmap = BitmapFactory.decodeResource(activity.getResouces(), imageArray[position], options );
myView.setImageBitmap(bitmap);
((ViewPager) view).addView(myView);
return myView;
If this still provides an error, use options.inSampleSize = 8;
I am getting the current wallpaper by using following code:
final WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
final Drawable wallpaperDrawable = wallpaperManager.getDrawable();
How can I create a bitmap from this?
like when I create a bitmap from res folder I use this
Resources res = getApplicationContext().getResources();
b = BitmapFactory.decodeResource(res, R.drawable.wall);
What code I should use to get current wallpaper into the bitmap so I can draw it on my canvas and use it as my live wallpaper background?
The Drawable fetched should really be a BitmapDrawable. You can verify this using instanceof if necessary.
That being the case, all you have to do is:
final Drawable wallpaperDrawable = wallpaperManager.getDrawable();
final Bitmap wallpaperBitmap = ((BitmapDrawable) wallpaperDrawable).getBitmap();
EDIT: If it turns out that the Drawable is NOT a BitmapDrawable, you can use the following method to convert it (found in this answer, credit to André):
public static Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable)drawable).getBitmap();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}