ImageIO javax.imageio;读取图片问题

今天在做二维码的时候,要在二维码中心放置一个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读取的格式以实际的图片格式为准。读取图片的实际格式要满足上面的格式才可以进行读取,改后缀名无效。否则就是空,也不会报错。


希望对遇到此类问题的同志们有用


 
  
 
  
 
  
 
  
 
  
 
 

你可能感兴趣的:(java)