java实现,PDF转换为TIF

目录

■JDK版本

■java代码・实现效果

■POM引用

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

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

■问题

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

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

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

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

■相关工具

SVF

foxit

■相关知识

ImageIO.write 的结果是 false 的原因

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

DPI是什么

一英寸 是多少厘米

图片的 位深度

■功能扩展

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

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

印章(在右上角)

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

PDF生成jpg图片

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


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

■JDK版本

1.8

■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 documentPDDocument document = PDDocument.load(new File("E:\\Users\\sxz\\Desktop\\PDF\\Test.pdf"));// Create a PDF rendererPDFRenderer pdfRenderer = new PDFRenderer(document);// Iterate over each page in the PDF documentfor (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 fileboolean flg = ImageIO.write(image, "tif", new File("E:\\Users\\sxz\\Desktop\\PDF\\output_" + (pageNumber + 1) + ".tif"));System.out.println(flg);}// Close the PDF documentdocument.close();System.out.println("PDF converted to TIF successfully");} catch (Exception e) {e.printStackTrace();}}}

===

====

=====

■POM引用

		<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中添加如下引用

		<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方式压缩 (质量高)

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 documentPDDocument document = PDDocument.load(new File("C:\\test\\PDF\\Test.pdf"));// Create a PDF rendererPDFRenderer pdfRenderer = new PDFRenderer(document);// Iterate over each page in the PDF documentfor (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 documentdocument.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!

==

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 documentPDDocument document = PDDocument.load(new File("C:\\test\\PDF\\Test.pdf"));// Create a PDF rendererPDFRenderer pdfRenderer = new PDFRenderer(document);// Iterate over each page in the PDF documentfor (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 documentdocument.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中添加以下依赖项:

		<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图像的指定坐标绘制文本信息:

例子代码

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();}}
}

===

完整代码

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 documentPDDocument document = PDDocument.load(new File("C:\\test\\PDF\\0830.pdf"));// Create a PDF rendererPDFRenderer pdfRenderer = new PDFRenderer(document);// Iterate over each page in the PDF documentfor (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 documentdocument.close();System.out.println("PDF converted to TIF successfully");} catch (Exception e) {e.printStackTrace();}}
}

===

===

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

==

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页的PDFpublic 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

===

印章(在右上角)

部分代码(参考)

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();}

全部代码

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 documentPDDocument document = PDDocument.load(new File("C:\\test\\PDF\\Test.pdf"));// Create a PDF rendererPDFRenderer pdfRenderer = new PDFRenderer(document);// Iterate over each page in the PDF documentfor (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();// ----endImageWriter 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 documentdocument.close();System.out.println("PDF converted to TIF successfully");} catch (Exception e) {e.printStackTrace();}}
}

===

===

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

初版 (修改前 Base)

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 documentPDDocument document = PDDocument.load(new File("C:\\test\\PDF\\Test.pdf"));// Create a PDF rendererPDFRenderer pdfRenderer = new PDFRenderer(document);// Iterate over each page in the PDF documentfor (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 documentdocument.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();}}

定义坐标位置

效果

代碼(修改后可用代碼)

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 documentPDDocument document = PDDocument.load(new File("C:\\test\\PDF\\Test.pdf"));// Create a PDF rendererPDFRenderer pdfRenderer = new PDFRenderer(document);// Iterate over each page in the PDF documentfor (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 documentdocument.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图片

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 documentPDDocument document = PDDocument.load(new File("C:\\test\\PDF\\Java.pdf"));// Create a PDF rendererPDFRenderer pdfRenderer = new PDFRenderer(document);// Iterate over each page in the PDF documentfor (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 documentdocument.close();System.out.println("PDF converted to TIF successfully");} catch (Exception e) {e.printStackTrace();}}
}

==

===

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

==

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/878852.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RAG与LLM原理及实践(14)---RAG Python 前端构建技术Flask

