Search code examples
androidcanvasimageviewpaintresolution

How to draw "crisp and sharp" lines on an low resolution ImageView?


I am drawing lines on an ImageView by doing something like this:

Bitmap imageBitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
Bitmap duplicateBitmap = Bitmap.createBitmap(imageBitmap.getWidth(),imageBitmap.getHeight(),Bitmap.Config.RGB_565);

Canvas targetCanvas = new Canvas(duplicateBitmap);
targetCanvas.drawBitmap(imageBitmap,0,0,null);
Paint paint = new Paint();
targetCanvas.drawLine(0f,100f, imageBitmap.getWidth(),100f,paint);
imageView.setImageDrawable(new BitmapDrawable(getResources(),duplicateBitmap));

This works fine when the Image has a decent or good resolution.

But it looks like this when the image has a low resolution. (Which is a bad experience)

Now, how do I draw sharp and crisp lines on a low res image?

For once I thought I should mask the image with a high res canvas. But then I was clueless about how to proceed with this idea. Also, this might be a memory inefficient implementation.


Solution

  • I finally figured out with @D. Karchnak's guidance...

    Let's say your phone's screen is 1080x1920, you create a layout with a fullscreen ImageView, therefore this ImageView is also 1080x1920. Now you load a .png image as a BitmapDrawable. This PNG image has a resolution of 400x400, therefore the bitmap inside BitmapDrawable is also 400x400. If you draw this "small" bitmap to a fullscreen ImageView, it will get blurred out, because of low resolution. If you draw a line to this 400x400 bitmap, this line will also get blurred out. That's also why it works with decent or good resolution.

    All I need to do is, create a subclass of android's ImageView and then shift my drawing logic into the onDraw method (of course after overriding it). Like so:

    public class FineLineImageView extends AppCompatImageView {
    
        public FineLineImageView(Context context) {
            this(context, null);
        }
    
        public FineLineImageView(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public FineLineImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        protected void onDraw(final Canvas canvas) {
            super.onDraw(canvas);
            // logic for drawing goes here
        }
    }