码迷,mamicode.com
首页 > 其他好文 > 详细

带圆角LOGO的QrCode二维码实时生成

时间:2014-12-24 21:35:49      阅读:266      评论:0      收藏:0      [点我收藏+]

标签:java   二维码生成   qrcode   

最近工作中经常要用到QrCode二维码,研究了一下,写了个带圆角LOGO的JAVA实现,QrCode之所以能在中间放个LOGO图标,是因为编码时的信息冗余。实现的具体代码如下:

方法接口:

import java.io.File;
import java.io.OutputStream;

public interface QRCodeService {

    public void generateToStream(String code, OutputStream stream);
    
    public void generateToStream(String code, OutputStream stream, int width);
    
    public void generateToStream(String code, OutputStream stream, int width, int frontColor);
    
    public void generateToStream(String code, OutputStream stream, int width, int frontColor, File logo);
}
接口实现类:

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

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;


@Service("qrCodeService")
public class QRCodeServiceImpl implements QRCodeService {

    private static final Logger LOGGER = LoggerFactory.getLogger(QRCodeServiceImpl.class);
    // 二维码的宽
    private static int WIDTH = 250;
    // 中间图片的宽
    private static int IMGWIDTH = 60;
    // 圆角半径
    private static int RADIUS = 10;
    // 留白填充宽度
    private static int MARGIN = 4;
    
    private static int FRONTCOLOR = 0x00000000;//0x00808080;
    
    /**
     * 功能描述:生成普通二维码到输出流
     */
    @Override
    public void generateToStream(String code, OutputStream stream) {
        this.generateToStream(code, stream, WIDTH, FRONTCOLOR, null);
    }
    
    @Override
    public void generateToStream(String code, OutputStream stream, int width) {
        this.generateToStream(code, stream, width, FRONTCOLOR, null);
    }

    @Override
    public void generateToStream(String code, OutputStream stream, int width, int frontColor) {
        this.generateToStream(code, stream, width, frontColor, null);
    }

    @Override
    public void generateToStream(String code, OutputStream stream, int width, int frontColor, File logo) {
        Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        // 修正容量高
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        // 边框留白
        hints.put(EncodeHintType.MARGIN, 1);
        BitMatrix matrix = null;
        try {
            matrix = new MultiFormatWriter().encode(code, BarcodeFormat.QR_CODE, width, width, hints);
        } catch (WriterException e) {
            LOGGER.error("", e);
        }
        proc(matrix, stream, frontColor, logo);
    }

    public void proc(BitMatrix matrix, OutputStream stream, int frontColor, File logo) {
        int width = matrix.getWidth();
        // 处理后图片的数据
        int pixels[] = new int[width * width];
        // 中间图片数组数据
        int src[][] = null;
        boolean hashlogo = false;
        if(logo != null){
            src = getPic(logo);
            hashlogo = true;
        }
        // 填充色
        int margincolor = 0xffffffff;// 白色
        int w_half = width / 2;
        int frame = MARGIN;
        int img_half = IMGWIDTH / 2;
        int r = RADIUS;
        int near = width / 2 - img_half - frame + r;//101
        int far = width / 2 + img_half + frame - r;//149
        for (int y = 0; y < width; y++) {
            for (int x = 0; x < width; x++) {
                if(!hashlogo){
                    // 二维码
                    pixels[y * width + x] = matrix.get(x, y) ? frontColor : margincolor;
                } else {
                    // 中间图片
                    if (x > w_half - img_half && x < w_half + img_half
                            && y > w_half - img_half && y < w_half + img_half) {
                        //
                        pixels[y * width + x] = src[x - w_half + img_half][y - w_half + img_half];

                    } else if ((x > w_half - img_half - frame // 左边框
                            && x < w_half - img_half + frame && y > w_half - img_half - frame && y < w_half
                            + img_half + frame)
                            || (x > w_half + img_half - frame // 右边框
                                    && x < w_half + img_half + frame
                                    && y > w_half - img_half - frame && y < w_half + img_half
                                    + frame)
                            || (x > w_half - img_half - frame // 上边框
                                    && x < w_half + img_half + frame
                                    && y > w_half - img_half - frame && y < w_half - img_half
                                    + frame)
                            || (x > w_half - img_half - frame // 下边框
                                    && x < w_half + img_half + frame
                                    && y > w_half + img_half - frame && y < w_half + img_half
                                    + frame)) {
                        
                        // 圆角处理
                        if(x<near && y<near && (near-x)*(near-x)+(near-y)*(near-y)> r*r){
                            // 左上圆角
                            pixels[y * width + x] = matrix.get(x, y) ? frontColor : margincolor;
                        } else if(x>far && y<near && (x-far)*(x-far)+(near-y)*(near-y) > r*r){
                            // 右上圆角
                            pixels[y * width + x] = matrix.get(x, y) ? frontColor : margincolor;
                        } else if(x<near && y>far && (near-x)*(near-x)+(y-far)*(y-far) > r*r){
                            // 左下圆角
                            pixels[y * width + x] = matrix.get(x, y) ? frontColor : margincolor;
                        } else if(x>far && y>far && (x-far)*(x-far)+(y-far)*(y-far) > r*r){
                            // 右下圆角 
                            pixels[y * width + x] = matrix.get(x, y) ? frontColor : margincolor;
                        } else {
                            // 边框填充颜色
                            pixels[y * width + x] = margincolor; 
                        }
                    } else {
                        // 二维码
                        pixels[y * width + x] = matrix.get(x, y) ? frontColor : margincolor; 
                    }
                }
            }
        }
        BufferedImage image = new BufferedImage(width, width, BufferedImage.TYPE_INT_RGB);
        image.getRaster().setDataElements(0, 0, width, width, pixels);
        try {
            ImageIO.write(image, "png", stream);
        } catch (IOException e) {
            //TODO
        }
    }

