Really basic stuff with Glide - android

So I have a basic question about Glide. Im doing an android test application and just want to transform an image to fit the screen.
This was the old code:
Bitmap background, backgroundresized;
(...)
//load image
background = BitmapFactory.decodeResource(context.getResources(), R.drawable.gamebackground);
}
void onDraw(Canvas canvas) {
if(first_time){
width = canvas.getWidth();
height = canvas.getHeight();
backgroundresized = Bitmap.createScaledBitmap(background, width, height, true);
first_time=false;
}
canvas.drawBitmap(backgroundresized, 0, 0, null);
}
This isn't the best approach to fit a screen, I know, I use this and drawable-xhdpi/xxhdpi/xxxhdpi folders.
But how to use Glide to do this, and hopefully recycle the image if the user comes back to this screen?

Allright, there are different ways to do, but easy way to keep static instance of that class because glide stays as inner class when you try to assign to upper. check following sample code
public class SomeActivity extends Activity {
static Bitmap somebitmap;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int myWidth = 512;
int myHeight = 384;
Glide.with(this)
.asBitmap()
.load("URL")
.into(new SimpleTarget<Bitmap>(myWidth, myHeight) {
#Override
public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {
somebitmap = resource;
}
});
}
}

Related

How to stop Glide upscaling?

I am using the Glide image loading library and I'm having issues when it comes to resizing bitmaps.
When using the following code:
Glide.with(getActivity())
.load(images.get(i))
.asBitmap().centerCrop()
.into(new SimpleTarget<Bitmap>(1200, 1200) {
#Override
public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
}
});
Every single bitmap gets resized to the specified dimensions. So, if the image is 400x300, it gets upscaled up to 1200 x 1200 which I do not want. How do I make it so that if the image is smaller than the specified dimensions, it won't resize it?
I'm specifying dimensions because I want every image that's bigger than the specified dimensions to be resized taking into account centerCrop; and then if the image is smaller than the specified dimensions, I don't want it to be resized.
I want every image that's bigger than the specified dimensions to be
resized taking into account centerCrop; and then if the image is
smaller than the specified dimensions, I don't want it to be resized.
You can obtain this behaviour with a custom transformation:
public class CustomCenterCrop extends CenterCrop {
public CustomCenterCrop(BitmapPool bitmapPool) {
super(bitmapPool);
}
public CustomCenterCrop(Context context) {
super(context);
}
#Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
if (toTransform.getHeight() > outHeight || toTransform.getWidth() > outWidth) {
return super.transform(pool, toTransform, outWidth, outHeight);
} else {
return toTransform;
}
}
}
and then use it like this:
Glide.with(getActivity())
.load(images.get(i))
.asBitmap()
.transform(new CustomCenterCrop(getActivity()))
.into(new SimpleTarget<Bitmap>(1200, 1200) {
#Override
public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
}
});

Android Glide: How to download bitmap at specific size?

I'm using Glide to load images on Scale ImageView - it is a custom view with pan and zoom gestures. I should pass Bitmap object to this custom view in order to set picture.
So I can use Glide's .asBitmap() with SimpleTarget:
private SimpleTarget target = new SimpleTarget<Bitmap>() {
#Override
public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {
scaleImageView.setImage(ImageSource.bitmap(bitmap));
}
};
private void loadImageSimpleTarget() {
Glide
.with(context)
.load(url)
.asBitmap()
.into(target);
}
This code snippet works well, but I will get fullsize Bitmap, which can lead to OutOfMemoryErrors. Also I could specify desired Bitmap size on constructor like this: ...new SimpleTarget<Bitmap>(250, 250)..., but I would have to manually calculate dimensions.
Is there a possibility to pass view (instance of CustomView) to Glide's request, so dimensions will calculated automatically and receive Bitmap object as a result?
Continuing the discussion from the comments, you get 0 for width and height when calling it from onCreateView. However, you can set a listener to be notified when the bounds of the view are actually calculated and then you can get the real width and height by calling getWidth or getHeight:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// ...
// your other stuff
// ...
// set listener
customView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Log.d("debug", "width after = " + customView.getHeight());
// pass the width and height now that it is available
target = new SimpleTarget<Bitmap>(customView.getWidth(), customView.getHeight()) {
#Override
public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {
scaleImageView.setImage(ImageSource.bitmap(bitmap));
}
};
// remove listener, we don't need to be notified again.
customView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
}

ImageView Resizing On Orientation changes

