因为项目需要,所以要做这么个工具类,发现了一些问题,接下来一一说明。

  需要引入jai-codec-1.1.3.jar跟jai_code-1.1.3.jar。

  1.判断图片格式:

  JPEG (jpg),文件头:FFD8FF ,结尾:FFD9

  PNG (png),文件头:89504E47

  GIF (gif),文件头:47494638

  TIFF (tif),文件头:49492A00
  Windows Bitmap (bmp),文件头:424D

  -- 可以通过UltraEdit进行查看图片的十六进制内容

    /**
* 判断图片格式
* @param fis
* @return
*/
private static String getPicType(FileInputStream fis) {
//读取文件的前几个字节来判断图片格式
byte[] b = new byte[4];
try {
fis.read(b, 0, b.length);
String type = bytesToHexString(b).toUpperCase();
if (type.contains("FFD8FF")) {
return "jpg";
} else if (type.contains("89504E47")) {
return "png";
} else if (type.contains("47494638")) {
return "gif";
} else if (type.contains("424D")) {
return "bmp";
}else{
return "unkown";
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
} private static String bytesToHexString(byte[] src){
StringBuilder stringBuilder = new StringBuilder();
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}

  2.多张图片合成TIF,因为合成之后可能文件会很大,所以采用了压缩模式(TIFFEncodeParam.COMPRESSION_JPEG_TTN2),但是压缩模式需要将图片都转为JPG格式

    /**
*
* @param imageFileList 图片路径列表 (图片为E:/xx/xx.jpg格式)
* @param toPath tif文件所放路径
* @param distFileName tif文件名
* @param convertPath 转换图片存放路径
* @param isCompress 是否压缩(压缩的时候是先将不是jpg的格式转为jpg,因为JAI可以设置JPEG的压缩模式。
* 但是png转jpg会有点失真,所以建议用非压缩的方式!!!)
*/
public static String manyImgToTif(List<String> imageFileList,String toPath, String distFileName, String convertPath, boolean isCompress) {
String tifFile = null;
if(imageFileList != null && imageFileList.size()>0){
List<File> fileArr = new ArrayList<File>();
String fileName;
String imageFile;
String fileType = "";
File tmpFile ;
FileInputStream tmpIns = null;
boolean isNeedTransfer = false;
for (int i = 0; i < imageFileList.size(); i++){
imageFile = imageFileList.get(i);
String[] tempFile = imageFile.split("/");
fileName = tempFile[tempFile.length-1];
tmpFile = new File(imageFile); // 处理文件
try {
// 以防是png格式的图片直接改后缀的情况
tmpIns = new FileInputStream(tmpFile);
fileType = getPicType(tmpIns); if(isCompress){
File convertFile = new File(convertPath);
if (!convertFile.exists()) {
convertFile.mkdirs();
} if ("bmp".equals(fileType)
|| "jpg".equals(fileType)){
// 有时图片有损坏,但是能展示,就是用这个架包的时候会报错,
// 比较严格,所以需要捕获异常做一下转换
isNeedTransfer = false;
try{
// 需要重新获取流,因为上面判断格式已经读过流了.
tmpIns = new FileInputStream(tmpFile);
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(tmpIns);
decoder.decodeAsBufferedImage();
} catch (TruncatedFileException e){
e.printStackTrace();
logger.info("图片有损坏,需要做转换,image:"+imageFile);
isNeedTransfer = true;
} if(isNeedTransfer){
fileArr.add(pngtoJpg(imageFile,convertPath,fileName));
} else {
fileArr.add(new File(imageFile));
} } else if("gif".equals(fileType)){
fileArr.add(giftoJpg(imageFile,convertPath,fileName));
}else if("png".equals(fileType)){
fileArr.add(pngtoJpg(imageFile,convertPath,fileName));
}
} else {
if ("bmp".equals(fileType)
|| "jpg".equals(fileType)
|| "gif".equals(fileType)
|| "png".equals(fileType)){
fileArr.add(new File(imageFile));
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(tmpIns != null){
try {
tmpIns.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} } if (fileArr.size() > 0) {
try {
ArrayList pages = new ArrayList(fileArr.size() - 1);
FileSeekableStream[] stream = new FileSeekableStream[fileArr.size()];
for (int i = 0; i < fileArr.size(); i++) {
stream[i] = new FileSeekableStream(fileArr.get(i).getCanonicalPath());
}
ParameterBlock pb = (new ParameterBlock());
PlanarImage firstPage = JAI.create("stream", stream[0]);
for (int i = 1; i < fileArr.size(); i++) {
PlanarImage page = JAI.create("stream", stream[i]);
pages.add(page);
}
TIFFEncodeParam param = new TIFFEncodeParam();
if(isCompress){
param.setCompression(TIFFEncodeParam.COMPRESSION_JPEG_TTN2);
} TIFFField[] extras = new TIFFField[4];
extras[0] = new TIFFField(262, TIFFField.TIFF_SHORT, 1, (Object) new short[] { 6 });
extras[1] = new TIFFField(282, 5, 1, (Object) new long[][]{{(long) 200, 1}, {0, 0}});
extras[2] = new TIFFField(283, 5, 1, (Object) new long[][]{{(long) 200, 1}, {0, 0}});
extras[3] = new TIFFField(258, TIFFField.TIFF_SHORT, 1, (Object) new char[] { 8 });
param.setExtraFields(extras);
param.setExtraImages(pages.iterator()); File f = new File(toPath);
if (!f.exists()) {
f.mkdirs();
} tifFile = toPath + "\\"+ distFileName+".tif";
OutputStream os = new FileOutputStream(tifFile);
ImageEncoder enc = ImageCodec.createImageEncoder("tiff", os, param); enc.encode(firstPage);
//关掉流
os.flush();
os.close();
for (int i = 0; i < fileArr.size(); i++) {
stream[i].close();
} logger.info("====manyImgToTif done====");
} catch (IOException e) {
e.printStackTrace();
}
}
}
return tifFile;
}

  3.遇到的问题:

java.lang.ArrayIndexOutOfBoundsException: 3
at com.sun.media.jai.codec.JPEGEncodeParam.getHorizontalSubsampling(JPEGEncodeParam.java:104)

  这个是因为图片不都是JPG格式,但却采用了TIFFEncodeParam.COMPRESSION_JPEG_TTN2压缩模式导致的出错,转为JPG格式就好了。

 java.lang.RuntimeException: - Unable to render RenderedOp for this operation.
at javax.media.jai.RenderedOp.createInstance(RenderedOp.java:827)
Caused by: com.sun.image.codec.jpeg.ImageFormatException: Not a JPEG file: starts with 0xff 0xd9

  这个是因为图片有损坏,例如JPG格式,文件头是FFD8FF ,但可能结尾不是FFD9,所以导致处理的时候会有问题,所以需要重读取流再转换一下就正常了。

  附录-两个转换方法(png->jpg,bmp->jpg)

     public static File pngtoJpg(String fromImg, String path , String fileName) {
File outFile = new File(path+ File.separator+fileName+"_convert.jpg");
try {
FileOutputStream out = new FileOutputStream(outFile);
File img = new File(fromImg);
BufferedImage image = ImageIO.read(img); BufferedImage newBufferedImage = new BufferedImage(image.getWidth(),
image.getHeight(), BufferedImage.TYPE_INT_RGB);
//TYPE_INT_RGB:创建一个RBG图像,24位深度,成功将32位图转化成24位
newBufferedImage.createGraphics().drawImage(image, 0, 0, Color.WHITE, null);
ImageIO.write(newBufferedImage,"jpg",outFile); out.flush();
out.close(); }catch (IOException e){
e.printStackTrace();
}
return outFile;
} public static File giftoJpg(String fromImg, String path, String fileName) {
File outFile = new File(path+ File.separator+fileName+"_convert.jpg");
try {
File infile = new File(fromImg);
BufferedImage src = null;
src = ImageIO.read(infile);
int wideth = src.getWidth(null);
int height = src.getHeight(null); BufferedImage tag = new BufferedImage(wideth , height , BufferedImage.TYPE_INT_RGB);
tag.getGraphics().drawImage(src, 0, 0, wideth , height , null);
FileOutputStream out = new FileOutputStream(outFile);
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
encoder.encode(tag);
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
} return outFile;
}

JAI 多图片合成TIF格式的更多相关文章

  1. C# 图片的裁剪,两个图片合成一个图片

    图片的裁剪,两个图片合成一个图片(这是从网上摘的) /// <summary>         /// 图片裁剪,生成新图,保存在同一目录下,名字加_new,格式1.png  新图1_ne ...

  2. 【开源java游戏框架libgdx专题】-12-开发工具-图片合成

    TexturePackerGui工具: 1.工具使用: 首先看到texturepacker的界面 界面介绍: New pack:创建项目按钮,单击后输入文件名称,创建文件. Input directo ...

  3. php 图片合成时文字颜色丢失

    最近在做图片合成的时候无意间发现文字颜色丢失了,仔细找了以后才发现原来是因为图片格式的原因 当图片是png图片时文字的颜色就变成了白色的,So.........去你妹的png,用jpg吧! $dest ...

  4. canvas图片合成中的坑

    需求 要用代码来实现多张外部图片和文字的合并而且要上传到七牛云,再将图片链接通过客户端分享出去.图片背景需要支持用户自定义更换. 实现方案 在一个canvas上多次调用drawImage函数,分别绘制 ...

  5. pyhton图片合成模块-PIL

    文章链接:https://www.cnblogs.com/lilinwei340/p/6474170.html python PIL实现图片合成   在项目中需要将两张图片合在一起.遇到两种情况,一种 ...

  6. python PIL实现图片合成

    在项目中需要将两张图片合在一起.遇到两种情况,一种就是两张非透明图片的合成, 一种是涉及到透明png的合成. 相关API见 http://pillow.readthedocs.io/en/latest ...

  7. CATIA 使用技巧--转换出轻巧的tif格式文件

    问题描述: 我们在与客户和供应商打交道的过程中经常需要TIF格式2D图纸文件,而默认的CATIA设置保存出来TIF文件非常大,不利于保存和传送.对于该问题,我们可以通过修改CATIA的默认设置选项,将 ...

  8. jpg/png格式图片转eps格式的方法总结

    jpg/png格式图片转eps格式的方法总结 转自http://blog.sina.com.cn/s/blog_5410e7b50101lme2.html 用latex写论文的筒子应该遇到这样的问题: ...

  9. Android  PNG透明图片转JPG格式背景变黑

    Android  PNG透明图片转JPG格式背景变黑 在上传图片是,需要把PNG格式转换成JPG格式的,但是在遇上透明背景时,转过来就变成黑色底图了! 原因是PNG支持透明图而 JPG格式不支持透明底 ...

  10. html5 图片转为base64格式异步上传

    因为有这个需求(移动端),所以就研究了一下,发现还挺不错的.这个主要是用了html5的API,不需要其他的JS插件,不过只有支持html5的浏览器才行,就现在而言应该大部份都支持的.<!DOCT ...

随机推荐

  1. python + pyqt 实现的你下载css背景图片的小工具(最终版)

    学习python有三个星期了,算是做的第一个小工具,其实也没必要做成图形界面,只是为的GUI学习(再说技术总归给人使用的,熟练很多shell命令只是个"匠人".) win8下面: ...

  2. 卸载K8s集群及k8s命令自动补全

    一.配置命令自动补全 yum install -y bash-completion source /usr/share/bash-completion/bash_completion source & ...

  3. textfsm

    from concurrent.futures import ThreadPoolExecutor import netmiko import os from threading import Loc ...

  4. java ArrayList 原理

    概述 底层通过数组实现,所以 查询/更新效率很高,删除/增加跟位置相关,除未实现同步外和 Vector 大致相同 自动扩容,每次扩容大概 1.5 倍,扩容代价比较高尽量避免 实现了 RandomAcc ...

  5. 基于excel的自动化框架

    设定项目文件大致结构 atp/: 项目名 conf/:存放配置文件 data/:存放sql文件 lib/: 存放项目的所有源代码. logs/:存放日志文件 uploads/:存放下载的文件 star ...

  6. requests库获取指定关键词的图片,并保存到本地

    var code = "45f4267f-9476-44ca-ac68-6d32aad2d4e1" 源码地址:https://gitee.com/myrensheng/data_a ...

  7. SpringMVC的常用操作汇总

    基本操作 #类级别的注解 @Controller @RestController @RequestMapping("/hello") #springMVC常用方法级别注解 @Res ...

  8. hdu 4283You Are the One

    The TV shows such as You Are the One has been very popular. In order to meet the need of boys who ar ...

  9. windows用curl报错

    https://www.shuzhiduo.com/A/kmzLRmgl5G/ IE浏览器 -> 设置 -> Internet选项 -> 安全 -> 本地Internet -& ...

  10. 解决python 操作 hbase报错:TTransportException(type=4,message=’TSocket read 0 bytes’)

    ```text# 解决报错:hbase报错TTransportException(type=4,message='TSocket read 0 bytes')这种情况一般协议问题和服务端没开启,如果服 ...