Javaでロゴ付きのカラーQRコードを生成する

少し前に、システムのユーザーごとにいくつかのQRコードを生成する必要がありました。 そして、このコードをスキャンすることを面白くするために、ロゴを追加することにしました。

QRコードの例

これを行う方法は、読み進めてください。





まえがき


QRコードはどこにでもありますが、それらを互いに区別する方法はありますか? QRコードは常に人気を集めていますが、いや、いや、近くにいくつかのピースがあります。 これは快適な光景ではありません-最初にスキャンするのはどれですか? とにかく、なぜあなたの目に波紋し始める何かをスキャンしますか?

QRコードのパーソナライズは、この問題の解決策として役立ちます。非標準の色、ロゴ、またはコード自体より少し低い説明碑文で、視聴者が興味を持っているかどうかを理解できます。

彼らの多くは美しいQRコードを見ました(おそらく、見たことがない人はハブまたはサードパーティのリソースを見ることができます)が、予約する必要があります-作成するには、画像を生成するアルゴリズムに大きなリソースを投資するか、Photoshopでそのようなコードを描画する必要がありますが、それは単一のインスタンスであり、私たちのほとんどにとってはそうではありません(もちろん、それらを自分で生成する一般的な必要性がない限り)。



これはどのように実装されますか?


QRコードの作成者は、コード自体であるエンコードされたメッセージに画像を挿入することを期待していませんでしたが、大量の回復情報の可能性を提供しました-コードには後者の最大30%を含めることができます。 大きいほど、画像は厚くなりますが、ユーザーが破損したコードをデコードする可能性が高くなります。 そして、それをロゴで台無しにします。

コードを生成するために、 ZXingライブラリが使用されました。これは、Javaに加えて、他の言語用のポートを備えたさまざまな1D / 2Dバーコードを処理するためのオープンソースライブラリです。

このライブラリの特徴は、モジュールに分割され、コンパイルが必要なソースコードで配布されることです。 しかし、幸いなことに、Mavenリポジトリにあります- コアモジュールは生成使用され、 java seモジュールはコードの検証に使用されました。

グラフィックを操作するために、java.awtパッケージ(JavaSE)の標準クラスが使用されました。



原因に!


実験のために、このセクションで説明するプロトタイプリポジトリであるgithubにある小さなコンソールプログラムを作成しました。



QRコードが必要な人は誰でも次のように書くことができます。

BitMatrix matrix = new MultiFormatWriter().encode("text to encode", BarcodeFormat.QR_CODE, width, height); MatrixToImageWriter.writeToFile(matrix, filename.substring(filename.lastIndexOf('.')+1), new File(filename));
      
      





それ以外の場合は、これを行うべきではありません-デフォルトでは、ライブラリは少し修復情報を追加し、ロゴを挿入した後、画像がコンピューターで復号化された場合でも、カメラから既に間違っていると見なされる場合があります。 したがって、最大限の回復情報を追加するのが適切な形式であり、色と画像を変更するため、結果を保存するために急ぐ必要はありません。

 Hashtable<EncodeHintType, ErrorCorrectionLevel> hintMap = new Hashtable<EncodeHintType, ErrorCorrectionLevel>(); hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); QRCodeWriter qrCodeWriter = new QRCodeWriter(); BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, qrCodeSize, qrCodeSize, hintMap);
      
      





コードマトリックスからの画像の作成はサイクルで行われます。適切なサイズの画像を作成し、コードマトリックスを渡して、画像上のマトリックスのビットの存在を有益なピクセルとして表示します。 このアクション中に、背景色とコード色を設定できます。

 int matrixWidth = bitMatrix.getWidth(); BufferedImage image = new BufferedImage(matrixWidth, matrixWidth, BufferedImage.TYPE_INT_RGB); image.createGraphics(); Graphics2D graphics = (Graphics2D) image.getGraphics(); graphics.setColor(Color.white); graphics.fillRect(0, 0, matrixWidth, matrixWidth); Color mainColor = new Color(51, 102, 153); graphics.setColor(mainColor); //Write Bit Matrix as image for (int i = 0; i < matrixWidth; i++) { for (int j = 0; j < matrixWidth; j++) { if (bitMatrix.get(i, j)) { graphics.fillRect(i, j, 1, 1); } } }
      
      





さて、1と0のマトリックスではなく画像で作業しているので、サイズが大きすぎる場合にコード全体と重ならないように事前に解像度を調整して、ロゴを中央に配置すると非常に便利です。

 BufferedImage logo = ImageIO.read( this.getLogoFile()); double scale = calcScaleRate(image, logo); logo = getScaledImage( logo, (int)( logo.getWidth() * scale), (int)( logo.getHeight() * scale) ); graphics.drawImage( logo, image.getWidth()/2 - logo.getWidth()/2, image.getHeight()/2 - logo.getHeight()/2, image.getWidth()/2 + logo.getWidth()/2, image.getHeight()/2 + logo.getHeight()/2, 0, 0, logo.getWidth(), logo.getHeight(), null); private BufferedImage getScaledImage(BufferedImage image, int width, int height) throws IOException { int imageWidth = image.getWidth(); int imageHeight = image.getHeight(); double scaleX = (double)width/imageWidth; double scaleY = (double)height/imageHeight; AffineTransform scaleTransform = AffineTransform.getScaleInstance(scaleX, scaleY); AffineTransformOp bilinearScaleOp = new AffineTransformOp( scaleTransform, AffineTransformOp.TYPE_BILINEAR); return bilinearScaleOp.filter( image, new BufferedImage(width, height, image.getType())); }
      
      





コードを悪用した後、間違いがないか必ず確認してください-理想的なカメラに十分な回復情報はありますか? それで十分なら、カチンカを保存してユーザーに渡す時間です:

 if ( isQRCodeCorrect(content, image)) { ImageIO.write(image, imageFormat, this.getGeneratedFileStream()); } private boolean isQRCodeCorrect(String content, BufferedImage image){ boolean result = false; Result qrResult = decode(image); if (qrResult != null && content != null && content.equals(qrResult.getText())){ result = true; } return result; } private Result decode(BufferedImage image){ if (image == null) { return null; } try { LuminanceSource source = new BufferedImageLuminanceSource(image); BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); Result result = new MultiFormatReader().decode(bitmap, Collections.EMPTY_MAP); return result; } catch (NotFoundException nfe) { return null; } }
      
      







目標が達成された-QRコードが生成されます。 ご清聴ありがとうございました!






All Articles