I have a question regarding the process of resizing an ImageView Have on orientation changes.
I have to place a bitmap on the top of an image view. (Basically a marker placed by the user when touching it). On orientation change, I store the relatives position of the marker and intent to restaure it when the image is re-displayed.
for now I do it this way :
on restauration I call this :
handler.post(setCollectedAnswersRunnable);
refering to this :
Runnable setCollectedAnswersRunnable = new Runnable() {
#Override
public void run() {
if (iv.getMeasuredHeight() != 0) {
int x = Math.round(coordinateCollectedAnswer.x * iv.getMeasuredWidth() / (float) question.getImage().getWidth());
int y = Math.round(coordinateCollectedAnswer.y * iv.getMeasuredHeight() / (float) question.getImage().getHeight());
selectedX = x;
selectedY = y;
addPointerImageView(x, y);
} else {
handler.postDelayed(this, 330);
}
}
};
The important thing to note is this works very well when I go from a larger ImageView to a smaller one ie when passing from landscape to portrait.
But in the other way, it doesn't. The ImageView seems to be restaured first with the same size and then scaling up witch mess my marker up. So I certainely could check if it's the same size as in portrait in addition to the !=0 condition in my runnable. but first I'm not very proud of that way to do it, I'd rather be notified when the ImageView get it's final sizing. And I would prefer not passing the viewsize in my state bundle.
Is there a simpler way to achieve this ?
By the way I load the ImageView this way :
Picasso.with(iv.getContext())
.load(AppConstants.SERVER_URL + "/api/" + question.getImage().getUrl())
.config(Bitmap.Config.RGB_565)
.into(new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
iv.setImageBitmap(bitmap);
iv.setAdjustViewBounds(true);
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
I´ve got a SurfaceView that keeps to be square. i´ve notice thatn when android runtime is doing all the stuff for layout will measure the component again and again and you never can tell when is the last time and the number of executions does not seem to be related to the amount of components on the screen, it is not random but maybe has something to do with the layout constraints of all the stuff around.
here´s my class overriding the measure ion order to keep square:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int w = MeasureSpec.getSize(widthMeasureSpec);
int h = MeasureSpec.getSize(heightMeasureSpec);
int size = w;
if (w < h) {
setMeasuredDimension(widthMeasureSpec, widthMeasureSpec);
} else {
size = h;
setMeasuredDimension(heightMeasureSpec, heightMeasureSpec);
}
if (h > 0 && squareSurfaceViewListener != null) {
squareSurfaceViewListener.onChangeSize(size);
}
}
So I´d inherit the imageview, detect the change and reload the image.
Using picasso it´ll cache the stuff but, maybe, you could forget about that and call for a new load each time the component is measured or add some kind of observer in the middle.

Stuttering Animation

I wrote an application which has an Image which fit to the whole screen.
The Image.resource is a png with the size 768x1024 pixel.
<ImageView
android:id="#+id/imgage1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:src="#drawable/imagepng" />
The code to animate this Imageview is as follows:
public void animate(int percent) {
height = imgage1.getMeasuredHeight()/100;
ObjectAnimator anim = ObjectAnimator.ofFloat(ActivityMain.this.imgage1, "translationY",ActivityMain.this.imgage1.getTranslationY(), - (percent*height));
ObjectAnimator.setFrameDelay(24);
anim.setDuration(5000);
anim.setInterpolator(new AccelerateDecelerateInterpolator());
anim.start();
}
unfortunately the animation stutters. I thought this stuttering comes from the scaletype "fitXY" because on every animationstepp the Imageview scales the png.
What can I do if I want to use fitXY with one PNG for all Windowsizes to eleminate the stuttering
Meanwhile I have found the reason why the animation is stuttering:
Because the scaletype of the Imageview is set to fitXY, the system renders on each frame a new scaled bitmap, that costs much performance.
So I dont attach the Bitmap by XML to the Imageview,. This work is done by a ncustom ImageView-Class:
public class CustomImageView extends ImageView {
Bitmap bitmapScaled;
Bitmap bitmapOrg;
public CustomImageView (Context context,AttributeSet attr) {
super(context,attr);
Resources mRes = context.getResources();
bitmapOrg = BitmapFactory.decodeResource(mRes, R.drawable.thepng);
}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawBitmap(bitmapScaled,0, 0, null);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if(bitmapScaled == null) {
bitmapScaled = Bitmap.createScaledBitmap(bitmapOrg,getMeasuredWidth(),getMeasuredHeight(),true);
}
}
}

Scale image within custom ImageView

I'm extending ImageView in order to manually scale an image within the view. I want to scale an image to fill the width of the custom view, and then draw it to the canvas, however, I'm unable to get the view width using this.getWidth()
It just returns 0, as the view has not yet been drawn and so has dimensions 0 by 0.
Currently I have the following in my main.xml:
<com.android.myapp.BackgroundView
android:id="#+id/background_view"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:src="#drawable/background"
android:dither="true"
/>
The custom class is as follows:
public class BackgroundView extends ImageView {
private Paint paint;
private Bitmap background;
public BackgroundView(Context context) {
super(context);
paint = new Paint();
loadBitmap();
}
public BackgroundView(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
loadBitmap();
}
public void loadBitmap() {
BitmapDrawable src = (BitmapDrawable) this.getDrawable();
background = src.getBitmap();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(background, 0, 0, paint);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
My Main.java class is:
public class Main extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
I can't use
Bitmap.createScaledBitmap(background, view.getWidth(), view.getHeight(), false)
as the view hasn't yet been drawn, how would I go about scaling the image to fill the view/screen width at this point?
Thanks in advance.
I believe what you want to do could also be achieved by using ImageView directly in conjunction with the scaleType attribute. Either use fitXY or centerCrop, depending on your needs.
But to answer the question, you can only use getWidth() and getHeight() after layout() has been called. So you should be able to use the values inside your onDraw method.
Also you could use another drawBitmap method so you wouldn't have to create a new bitmap in memory.

Categories

Resources