0

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);
    }
}
kvgr
  • 325
  • 4
  • 17
  • The SVG is converted to bitmap in order to be displayed, you need to increase the resolution for it to retain sharpness when scaled. – methodofaction Nov 10 '16 at 12:28

1 Answers1

0

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.

Paul LeBeau
  • 97,474
  • 9
  • 154
  • 181
  • Thanks for the advice. It got better a little, but some pixels are still visible on the sides http://snpy.in/yrL1xa – kvgr Nov 10 '16 at 12:54
  • It is not visible on the phone screen, but I will also need to work with QR code and I am afraid it will lower the readability of the code by scanners. – kvgr Nov 10 '16 at 12:56
  • Post an example barcode SVG if you want us to look at it. But it is extremely unlikely that the odd antialiased pixel will prevent it from being scanned. If you want to prevent anti-aliasing, you should make sure that the bars are on pixel boundaries and the barcode is rendered at 1:1 scale. – Paul LeBeau Nov 10 '16 at 14:43