DUICUO

このJavaコードは、オープンソースコンポーネントに基づいてプロフィール写真付きのQRコードを生成します。保存に非常におすすめです!

QRコードは私たちの日常生活や仕事のいたるところに存在しています。日々の開発作業では、QRコードを生成しなければならない場面に必ず遭遇します。オンラインで利用できるオープンソースプラットフォームは数多くありますが、ここではいくつかのオープンソースコンポーネントを使って自分でQRコードを実装することができます。

始める前に、何をすべきか考えてみましょう。まずQRコードを生成し、QRコードの中央にアバターを追加する必要があります。

ここでは、QRコードを生成するためにzxingというツールを使い、画像を合成するためにthumbnailatorというツールを使います。試してみましょう。

QRコードを生成する

まず、ターゲットアドレスに基づいてQRコードを生成します。ここではzxingコンポーネントを使用しています。Spring Bootのpom依存関係に以下の依存関係を追加します。

 <依存関係>
<グループID>com.google.zxing</グループID>
<artifactId>コア</artifactId>
<バージョン>3.4.0</バージョン>
</依存関係>
<依存関係>
<グループID>com.google.zxing</グループID>
<artifactId>javase</artifactId>
<バージョン>3.4.0</バージョン>
</依存関係>

次に、ユーティリティクラスQRCodeGenerator.javaを記述します。

 com.google.zxing.BarcodeFormat をインポートします。
com.google.zxing.EncodeHintType をインポートします。
com.google.zxing.MultiFormatWriter をインポートします。
com.google.zxing.WriterException をインポートします。
com.google.zxing.client.j2se.MatrixToImageWriter をインポートします。
com.google.zxing.common.BitMatrix をインポートします。

java.io.IOException をインポートします。
java.nio.file.FileSystems をインポートします。
java.nio.file.Path をインポートします。
java.util.HashMap をインポートします。


