java 多张jpg合成tif后避免tif文件过大的方法

2023-12-22 05:58

本文主要是介绍java 多张jpg合成tif后避免tif文件过大的方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这几天突然有个需求要求把之前的通过扫描仪扫出来的jpg图片给合成一个tif文件,乍一看这个需求还是没啥问题的,于是乎直接上网找一个方法下来就好啦,百度“多张jpg合成tif”得到如下方法:

	/*** 合并成一个tif* @param bookFilePaths 要合并的图片集合,字符串为图片的全路径* @param toPath 目的文件夹路径* @param distFileName 合成的文件名(带后缀)*/public static void many2one(List<String> bookFilePaths, String toPath, String distFileName) {if (bookFilePaths != null && bookFilePaths.size() > 0) {File[] files = new File[bookFilePaths.size()];for (int i = 0; i < bookFilePaths.size(); i++) {files[i] = new File(bookFilePaths.get(i));}if (files != null && files.length > 0) {try {ArrayList pages = new ArrayList(files.length - 1);FileSeekableStream[] stream = new FileSeekableStream[files.length];for (int i = 0; i < files.length; i++) {stream[i] = new FileSeekableStream(files[i].getPath());}ParameterBlock pb = (new ParameterBlock());PlanarImage firstPage = JAI.create("stream", stream[0]);for (int i = 1; i < files.length; i++) {PlanarImage page = JAI.create("stream", stream[i]);pages.add(page);}TIFFEncodeParam param = new TIFFEncodeParam();File f = new File(toPath);if (!f.exists()) {f.mkdirs();}OutputStream os = new FileOutputStream(toPath + File.separator + distFileName);ImageEncoder enc = ImageCodec.createImageEncoder("tiff", os, param);param.setExtraImages(pages.iterator());enc.encode(firstPage);for (int i = 0; i < files.length; i++) {stream[i].close();if (files[i].isFile() && files[i].exists()) {files[i].delete();}}os.close();} catch (IOException e) {e.printStackTrace();}}}}

参数意义明确,感觉胜利就在眼前,迅速把图片放上去试一下,结果发现30张300K左右的jpg图片合成完之后却有340M!这个是肯定不接受的。上网找了一个软件来合成这30张jpg大小为9M,与30张的大小之和基本一致。

想了以下几个办法解决:

1.直接压缩340M的tif

2.先压缩jpg再合成tif

3.先把30张jpg转为pdf再转tif

4.重新review方法找原因

