Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable anti-aliasing on Android Imageview

I'm showing 96x96 pixel art sprites in imageviews and can't get it to display without applying anti-aliasing (or at least some form of interpolation, if it isn't anti-aliasing), which ruins the sharp edge of the sprites.

How can this be done? I've tried the following methods I've picked up from around the internet, but none work.

METHOD ONE

creating an xml resource file with a bitmap, and setting the anti-alias flag to false. Didn't work at all

METHOD TWO

creating a bitmap object from the resource, and setting the anti-alias flag to false. Didn't work at all.

    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dryad_back_large);
    BitmapDrawable drawable = new BitmapDrawable(getResources(), bitmap);
    drawable.setAntiAlias(false);
    playerMonsterImageView.setImageDrawable(drawable);

METHOD THREE Using sprites which are large enough so that they will never need to be scaled down, only up (512x512 worked for me)

So this third method WORKS, but it seems really ham-fisted, and I was hoping there was a better way of going about this.

Maybe there's something other than anti-aliasing going on here that I've missed?

like image 628
Dportology Avatar asked Sep 03 '17 23:09

Dportology


2 Answers

There are multiple things that may be scaling your image with anti-aliasing.

One is BitmapFactory. For example, if you have a drawable-mdpi resource and the current resource configuration is xhdpi, it will scale at decode time. You can provide options to avoid this, but the easiest way around it is to put these resources in drawable-nodpi.

The canvas also scales the image with bilinear sampling by default. To avoid that, use a Paint with .setFilterBitmap(false) when drawing to the Canvas. One way to do that is by using a custom Drawable which wraps the underlying .draw() call with a DrawFilter modifying the desired paint flags.

public class AliasingDrawableWrapper extends DrawableWrapper {
    private static final DrawFilter DRAW_FILTER =
        new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0);

    public AliasingDrawableWrapper(Drawable wrapped) {
        super(wrapped);
    }

    @Override
    public void draw(Canvas canvas) {
        DrawFilter oldDrawFilter = canvas.getDrawFilter();
        canvas.setDrawFilter(DRAW_FILTER);
        super.draw(canvas);
        canvas.setDrawFilter(oldDrawFilter);
    }
}
imageView.setDrawable(new AliasingDrawableWrapper(getDrawable(R.drawable.bitmap)));
like image 62
ephemient Avatar answered Nov 09 '22 17:11

ephemient


In "METHOD TWO", set the filter of the Drawable to false with

drawable.setFilterBitmap(false);

instead of using the setAntialias method you mention.

like image 26
Pau Fernández Avatar answered Nov 09 '22 15:11

Pau Fernández