パブリッククラス QRコードジェネレータ {

/**
* 内容とサイズに基づいて QR コードを生成し、指定されたパスに送信します。
*
* @param contents ジャンプ先のリンク。
* @param width 幅
* @param 高さ
* @param filePath (パス)
* @throwsWriterException
* IOException をスローします
/
パブリック静的void generateQrWithImage(String contents, int width, int height, String filePath) throws WriterException, IOException {
// QRコードライターを構築する
マルチフォーマットライター mutiWriter = 新しい com.google.zxing.MultiFormatWriter();
HashMap<EncodeHintType, Object> ヒント = 新しい HashMap<>(16);
hint.put(EncodeHintType.CHARACTER_SET, "UTF-8");
ヒント.put(EncodeHintType.ERROR_CORRECTION、com.google.zxing.qrcode.decoder.ErrorCorrectionLevel.H);
ヒントを EncodeHintType.MARGIN に 1 として入力します。
//QRコードを生成する
BitMatrix bitMatrix = mutiWriter.encode(contents, BarcodeFormat.QR_CODE, width, height, hint);
パス path = FileSystems.getDefault().getPath(filePath);
MatrixToImageWriter.writeToPath(bitMatrix、"jpeg"、パス);
}
}

この静的メソッドには 4 つのパラメーターがあります。

  • リダイレクトされたリンクの内容。
  • QR コードの幅。
  • QR コードの高さ。
  • 生成された QR コードの保存パス。

コードには、エンコーディングを表す EncodeHintType.CHARACTER_SET、QR コードのエラー許容度を表す EncodeHintType.ERROR_CORRECTION、QR コードの境界を表す EncodeHintType.MARGIN など、いくつかの定数も含まれています。

QRコードのエラー許容度とは何かをご説明しましょう。日常生活や仕事の中で、簡単なスキャンでうまく読み取れるQRコードもあれば、なかなか読み取れないQRコードもあることに気づいたことがあるかもしれません。これはQRコードのエラー許容度によるものです(もちろん、ネットワークの問題ではない場合もあります)。

QRコードの密度によって、エンコードされた文字数とエラー許容率が異なります。密度が低いほど、エンコードされた文字数が少なくなり、エラー許容率も低くなります。QRコードのエラー許容率は、QRコードアイコンがどの程度隠れてもスキャンできることを示します。現在、一般的なQRコードのエラー許容率は、7%、15%、25%、30%の4段階に分かれています。エラー許容率が高いほど、スキャン速度が速くなります。しかし、エラー許容率が高いほど、QRコード内の白黒の四角形が多くなります。そのため、ほとんどの主流の携帯電話では、7%のエラー許容率で十分なスキャンが可能です。

興味のある人は、いくつかの異なるエラー許容レベルを試して、コードのスキャンの難易度が変化するかどうかを確認できます。

次に、QR コードを生成するためのメイン メソッドを記述します。

パブリック静的void main(String[] args) {
試す {
QRコードジェネレーター.generateQrWithImage("https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzkzODE3OTI0Ng==&scene=124#wechat_redirect", 500, 500, "./QRCode.jpeg");
} キャッチ (例外 e) {
}
}

上記のメインメソッドを実行すると、QRコードが生成されます。これで最初のステップは完了です。次のステップは、このQRコードにアバターを追加することです。

アバターを追加

アバターを追加するには、写真を用意する必要があります。ここではA-Fenさんのアバターを使用します。特定のサイズの既製のアバターがある場合は、それをそのまま使用しても構いません。ない場合は、自分でトリミングしても構いません。ここでは、画像処理ツール「Thumbnailator」を使用します。

アーフェン

まず、アバターのサイズを 100 x 100 ピクセルに変更し、合成します。コードは次のとおりです。

パブリック静的void main(String[] args) {
試す {
// 大きな画像を指定されたサイズに縮小する
// ThumbnailsImageUtils.size("./阿粉.jpeg", 100, 100, 1, "./阿粉100.png");
// 生成された QR コードにアバターを透かしとして追加します。
ThumbnailsImageUtils.watermark("./QRCode.jpeg",
500, 500, Positions.CENTER, "./阿粉100.png",
1f、1f、「./result.png」);
} キャッチ (例外 e) {
}
}

これはあなたのプロフィール写真が入った最終的に生成されたQRコードです。ご注意:このコードをスキャンすると、より高品質な記事をご覧いただけます。

上記のコードからわかるように、ThumbnailsImageUtilsは非常に強力です。たった1行のコードで画像のサイズ変更と合成を処理できます。ThumbnailsImageUtilsユーティリティクラスのより詳細なコード例を以下に示します。ブックマークに追加しておいてください。


 net.coobird.thumbnailator.Thumbnailsをインポートします。
net.coobird.thumbnailator.geometry.Positions をインポートします。
org.slf4j.Logger をインポートします。
org.slf4j.LoggerFactory をインポートします。

javax.imageio.ImageIO をインポートします。
java.awt.* をインポートします。
java.awt.image.BufferedImage をインポートします。
java.io.File をインポートします。
java.io.FileOutputStream をインポートします。
java.io.IOException をインポートします。
java.io.OutputStream をインポートします。

/**
* <br>
* <b>機能:</b><br>
* <b>著者:</b>@author ziyou<br>
* **日付:** 2018-05-25 16:17
* **詳細な説明:** このセクションでは、Google のオープンソース ツールである Thumbnailator を使用して一連の画像処理手順を実行する方法について説明します。
/
パブリッククラス ThumbnailsImageUtils {

プライベートfinalstaticロガー logger = LoggerFactory.getLogger(ThumbnailsImageUtils.class);

/**
* 指定されたサイズに従って元の画像から新しい画像を生成します。
*
* @param sourceFilePath 元の画像パス
* @param width 画像の幅を指定します
* @param height 画像の高さを指定します
* @param targetFilePath ターゲット画像パス
* @return 対象画像のパス
* IOException をスローします
/
パブリック静的String thumb(String sourceFilePath, Integer width, Integer height, String targetFilePath) throws IOException {
サムネイル.of(ソースファイルパス)
.forceSize(幅, 高さ)
.toFile(ターゲットファイルパス);
targetFilePath を返します。
}


/**
* 比例して拡大縮小
*
* @param sourceFilePath 元の画像パス
* @param スケール スケール(スケール)
* @param targetFilePath ターゲット画像パス
* @return 対象画像のパス
* IOException をスローします
/
パブリック静的Stringスケール(Stringソースファイルパス、Doubleスケール、Stringターゲットファイルパス)はIOExceptionをスローします{
サムネイル.of(ソースファイルパス)
.scale(スケール)
.toFile(ターゲットファイルパス);
targetFilePath を返します。
}


/**
* 指定されたサイズを不均等に拡大する
*
* @param sourceFilePath 元の画像パス
* @param width 画像の幅を指定します
* @param height 画像の高さを指定します
* @param targetFilePath ターゲット画像パス
* `keepAspectRatio(false)` はデフォルトで比例してスケーリングします。
* @return 対象画像のパス
* IOException をスローします
/
パブリック静的文字列サイズ(文字列ソースファイルパス、整数幅、整数高さ、浮動小数点品質、文字列ターゲットファイルパス) IOException をスローします {
サムネイル.of(ソースファイルパス)
.size(幅, 高さ)
.outputQuality(品質)
.keepAspectRatio(false)
.toFile(ターゲットファイルパス);
targetFilePath を返します。
}


/**
* サイズと角度を指定して回転する
*
* @param sourceFilePath 元の画像パス
* @param width 画像の幅を指定します
* @param height 画像の高さを指定します
* @param rotate rotate(angle), 正の数: 時計回り、負の数: 反時計回り
* @param targetFilePath ターゲット画像パス
* @return 対象画像のパス
* IOException をスローします
/
パブリック静的String rotate(String sourceFilePath, Integer width, Integer height, Double rotate, String targetFilePath) throws IOException {
サムネイル.of(ソースファイルパス)
.size(幅, 高さ)
.rotate(回転)
.toFile(ターゲットファイルパス);
targetFilePath を返します。
}


/**
指定した角度で​​回転する
*
* @param sourceFilePath 元の画像パス
* @param rotate rotate(angle), 正の数: 時計回り、負の数: 反時計回り
* @param targetFilePath ターゲット画像パス
* @return 対象画像のパス
* IOException をスローします
/
パブリック静的String rotate(String sourceFilePath, Double rotate, String targetFilePath) はIOExceptionをスローします {
サムネイル.of(ソースファイルパス)
.rotate(回転)
.toFile(ターゲットファイルパス);
targetFilePath を返します。
}


/**
* @param sourceFilePath 元の画像パス
* @param width 画像の幅を指定します
* @param height 画像の高さを指定します
* @param position 透かしの位置
* @param waterFile 透かしファイル
* @param opacity 透かしの透明度
* @param quality 出力ファイルの品質。
* @param targetFilePath ターゲット画像パス
* @return 対象画像のパス
* IOException をスローします
/
public static String watermark(String sourceFilePath, Integer width, Integer height, Positions position, String waterFile, float opacity, float quality, String targetFilePath) throws IOException {
サムネイル.of(ソースファイルパス)
.size(幅, 高さ)
.watermark(位置, ImageIO.read(新しいファイル(waterFile)), 不透明度)
.outputQuality(品質)
.toFile(ターゲットファイルパス);
targetFilePath を返します。
}


パブリック静的BufferedImageウォーターマークリスト(BufferedImage buffImg, int length, File[] waterFileArray)はIOExceptionをスローします{
整数x = 0;
整数 y = 0;
if (buffImg == null) {
// ベースマップを取得する
buffImg = 新しい BufferedImage(1200, 1200, BufferedImage.SCALE_SMOOTH);
} それ以外 {
x = (長さ % 30) * 40;
y = (長さ / 30) * 40;
}
// ベースマップ オブジェクトに描画する Graphics2D オブジェクトを作成します。
グラフィックス2D g2d = buffImg.createGraphics();
// 画像を白で塗りつぶす
g2d.setColor(Color.WHITE);
g2d.fillRect(x, y, 1200, 40 * (waterFileArray.length + 長さ));
for (int i = 0; i < waterFileArray.length; i++) {
// レイヤーグラフを取得する
バッファイメージ waterImg = ImageIO.read(waterFileArray[i]);
// レイヤー図の幅を取得する
int waterImgWidth = waterImg.getWidth();
// レイヤー図の高さを取得する
waterImgHeight を waterImg.getHeight() に格納します。
// グラフィックスと画像にブレンドと透明効果を実現します
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1));
// 描画
整数 j = i / 30;
整数インデックス = i - j * 30;
g2d.drawImage(waterImg、waterImgWidth * インデックス + 1、waterImgHeight * j、waterImgWidth、waterImgHeight、null);

}

// グラフィックスコンテキストで使用されているシステムリソースを解放します
g2d.dispose();
buffImg を返します。
}

/**
* @param sourceFilePath 元の画像パス
* @param waterFile 透かしファイル
* @param targetFilePath ターゲット画像パス
* 透明度のデフォルトは 0.5f、品質のデフォルトは 0.8f です。
* @return 対象画像のパス
* IOException をスローします
/
パブリック静的文字列ウォーターマーク(文字列ソースファイルパス、文字列ウォーターファイル、文字列ターゲットファイルパス) はIOExceptionをスローします {
画像 image = ImageIO.read(new File(waterFile));
整数幅 = image.getWidth(null);
整数の高さ = image.getHeight(null);
ウォーターマークを返します(sourceFilePath, 幅, 高さ,
Positions.BOTTOM_RIGHT、waterFile、0.5f、0.8f、targetFilePath);
}


/**
画像を指定されたサイズと形式に変換します。
*
* @param ソースファイルパス
* @param 幅
* @param 高さ
* @param フォーマット
* @param ターゲットファイルパス
@戻る
* IOException をスローします
/
パブリック静的文字列 changeFormat(文字列 sourceFilePath、整数幅、整数高さ、文字列形式、文字列 targetFilePath) は IOException をスローします {
サムネイル.of(ソースファイルパス)
.size(幅, 高さ)
.出力品質(0.8f)
.outputFormat(フォーマット)
.toFile(ターゲットファイルパス);
targetFilePath を返します。
}


/**
* 元のサイズに基づいて指定された形式に変換します
*
* @param ソースファイルパス
* @param フォーマット
* @param ターゲットファイルパス
@戻る
* IOException をスローします
/
パブリック静的文字列 changeFormat(文字列 sourceFilePath, 文字列 format, 文字列 targetFilePath) は IOException をスローします {
画像 image = ImageIO.read(new File(sourceFilePath));
整数幅 = image.getWidth(null);
整数の高さ = image.getHeight(null);
サムネイル.of(ソースファイルパス)
.size(幅, 高さ)
.outputFormat(フォーマット)
.toFile(ターゲットファイルパス);
targetFilePath を返します。
}

/**
* 出力ストリームに出力
*
* @param ソースファイルパス
* @param ターゲットファイルパス
@戻る
* IOException をスローします
/
パブリック静的文字列 toOutputStream(文字列 sourceFilePath、文字列 targetFilePath) は IOException をスローします {
出力ストリーム os = 新しい FileOutputStream(targetFilePath);
Thumbnails.of(sourceFilePath).toOutputStream(os);
targetFilePath を返します。
}


/**
* BufferedImage に出力
*
* @param ソースファイルパス
* @param フォーマット
* @param ターゲットファイルパス
@戻る
* IOException をスローします
/
パブリック静的文字列 asBufferedImage(文字列 sourceFilePath, 文字列 format, 文字列 targetFilePath) は IOException をスローします {
/**
* asBufferedImage() は BufferedImage を返します
/
BufferedImage サムネイル = Thumbnails.of(sourceFilePath).size(1280, 1024).asBufferedImage();
ImageIO.write(サムネイル、フォーマット、新しいファイル(targetFilePath));
targetFilePath を返します。
}
}

要約

今日は、A-Fenが2つのコンポーネントを使ってQRコードと画像を作成する手順をご紹介します。この2つのテクニックは仕事で必ず使うものなので、ぜひ保存して活用してみてください!