第一种方法压缩之后离要求的大小还是相差很大;第二种先压缩再合成也是这样,而且还改变了原jpg的dpi,这种方案也是不行;第三种方案,pdf转tif有问题,不是对于中文pdf支持有问题就是转不出多页tif,也pass;最后一种方案,好好研究了一下TIFFEncodeParam,TIFFField这两个类,先贴成功之后的代码

	public static void many2one(List<String> bookFilePaths, String toPath, String distFileName) {if (bookFilePaths != null && bookFilePaths.size() > 0) {File[] files = new File[bookFilePaths.size()];for (int i = 0; i < bookFilePaths.size(); i++) {files[i] = new File(bookFilePaths.get(i));}if (files != null && files.length > 0) {try {ArrayList pages = new ArrayList(files.length - 1);FileSeekableStream[] stream = new FileSeekableStream[files.length];for (int i = 0; i < files.length; i++) {stream[i] = new FileSeekableStream(files[i].getCanonicalPath());}ParameterBlock pb = (new ParameterBlock());PlanarImage firstPage = JAI.create("stream", stream[0]);for (int i = 1; i < files.length; i++) {PlanarImage page = JAI.create("stream", stream[i]);pages.add(page);}TIFFEncodeParam param = new TIFFEncodeParam();param.setCompression(TIFFEncodeParam.COMPRESSION_JPEG_TTN2);
//					param.setCompression(TIFFEncodeParam.COMPRESSION_DEFLATE);
//					param.setDeflateLevel(9);
//					param.setWriteTiled(true);
//					param.setReverseFillOrder(true);TIFFField[] extras = new TIFFField[4];extras[0] = new TIFFField(262, TIFFField.TIFF_SHORT, 1, (Object) new short[] { 6 });extras[1] = new TIFFField(282, TIFFTag.TIFF_RATIONAL, 1, (Object) new long[][]{{(long) 200, 1}, {0, 0}});  extras[2] = new TIFFField(283, TIFFTag.TIFF_RATIONAL, 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();}OutputStream os = new FileOutputStream(toPath + File.separator + distFileName);ImageEncoder enc = ImageCodec.createImageEncoder("tiff", os, param);enc.encode(firstPage);os.close();System.out.println("over");} catch (IOException e) {e.printStackTrace();}}}}

TIFFEncodeParam类

https://docs.oracle.com/cd/E17802_01/products/products/java-media/jai/forDevelopers/jai-apidocs/com/sun/media/jai/codec/TIFFEncodeParam.html#COMPRESSION_DEFLATE

这几种可以理解成是合成tif时候的方式

下面是tiff6.0的格式简介

http://www.codeweblog.com/tiff6-0%E6%A0%BC%E5%BC%8F%E7%AE%80%E4%BB%8B/

这之后的部分很重要,各位可以根据自己的需求选择搭配的属性。这个地方他说的这些属性指的就是tif图片的属性,要在TIFFField这里设置,这也就是我上面提到的第二个类。

https://www.awaresystems.be/imaging/tiff/tifftags/baseline.html

这里面就是可以设置的参数,表中的DEC就是上面代码中的258,262,282,283这些。至于第二、四个参数应该填什么还是要上tiff6.0的格式简介里面去查,查到的类型去这里匹配

把构造方法的几个参数填上之后,赶紧试一下效果。合成的图片就只有9M多了。但是还有个问题就是等待的时间很长,30张图片要2分钟,这个问题还需要以后有时间解决~

还有一篇文章也有用到,放在下边,自取

http://www.libtiff.org/support.html

这篇关于java 多张jpg合成tif后避免tif文件过大的方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/522793

相关文章

Python中提取文件名扩展名的多种方法实现

《Python中提取文件名扩展名的多种方法实现》在Python编程中,经常会遇到需要从文件名中提取扩展名的场景,Python提供了多种方法来实现这一功能,不同方法适用于不同的场景和需求,包括os.pa... 目录技术背景实现步骤方法一:使用os.path.splitext方法二:使用pathlib模块方法三

javax.net.ssl.SSLHandshakeException:异常原因及解决方案

《javax.net.ssl.SSLHandshakeException:异常原因及解决方案》javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SS... 目录报错原因在程序中绕过服务器的安全验证注意点最后多说一句报错原因一般出现这种问题是因为目标服务器

Python打印对象所有属性和值的方法小结

《Python打印对象所有属性和值的方法小结》在Python开发过程中,调试代码时经常需要查看对象的当前状态,也就是对象的所有属性和对应的值,然而,Python并没有像PHP的print_r那样直接提... 目录python中打印对象所有属性和值的方法实现步骤1. 使用vars()和pprint()2. 使

CSS实现元素撑满剩余空间的五种方法

《CSS实现元素撑满剩余空间的五种方法》在日常开发中,我们经常需要让某个元素占据容器的剩余空间,本文将介绍5种不同的方法来实现这个需求,并分析各种方法的优缺点,感兴趣的朋友一起看看吧... css实现元素撑满剩余空间的5种方法 在日常开发中,我们经常需要让某个元素占据容器的剩余空间。这是一个常见的布局需求

Java实现删除文件中的指定内容

《Java实现删除文件中的指定内容》在日常开发中,经常需要对文本文件进行批量处理,其中,删除文件中指定内容是最常见的需求之一,下面我们就来看看如何使用java实现删除文件中的指定内容吧... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细介绍3.1 Ja

springboot项目中整合高德地图的实践

《springboot项目中整合高德地图的实践》:本文主要介绍springboot项目中整合高德地图的实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一:高德开放平台的使用二:创建数据库(我是用的是mysql)三:Springboot所需的依赖(根据你的需求再

spring中的ImportSelector接口示例详解

《spring中的ImportSelector接口示例详解》Spring的ImportSelector接口用于动态选择配置类,实现条件化和模块化配置,关键方法selectImports根据注解信息返回... 目录一、核心作用二、关键方法三、扩展功能四、使用示例五、工作原理六、应用场景七、自定义实现Impor

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

SpringBoot整合Flowable实现工作流的详细流程

《SpringBoot整合Flowable实现工作流的详细流程》Flowable是一个使用Java编写的轻量级业务流程引擎,Flowable流程引擎可用于部署BPMN2.0流程定义,创建这些流程定义的... 目录1、流程引擎介绍2、创建项目3、画流程图4、开发接口4.1 Java 类梳理4.2 查看流程图4

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热