在对图片进行处理过程中,发现java 不支持 某些图片的操作(放大,缩小),报一下错误:
[ERROR][2024-03-18 11:23:04,661][com.elink.base.util.ImageUtil]error imgLoadUrl
javax.imageio.IIOException: Invalid icc profile: invalid number of icc markers
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImageHeader(Native Method)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readNativeHeader(JPEGImageReader.java:628)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.checkTablesOnly(JPEGImageReader.java:347)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.gotoImage(JPEGImageReader.java:495)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readHeader(JPEGImageReader.java:621)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1078)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1058)
at javax.imageio.ImageIO.read(ImageIO.java:1462)
at javax.imageio.ImageIO.read(ImageIO.java:1309)
at com.elink.base.util.ImageUtil.imgLoadUrl(ImageUtil.java:190)
at com.elink.share.util.PdfHelper.image2pdfWithStamp(PdfHelper.java:69)
一般这些图片,是由扫描仪扫描,或者数码相机拍摄,并且处理时,图片的颜色空间(colorspace)为CMYK模式。
导致了ImageIO.read()方法抛出异常的原因。
一般情况为RGB模式。
在 sun 的官方网站,有该bug 的讨论:
更详细描述如下:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6245283
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6404011
在ImageIO.read方法前,把jpg图片文件从写,就不会有问题。.
File srcImageFileGood = new File(dstImageFileName);
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(new FileInputStream(srcImageFile));
BufferedImage image = decoder.decodeAsBufferedImage();
ImageIO.write(image, "JPEG", srcImageFileGood);
原方法:
package com.elink.base.util;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageDecoder;
import org.apache.log4j.Logger;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
public class ImageUtil {
private static Integer ROTATION_ANGLE = 360; //弧度
private static Integer LOAD_NETWORK = 0; //图片来源网络
private static Integer LOAD_LOCAL = 1; //图片来源本地
private static Logger log = Logger.getLogger(ImageUtil.class);
//测试
public static void main(String[] args) {
//获取背景图
BufferedImage bgImg = imgLoadUrl("E:/002.png", LOAD_LOCAL);
//需要叠加的图片列表
List<ImgBean> imgBeans = new ArrayList<ImgBean>();
//需要添加的文字列表
List<TextBean> textBeans = new ArrayList<TextBean>();
//获取圆形图片 //margin=null 则不设置图片背景
// BufferedImage circularImg = getCircularImg(imgLoadUrl("图片路径", LOAD_NETWORK), 30, 30, ROTATION_ANGLE, 20, Color.WHITE);
// imgBeans.add(imgParameter(circularImg, true, null, 200, 300, 50));
imgBeans.add(imgParameter(imgLoadUrl("E:/001_1.png", LOAD_LOCAL), true, null, bgImg.getHeight()/2-111, 222, 222));
// textBeans.add(textParameter("需要输入的文字", true, null, 12, Color.white, new Font("微软雅黑", Font.PLAIN, 30)));
try {
ImageIO.write(createImg(bgImg, textBeans, imgBeans), "png", new File("E:/002_new.png"));
} catch (IOException e) {
log.error("error main", e);
}
}
public static BufferedImage createImg(BufferedImage bgImg, List<TextBean> textBeans, List<ImgBean> imgBeans) {
Graphics2D g = bgImg.createGraphics();
//去锯齿
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//图片叠加
imgSuperposition(g, bgImg.getWidth(), imgBeans);
//添加文字
textAddImg(g, bgImg.getWidth(), textBeans);
return bgImg;
}
/**
* 图片叠加
*
* @param g
* @param
* @param imgBeans
*/
private static Graphics2D imgSuperposition(Graphics2D g, Integer bgImgWidth, List<ImgBean> imgBeans) {
try {
for (int i = 0; i < imgBeans.size(); i++) {
ImgBean imgBean = imgBeans.get(i);
if (imgBean.isCenter()) { //是否居中判断
int x = (bgImgWidth - imgBean.getW()) / 2;
g.drawImage(imgBeans.get(i).getImg(), x, imgBean.getY(), imgBean.getW(), imgBean.getH(), null);
} else {
g.drawImage(imgBeans.get(i).getImg(), imgBean.getX(), imgBean.getY(), imgBean.getW(), imgBean.getH(), null);
}
}
} catch (Exception e) {
log.error("error imgSuperposition", e);
}
return g;
}
/**
* 添加文字
*
* @param g
* @param bgImgWidth
* @param textBeans
*/
private static Graphics2D textAddImg(Graphics2D g, Integer bgImgWidth, List<TextBean> textBeans) {
try {
for (int i = 0; i < textBeans.size(); i++) {
TextBean textBean = textBeans.get(i);
g.setColor(textBean.getColor());
g.setFont(textBean.getFont());
if (textBean.isCenter()) { //是否居中判断
int x = g.getFontMetrics().stringWidth(textBean.getName());
g.drawString(textBean.getName(), (bgImgWidth - x) / 2, textBean.getY());
} else {
g.drawString(textBean.getName(), textBean.getX(), textBean.getY());
}
}
} catch (Exception e) {
log.error("error textAddImg", e);
}
return g;
}
/**
* 图片圆形处理 返回处理后的图片
*
* @param img 图片
* @param width 宽
* @param height 高
* @param rotationAngle 弧度
* @param margin 边距 不传则不设置背景
* @return
*/
public static BufferedImage getCircularImg(BufferedImage img, Integer width, Integer height, Integer rotationAngle, Integer margin, Color color) {
BufferedImage circularImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = circularImg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.WHITE);
g2.fill(new RoundRectangle2D.Float(0, 0, width, height, rotationAngle, rotationAngle));
g2.setComposite(AlphaComposite.SrcAtop);
g2.drawImage(img, 0, 0, width, height, null);
g2.dispose();
if (margin != null) {
circularImg = getCircularImgByBorder(circularImg, margin, color);
}
return circularImg;
}
/**
* 圆形图片添加圆形背景
*
* @param circularImg 传入的图
* @param margin 边距
* @param color 背景颜色
* @return
*/
public static BufferedImage getCircularImgByBorder(BufferedImage circularImg, Integer margin, Color color) {
BufferedImage circularImgByBorder = new BufferedImage(circularImg.getWidth() + margin, circularImg.getHeight() + margin, circularImg.getType());
Graphics2D g = circularImgByBorder.createGraphics();
//去锯齿
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(color == null ? Color.WHITE : color);
g.fill(new RoundRectangle2D.Float(0, 0, circularImg.getWidth() + margin, circularImg.getHeight() + margin, ROTATION_ANGLE, ROTATION_ANGLE));
g.setComposite(AlphaComposite.SrcAtop);
g.drawImage(circularImg, margin / 2, margin / 2, circularImg.getWidth(), circularImg.getHeight(), null);
g.dispose();
return circularImgByBorder;
}
/**
* 获取图片
*
* @param imgUrl 图片路径
* @param type 图片来源:0=网络/ 1=本地
*/
public static BufferedImage imgLoadUrl(String imgUrl, Integer type) {
try {
try {
return CMYK.readImage(imgUrl);
}catch (Exception ex) {
File srcImageFileGood = new File(imgUrl);
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(new FileInputStream(imgUrl));
BufferedImage image = decoder.decodeAsBufferedImage();
ImageIO.write(image, "JPEG", srcImageFileGood);
if (LOAD_NETWORK.equals(type)) {
return ImageIO.read(new URL(imgUrl));
} else if (LOAD_LOCAL.equals(type)) {
return ImageIO.read(new File(imgUrl));
}
}
} catch (Exception e) {
log.error("error imgLoadUrl", e);
try {
JPEGImageDecoder decoder = null;
if (LOAD_LOCAL.equals(type)) {
decoder = JPEGCodec.createJPEGDecoder(new FileInputStream((new File(imgUrl))));
}else if (LOAD_NETWORK.equals(type)) {
decoder = JPEGCodec.createJPEGDecoder(new URL(imgUrl).openStream());
}
return decoder.decodeAsBufferedImage();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
return null;
}
/**
* 图片设置参数
*
* @param img 图片
* @param center 是否居中
* @param x 如果居中 此值可以不用传
* @param y 图片y轴初始位置
* @param w 图片宽
* @param h 图片高
*/
public static ImgBean imgParameter(BufferedImage img, boolean center, Integer x, Integer y, Integer w, Integer h) {
try {
ImgBean imgBean = new ImgBean();
imgBean.setImg(img);
imgBean.setCenter(center);
imgBean.setX(x == null ? 0 : x);
imgBean.setY(y == null ? 0 : y);
imgBean.setW(w == null ? img.getWidth() : w);
imgBean.setH(h == null ? img.getHeight() : h);
return imgBean;
} catch (Exception e) {
log.error("error imgParameter", e);
}
return null;
}
/**
* 文字设置参数
*
* @param name 传入文字
* @param center 是否居中
* @param x x轴位置
* @param y y轴位置
* @param color 颜色
* @param font 画笔
*/
public static TextBean textParameter(String name, boolean center, Integer x, Integer y, Color color, Font font) {
try {
TextBean textBean = new TextBean();
textBean.setName(name);
textBean.setCenter(center);
textBean.setX(x == null ? 0 : x);
textBean.setY(y == null ? 0 : y);
textBean.setColor(color == null ? Color.WHITE : color);
textBean.setFont(font == null ? new Font("微软雅黑", Font.PLAIN, 30) : font);
} catch (Exception e) {
log.error("error textParameter", e);
}
return null;
}
/**
* 图片设置类
* title imgParameter
*/
public static class ImgBean {
/**
* 图片buffer
*/
private BufferedImage img;
/**
* 图片x轴标
*/
private int x;
/**
* 图片y轴坐标
*/
private int y;
/**
* 图片宽
*/
private int w;
/**
* 图片高
*/
private int h;
/**
* 图片是否居中
*/
private boolean center;
public BufferedImage getImg() {
return img;
}
public void setImg(BufferedImage img) {
this.img = img;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getW() {
return w;
}
public void setW(int w) {
this.w = w;
}
public int getH() {
return h;
}
public void setH(int h) {
this.h = h;
}
public boolean isCenter() {
return center;
}
public void setCenter(boolean center) {
this.center = center;
}
}
/**
* 文字bean
* title TextBean
*/
public static class TextBean {
/**
* 输入的文字
*/
private String name;
/**
* 文字是否居中
*/
private boolean center;
/**
* 文字的x轴位置
*/ //居中此值不用传
private int x;
/**
* 文字的y轴位置
*/ //注:文字的位置计算是以文字的底部开始的,右下角,不像图片从左上角
private int y;
/**
* 文字的颜色
*/
private Color color;
/**
* 画笔
*/
private Font font;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isCenter() {
return center;
}
public void setCenter(boolean center) {
this.center = center;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public Font getFont() {
return font;
}
public void setFont(Font font) {
this.font = font;
}
}
}