今天在做二维码的时候,要在二维码中心放置一个logo图标,当时用ImageIO读取的时候始终为空。最后发现是图片格式问题。
整个class代码,utils:
package com.allk.utils;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.UUID;
import javax.imageio.ImageIO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
/**
* @Author Darren
* @Time 2017年9月5日 上午10:57:14
* @Description:二维码生成/解析
*/
@Component
public class QRCodeUtils {
public static String QRCode$imagePath;
/** 图片格式 */
public static final String QRCODE_PNG = "png";
public static final String QRCODE_JPG = "jpg";
public static final String QRCODE_GIF = "gif";
public static final String QRCODE_BMP = "bmp";
public static final String QRCODE_JPEG = "jpeg";
public static final String QRCODE_PNM = "pnm";
private static final Integer QRCode$width = 200;
private static final Integer QRCode$height = 200;
private static final int QRCOLOR = 0xFF000000; // 默认是黑色
private static final int BGWHITE = 0xFFFFFFFF; // 背景颜色
/**二维码扫描请求链接,验证是否有效(优惠券)*/
public static final String QRCode$DimensionalCodeUrl="http://10.192.1.125:8081/dimensionalCode/verifyCode.do/";
/** 二维码logo图片,默认使用logo图片 */
public static final String QRCode$logoImg = "/pinklogo.jpg";
/**
* 不带logo的二维码
*
* @param text 二维码附带的信息
* @param path 要存放二维码图片的路径
* @param format 图片格式 /jpg,png,gif..........
* @param file 需要显示在二维码中心位置的小图标(图片)
* @throws Exception
* @throws WriterException
* @throws IOException
*/
public static final String[] createQRCode(String text, String path, String format)
throws WriterException, IOException {
BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, QRCode$width, QRCode$height,
getDecodeHintType());
String serverImgName = createServerImgName();
String filePath = path + "/" + serverImgName;
File outputFile = new File(filePath);
MatrixToImageWriter.writeToFile(bitMatrix, format, outputFile);// 生成不带中心位置图标的二维码图片
String[] img = new String[3];
img[0] = serverImgName;
img[1] = String.valueOf(QRCode$width);
img[2] = String.valueOf(QRCode$height);
return img;
}
/**
* 带logo的二维码
*
* @param text 二维码附带的信息
* @param path 要存放二维码图片的路径
* @param format 图片格式 /jpg,png,gif..........
* @param file 需要显示在二维码中心位置的小图标(图片)
* @throws Exception
* @throws WriterException
* @throws IOException
*/
public static final String[] createLogoQRCode(String text, String path, String format, File file)
throws WriterException, IOException {
BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, QRCode$width, QRCode$height,
getDecodeHintType());
int w = bitMatrix.getWidth();
int h = bitMatrix.getHeight();
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
// 开始利用二维码数据创建Bitmap图片,分别设为黑(0xFFFFFFFF)白(0xFF000000)两色
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
image.setRGB(x, y, bitMatrix.get(x, y) ? QRCOLOR : BGWHITE);
}
}
BufferedImage bufferedImage = null;
if (file != null) {
bufferedImage = encodeImgLogo(image, file);// 绘制二维码自定义中心位置图片,注意实际格式,更改图片后缀名为满足的格式无效
} else {
// logo图片
String logoPath = path + QRCode$logoImg;
bufferedImage = encodeImgLogo(image, new File(logoPath));// 绘制二维码中心位置logo图片
}
if (bufferedImage == null) {
return null;
}
// 重新生成带logo的二维码图片
String imgName = createServerImgName();
String QRClogCode = path + "/" + imgName;
ImageIO.write(bufferedImage, format, new File(QRClogCode));// 生成带中心位置图标的二维码图片
String[] img = new String[3];
img[0] = imgName;
img[1] = String.valueOf(QRCode$width);
img[2] = String.valueOf(QRCode$height);
return img;
}
/**
* 解析二维码,需要javase包。 文件方式解码
*
* @param file
* @return
*/
public static String decode(File file) {
BufferedImage image;
try {
if (file == null || file.exists() == false) {
throw new Exception(" File not found:" + file.getPath());
}
image = ImageIO.read(file);
return unifiedDecode(image);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 解析二维码 流方式解码
*
* @param input
* @return
*/
public static String decode(InputStream input) {
BufferedImage image;
try {
if (input == null) {
throw new Exception(" input is null");
}
image = ImageIO.read(input);
return unifiedDecode(image);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String unifiedDecode(BufferedImage image) throws NotFoundException {
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result result;
// 解码设置编码方式为:utf-8,
Hashtable hints = new Hashtable();
hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
result = new MultiFormatReader().decode(bitmap, hints);
return result.getText();
}
/**
* 生成文件名
* @return
*/
public static final String createServerImgName() {
UUID serverImgUuid = UUID.randomUUID();
return DateFormatterUtils.getDateTime() + serverImgUuid.toString();// 文件名
}
/**
* 设置二维码的格式参数
*
* @return
*/
public static Map getDecodeHintType() {
// 用于设置QR二维码参数
Map hints = new HashMap();
// 设置QR二维码的纠错级别(H为最高级别)具体级别信息
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 设置编码方式
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;
}
/**
* 二维码绘制logo
*
* @param image
* @param logoImg
* logo图片文件 格式:JPG, jpg, tiff, pcx, PCX, bmp, BMP, gif, GIF,
* WBMP, png, PNG, raw, RAW, JPEG, pnm, PNM, tif, TIF, TIFF,
* wbmp, jpeg
* @throws IOException
*/
public static BufferedImage encodeImgLogo(BufferedImage image, File logoImg) throws IOException {
// String[] names = ImageIO.getReaderFormatNames();
// System.out.println(Arrays.toString(names));
// 能读取的图片格式:JPG, jpg, tiff, pcx, PCX, bmp, BMP, gif, GIF, WBMP, png, PNG, raw, RAW, JPEG, pnm, PNM, tif, TIF, TIFF, wbmp, jpeg
// 读取二维码图片
// 获取画笔
Graphics2D g = image.createGraphics();
// 读取logo图片
BufferedImage logo = ImageIO.read(logoImg);
// 设置二维码大小,太大,会覆盖二维码,此处20%
int logoWidth = logo.getWidth(null) > image.getWidth() * 2 / 10 ? (image.getWidth() * 2 / 10)
: logo.getWidth(null);
int logoHeight = logo.getHeight(null) > image.getHeight() * 2 / 10 ? (image.getHeight() * 2 / 10)
: logo.getHeight(null);
// 设置logo图片放置位置
// 中心
int x = (image.getWidth() - logoWidth) / 2;
int y = (image.getHeight() - logoHeight) / 2;
// 右下角,15为调整值
// int x = twodimensioncode.getWidth() - logoWidth-15;
// int y = twodimensioncode.getHeight() - logoHeight-15;
// 开始合并绘制图片
g.drawImage(logo, x, y, logoWidth, logoHeight, null);
g.drawRoundRect(x, y, logoWidth, logoHeight, 15, 15);
// logo边框大小
g.setStroke(new BasicStroke(2));
// logo边框颜色
g.setColor(Color.WHITE);
g.drawRect(x, y, logoWidth, logoHeight);
g.dispose();
logo.flush();
image.flush();
return image;
}
public String getQRCode$imagePath() {
return QRCode$imagePath;
}
@Value("${upload.path}")
public void setQRCode$imagePath(String qRCode$imagePath) {
QRCode$imagePath = qRCode$imagePath;
}
}
// String[] names = ImageIO.getReaderFormatNames();
// System.out.println(Arrays.toString(names));
// 能读取的图片格式:JPG, jpg, tiff, pcx, PCX, bmp, BMP, gif, GIF, WBMP, png, PNG, raw, RAW, JPEG, pnm, PNM, tif, TIF, TIFF, wbmp, jpeg
在236行那里ImageIO.read(logoImg)读取logo的时候得到的一直是null,百思不得其解。网上也查看了很多都没有错,最终发现是图片格式问题
最开始是一张后缀为ico的图片,将其改为了jpg,还是不行。ImageIO读取的时候并不是以后缀名格式来读取,所以改后缀名没有用,因为实际的图片格式并没有更改。
ImageIO读取的格式以实际的图片格式为准。读取图片的实际格式要满足上面的格式才可以进行读取,改后缀名无效。否则就是空,也不会报错。
希望对遇到此类问题的同志们有用