org.uva.itast.blended.omr.scanners.BarcodeScanner.java Source code

Java tutorial

Introduction

Here is the source code for org.uva.itast.blended.omr.scanners.BarcodeScanner.java

Source

/*
* ====================================================================
*
* License:        GNU General Public License
*
* Note: Original work copyright to respective authors
*
* This file is part of Blended (c) 2009-2010 University of Valladolid..
*
* Blended is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* Blended is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
*
* Module developed at the University of Valladolid http://www.eduvalab.uva.es
*
* http://www.itnt.uva.es , http://www.eduvalab.uva.es
*
* Designed and directed by Juan Pablo de Castro with 
* the effort of many other students of telecommunication 
* engineering.
* This module is provides as-is without any 
* guarantee. Use it as your own risk.
*
* @author Juan Pablo de Castro
* @author Jesus Rodilana
* @author Mara Jess Verd 
* @author Luisa Regueras 
* @author Elena Verd
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package blended
 ***********************************************************************/

/***********************************************************************
 * Module developed at the University of Valladolid http://www.eduvalab.uva.es
 * Designed and directed by Juan Pablo de Castro with 
 * the effort of many other students of telecommunciation 
 * engineering this module is provides as-is without any 
 * guarantee. Use it as your own risk.
 *
 ***********************************************************************/

package org.uva.itast.blended.omr.scanners;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.RasterFormatException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.uva.itast.blended.omr.Field;
import org.uva.itast.blended.omr.OMRProcessor;
import org.uva.itast.blended.omr.OMRUtils;
import org.uva.itast.blended.omr.pages.PageImage;
import org.uva.itast.blended.omr.pages.SubImage;

import com.google.zxing.BinaryBitmap;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.result.ParsedResult;
import com.google.zxing.client.result.ResultParser;
import com.google.zxing.common.HybridBinarizer;

public final class BarcodeScanner extends MarkScanner {
    /**
     * Logger for this class
     */
    static final Log logger = LogFactory.getLog(BarcodeScanner.class);

    static final double BARCODE_AREA_PERCENT = 0.2d;

    private BufferedImage subimage;

    public BarcodeScanner(OMRProcessor omr, PageImage imagen, boolean medianfilter) {
        super(omr, imagen, medianfilter);
    }

    /**
     * Iterate one more time expanding the scanned area with a smaller expansion percentage than other mark types
     * @see org.uva.itast.blended.omr.scanners.MarkScanner#scanField(org.uva.itast.blended.omr.Field)
     */
    @Override
    public ScanResult scanField(Field campo) throws MarkScannerException {

        try {
            return super.scanField(campo);
        } catch (MarkScannerException e) {
            Rectangle2D expandedBbox = getExpandedArea(campo.getBBox(), BARCODE_AREA_PERCENT * 2);
            // Try with a wider area
            logger.debug(
                    "Last attempt to read mark was in error: RETRY one more try with a wider area. Scanner reported:"
                            + e.getMessage());
            ScanResult result = scanAreaForFieldData(expandedBbox);
            this.lastResult = result;
            return result;
        }
    }

    /**
     * 
     */
    public String getParsedCode(Field field) throws MarkScannerException {
        String parsedCode;
        try {
            parsedCode = getParsedCode(scanField(field));
        } finally {
            if (logger.isInfoEnabled())
                markBarcode(field);
        }
        return parsedCode;
    }

    /**
     * @param result
     * @return
     */
    public String getParsedCode(ScanResult result) {
        String barcode;
        if (result != null) {
            ParsedResult parsedResult = ResultParser.parseResult((Result) result.getResult());

            barcode = parsedResult.getDisplayResult();
        } else
            barcode = null;

        return barcode;
    }

    /**
     * Generates an expanded boundingbox in milimeters
     * 
     * @see {@link #BARCODE_AREA_PERCENT}
     * @see {@value #BARCODE_AREA_PERCENT}
     * @param rect
     * @return milimeteres
     */
    protected Rectangle2D getExpandedArea(Rectangle2D rect, double percent) {
        Rectangle expandedRect = new Rectangle();
        expandedRect.setFrame((rect.getX() - rect.getWidth() * (percent) / 2),
                (rect.getY() - rect.getHeight() * (percent) / 2), (rect.getWidth() * (1 + percent)),
                (rect.getHeight() * (1 + percent)));
        return expandedRect;
    }

