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

相关文章

Springboot配置文件相关语法及读取方式详解

《Springboot配置文件相关语法及读取方式详解》本文主要介绍了SpringBoot中的两种配置文件形式,即.properties文件和.yml/.yaml文件,详细讲解了这两种文件的语法和读取方... 目录配置文件的形式语法1、key-value形式2、数组形式读取方式1、通过@value注解2、通过

Java 接口定义变量的示例代码

《Java接口定义变量的示例代码》文章介绍了Java接口中的变量和方法,接口中的变量必须是publicstaticfinal的,用于定义常量,而方法默认是publicabstract的,必须由实现类... 在 Java 中,接口是一种抽象类型,用于定义类必须实现的方法。接口可以包含常量和方法,但不能包含实例

JAVA Calendar设置上个月时,日期不存在或错误提示问题及解决

《JAVACalendar设置上个月时,日期不存在或错误提示问题及解决》在使用Java的Calendar类设置上个月的日期时,如果遇到不存在的日期(如4月31日),默认会自动调整到下个月的相应日期(... 目录Java Calendar设置上个月时,日期不存在或错误提示java进行日期计算时如果出现不存在的

Springboot的配置文件及其优先级说明

《Springboot的配置文件及其优先级说明》文章介绍了SpringBoot的配置文件,包括application.properties和application.yml的使用,以及它们的优先级,还讨... 目录配置文件内置配置文件yml与properties的比较优先级比较外置配置文件springboot

自定义注解SpringBoot防重复提交AOP方法详解

《自定义注解SpringBoot防重复提交AOP方法详解》该文章描述了一个防止重复提交的流程,通过HttpServletRequest对象获取请求信息,生成唯一标识,使用Redis分布式锁判断请求是否... 目录防重复提交流程引入依赖properties配置自定义注解切面Redis工具类controller

Java利用Spire.XLS for Java自动化设置Excel的文档属性

《Java利用Spire.XLSforJava自动化设置Excel的文档属性》一个专业的Excel文件,其文档属性往往能大大提升文件的可管理性和可检索性,下面我们就来看看Java如何使用Spire... 目录Spire.XLS for Java 库介绍与安装Java 设置内置的 Excel 文档属性Java

Java中的CompletableFuture核心用法和常见场景

《Java中的CompletableFuture核心用法和常见场景》CompletableFuture是Java8引入的强大的异步编程工具,支持链式异步编程、组合、异常处理和回调,介绍其核心用法,通过... 目录1、引言2. 基本概念3. 创建 CompletableFuture3.1. 手动创建3.2.

java中4种API参数传递方式统一说明

《java中4种API参数传递方式统一说明》在Java中,我们可以使用不同的方式来传递参数给方法或函数,:本文主要介绍java中4种API参数传递方式的相关资料,文中通过代码介绍的非常详细,需要的... 目录1. 概述2. 参数传递方式分类2.1 Query Parameters(查询参数)2.2 Path

SpringBoot整合 Quartz实现定时推送实战指南

《SpringBoot整合Quartz实现定时推送实战指南》文章介绍了SpringBoot中使用Quartz动态定时任务和任务持久化实现多条不确定结束时间并提前N分钟推送的方案,本文结合实例代码给大... 目录前言一、Quartz 是什么?1、核心定位:解决什么问题?2、Quartz 核心组件二、使用步骤1

Java线程池核心参数原理及使用指南

《Java线程池核心参数原理及使用指南》本文详细介绍了Java线程池的基本概念、核心类、核心参数、工作原理、常见类型以及最佳实践,通过理解每个参数的含义和工作原理,可以更好地配置线程池,提高系统性能,... 目录一、线程池概述1.1 什么是线程池1.2 线程池的优势二、线程池核心类三、ThreadPoolE