目录 背景 Flask 简介 Flask 的特点 flask 安装 Flask python server 端处理 app 资源映射 router概念 Flask 客户端处理 Jinja2 概述 具体语法 实例 python 后端 代码 前端相关代码 代码解释 运行 check 启动日志 背景 本专栏之前的文章都在描述RAG后台的搭…

MySQL之DQL-分组函数

1、分组函数 1. 分组函数语法 分组函数也叫聚合函数。是对表中一组记录进行操作&#xff0c;每组只返回一个结果。我们只讲如下5个常用的分组函数&#xff1a; 分组函数 含义 MAX 求最大值 MIN 求最小值 SUM 求和 AVG 求平均值 COUNT 求个数 分组函数的语法如下…

Java中的强引用、软引用、弱引用和虚引用于JVM的垃圾回收机制

参考资料 https://juejin.cn/post/7123853933801373733 在 Java 中&#xff0c;引用类型分为四种&#xff1a;强引用&#xff08;Strong Reference&#xff09;、软引用&#xff08;Soft Reference&#xff09;、弱引用&#xff08;Weak Reference&#xff09;和虚引用&#xf…

水晶连连看 - 无限版软件操作说明书

水晶连连看 – 无限版游戏软件使用说明书 文章目录 水晶连连看 – 无限版游戏软件使用说明书1 引言1.1 编写目的1.2 项目名称1.3 项目背景1.4 项目开发环境 2 概述2.1 目标2.2 功能2.3 性能 3 运行环境3.1 硬件3.2 软件 4 使用说明4.1 游戏开始界面4.2 游戏设定4.2.1 游戏帮助4…

9.6学习记录+三场笔试

一、去哪儿笔试挚文集团 1.在调度算法中平均等待时间最短的是什么? 短作业优先 2.给定一个字符串s&#xff0c;最有效的找到其中第一个不重复的字符的方法是? 一、使用哈希表 创建一个哈希表&#xff0c;用于存储字符及其出现的次数。可以使用编程语言中提供的字典&#x…

AI学习指南深度学习篇-随机梯度下降法(Stochastic Gradient Descent,SGD)简介

AI学习指南深度学习篇-随机梯度下降法&#xff08;Stochastic Gradient Descent&#xff0c;SGD&#xff09;简介 在深度学习领域&#xff0c;优化算法是至关重要的一部分。其中&#xff0c;随机梯度下降法&#xff08;Stochastic Gradient Descent&#xff0c;SGD&#xff09…

Android 15 正式发布到 AOSP ,来了解下新特性和适配需求

其实在年初的时候就整理过《2024 &#xff0c;Android 15 预览版来了》 和《提前窥探 Android 15 的新功能与适配》的相关内容&#xff0c;而随着时间进度推进&#xff0c;近日谷歌也正式发布了 Android 15 的正式版&#xff0c;虽然没什么「大亮点」&#xff0c;但是作为开发者…

11.2.软件系统分析与设计-数据库分析与设计

数据库分析与设计 数据库分析与设计的步骤 ER图和关系模型

目标检测-YOLOv1

YOLOv1介绍 YOLOv1&#xff08;You Only Look Once version 1&#xff09;是一种用于目标检测的深度学习算法&#xff0c;由Joseph Redmon等人于2016年提出。它基于单个卷积神经网络&#xff0c;将目标检测任务转化为一个回归问题&#xff0c;通过在图像上划分网格并预测每个网…

基于发布-订阅模型的音视频流分发框架

有时需要同时网络推流和把流封装为某格式&#xff0c;或做一些其它操作。这就需要一个分发流的机制&#xff0c;把同一路流分发给多个使用者去操作&#xff0c;下面实现了一个简易的线程安全的音视频流分发框架。代码如下&#xff1a; avStreamHub.h #ifndef STREAMHUB_H #def…

python连接MySQL获取表中数据

