Generate two-dimensional code to add LOGO

Remind future self: when using the optimistic path changed a bit on the line
<! - generated two-dimensional code ->
<dependency>
  <groupId>com.google.zxing</groupId>
  <artifactId>core</artifactId>
  <version>${zxing.version}</version>
</dependency>
<dependency>
  <groupId>com.google.zxing</groupId>
  <artifactId>android-core</artifactId>
  <version>3.3.0</version>
</dependency>
<dependency>
  <groupId>com.google.zxing</groupId>
  <artifactId>android-integration</artifactId>
  <version>3.3.0</version>
</dependency>
<dependency>
  <groupId>com.google.zxing</groupId>
  <artifactId>javase</artifactId>
  <version>${zxing.version}</version>
</dependency>
package com.sun.test.QRcode.AddLOGO;

public class QrCodeTest {
 
   public static void main(String[] args) throws Exception {
       long start = System.currentTimeMillis();
      // store the contents in the two-dimensional codes
      String text = "I'm Xiaoming Why Why Why Why Why";
      // two-dimensional code embedded image path
      String imgPath = "http://shenghuoplus.oss-cn-shenzhen.aliyuncs.com/ Dish Images /779b931afa3f7910bc40b79b2cfb36aa.jpg";
      // path and name of the generated two-dimensional code
      String destPath = "F:/play.png";
      // generate two-dimensional code
      QRCodeUtil.encode(text, imgPath, destPath, true);
        long generateEnd = System.currentTimeMillis();
        System.out.println ( "Time to generate two-dimensional code:" + (generateEnd - start));

      // parse the two-dimensional code
      String str = QRCodeUtil.decode(destPath);
        System.out.println ( "resolved two-dimensional code:" + (System.currentTimeMillis () - generateEnd));
      // print out the contents parsed
      System.out.println ( "print out the contents of the parsed:" + str);

   }
 
}
package com.sun.test.QRcode.AddLOGO;

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io. *;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Hashtable;

public class QRCodeUtil {

    private static final String CHARSET = "utf-8";
    private static final String FORMAT_NAME = "JPG";
    // size two-dimensional code
    private static final int QRCODE_SIZE = 300;
    // LOGO width
    private static final int WIDTH = 60;
    // LOGO height
    private static final int HEIGHT = 60;

    private static BufferedImage createImage(String content, String imgPath, boolean needCompress) throws Exception {
        Hashtable hints = new Hashtable();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        hints.put(EncodeHintType.MARGIN, 1);
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE,
                hints);
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }
        if (imgPath == null || "".equals(imgPath)) {
            return image;
        }

        // new a URL object
        URL url = new URL("http://shenghuoplus.oss-cn-shenzhen.aliyuncs.com/%E8%8F%9C%E5%93%81%E5%9B%BE%E7%89%87%2F779b931afa3f7910bc40b79b2cfb36aa.jpg");
// Open link
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
// Set the request method to "GET"
        conn.setRequestMethod("GET");
// response timeout time is 5 seconds
        conn.setConnectTimeout(5 * 1000);
// Get the picture data through the input stream
        InputStream inStream = conn.getInputStream();
// binary image data obtained in order to obtain binary data package, having versatility
        byte[] data = readInputStream(inStream);
// new file object to save a picture, save the default root directory of the current project
        File imageFile = new File("F:/play.png");
// Create output stream
        FileOutputStream outStream = new FileOutputStream(imageFile);
//data input
        outStream.write(data);
