/* * Copyright (c) 2018-2019. Developed by Hedgecode. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hedgecode.chess.qrcode; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.util.EnumMap; import java.util.Map; import javax.imageio.ImageIO; import com.google.zxing.BinaryBitmap; import com.google.zxing.DecodeHintType; import com.google.zxing.ReaderException; import com.google.zxing.client.j2se.BufferedImageLuminanceSource; import com.google.zxing.common.DecoderResult; import com.google.zxing.common.DetectorResult; import com.google.zxing.common.HybridBinarizer; import com.google.zxing.qrcode.decoder.Decoder; import com.google.zxing.qrcode.detector.Detector; /** * Chess-specific QR Codes reader (image decoder). * * @author Dmitry Samoshin aka gotty */ public class ChessQRCodeReader { private final Decoder decoder; private static ChessQRCodeReader _instance = new ChessQRCodeReader(); protected ChessQRCodeReader() { decoder = new Decoder(); } public ChessQRResult read(File qrCodeImageFile) throws ChessQRCodeException { BufferedImage qrCodeImage; try { qrCodeImage = ImageIO.read(qrCodeImageFile); } catch (IOException e) { throw new ChessQRCodeException( ChessQRCodeException.Type.READ, "read.input.qrcode.file", qrCodeImageFile.getName() ); } return read(qrCodeImage); } public ChessQRResult read(InputStream qrCodeInputStream) throws ChessQRCodeException { BufferedImage qrCodeImage; try { qrCodeImage = ImageIO.read(qrCodeInputStream); } catch (IOException e) { throw new ChessQRCodeException( ChessQRCodeException.Type.READ, "read.input.qrcode.stream", e.getMessage() ); } return read(qrCodeImage); } public ChessQRResult read(URI qrCodeUri) throws ChessQRCodeException { BufferedImage qrCodeImage; try { qrCodeImage = ImageIO.read(qrCodeUri.toURL()); } catch (IOException e) { throw new ChessQRCodeException( ChessQRCodeException.Type.READ, "read.input.qrcode.url", qrCodeUri.toASCIIString() ); } return read(qrCodeImage); } public ChessQRResult read(BufferedImage qrCodeImage) throws ChessQRCodeException { BinaryBitmap bitmap = new BinaryBitmap( new HybridBinarizer( new BufferedImageLuminanceSource(qrCodeImage) ) ); return decode(bitmap, null); } private ChessQRResult decode(BinaryBitmap image, Map hints) throws ChessQRCodeException { Map newHints = new EnumMap<>(DecodeHintType.class); if (hints != null) { newHints.putAll(hints); if (!hints.containsKey(DecodeHintType.CHARACTER_SET)) newHints.put(DecodeHintType.CHARACTER_SET, ChessQRCodeConstants.CHARSET.name()); } else { newHints.put(DecodeHintType.CHARACTER_SET, ChessQRCodeConstants.CHARSET.name()); } hints = newHints; DecoderResult decoderResult; try { DetectorResult detectorResult = new Detector( image.getBlackMatrix() ).detect(hints); decoderResult = decoder.decode( detectorResult.getBits(), hints ); } catch (ReaderException e) { throw new ChessQRCodeException( ChessQRCodeException.Type.READ, "read.zxing.qrcode.error", e.getMessage() ); } return createResult(decoderResult); /* ResultPoint[] points = detectorResult.getPoints(); if (decoderResult.getOther() instanceof QRCodeDecoderMetaData) { ((QRCodeDecoderMetaData) decoderResult.getOther()).applyMirroredCorrection(points); } Result result = new Result( decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.QR_CODE ); List byteSegments = decoderResult.getByteSegments(); if (byteSegments != null) { result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments); } String ecLevel = decoderResult.getECLevel(); if (ecLevel != null) { result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); } if (decoderResult.hasStructuredAppend()) { result.putMetadata( ResultMetadataType.STRUCTURED_APPEND_SEQUENCE, decoderResult.getStructuredAppendSequenceNumber() ); result.putMetadata( ResultMetadataType.STRUCTURED_APPEND_PARITY, decoderResult.getStructuredAppendParity() ); } return result; */ } protected ChessQRResult createResult(DecoderResult decoderResult) throws ChessQRCodeException { String result = decoderResult.getText(); ChessQRCodeMode mode = ChessQRResult.getMode(result); if (mode == null) { throw new ChessQRCodeException( ChessQRCodeException.Type.READ, "read.unknown.chess.mode" ); } return new ChessQRResult( mode, ChessQRResult.getContents(result) ); } public static ChessQRCodeReader getInstance() { return _instance; } public static void main(String[] args) { try { ChessQRResult qrCodeResult = ChessQRCodeReader.getInstance().read( new File("qrcode.png") ); System.out.println("Decoded format = " + qrCodeResult.getMode()); System.out.println("Decoded text = " + qrCodeResult.getContents()); } catch (ChessQRCodeException e) { System.out.println("Could not decode QR Code. Exception: " + e.getMessage()); } } }