    // 图片的压缩、圆角处理,并生成数组
    public int[][] getPic(File logo) {
        BufferedImage biSrc = null;
        try {
            biSrc = ImageIO.read(logo);
        } catch (IOException e) {
            
        }
        BufferedImage biTarget = new BufferedImage(IMGWIDTH, IMGWIDTH, BufferedImage.TYPE_3BYTE_BGR);
        biTarget.getGraphics().drawImage(biSrc.getScaledInstance(IMGWIDTH, IMGWIDTH, Image.SCALE_SMOOTH), 0, 0, null);
        int src[][] = new int[IMGWIDTH][IMGWIDTH];
        // 圆角处理半径
        int r = RADIUS;
        int max = IMGWIDTH;
        int bordercolor = 0x00000000;
        int whitecolor = 0xffffffff;
        for (int x = 0; x < IMGWIDTH; x++) {
            for (int y = 0; y < IMGWIDTH; y++) {
                if(x<r&&y<r&&((r-x)*(r-x)+(r-y)*(r-y)>(r-1)*(r-1))){
                    // 左上圆角
                    if((r-x)*(r-x)+(r-y)*(r-y)>r*r){
                        src[x][y] = whitecolor;
                    } else {
                        src[x][y] = bordercolor;
                    }
                } else if (x>(max-r)&&y<r&&(x+r-max)*(x+r-max)+(r-y)*(r-y)>(r-1)*(r-1)){
                    // 右上圆角
                    if((x+r-max)*(x+r-max)+(r-y)*(r-y)>r*r){
                        src[x][y] = whitecolor;
                    }else{
                        src[x][y] = bordercolor;
                    }
                } else if (x<r&&y>(max-r)&&(r-x)*(r-x)+(y+r-max)*(y+r-max)>(r-1)*(r-1)){
                    // 左下圆角
                    if((r-x)*(r-x)+(y+r-max)*(y+r-max)>r*r){
                        src[x][y] = whitecolor;
                    }else{
                        src[x][y] = bordercolor;
                    }
                } else if (x>(max-r)&&y>(max-r)&&(x+r-max)*(x+r-max)+(y+r-max)*(y+r-max)>(r-1)*(r-1)){
                    // 右下圆角 
                    if((x+r-max)*(x+r-max)+(y+r-max)*(y+r-max)>r*r){
                        src[x][y] = whitecolor;
                    }else{
                        src[x][y] = bordercolor;
                    }
                } else {
                    if(((x>=r && x<=max-r) && (y==0||y==1||y==max-1||y==max)) || ((y>=r &&y<=max-r) && (x==0||x==1||x==max-1||x==max))){
                        // 四周除圆角的边框
                        src[x][y] = bordercolor;
                    } else {
                        // 图片值
                        src[x][y] = biTarget.getRGB(x, y);
                    }
                }
            }
        }
        return src;
    }
}
控制器类:

@Controller
@RequestMapping("")
public class QrCodeController {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(QrCodeController.class);

    @Resource(name = "qrCodeService")
    QRCodeService qrCodeService;
    
    @RequestMapping("qrcode")
    public void generateQrCode(HttpServletRequest request,HttpServletResponse response){
        try {
            String code = request.getParameter("url");
            if(StringUtils.isBlank(code)){
                LOGGER.error("url is null");
                return;
            }
            String width = request.getParameter("width");
            String color = request.getParameter("color");
            String logo = request.getParameter("logo");
            OutputStream os = response.getOutputStream();
            if (StringUtils.isNotBlank(width) && StringUtils.isNotBlank(color) && StringUtils.isNotBlank(logo)){
                int my_width = Integer.valueOf(width);
                int my_color = Integer.valueOf(color);
                //int my_logo = Integer.valueOf(logo);
                LOGGER.info("hash logo");
                File logofile = new File("logo.jpg");
                qrCodeService.generateToStream(code, os, my_width, my_color, logofile);
            } else if (StringUtils.isNotBlank(width) && StringUtils.isNotBlank(color)){
                int my_width = Integer.valueOf(width);
                int my_color = Integer.valueOf(color);
                qrCodeService.generateToStream(code, os, my_width, my_color);
            } else if(StringUtils.isNotBlank(width)) {
                int my_width = Integer.valueOf(width);
                qrCodeService.generateToStream(code, os, my_width);
            } else {
                qrCodeService.generateToStream(code, os);
            }
            os.flush();
            os.close();
            LOGGER.info("generate qrcode succeed");
        } catch (IOException e) {
            LOGGER.error("generate qrcode error : ", e);
        }
    }
    
}
生成效果:

技术分享

带圆角LOGO的QrCode二维码实时生成

标签:java   二维码生成   qrcode   

原文地址:http://blog.csdn.net/zhaowen25/article/details/42127357

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!