// close the output stream
        outStream.close();

        // Insert Picture
        QRCodeUtil.insertImage(image, imageFile.getPath(), needCompress);
        return image;
    }

    public static byte[] readInputStream(InputStream inStream) throws Exception{
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
// create a string Buffer
        byte[] buffer = new byte[1024];
// string length is read each time, or -1, representing the completion of reading all
        int len ​​= 0;
// use an input data stream read from the buffer in
        while( (len=inStream.read(buffer)) != -1 ){
// output buffer write data to the stream, the parameter represents the intermediate position from which to start reading, len representative of the read length
            outStream.write(buffer, 0, len);
        }
// close the input stream
        inStream.close();
// write the data in the memory outStream
        byte[] b  =outStream.toByteArray();
        outStream.close();
        return b;
    }

    private static void insertImage(BufferedImage source, String imgPath, boolean needCompress) throws Exception {
        File file = new File(imgPath);
        if (!file.exists()) {
            System.err.println ( "" + imgPath + "The file does not exist"!);
            return;
        }

        Image src = ImageIO.read(new File(imgPath));
        int width = src.getWidth(null);
        int height = src.getHeight(null);
        if (needCompress) {// compression LOGO
            if (width > WIDTH) {
                width = WIDTH;
            }
            if (height > HEIGHT) {
                height = HEIGHT;
            }
            // todo a problem
            Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
            BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics g = tag.getGraphics();
            g.drawImage (image, 0, 0, null); // the reduced sketch
            g.dispose ();
            src = image;
        }


        // insert LOGO
        Graphics2D graph = source.createGraphics();
        int x = (QRCODE_SIZE - width) / 2;
        int y = (QRCODE_SIZE - height) / 2;
        graph.drawImage(src, x, y, width, height, null);
        Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
        graph.setStroke(new BasicStroke(3f));
        graph.draw(shape);
        graph.dispose();
    }

    public static void encode(String content, String imgPath, String destPath, boolean needCompress) throws Exception {
        BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
        mkdirs(destPath);
        ImageIO.write(image, FORMAT_NAME, new File(destPath));
    }

    public static BufferedImage encode(String content, String imgPath, boolean needCompress) throws Exception {
        BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
        return image;
    }

    public static void mkdirs(String destPath) {
        File file = new File(destPath);
        // When the folder does not exist, mkdirs will automatically create several directory different from the mkdir. (Mkdir if the parent directory does not exist it will throw an exception)
        if (!file.exists() && !file.isDirectory()) {
            file.mkdirs();
        }
    }

    public static void encode(String content, String imgPath, String destPath) throws Exception {
        QRCodeUtil.encode(content, imgPath, destPath, false);
    }
    // method annotated
    /*
     * public static void encode(String content, String destPath, boolean
     * needCompress) throws Exception { QRCodeUtil.encode(content, null, destPath,
     * needCompress); }
     */

    public static void encode(String content, String destPath) throws Exception {
        QRCodeUtil.encode(content, null, destPath, false);
    }

    public static void encode(String content, String imgPath, OutputStream output, boolean needCompress)
            throws Exception {
        BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
        ImageIO.write(image, FORMAT_NAME, output);
    }

    public static void encode(String content, OutputStream output) throws Exception {
        QRCodeUtil.encode(content, null, output, false);
    }

    public static String decode(File file) throws Exception {
        BufferedImage image;
        image = ImageIO.read(file);
        if (image == null) {
            return null;
        }
        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        Result result;
        Hashtable hints = new Hashtable();
        hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
        result = new MultiFormatReader().decode(bitmap, hints);
        String resultStr = result.getText();
        return resultStr;
    }

    public static String decode(String path) throws Exception {
        return QRCodeUtil.decode(new File(path));
    }

}
package com.sun.test.QRcode.AddLOGO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.apache.commons.codec.binary.Base64;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description: (two-dimensional code)
 * @Author: luoguohui
 * @Date: 2015-10-29 05:27:13 PM
 */
public class ZXingCode {
    private static final int QRCOLOR = 0xFF000000; // default is black
    private static final int BGWHITE = 0xFFFFFFFF; // background color


    public static void main(String[] args) throws WriterException {

        try {
            getLogoQRCode ( "https://www.baidu.com/", "jump to Baidu two-dimensional code");
        } catch (Exception e) {
            e.printStackTrace ();
        }
    }


    /**
     * Generate two-dimensional code with the logo picture
     */
    public static String getLogoQRCode(String qrUrl, String productName) {
//      String filePath = (javax.servlet.http.HttpServletRequest)request.getSession().getServletContext().getRealPath("/") + "resources/images/logoImages/llhlogo.png";
        // filePath is the path to the two-dimensional code logo, but actually we are on a path of the project below, the path with the above, the following comments like
        String filePath = "C:/Users/DELL/Desktop/T.png";  //TODO
        String content = qrUrl;
        try {
            ZXingCode zp = new ZXingCode();
            BufferedImage bim = zp.getQR_CODEBufferedImage(content, BarcodeFormat.QR_CODE, 400, 400, zp.getDecodeHintType());
            return zp.addLogo_QRCode(bim, new File(filePath), new LogoConfig(), productName);
        } catch (Exception e) {
            e.printStackTrace ();
        }
        return null;
    }