    /**
     * @param rect area in milimeters to be scanned
     * @return
     * @throws ReaderException
     */
    public ScanResult scanAreaForFieldData(Rectangle2D rect) throws MarkScannerException {
        SubImage subimage;
        try {
            subimage = pageImage.getSubimage(rect, BufferedImage.TYPE_BYTE_GRAY);
        } catch (RasterFormatException e2) {
            logger.error(e2);
            throw new MarkScannerException(e2);
        }

        if (subimage == null) {
            logger.error("leerBarcode(Campo) - " + pageImage.toString() + ": No es posible cargar la imagen", null); //$NON-NLS-1$ //$NON-NLS-2$
            //Lanzar otra Excepcion
            throw new RuntimeException("Can't extract subimage from page.");
        }
        //      if (logger.isDebugEnabled())
        //         OMRUtils.logSubImage(omr, "codebar2D",subimage);  

        //  MonochromeBitmapSource source = new BufferedImageMonochromeBitmapSource(subimage);
        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(subimage);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        Result result = null;
        try {
            result = new MultiFormatReader().decode(bitmap, null);
        } catch (ReaderException e) {
            //retry after filtering
            if (medianfilter == true) {
                if (logger.isDebugEnabled())
                    OMRUtils.logSubImage(omr, subimage);

                long start = System.currentTimeMillis();
                BufferedImage medianed = medianFilter(subimage);
                logger.debug("scanAreaForBarcode(MedianFilter area=" + subimage.getWidth() + "x" //$NON-NLS-1$//$NON-NLS-2$
                        + subimage.getHeight() + ") In (ms) " + (System.currentTimeMillis() - start));

                if (logger.isDebugEnabled())
                    OMRUtils.logSubImage(omr, "debug_median", medianed);

                source = new BufferedImageLuminanceSource(medianed);
                bitmap = new BinaryBitmap(new HybridBinarizer(source));

                try {
                    result = new MultiFormatReader().decode(bitmap, null);
                } catch (ReaderException e1) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Can't recognize any code in the field located at: " + rect
                                + "(see debug output image)", e1);
                        OMRUtils.logSubImage(this.omr, "debug_monochrome_barcode", subimage);
                    }
                    throw new MarkScannerException(e1);
                }

                //subimage=medianed; // store medianed image for reporting

            } else {
                if (logger.isDebugEnabled()) {
                    logger.debug("Can't recognize any code in the field located at: " + rect
                            + "(see debug output image)", e);
                    OMRUtils.logSubImage(this.omr, "debug_monochrome_barcode", subimage);
                }

                throw new MarkScannerException(e); // re-throw exception to
                // notify caller
            }
        }
        this.lastResult = new ScanResult("Barcode", result);
        lastResult.setLocation(rect);
        return lastResult;
    }

    /**
     * @param campo
     */
    public void markBarcode(Field campo) {
        try {
            //get bbox in pixels
            Rectangle rect = pageImage.toPixels(campo.getBBox());
            // expand the area for some tolerance
            Rectangle2D expandedArea = getExpandedArea(campo.getBBox(), (float) BARCODE_AREA_PERCENT);
            Rectangle expandedRect = pageImage.toPixels(expandedArea);

            Graphics2D g = pageImage.getReportingGraphics();
            AffineTransform t = g.getTransform();
            g.setStroke(new BasicStroke(1, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND, 1,
                    new float[] { (float) (3 / t.getScaleX()), (float) (6 / t.getScaleY()) }, 0));
            if (lastResult != null)
                g.setColor(Color.BLUE);
            else
                g.setColor(Color.RED);

            g.drawRoundRect(rect.x, rect.y, rect.width, rect.height, 3, 3);
            g.drawRoundRect(expandedRect.x, expandedRect.y, expandedRect.width, expandedRect.height, 3, 3);

            g.setFont(new Font("Arial", Font.BOLD, (int) (12 / t.getScaleX())));
            String message;
            if (lastResult != null)
                message = ((Result) lastResult.getResult()).getBarcodeFormat().toString() + "="
                        + getParsedCode(lastResult);
            else
                message = "UNRECOGNIZED!";
            g.drawString(message, rect.x, rect.y);

        } catch (Exception e) {
            logger.error("Unexpected errr while logging the image:", e);
        }

    }

    @Override
    public void putEmphasisMarkOnImage(PageImage pageImage2, Color color) {
        if (lastResult != null) {
            OMRUtils.logFrame(pageImage2, lastResult.getLocation(), Color.RED, "BarCodeDetected");
        }

    }

    /**
     * 
     * Generates an expanded boundingbox in milimeters
     * 
     * @see {@link #BARCODE_AREA_PERCENT}
     * @see {@value #BARCODE_AREA_PERCENT}
     * @param rect
     * @return milimeteres
     */
    @Override
    protected Rectangle2D getExpandedArea(Rectangle2D coords) {
        return getExpandedArea(coords, (float) BARCODE_AREA_PERCENT);
    }
}