zoukankan      html  css  js  c++  java
  • (转)ZXing解析二维码

    1 ZXing解析二维码

    上一篇文件已经说过如何用ZXing进行生成二维码和带图片的二维码,下面说下如何解析二维码

    二维码的解析和生成类似,也可以参考google的一个操作类 BufferedImageLuminanceSource类,该类可在google的测试包中找到,另外j2se中也有该类,你可以将该类直接拷贝到源码中使用,你也可以自己写个。

    1.1 BufferedImageLuminanceSource类

    package t1;
    
    import java.awt.Graphics2D;  
    import java.awt.geom.AffineTransform;  
    import java.awt.image.BufferedImage;  
    import java.awt.image.WritableRaster;  
    import com.google.zxing.LuminanceSource;  
      
    /** 
     *  
     * 二维码的解析需要借助BufferedImageLuminanceSource类,该类是由Google提供的,可以将该类直接拷贝到源码中使用,当然你也可以自己写个 
     * 解析条形码的基类 
     */  
      
    public final class BufferedImageLuminanceSource extends LuminanceSource {  
      
      private static final double MINUS_45_IN_RADIANS = -0.7853981633974483; // Math.toRadians(-45.0)  
      
      private final BufferedImage image;  
      private final int left;  
      private final int top;  
      
      private static final boolean EXPLICIT_LUMINANCE_CONVERSION;  
      static {  
        String property = System.getProperty("explicitLuminanceConversion");  
        if (property == null) {  
          property = System.getenv("EXPLICIT_LUMINANCE_CONVERSION");  
        }  
        EXPLICIT_LUMINANCE_CONVERSION = Boolean.parseBoolean(property);  
      }  
      
      public BufferedImageLuminanceSource(BufferedImage image) {  
        this(image, 0, 0, image.getWidth(), image.getHeight());  
      }  
      
      public BufferedImageLuminanceSource(BufferedImage image, int left, int top, int width, int height) {  
        super(width, height);  
      
        if (image.getType() == BufferedImage.TYPE_BYTE_GRAY) {  
          this.image = image;  
        } else {  
          int sourceWidth = image.getWidth();  
          int sourceHeight = image.getHeight();  
          if (left + width > sourceWidth || top + height > sourceHeight) {  
            throw new IllegalArgumentException("Crop rectangle does not fit within image data.");  
          }  
      
          this.image = new BufferedImage(sourceWidth, sourceHeight, BufferedImage.TYPE_BYTE_GRAY);  
      
          if (EXPLICIT_LUMINANCE_CONVERSION) {  
      
            WritableRaster raster = this.image.getRaster();  
            int[] buffer = new int[width];  
            for (int y = top; y < top + height; y++) {  
              image.getRGB(left, y, width, 1, buffer, 0, sourceWidth);  
              for (int x = 0; x < width; x++) {  
                int pixel = buffer[x];  
      
                // see comments in implicit branch  
                if ((pixel & 0xFF000000) == 0) {  
                  pixel = 0xFFFFFFFF; // = white  
                }  
      
                // .229R + 0.587G + 0.114B (YUV/YIQ for PAL and NTSC)  
                buffer[x] =  
                    (306 * ((pixel >> 16) & 0xFF) +  
                     601 * ((pixel >> 8) & 0xFF) +  
                     117 * (pixel & 0xFF) +  
                     0x200) >> 10;  
              }  
              raster.setPixels(left, y, width, 1, buffer);  
            }  
      
          } else {  
      
            // The color of fully-transparent pixels is irrelevant. They are often, technically, fully-transparent  
            // black (0 alpha, and then 0 RGB). They are often used, of course as the "white" area in a  
            // barcode image. Force any such pixel to be white:  
            if (image.getAlphaRaster() != null) {  
              int[] buffer = new int[width];  
              for (int y = top; y < top + height; y++) {  
                image.getRGB(left, y, width, 1, buffer, 0, sourceWidth);  
                boolean rowChanged = false;  
                for (int x = 0; x < width; x++) {  
                  if ((buffer[x] & 0xFF000000) == 0) {  
                    buffer[x] = 0xFFFFFFFF; // = white  
                    rowChanged = true;  
                  }  
                }  
                if (rowChanged) {  
                  image.setRGB(left, y, width, 1, buffer, 0, sourceWidth);  
                }  
              }  
            }  
      
            // Create a grayscale copy, no need to calculate the luminance manually  
            this.image.getGraphics().drawImage(image, 0, 0, null);  
      
          }  
        }  
        this.left = left;  
        this.top = top;  
      }  
      
      @Override  
      public byte[] getRow(int y, byte[] row) {  
        if (y < 0 || y >= getHeight()) {  
          throw new IllegalArgumentException("Requested row is outside the image: " + y);  
        }  
        int width = getWidth();  
        if (row == null || row.length < width) {  
          row = new byte[width];  
        }  
        // The underlying raster of image consists of bytes with the luminance values  
        image.getRaster().getDataElements(left, top + y, width, 1, row);  
        return row;  
      }  
      
      @Override  
      public byte[] getMatrix() {  
        int width = getWidth();  
        int height = getHeight();  
        int area = width * height;  
        byte[] matrix = new byte[area];  
        // The underlying raster of image consists of area bytes with the luminance values  
        image.getRaster().getDataElements(left, top, width, height, matrix);  
        return matrix;  
      }  
      
      @Override  
      public boolean isCropSupported() {  
        return true;  
      }  
      
      @Override  
      public LuminanceSource crop(int left, int top, int width, int height) {  
        return new BufferedImageLuminanceSource(image, this.left + left, this.top + top, width, height);  
      }  
      
      /** 
       * This is always true, since the image is a gray-scale image. 
       * 
       * @return true 
       */  
      @Override  
      public boolean isRotateSupported() {  
        return true;  
      }  
      
      @Override  
      public LuminanceSource rotateCounterClockwise() {  
        int sourceWidth = image.getWidth();  
        int sourceHeight = image.getHeight();  
      
        // Rotate 90 degrees counterclockwise.  
        AffineTransform transform = new AffineTransform(0.0, -1.0, 1.0, 0.0, 0.0, sourceWidth);  
      
        // Note width/height are flipped since we are rotating 90 degrees.  
        BufferedImage rotatedImage = new BufferedImage(sourceHeight, sourceWidth, BufferedImage.TYPE_BYTE_GRAY);  
      
        // Draw the original image into rotated, via transformation  
        Graphics2D g = rotatedImage.createGraphics();  
        g.drawImage(image, transform, null);  
        g.dispose();  
      
        // Maintain the cropped region, but rotate it too.  
        int width = getWidth();  
        return new BufferedImageLuminanceSource(rotatedImage, top, sourceWidth - (left + width), getHeight(), width);  
      }  
      
      @Override  
      public LuminanceSource rotateCounterClockwise45() {  
        int width = getWidth();  
        int height = getHeight();  
      
        int oldCenterX = left + width / 2;  
        int oldCenterY = top + height / 2;  
      
        // Rotate 45 degrees counterclockwise.  
        AffineTransform transform = AffineTransform.getRotateInstance(MINUS_45_IN_RADIANS, oldCenterX, oldCenterY);  
      
        int sourceDimension = Math.max(image.getWidth(), image.getHeight());  
        BufferedImage rotatedImage = new BufferedImage(sourceDimension, sourceDimension, BufferedImage.TYPE_BYTE_GRAY);  
      
        // Draw the original image into rotated, via transformation  
        Graphics2D g = rotatedImage.createGraphics();  
        g.drawImage(image, transform, null);  
        g.dispose();  
      
        int halfDimension = Math.max(width, height) / 2;  
        int newLeft = Math.max(0, oldCenterX - halfDimension);  
        int newTop = Math.max(0, oldCenterY - halfDimension);  
        int newRight = Math.min(sourceDimension - 1, oldCenterX + halfDimension);  
        int newBottom = Math.min(sourceDimension - 1, oldCenterY + halfDimension);  
      
        return new BufferedImageLuminanceSource(rotatedImage, newLeft, newTop, newRight - newLeft, newBottom - newTop);  
      }  
      
    }  

    1.2 操作类:DecodeTest

    package t1;
    
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.util.Hashtable;
    
    import javax.imageio.ImageIO;
    
    import com.google.zxing.Binarizer;
    import com.google.zxing.BinaryBitmap;
    import com.google.zxing.DecodeHintType;
    import com.google.zxing.LuminanceSource;
    import com.google.zxing.MultiFormatReader;
    import com.google.zxing.Result;
    import com.google.zxing.common.HybridBinarizer;
      
    /** 
     * 解析二维码  
     * @author Administrator 
     * 
     */  
    public class DecodeHelper {  
          
        public static void main(String[] args) throws Exception {  
             try {   
                 MultiFormatReader formatReader = new MultiFormatReader();   
                 String filePath = "e:\new-1.gif"; //new.png  
                 File file = new File(filePath);   
                   
                 BufferedImage image = ImageIO.read(file);  
                   
                 LuminanceSource source = new BufferedImageLuminanceSource(image);   
                   
                 Binarizer  binarizer = new HybridBinarizer(source);   
                   
                 BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);   
                   
                 Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();      
                 hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");      
                   
                 Result result = formatReader.decode(binaryBitmap,hints);   
      
                 System.out.println("result = "+ result.toString());   
                 System.out.println("resultFormat = "+ result.getBarcodeFormat());   
                 System.out.println("resultText = "+ result.getText());   
      
             } catch (Exception e) {   
                 e.printStackTrace();   
                 }   
        }  
    }  

    1.3 补充

      a.读取二维码图片,并送给 Zxing LuminanceSource 和 Binarizer 两兄弟的处理。

       b.处理完的位图和相应的解析参数,交由 MultiFormatReader 处理,并返回解析后的结果。

       c.如果对上述 两兄弟的处理 和 MultiFormatReader  的解析有兴趣,可以读读源码。

     本博客与二维码相关的文章:

    (转)ZXing生成二维码和带logo的二维码,模仿微信生成二维码效果
    (转)js jquery.qrcode生成二维码 带logo 支持中文

  • 相关阅读:
    hdu 2485 Destroying the bus stations 迭代加深搜索
    hdu 2487 Ugly Windows 模拟
    hdu 2492 Ping pong 线段树
    hdu 1059 Dividing 多重背包
    hdu 3315 My Brute 费用流,费用最小且代价最小
    第四天 下载网络图片显示
    第三天 单元测试和数据库操作
    第二天 布局文件
    第一天 安卓简介
    Android 获取存储空间
  • 原文地址:https://www.cnblogs.com/lixuwu/p/5953271.html
Copyright © 2011-2022 走看看