    /**
     * Add pictures to the two-dimensional code Logo
     */
    public String addLogo_QRCode(BufferedImage bim, File logoPic, LogoConfig logoConfig, String productName) {
        try {
            /**
             * Read two-dimensional code images and drawing objects to build
             */
            BufferedImage image = bim;
            Graphics2D g = image.createGraphics();

            /**
             * Read Logo Picture
             */
            BufferedImage logo = ImageIO.read(logoPic);
            /**
             * Set the size of the logo, I set the two-dimensional code images 20%, because the General Assembly had the cover off the two-dimensional code
             */
            int widthLogo = logo.getWidth(null) > image.getWidth() * 3 / 10 ? (image.getWidth() * 3 / 10) : logo.getWidth(null),
                    heightLogo = logo.getHeight(null) > image.getHeight() * 3 / 10 ? (image.getHeight() * 3 / 10) : logo.getWidth(null);

            /**
             * Logo placed in the center
             */
            int x = (image.getWidth() - widthLogo) / 2;
            int y = (image.getHeight() - heightLogo) / 2;
            /**
             * Logo on the bottom right corner
             *  int x = (image.getWidth() - widthLogo);
             *  int y = (image.getHeight() - heightLogo);
             */

            // start drawing pictures
            g.drawImage(logo, x, y, widthLogo, heightLogo, null);
//            g.drawRoundRect(x, y, widthLogo, heightLogo, 15, 15);
//            g.setStroke(new BasicStroke(logoConfig.getBorder()));
//            g.setColor(logoConfig.getBorderColor());
//            g.drawRect(x, y, widthLogo, heightLogo);
            g.dispose ();

            // add up the trade name, trade name not too long Oh, supports up to two lines here. Too long will automatically intercept it
            if (productName != null && !productName.equals("")) {
                // new image, the two-dimensional code with the following logo plus text
                BufferedImage outImage = new BufferedImage(400, 445, BufferedImage.TYPE_4BYTE_ABGR);
                Graphics2D outg = outImage.createGraphics();
                // draw two-dimensional code to the new panel
                outg.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
                // draw the text to the new panel
                outg.setColor(Color.BLACK);
                outg.setFont (new Font ( "Arial", Font.BOLD, 30)); // font, font, font size
                int strWidth = outg.getFontMetrics().stringWidth(productName);
                if (strWidth > 399) {
// // taken too long on the front portion
//                  outg.drawString(productName, 0, image.getHeight() + (outImage.getHeight() - image.getHeight())/2 + 5 ); //画文字
                    // too long to wrap
                    String productName1 = productName.substring(0, productName.length() / 2);
                    String productName2 = productName.substring(productName.length() / 2, productName.length());
                    int strWidth1 = outg.getFontMetrics().stringWidth(productName1);
                    int strWidth2 = outg.getFontMetrics().stringWidth(productName2);
                    outg.drawString (productName1, 200 - strWidth1 / 2, image.getHeight () + (outImage.getHeight () - image.getHeight ()) / 2 + 12);
                    BufferedImage outImage2 = new BufferedImage(400, 485, BufferedImage.TYPE_4BYTE_ABGR);
                    Graphics2D outg2 = outImage2.createGraphics();
                    outg2.drawImage (outImage, 0, 0, outImage.getWidth () outImage.getHeight (), null);
                    outg2.setColor(Color.BLACK);
                    outg2.setFont (new Font ( "Arial", Font.BOLD, 30)); // font, font, font size
                    outg2.drawString (productName2, 200 - strWidth2 / 2 outImage.getHeight () + (outImage2.getHeight () - outImage.getHeight ()) / 2 + 5);
                    outg2.dispose ();
                    outImage2.flush ();
                    outImage = outImage2;
                } else {
                    outg.drawString(productName, 200 - strWidth / 2, image.getHeight() + (outImage.getHeight() - image.getHeight()) / 2 + 12); //画文字
                }
                outg.dispose ();
                outImage.flush ();
                image = outImage;
            }
            logo.flush();
            image.flush();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            baos.flush();
            ImageIO.write(image, "png", baos);

            // path generated two-dimensional code, but the actual project, we put the generated two-dimensional code displayed on the screen, so the following code can be wrapped commented
            // You can see that this method is the final return of the two-dimensional code string imageBase64
            // distal end with <play src = "data: image / png; base64, $ {imageBase64QRCode}" /> where $ {imageBase64QRCode} corresponding to the two-dimensional code string imageBase64
//            ImageIO.write(image, "png", new File("C:/Users/luoguohui/Desktop/TDC-" + new Date().getTime() + "test.png")); //TODO
            ImageIO.write(image, "png", new File("F:/" + new Date().getTime() + "test.png"));
            String imageBase64QRCode = Base64.encodeBase64URLSafeString(baos.toByteArray());

            baos.close();
            return imageBase64QRCode;
        } catch (Exception e) {
            e.printStackTrace ();
        }
        return null;
    }


