androidsvgandroidsvg

AndroidSVG fuzzy edges on image


I am want to display Barcode on android. As input I get SVG string. As a SVG library I use AndroidSVG. I used sample code from library website and everything seem to be fine. But when I zoom on image, I get distorted edges (Anti-alias?). I tried to disable all the flags. But the image still has fuzzy edges. What can be wrong with my code?

Picture: Try to zoom to max, you will see the fuzzy edges. enter image description here

Code:

private void loadQRCode(String svgString) {
    SVG svg = null;
    try {
        svg = SVG.getFromString(svgString);
    } catch (SVGParseException e) {
        e.printStackTrace();
    }

    if (svg.getDocumentWidth() != -1) {
        int widthPx = Utils.pxFromDp(400);
        int heightDp = Utils.pxFromDp(300);

        svg.setDocumentWidth(widthPx);
        svg.setDocumentHeight(heightDp);

        int width = (int) Math.ceil(svg.getDocumentWidth());
        int height = (int) Math.ceil(svg.getDocumentHeight());
        Bitmap newBM = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

        Canvas bmcanvas = new Canvas(newBM);
        final DrawFilter filter = new PaintFlagsDrawFilter(Paint.ANTI_ALIAS_FLAG| Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG, 0);
        bmcanvas.setDrawFilter(filter);

        barcode.setLayerType(View.LAYER_TYPE_SOFTWARE,null);
        bmcanvas.drawRGB(255, 255, 255);

        svg.renderToCanvas(bmcanvas);
        barcode.setImageBitmap(newBM);
    }
}

Solution

  • If the edges of the bars do not lie exactly on pixel boundaries, you will get anti-aliasing. On a high resolution screen, this should not normally be visible.

    However, in your code, you are rendering the SVG to a bitmap and setting the bitmap to an ImageView. If that ImageView has a size larger than the bitmap - ie. greater than 400 x 300, then the anti-aliased pixels in that bitmap will likely be rendered larger and thus more visible.

    One solution is to avoid using a bitmap. Use a Picture/PictureDrawable instead. That way the barcode will be rendered at highest quality no matter what size it is. As vector graphics are supposed to be.

    Follow the example on this page:

    http://bigbadaboom.github.io/androidsvg/use_with_ImageView.html

    So your code should probably look something like the following:

    private void loadQRCode(String svgString) {
        try {
            SVG svg = SVG.getFromString(svgString);
    
            barcode.setLayerType(View.LAYER_TYPE_SOFTWARE,null);
            Drawable drawable = new PictureDrawable(svg.renderToPicture());
            barcode.setImageDrawable(drawable);
    
        } catch (SVGParseException e) {
            e.printStackTrace();
        }
    
    }
    

    If for some reason you need to use bitmaps - maybe you are caching them or something - then you should watch for changes in the size of the ImageView and then recreate the bitmap at the new size. So the bitmap is always the same size as the ImageView to which it is assigned.