import pymysql# 连接数据库 conn pymysql.connect(hostlocalhost,userroot,passwordroot,dbtest,charsetutf8mb4,cursorclasspymysql.cursors.DictCursor )def data_upload(key, value):# print(f"Key:{key},Value:{value}")print(f"{key},{value}")try:…

Ubuntu2204配置连续失败后账户锁定

配置启用pam_faillock sudo nano /etc/pam.d/common-auth在最上面添加以下内容 auth required pam_faillock.so preauth silent audit auth sufficient pam_unix.so nullok try_first_pass auth [defaultdie] pam_faillock.so authfail auditsudo nano /etc/pam.d/…

SealSuite 一站式 IT 管理与办公安全解决方案,助力出海企业夯实数字化底座

数字化办公时代&#xff0c;企业升级 IT 基础设施&#xff0c;已不再是选择题&#xff0c;而是必答题。 数字化办公时代&#xff0c;企业为何要升级 IT 基础设施&#xff1f; 随着时代变化与科技进步&#xff0c;人们的工作方式也发生了巨大变化。如今&#xff0c;远程办公、全…

VMware命令

打开终端&#xff1a;Ctrl Alt T 注意&#xff1a;时刻谨记空格号 自己常用命令&#xff1a; cd 拖入需要切换的文件夹&#xff1a;切换至指定文件夹&#xff1b; cd /&#xff1a;切换至根目录&#xff1b; unzip archive_name.zip&#xff1a;解压zip文件&#xff1b; na…

【论文精读】SCINet-基于降采样和交互学习的时序卷积模型

《SCINet: Time Series Modeling and Forecasting with Sample Convolution and Interaction》的作者团队来自香港中文大学,发表在NeurIPS 2022会议上。 动机 该论文的出发点是观察到时间序列数据具有独特的属性:即使在将时间序列下采样成两个子序列后,时间关系(例如数据…

科研小白成长记40——第三个五年计划

小gap期间&#xff0c;拼命玩和拼命休息的同时&#xff0c;仔细思考了下我期望的五年之后的样子&#xff0c;gap结束&#xff0c;算是目标愈发清晰起来。曾经&#xff0c;读博的目标是成为一名independent researcher&#xff0c;并且具备发至少一篇顶会的能力。而现在&#xf…

iOS面试:如何手动触发一个value的KVO?

在 iOS 开发中&#xff0c;手动触发一个属性的 KVO&#xff08;Key-Value Observing&#xff09;更新&#xff0c;通常是在属性的值在代码中发生变化时&#xff0c;确保观察者能够收到这些变化的通知。虽然 KVO 通常是在观察某些属性变化时自动通知观察者的&#xff0c;但如果你…

【PPT学习笔记】使用PPT制作动画/手书/视频等作品的适配性和可能性?

【PPT学习笔记】使用PPT制作动画/手书等作品的可能性&#xff1f; 背景前摇&#xff1a;&#xff08;省流可不看&#xff09; 最近找到另外一份新的实习工作&#xff0c;有很多需要用到PPT动画的地方。 然而&#xff0c;我们之前制作的理工科PPT全是摒弃了形式主义的艰苦朴素…

STM32 HAL CAN通讯 实操

1、简介 相比于串口通讯,对于刚接触CAN通讯的小白来说,CAN通讯相对复杂,看各种视频、帖子理论,总是一知半解。本次通过傻瓜式操作,先实现CAN通讯的交互,以提高小白的信心,也便于自己复习观看。本次以STM32CubeMX进行初始化配置,通过Keil 5软件进行软件设计,通过CAN盒…

各种各样的正则表达式

一、校验数字的表达式 数字:^[0-9]*$ n位的数字:^\d{n}$ 至少n位的数字:^\d{n,}$ m-n位的数字:^\d{m,n}$ 零和非零开头的数字:^(0|[1-9][0-9]*)$ 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$ 带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?$ 正…