    /**
     * Construction of two-dimensional code to initialize
     *
     * @Param bm
     * @return
     */
    public BufferedImage fileToBufferedImage(BitMatrix bm) {
        BufferedImage image = null;
        try {
            int w = bm.getWidth(), h = bm.getHeight();
            image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);

            for (int x = 0; x < w; x++) {
                for (int y = 0; y < h; y++) {
                    image.setRGB(x, y, bm.get(x, y) ? 0xFF000000 : 0xFFCCDDEE);
                }
            }

        } catch (Exception e) {
            e.printStackTrace ();
        }
        return image;
    }

    /**
     * Generate two-dimensional code bufferedImage Pictures
     *
     * @Param content encoded content
     * @Param barcodeFormat encoding type
     * @Param width image width
     * @Param height Image Height
     * @Param hints parameter settings
     * @return
     */
    public BufferedImage getQR_CODEBufferedImage(String content, BarcodeFormat barcodeFormat, int width, int height, Map<EncodeHintType, ?> hints) {
        MultiFormatWriter multiFormatWriter = null;
        BitMatrix bm = null;
        BufferedImage image = null;
        try {
            multiFormatWriter = new MultiFormatWriter();
            // parameters are sequence: encoding the content, coding type, generating a picture width, picture height generated, setting parameters
            bm = multiFormatWriter.encode(content, barcodeFormat, width, height, hints);
            int w = bm.getWidth();
            int h = bm.getHeight();
            image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);

            // start using the data to create two-dimensional code Bitmap images are set to black (0xFFFFFFFF) White (0xFF000000) two-color
            for (int x = 0; x < w; x++) {
                for (int y = 0; y < h; y++) {
                    image.setRGB(x, y, bm.get(x, y) ? QRCOLOR : BGWHITE);
                }
            }
        } catch (WriterException e) {
            e.printStackTrace ();
        }
        return image;
    }

    /**
     * Set of two-dimensional code format parameters
     *
     * @return
     */
    public Map<EncodeHintType, Object> getDecodeHintType() {
        // QR two-dimensional code is used to set parameters
        Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
        // set the QR two-dimensional code error correction level (H being the highest level) information specific level
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        // set the encoding
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        hints.put(EncodeHintType.MARGIN, 0);
        hints.put(EncodeHintType.MAX_SIZE, 350);
        hints.put(EncodeHintType.MIN_SIZE, 100);

        return hints;
    }
}

class LogoConfig {
    // logo default border color
    public static final Color DEFAULT_BORDERCOLOR = Color.WHITE;
    // logo default border width
    public static final int DEFAULT_BORDER = 2;
    // logo size defaults to photo 1/5
    public static final int DEFAULT_LOGOPART = 5;

    private final int border = DEFAULT_BORDER;
    private final Color borderColor;
    private final int logoPart;

    /**
     */
    public LogoConfig() {
        this(DEFAULT_BORDERCOLOR, DEFAULT_LOGOPART);
    }

    public LogoConfig(Color borderColor, int logoPart) {
        this.borderColor = borderColor;
        this.logoPart = logoPart;
    }

    public Color getBorderColor() {
        return borderColor;
    }

    public int getBorder() {
        return border;
    }

    public int getLogoPart() {
        return logoPart;
    }
}

Guess you like

Origin blog.csdn.net/weixin_41825468/article/details/90772394