java实现,PDF转换为TIF

目录

■JDK版本

■java代码・实现效果

■POM引用

■之前TIF相关的问题(两张TIF合并)

■对于成果物TIF,需要考虑的点

■问题

■问题1:无法生成TIF,已解决

■问题2:生成的TIF过大,已解决

[解决方法1:使用LZW方式压缩 (质量高)](#解决方法1:使用LZW方式压缩 (质量高))

[解决方法2:让图片位深度为黑白(binary),并且使用CCITT方式压缩 (质量低)](#解决方法2:让图片位深度为黑白(binary),并且使用CCITT方式压缩 (质量低))

■相关工具

SVF

foxit

■相关知识

[ImageIO.write 的结果是 false 的原因](#ImageIO.write 的结果是 false 的原因)

[转换时报错 type 4 gsub lookup table is not supported](#转换时报错 type 4 gsub lookup table is not supported)

DPI是什么

[一英寸 是多少厘米](#一英寸 是多少厘米)

[图片的 位深度](#图片的 位深度)

■功能扩展

转换为TIF时,能否在TIF中的某个坐标点,再追加什么信息

4页的PDF,取出一部分,生成3页的PDF

印章(在右上角)

印章(改进版)(坐标自己定义)

PDF生成jpg图片

[代码比较(印章 和 JPG),代码原理](#代码比较(印章 和 JPG),代码原理)

[介绍一下 java中的Graphics2D 类](#介绍一下 java中的Graphics2D 类)

印章代码参照


=================

■JDK版本

1.8

■java代码・实现效果

java 复制代码
package com.sxz.study.pdf;

import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;

public class TestPDFToTIF {

    public static void main(String[] args) {
        try {
            // Load the PDF document
            PDDocument document = PDDocument.load(new File("E:\\Users\\sxz\\Desktop\\PDF\\Test.pdf"));
            
            // Create a PDF renderer
            PDFRenderer pdfRenderer = new PDFRenderer(document);
            
            // Iterate over each page in the PDF document
            for (int pageNumber = 0; pageNumber < document.getNumberOfPages(); pageNumber++) {
                // Render the PDF page to a BufferedImage
                // BufferedImage image = pdfRenderer.renderImageWithDPI(pageNumber, 300, ImageType.RGB);
            	BufferedImage image = pdfRenderer.renderImageWithDPI(pageNumber, 200, ImageType.GRAY);
                
                // Save the BufferedImage as a TIF file
                boolean flg = ImageIO.write(image, "tif", new File("E:\\Users\\sxz\\Desktop\\PDF\\output_" + (pageNumber + 1) + ".tif"));
                System.out.println(flg);
            }
            
            // Close the PDF document
            document.close();
            
            System.out.println("PDF converted to TIF successfully");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

===

====

=====

■POM引用

XML 复制代码
		<dependency>
		    <groupId>org.apache.pdfbox</groupId>
		    <artifactId>pdfbox</artifactId>
		    <version>2.0.24</version> <!-- 可以根据需要选择最新版本 -->
		</dependency>
		<dependency>
		    <groupId>org.apache.pdfbox</groupId>
		    <artifactId>pdfbox-tools</artifactId>
		    <version>2.0.24</version> <!-- 可以根据需要选择最新版本 -->
		</dependency>
		<dependency>
		    <groupId>org.apache.pdfbox</groupId>
		    <artifactId>fontbox</artifactId>
		    <version>2.0.24</version> <!-- 可以根据需要选择最新版本 -->
		</dependency>
		
		<dependency>
		    <groupId>com.github.jai-imageio</groupId>
		    <artifactId>jai-imageio-core</artifactId>
		    <version>1.4.0</version>
		</dependency>

====

====

■之前TIF相关的问题(两张TIF合并)

TIF合并Java代码_jai-codec-CSDN博客

====

■对于成果物TIF,需要考虑的点

不是单纯生成TIF就可以了,还要考虑以下问题

①白黒閾値

②解像度 (分辨率) (DPI) ⇒ 一般设置为200

③圧縮方式 -----CCITT T.4

④位深度 1,8,24,32 // 代码  ⇒  ImageType.BINARY

⑤XXXX高 XXXX幅  ⇒ 影响坐标位置

⑥ファイルのサイズ  XXXXKB

⑦分辨率单位 // TODO 代码如何指定

⑧是否还要在生成的TIF上写入什么(番号),或者重新写入什么(比如页码 1/4 ⇒1/5)// 已经实现

⑨4页的PDF,出力1,2,4页**// 已经实现**

⑩処理スピード(处理速度)

⑪事前確認 上流SystemのInput (PDF)

下流Systemへ連携のTIF (受到上面①~⑦影響、下流系统能否正常读取)

====

====

■问题

■问题1:无法生成TIF,已解决

问题:结果全部为false。

解决:

方法1:pom中添加如下引用

XML 复制代码
		<dependency>
		    <groupId>com.github.jai-imageio</groupId>
		    <artifactId>jai-imageio-core</artifactId>
		    <version>1.4.0</version>
		</dependency>

方法2:使用jdk9

====

■问题2:生成的TIF过大,已解决

====

我原本文件才0.3M,生成的TIF有3M的大小。。。。

====方法2解决后的效果

===

解决方法1:使用LZW方式压缩 (质量高)

java 复制代码
package com.sxz.study.pdf;

import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;

public class TestPDFToTIFCompress {

	public static void main(String[] args) {
		try {
			// Load the PDF document
			PDDocument document = PDDocument.load(new File("C:\\test\\PDF\\Test.pdf"));

			// Create a PDF renderer
			PDFRenderer pdfRenderer = new PDFRenderer(document);

			// Iterate over each page in the PDF document
			for (int pageNumber = 0; pageNumber < document.getNumberOfPages(); pageNumber++) {
				// Render the PDF page to a BufferedImage
				// BufferedImage image = pdfRenderer.renderImageWithDPI(pageNumber, 300,
				// ImageType.RGB);
				BufferedImage image = pdfRenderer.renderImageWithDPI(pageNumber, 200, ImageType.GRAY);

		        ImageWriter writer = ImageIO.getImageWritersByFormatName("tiff").next();
		        ImageWriteParam writeParam = writer.getDefaultWriteParam();
		        writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
		        writeParam.setCompressionType("LZW");
				
		        // 创建输出文件流
		        FileImageOutputStream output = new FileImageOutputStream(new File("C:\\test\\PDF\\output_" + (pageNumber + 1) + ".tif"));
		        writer.setOutput(output);

		        // 写入压缩后的TIF图像
		        writer.write(null, new IIOImage(image, null, null), writeParam);

		        // 关闭输出流
		        output.close();
		        
			}

			// Close the PDF document
			document.close();

			System.out.println("PDF converted to TIF successfully");
		} catch (Exception e) {
			e.printStackTrace();

		}
	}
}

===

ImageType.GRAY

位深度是 8

====

解决方法2:让图片位深度为黑白(binary),并且使用CCITT方式压缩 (质量低)

===

ImageType.GRAY 时,代码运行会报错

Caused by: javax.imageio.IIOException: Bits per sample must be 1 for T4 compression!

==

java 复制代码
package com.sxz.study.pdf;

import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;

public class TestPDFToTIFCompress {

	public static void main(String[] args) {
		try {
			// Load the PDF document
			PDDocument document = PDDocument.load(new File("C:\\test\\PDF\\Test.pdf"));

			// Create a PDF renderer
			PDFRenderer pdfRenderer = new PDFRenderer(document);

			// Iterate over each page in the PDF document
			for (int pageNumber = 0; pageNumber < document.getNumberOfPages(); pageNumber++) {
				// Render the PDF page to a BufferedImage
				// BufferedImage image = pdfRenderer.renderImageWithDPI(pageNumber, 300,
				// ImageType.RGB);
				BufferedImage image = pdfRenderer.renderImageWithDPI(pageNumber, 200, ImageType.GRAY);

		        ImageWriter writer = ImageIO.getImageWritersByFormatName("tiff").next();
		        ImageWriteParam writeParam = writer.getDefaultWriteParam();
		        writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
		        writeParam.setCompressionType("LZW");
				
		        // 创建输出文件流
		        FileImageOutputStream output = new FileImageOutputStream(new File("C:\\test\\PDF\\output_" + (pageNumber + 1) + ".tif"));
		        writer.setOutput(output);

		        // 写入压缩后的TIF图像
		        writer.write(null, new IIOImage(image, null, null), writeParam);

		        // 关闭输出流
		        output.close();
		        
			}

			// Close the PDF document
			document.close();

			System.out.println("PDF converted to TIF successfully");
		} catch (Exception e) {
			e.printStackTrace();

		}
	}
}

===

===

■相关工具

SVF

====4141

1.1. SVF Connect for Java APIの機能概要 (wingarc.com)

==== ウイングアーク1stコーポレートサイト

会社概要 | ウイングアーク1stコーポレートサイト (wingarc.com)

===

foxit

xxx

===

■相关知识

ImageIO.write 的结果是 false 的原因

如果ImageIO.write方法返回false,可能有几种原因导致无法成功将BufferedImage写入TIF文件。以下是一些常见原因和可能解决方法:

  1. 缺少合适的ImageWriter:ImageIO在写入图像时需要能够识别和处理指定格式(这里是TIF)的ImageWriter。可能需要确保已经安装了支持TIF格式的插件。通常,这些插件会提供相应的ImageWriter类。

    解决方法:可以尝试安装支持TIF格式的插件,例如JAI Image I/O Tools。您可以在Maven中添加以下依赖项:

XML 复制代码
		<dependency>
		    <groupId>com.github.jai-imageio</groupId>
		    <artifactId>jai-imageio-core</artifactId>
		    <version>1.4.0</version>
		</dependency>

转换时报错 type 4 gsub lookup table is not supported

报错"Type 4 gsub lookup table is not supported"通常是由于字体文件中的某种字符映射表(lookup table)不受支持而导致的。字形字体(OpenType字体)中的子集(subset)可能包含一些复杂的字符映射表,而某些库可能无法正确解析或处理这些表。您可以尝试以下解决方法:

  1. 使用全字形字体(Full OpenType Font):如果可能,尝试使用未经子集化的完整字形字体,而不是子集化的字体。全字形字体包含完整的字符集和字符映射表,可能更容易被解析和处理。

  2. 更新软件版本:检查您使用的库或工具是否存在更新版本,有时新版本可能会修复一些已知的问题。

  3. 选择其他字体或库:尝试使用其他字体或处理字体的库来查看能否解决该问题。不同的库可能有不同的实现方式,可能支持更多的字符映射表类型。

  4. 解析错误:检查报错代码所在的地方,看看是否可以在代码中进行特定的处理,例如跳过不支持的部分或者采取其他替代方案。

DPI是什么

DPI代表"每英寸点数"(Dots Per Inch),是衡量输出设备打印或显示分辨率的度量单位。它表示在每英寸内打印机或显示器能够输出多少个像素点。在打印领域中,DPI表示每英寸的打印点密度,越高的DPI通常意味着更高的打印质量和更细致的图像。在显示器领域中,DPI用来描述屏幕的像素密度,影响屏幕展示的清晰度和细节。

例如,如果一台打印机的DPI为600,则表示在打印一英寸长度的纸张上,这台打印机可以输出600个点(像素),从而打印出高分辨率的图像或文档。

在设计和图像处理中,DPI也很重要,因为它决定了图像在输出时的清晰度和质量。对于印刷品、海报、名片等需要高质量印刷的材料,通常需要使用高DPI的图像以确保印刷效果。

总之,DPI是衡量输出设备分辨率的重要指标,对于打印、显示和图像处理等领域都有着重要作用。

一英寸 是多少厘米

一英寸等于2.54厘米。这是国际上普遍接受的英制和公制长度单位之间的换算关系。根据这个换算关系,1英寸等于2.54厘米。

图片的 位深度

图片的位深度是指图像中每个像素的颜色值所占用的位数。位深度越高,可以表示的颜色范围就越大,图像也会更加细致。常见的位深度有:

1位深度:每个像素只有两种颜色,通常用于黑白图像或简单的图标。 ImageType.BINARY

8位深度:每个像素有256种颜色,通常用于网页图像或简单的照片。 ImageType.GRAY

24位深度:每个像素有约1677万种颜色,通常用于高质量的照片。

32位深度:除了颜色信息外,还包含Alpha通道信息,用于透明度处理。

不同的位深度会影响图像的颜色表现和细节展现,选择合适的位深度能够更好地展现图片的效果。

==

■功能扩展

转换为TIF时,能否在TIF中的某个坐标点,再追加什么信息

==

要在TIF图像的某个坐标点追加额外信息,你可以使用Java开发中的图像处理库,如ImageMagick或Java自带的图像处理库,来在生成的TIF图像上绘制文本或其他图形。

下面是一个示例代码,演示如何使用Java的Graphics2D来在TIF图像的指定坐标绘制文本信息:

例子代码

java 复制代码
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.tools.imageio.ImageIOUtil;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;

public class PdfToTifConverter {

    public static void main(String[] args) {
        try {
            File pdfFile = new File("input.pdf");
            PDDocument document = PDDocument.load(pdfFile);
            PDFRenderer pdfRenderer = new PDFRenderer(document);

            for (int page = 0; page < document.getNumberOfPages(); ++page) {
                BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB);

                // 在图像上绘制文本信息
                Graphics2D g = bim.createGraphics();
                g.setColor(Color.RED);
                g.setFont(new Font("Arial", Font.PLAIN, 20));
                g.drawString("Additional Info", 100, 100);
                g.dispose();

                ImageIOUtil.writeImage(bim, "output_" + page + ".tif", 300);
            }

            document.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

===

完整代码

java 复制代码
package com.sxz.study.pdf;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;

public class TestPdfToTifComPressCCITTWithInfo {

	public static void main(String[] args) {
		try {
			// Load the PDF document
			PDDocument document = PDDocument.load(new File("C:\\test\\PDF\\0830.pdf"));

			// Create a PDF renderer
			PDFRenderer pdfRenderer = new PDFRenderer(document);

			// Iterate over each page in the PDF document
			for (int pageNumber = 0; pageNumber < document.getNumberOfPages(); pageNumber++) {
				// Render the PDF page to a BufferedImage
				// BufferedImage image = pdfRenderer.renderImageWithDPI(pageNumber, 300,
				// ImageType.RGB);
				BufferedImage image = pdfRenderer.renderImageWithDPI(pageNumber, 200, ImageType.BINARY);

				
		        // 在图像上绘制文本信息
                // 抹去之前的信息
                Graphics2D g2 = image.createGraphics();
                g2.setColor(Color.white);
                g2.setFont(new Font("Arial", Font.PLAIN, 80));
                g2.drawString("■■■■■■■■■■■■■■■■■■■■■■■■", 400, 400);
                g2.dispose();

                Graphics2D g3 = image.createGraphics();
                g3.setColor(Color.white);
                g3.setFont(new Font("Arial", Font.PLAIN, 80));
                g3.drawString("■■■■■■■■■■■■■■■■■■■■■■■■", 405, 400);
                g3.dispose();
                
                Graphics2D g4 = image.createGraphics();
                g4.setColor(Color.white);
                g4.setFont(new Font("Arial", Font.PLAIN, 80));
                g4.drawString("■■■■■■■■■■■■■■■■■■■■■■■■", 410, 400);
                g4.dispose();
                
                Graphics2D g5 = image.createGraphics();
                g5.setColor(Color.white);
                g5.setFont(new Font("Arial", Font.PLAIN, 80));
                g5.drawString("■■■■■■■■■■■■■■■■■■■■■■■■", 415, 400);
                g5.dispose();
                
                // 写上想要的信息
                Graphics2D g = image.createGraphics();
                g.setColor(Color.BLACK);
                g.setFont(new Font("Arial", Font.PLAIN, 20));
                g.drawString("66666666666666666666666666666666666666666", 410, 400);
                g.dispose();
                

		        ImageWriter writer = ImageIO.getImageWritersByFormatName("tiff").next();
		        ImageWriteParam writeParam = writer.getDefaultWriteParam();
		        writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
		        writeParam.setCompressionType("CCITT T.4");
		        //writeParam.setCompressionQuality(1.0f);
				
		        // 创建输出文件流
		        FileImageOutputStream output = new FileImageOutputStream(new File("C:\\test\\PDF\\output_" + (pageNumber + 1) + ".tif"));
		        writer.setOutput(output);

		        // 写入压缩后的TIF图像
		        writer.write(null, new IIOImage(image, null, null), writeParam);

		        // 关闭输出流
		        output.close();
		        
			}

			// Close the PDF document
			document.close();

			System.out.println("PDF converted to TIF successfully");
		} catch (Exception e) {
			e.printStackTrace();

		}
	}
}

===

===

4页的PDF,取出一部分,生成3页的PDF

==

java 复制代码
package com.sxz.study.pdf;

import java.io.File;
import java.io.IOException;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;

public class TestPdfAllToPDF {

	// java代码实现,iput1:1到页的PDF,output :1,2,4页的PDF
    public static void main(String[] args) {
        try {
            File inputFile = new File("C:\\test\\PDF\\input.pdf");
            PDDocument document = PDDocument.load(inputFile);

            PDDocument outputDocument = new PDDocument();
            int[] selectedPages = {0, 1, 3}; // 选择要提取的页面,索引从0开始

            for (int pageNumber : selectedPages) {
                if (pageNumber < document.getNumberOfPages()) {
                    PDPage page = document.getPage(pageNumber);
                    outputDocument.addPage(page);
                } else {
                    System.out.println("Invalid page number: " + (pageNumber + 1));
                }
            }

            outputDocument.save("C:\\test\\PDF\\output.pdf");
            outputDocument.close();

            document.close();
            System.out.println("Selected pages extracted successfully.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

xxx

===

印章(在右上角)

部分代码(参考)

java 复制代码
public static void main(String[] args) throws IOException {
    int imageSize = 150;
    BufferedImage bufferedImage = new BufferedImage(imageSize, imageSize, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2d = bufferedImage.createGraphics();
    // 防止出现锯齿
    g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
    g2d.setComposite(AlphaComposite.Src);
    g2d.setColor(Color.red);
    g2d.setStroke(new BasicStroke(3));
    // 绘画起点xy坐标并非圆心坐标
    g2d.drawOval(2, 2, imageSize - 4, imageSize - 4);

    // 绘画五角星
    int r = 20;
    int centerPoint = imageSize / 2;
    Map<String, List<Integer>> pointersMap = new HashMap<>();
    // 五角星6点坐标 O为圆心点
    pointersMap.put("O", Arrays.asList(centerPoint, centerPoint));
    pointersMap.put("A", Arrays.asList(centerPoint, centerPoint - r));
    pointersMap.put("B", Arrays.asList((int)(centerPoint + Math.sin(0.4 * Math.PI) * r), (int)(centerPoint - Math.cos(0.4 * Math.PI) * r)));
    pointersMap.put("C", Arrays.asList((int)(centerPoint + Math.sin(0.2 * Math.PI) * r), (int)(centerPoint + Math.cos(0.2 * Math.PI) * r)));
    pointersMap.put("D", Arrays.asList((int)(centerPoint - Math.sin(0.2 * Math.PI) * r), (int)(centerPoint + Math.cos(0.2 * Math.PI) * r)));
    pointersMap.put("E", Arrays.asList((int)(centerPoint - Math.sin(0.4 * Math.PI) * r), (int)(centerPoint - Math.cos(0.4 * Math.PI) * r)));
    // 6点组合绘画图像
    List<String> pointerComposes = Arrays.asList("A,D,O,C", "B,E,O,D", "C,A,O,E", "D,A,O,B", "E,C,O,B");
    // 查找绘画点进行绘画
    for (String pointerCompose : pointerComposes) {
      String[] pointerKeys = pointerCompose.split(",");
      Polygon polygon = new Polygon();
      for (String pointerKey : pointerKeys) {
        polygon.addPoint(pointersMap.get(pointerKey).get(0), pointersMap.get(pointerKey).get(1));
      }
      g2d.fillPolygon(polygon);
    }

    int whiteSpace = 75;
    double padding = 1.5;
    String companyName = "XXXXXXXXXXXXXXXXXX";
    // 根据名称长度 动态设置字体大小 防止文字过多发生文字碰撞
    int fontSize = (60 - companyName.length()) / 3;
    // 平移画布使环形文字在圆圈内
    g2d.translate(centerPoint - fontSize / 2, 0);
    // 文字开始位置 大概在左下角
    g2d.rotate(((double) whiteSpace / 360) * Math.PI + Math.PI, fontSize / 2, centerPoint);
    Font font = new Font("FangSong_GB2312", Font.ROMAN_BASELINE, fontSize);
    g2d.setFont(font);
    // 在文字开始位置 第二个字符开始进行按计算角度进行旋转 从而生成环形文字
    double rotateAngle = (double) (360 - whiteSpace) * Math.PI / (180 * (companyName.length() - 1));
    for (int i = 0; i < companyName.toCharArray().length; i++) {
      if (i != 0) {
        g2d.rotate(rotateAngle, fontSize/2, centerPoint);
      }
      g2d.drawString(String.valueOf(companyName.toCharArray()[i]), 0, (int) (fontSize * padding));
    }

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write(bufferedImage, "png", baos);

    String path = String.format("D:/data/seal_image/seal.%s.png",
        DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS").format(
            LocalDateTime.now()));
    File file = new File(path);
    FileOutputStream fileOutputStream = new FileOutputStream(file);
    fileOutputStream.write(baos.toByteArray());
    baos.close();
    fileOutputStream.close();
  }

全部代码

java 复制代码
package com.sxz.study.pdf;

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;

public class TestPDFToTIFCompressLZWWithStamp {

    public static void main(String[] args) {
        try {
            // Load the PDF document
            PDDocument document = PDDocument.load(new File("C:\\test\\PDF\\Test.pdf"));
            
            // Create a PDF renderer
            PDFRenderer pdfRenderer = new PDFRenderer(document);
            
            // Iterate over each page in the PDF document
            for (int pageNumber = 0; pageNumber < document.getNumberOfPages(); pageNumber++) {
				// Render the PDF page to a BufferedImage
				// BufferedImage image = pdfRenderer.renderImageWithDPI(pageNumber, 300,
				// ImageType.RGB);
				BufferedImage image = pdfRenderer.renderImageWithDPI(pageNumber, 200, ImageType.GRAY);

				
				
		        // 在图像上绘制  印章
                Graphics2D g2d = image.createGraphics();
 
                int imageSize = 150;
                // 防止出现锯齿
                g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
                g2d.setComposite(AlphaComposite.Src);
                g2d.setColor(Color.red);
                g2d.setStroke(new BasicStroke(3));
                // 绘画起点xy坐标并非圆心坐标
                g2d.drawOval(2, 2, imageSize - 4, imageSize - 4);
             
                // 绘画五角星
                int r = 20;
                int centerPoint = imageSize / 2;
                Map<String, List<Integer>> pointersMap = new HashMap<>();
                // 五角星6点坐标 O为圆心点
                pointersMap.put("O", Arrays.asList(centerPoint, centerPoint));
                pointersMap.put("A", Arrays.asList(centerPoint, centerPoint - r));
                pointersMap.put("B", Arrays.asList((int)(centerPoint + Math.sin(0.4 * Math.PI) * r), (int)(centerPoint - Math.cos(0.4 * Math.PI) * r)));
                pointersMap.put("C", Arrays.asList((int)(centerPoint + Math.sin(0.2 * Math.PI) * r), (int)(centerPoint + Math.cos(0.2 * Math.PI) * r)));
                pointersMap.put("D", Arrays.asList((int)(centerPoint - Math.sin(0.2 * Math.PI) * r), (int)(centerPoint + Math.cos(0.2 * Math.PI) * r)));
                pointersMap.put("E", Arrays.asList((int)(centerPoint - Math.sin(0.4 * Math.PI) * r), (int)(centerPoint - Math.cos(0.4 * Math.PI) * r)));
                // 6点组合绘画图像
                List<String> pointerComposes = Arrays.asList("A,D,O,C", "B,E,O,D", "C,A,O,E", "D,A,O,B", "E,C,O,B");
                // 查找绘画点进行绘画
                for (String pointerCompose : pointerComposes) {
                  String[] pointerKeys = pointerCompose.split(",");
                  Polygon polygon = new Polygon();
                  for (String pointerKey : pointerKeys) {
                    polygon.addPoint(pointersMap.get(pointerKey).get(0), pointersMap.get(pointerKey).get(1));
                  }
                  g2d.fillPolygon(polygon);
                }
             
                int whiteSpace = 75;
                double padding = 1.5;
                String companyName = "中国足球七比零";
                // 根据名称长度 动态设置字体大小 防止文字过多发生文字碰撞
                int fontSize = (60 - companyName.length()) / 3;
                // 平移画布使环形文字在圆圈内
                g2d.translate(centerPoint - fontSize / 2, 0);
                // 文字开始位置 大概在左下角
                g2d.rotate(((double) whiteSpace / 360) * Math.PI + Math.PI, fontSize / 2, centerPoint);
                Font font = new Font("FangSong_GB2312", Font.ROMAN_BASELINE, fontSize);
                g2d.setFont(font);
                // 在文字开始位置 第二个字符开始进行按计算角度进行旋转 从而生成环形文字
                double rotateAngle = (double) (360 - whiteSpace) * Math.PI / (180 * (companyName.length() - 1));
                for (int i = 0; i < companyName.toCharArray().length; i++) {
                  if (i != 0) {
                    g2d.rotate(rotateAngle, fontSize/2, centerPoint);
                  }
                  g2d.drawString(String.valueOf(companyName.toCharArray()[i]), 0, (int) (fontSize * padding));
                }
             
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                
				g2d.setColor(Color.BLACK);
				g2d.dispose();
             
//                String path = String.format("D:/data/seal_image/seal.%s.png",
//                    DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS").format(
//                        LocalDateTime.now()));
//                File file = new File(path);
//                FileOutputStream fileOutputStream = new FileOutputStream(file);
//                fileOutputStream.write(baos.toByteArray());
//                baos.close();
//                fileOutputStream.close();
			
                // ----end
				
				
		        ImageWriter writer = ImageIO.getImageWritersByFormatName("tiff").next();
		        ImageWriteParam writeParam = writer.getDefaultWriteParam();
		        writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
		        writeParam.setCompressionType("LZW");
		        //writeParam.setCompressionQuality(1.0f);
				
		        // 创建输出文件流
		        FileImageOutputStream output = new FileImageOutputStream(new File("C:\\test\\PDF\\output_" + (pageNumber + 1) + ".tif"));
		        writer.setOutput(output);

		        // 写入压缩后的TIF图像
		        writer.write(null, new IIOImage(image, null, null), writeParam);

		        // 关闭输出流
		        output.close();
		        
			}

			// Close the PDF document
			document.close();

			System.out.println("PDF converted to TIF successfully");
		} catch (Exception e) {
			e.printStackTrace();

		}
	}
}

===

===

印章(改进版)(坐标自己定义)

初版 (修改前 Base)

java 复制代码
package com.sxz.study.pdf;

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;

public class TestPDFToTIFCompressLZWWithStampXY {

    public static void main(String[] args) {
        try {
            // Load the PDF document
            PDDocument document = PDDocument.load(new File("C:\\test\\PDF\\Test.pdf"));
            
            // Create a PDF renderer
            PDFRenderer pdfRenderer = new PDFRenderer(document);
            
            // Iterate over each page in the PDF document
            for (int pageNumber = 0; pageNumber < document.getNumberOfPages(); pageNumber++) {
				// Render the PDF page to a BufferedImage
				// BufferedImage image = pdfRenderer.renderImageWithDPI(pageNumber, 300,
				// ImageType.RGB);
				BufferedImage image = pdfRenderer.renderImageWithDPI(pageNumber, 200, ImageType.GRAY);

				
				// 打印图章
				printStamp(image, 0, 0);


		        ImageWriter writer = ImageIO.getImageWritersByFormatName("tiff").next();
		        ImageWriteParam writeParam = writer.getDefaultWriteParam();
		        writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
		        writeParam.setCompressionType("LZW");
		        //writeParam.setCompressionQuality(1.0f);
				
		        // 创建输出文件流
		        FileImageOutputStream output = new FileImageOutputStream(new File("C:\\test\\PDF\\output_" + (pageNumber + 1) + ".tif"));
		        writer.setOutput(output);

		        // 写入压缩后的TIF图像
		        writer.write(null, new IIOImage(image, null, null), writeParam);

		        // 关闭输出流
		        output.close();
		        
			}

			// Close the PDF document
			document.close();

			System.out.println("PDF converted to TIF successfully");
		} catch (Exception e) {
			e.printStackTrace();

		}
	}
    
    
    public static void printStamp(BufferedImage image, int xxx ,int yyy){
    	
        // 在图像上绘制  印章
        Graphics2D g2d = image.createGraphics();

        int imageSize = 150;
        // 防止出现锯齿
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
        g2d.setComposite(AlphaComposite.Src);
        g2d.setColor(Color.red);
        g2d.setStroke(new BasicStroke(3));
        // 绘画起点xy坐标并非圆心坐标
        g2d.drawOval(2, 2, imageSize - 4, imageSize - 4);
     
        // 绘画五角星
        int r = 20;
        int centerPoint = imageSize / 2;
        Map<String, List<Integer>> pointersMap = new HashMap<>();
        // 五角星6点坐标 O为圆心点
        pointersMap.put("O", Arrays.asList(centerPoint, centerPoint));
        pointersMap.put("A", Arrays.asList(centerPoint, centerPoint - r));
        pointersMap.put("B", Arrays.asList((int)(centerPoint + Math.sin(0.4 * Math.PI) * r), (int)(centerPoint - Math.cos(0.4 * Math.PI) * r)));
        pointersMap.put("C", Arrays.asList((int)(centerPoint + Math.sin(0.2 * Math.PI) * r), (int)(centerPoint + Math.cos(0.2 * Math.PI) * r)));
        pointersMap.put("D", Arrays.asList((int)(centerPoint - Math.sin(0.2 * Math.PI) * r), (int)(centerPoint + Math.cos(0.2 * Math.PI) * r)));
        pointersMap.put("E", Arrays.asList((int)(centerPoint - Math.sin(0.4 * Math.PI) * r), (int)(centerPoint - Math.cos(0.4 * Math.PI) * r)));
        // 6点组合绘画图像
        List<String> pointerComposes = Arrays.asList("A,D,O,C", "B,E,O,D", "C,A,O,E", "D,A,O,B", "E,C,O,B");
        // 查找绘画点进行绘画
        for (String pointerCompose : pointerComposes) {
          String[] pointerKeys = pointerCompose.split(",");
          Polygon polygon = new Polygon();
          for (String pointerKey : pointerKeys) {
            polygon.addPoint(pointersMap.get(pointerKey).get(0), pointersMap.get(pointerKey).get(1));
          }
          g2d.fillPolygon(polygon);
        }
     
        int whiteSpace = 75;
        double padding = 1.5;
        String companyName = "中国足球七比零";
        // 根据名称长度 动态设置字体大小 防止文字过多发生文字碰撞
        int fontSize = (60 - companyName.length()) / 3;
        // 平移画布使环形文字在圆圈内
        g2d.translate(centerPoint - fontSize / 2, 0);
        // 文字开始位置 大概在左下角
        g2d.rotate(((double) whiteSpace / 360) * Math.PI + Math.PI, fontSize / 2, centerPoint);
        Font font = new Font("FangSong_GB2312", Font.ROMAN_BASELINE, fontSize);
        g2d.setFont(font);
        // 在文字开始位置 第二个字符开始进行按计算角度进行旋转 从而生成环形文字
        double rotateAngle = (double) (360 - whiteSpace) * Math.PI / (180 * (companyName.length() - 1));
        for (int i = 0; i < companyName.toCharArray().length; i++) {
          if (i != 0) {
            g2d.rotate(rotateAngle, fontSize/2, centerPoint);
          }
          g2d.drawString(String.valueOf(companyName.toCharArray()[i]), 0, (int) (fontSize * padding));
        }
     
		g2d.setColor(Color.BLACK);
		g2d.dispose();
     	
    }
    
    
    
}

定义坐标位置

效果

代碼(修改后可用代碼)

java 复制代码
package com.sxz.study.pdf;

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;

public class TestPDFToTIFCompressLZWWithStampXY {

    public static void main(String[] args) {
        try {
            // Load the PDF document
            PDDocument document = PDDocument.load(new File("C:\\test\\PDF\\Test.pdf"));
            
            // Create a PDF renderer
            PDFRenderer pdfRenderer = new PDFRenderer(document);
            
            // Iterate over each page in the PDF document
            for (int pageNumber = 0; pageNumber < document.getNumberOfPages(); pageNumber++) {
				// Render the PDF page to a BufferedImage
				// BufferedImage image = pdfRenderer.renderImageWithDPI(pageNumber, 300,
				// ImageType.RGB);
				BufferedImage image = pdfRenderer.renderImageWithDPI(pageNumber, 200, ImageType.GRAY);

				
				// 打印图章
				printStamp(image, 600, 500);


		        ImageWriter writer = ImageIO.getImageWritersByFormatName("tiff").next();
		        ImageWriteParam writeParam = writer.getDefaultWriteParam();
		        writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
		        writeParam.setCompressionType("LZW");
		        //writeParam.setCompressionQuality(1.0f);
				
		        // 创建输出文件流
		        FileImageOutputStream output = new FileImageOutputStream(new File("C:\\test\\PDF\\output_" + (pageNumber + 1) + ".tif"));
		        writer.setOutput(output);

		        // 写入压缩后的TIF图像
		        writer.write(null, new IIOImage(image, null, null), writeParam);

		        // 关闭输出流
		        output.close();
		        
			}

			// Close the PDF document
			document.close();

			System.out.println("PDF converted to TIF successfully");
		} catch (Exception e) {
			e.printStackTrace();

		}
	}
    
    
    public static void printStamp(BufferedImage image, int xxx ,int yyy){
    	
        // 在图像上绘制  印章
        Graphics2D g2d = image.createGraphics();

        int imageSize = 150;
        // 防止出现锯齿
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
        g2d.setComposite(AlphaComposite.Src);
        g2d.setColor(Color.red);
        g2d.setStroke(new BasicStroke(3));
        // 绘画起点xy坐标并非圆心坐标
		g2d.drawOval(2 + xxx, 2 + yyy, imageSize - 4, imageSize - 4);
     
        // 绘画五角星
        int r = 20;
        int centerPoint = imageSize / 2;
        Map<String, List<Integer>> pointersMap = new HashMap<>();
        // 五角星6点坐标 O为圆心点
        pointersMap.put("O", Arrays.asList(centerPoint, centerPoint));
        pointersMap.put("A", Arrays.asList(centerPoint, centerPoint - r));
        pointersMap.put("B", Arrays.asList((int)(centerPoint + Math.sin(0.4 * Math.PI) * r), (int)(centerPoint - Math.cos(0.4 * Math.PI) * r)));
        pointersMap.put("C", Arrays.asList((int)(centerPoint + Math.sin(0.2 * Math.PI) * r), (int)(centerPoint + Math.cos(0.2 * Math.PI) * r)));
        pointersMap.put("D", Arrays.asList((int)(centerPoint - Math.sin(0.2 * Math.PI) * r), (int)(centerPoint + Math.cos(0.2 * Math.PI) * r)));
        pointersMap.put("E", Arrays.asList((int)(centerPoint - Math.sin(0.4 * Math.PI) * r), (int)(centerPoint - Math.cos(0.4 * Math.PI) * r)));
        // 6点组合绘画图像
        List<String> pointerComposes = Arrays.asList("A,D,O,C", "B,E,O,D", "C,A,O,E", "D,A,O,B", "E,C,O,B");
        // 查找绘画点进行绘画
        for (String pointerCompose : pointerComposes) {
          String[] pointerKeys = pointerCompose.split(",");
          Polygon polygon = new Polygon();
          for (String pointerKey : pointerKeys) {
            polygon.addPoint(pointersMap.get(pointerKey).get(0) + xxx, pointersMap.get(pointerKey).get(1) + yyy);
          }
          g2d.fillPolygon(polygon);
        }
     
        int whiteSpace = 75;
        double padding = 1.5;
        String companyName = "中国足球七比零";
        // 根据名称长度 动态设置字体大小 防止文字过多发生文字碰撞
        int fontSize = (60 - companyName.length()) / 3;
        // 平移画布使环形文字在圆圈内
		g2d.translate((centerPoint - fontSize / 2) + xxx, 0 + yyy);
        // 文字开始位置 大概在左下角
        g2d.rotate(((double) whiteSpace / 360) * Math.PI + Math.PI, fontSize / 2, centerPoint);
        Font font = new Font("FangSong_GB2312", Font.ROMAN_BASELINE, fontSize);
        g2d.setFont(font);
        // 在文字开始位置 第二个字符开始进行按计算角度进行旋转 从而生成环形文字
        double rotateAngle = (double) (360 - whiteSpace) * Math.PI / (180 * (companyName.length() - 1));
        for (int i = 0; i < companyName.toCharArray().length; i++) {
          if (i != 0) {
            g2d.rotate(rotateAngle, fontSize/2, centerPoint);
          }
          g2d.drawString(String.valueOf(companyName.toCharArray()[i]), 0 , (int) (fontSize * padding) );
        }
     
		g2d.setColor(Color.BLACK);
		g2d.dispose();
     	
    }
    
    
    
}

====

PDF生成jpg图片

java 复制代码
package com.sxz.study.pdf;

import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;

public class TestPDFToJpg {

	public static void main(String[] args) {
		try {
			// Load the PDF document
			PDDocument document = PDDocument.load(new File("C:\\test\\PDF\\Java.pdf"));

			// Create a PDF renderer
			PDFRenderer pdfRenderer = new PDFRenderer(document);

			// Iterate over each page in the PDF document
			for (int pageNumber = 0; pageNumber < document.getNumberOfPages(); pageNumber++) {
				// Render the PDF page to a BufferedImage
				// BufferedImage image = pdfRenderer.renderImageWithDPI(pageNumber, 300,
				// ImageType.RGB);
				BufferedImage image = pdfRenderer.renderImageWithDPI(pageNumber, 200, ImageType.RGB);

		        ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
		        ImageWriteParam writeParam = writer.getDefaultWriteParam();
		        writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
//		        writeParam.setCompressionType("LZW");
				
		        // 创建输出文件流
		        FileImageOutputStream output = new FileImageOutputStream(new File("C:\\test\\PDF\\output_" + (pageNumber + 1) + ".jpg"));
		        writer.setOutput(output);

		        // 写入压缩后的TIF图像
		        writer.write(null, new IIOImage(image, null, null), writeParam);

		        // 关闭输出流
		        output.close();
		        
			}

			// Close the PDF document
			document.close();

			System.out.println("PDF converted to TIF successfully");
		} catch (Exception e) {
			e.printStackTrace();

		}
	}
}

==

===

代码比较(印章 和 JPG),代码原理

==

介绍一下 java中的Graphics2D 类

Graphics2D类是Java 2D图形库中的一个关键类,它扩展了Graphics类,提供了更强大和灵活的绘图功能。Graphics2D类允许开发人员在屏幕上绘制2D图形,包括线条、形状、文本和图像等。以下是Graphics2D类的一些重要特性和用途:

  1. 继承自Graphics类:Graphics2D类继承自Graphics类,因此可以使用所有Graphics类中定义的方法,并添加了更多的高级图形绘制方法。

  2. 支持图形的平移、旋转、缩放等操作:通过Graphics2D类提供的方法,可以轻松地对绘制的2D图形进行平移、旋转、缩放等变换操作,从而实现更灵活的绘图效果。

  3. 支持抗锯齿渲染:Graphics2D类可以实现图形的抗锯齿渲染,使绘制出来的图形边缘更加平滑,提高图形绘制的质量。

  4. 绘制简单图形:通过drawLine()drawRect()drawOval()等方法,可以在画布上绘制直线、矩形、椭圆等简单形状。

  5. 绘制复杂图形:Graphics2D类提供了一系列高级绘图方法,使开发人员可以创建和绘制复杂的图形,如贝塞尔曲线、路径、复杂的多边形等。

  6. 绘制文本和图像:除了绘制图形外,Graphics2D类还提供了绘制文本和图像的方法,可以在图形上添加文字或插入图片。

总的来说,Graphics2D类是Java中2D图形绘制的一个核心类,提供了丰富的功能和方法,使开发人员可以实现各种各样的绘图效果。如果您需要在Java应用程序中进行2D图形绘制和渲染操作,Graphics2D类是一个非常有用和强大的工具。

==

印章代码参照

java圆形印章生成_java.awt 画印章-CSDN博客

====

相关推荐
拓端研究室7 小时前
专题:2025全球消费趋势与中国市场洞察报告|附300+份报告PDF、原数据表汇总下载
大数据·信息可视化·pdf
Kyln.Wu2 天前
【python实用小脚本-190】Python一键删除PDF任意页:输入页码秒出干净文件——再也不用在线裁剪排队
服务器·python·pdf
阿幸软件杂货间2 天前
免费万能电子书格式转换器!Neat Converter支持 ePub、Azw3、Mobi、Doc、PDF、TXT 文件的相互转换。
pdf·格式转换
星马梦缘3 天前
CSDN转PDF【无水印且免费!!!】
pdf·免费·pandoc·转pdf·无水印·csdn转pdf·wkhtmlpdf
画月的亮3 天前
前端处理导出PDF。Vue导出pdf
前端·vue.js·pdf
伊织code4 天前
pdfminer.six
python·pdf·图片·提取·文本·pdfminer·pdfminer.six
HAPPY酷4 天前
给纯小白的Python操作 PDF 笔记
开发语言·python·pdf
代码AI弗森5 天前
PDF OCR + 大模型:让文档理解不止停留在识字
pdf·ocr
小周同学:5 天前
在 Vue2 中使用 pdf.js + pdf-lib 实现 PDF 预览、手写签名、文字批注与高保真导出
开发语言·前端·javascript·vue.js·pdf
Kyln.Wu6 天前
【python实用小脚本-187】Python一键批量改PDF文字:拖进来秒出新文件——再也不用Acrobat来回导
python·pdf·c#