审计文件标识作为水印打印在pdf页面边角

news2025/1/19 7:42:15

目录

  • 说明

说明

将审计文件的所需要贴的编码直接作为水印贴在页面四个角落,节省辨别时间

我曾经写过一个给pdf页面四个角落加上文件名水印的python脚本,现在需要加一个图形界面进一步加强其实用性。首先通过路径浏览指定文件路径,先检测该路径是不是已经存在的文件夹,如果不是,再判断是不是txt如果也不是,提示需要txt路径列表或者提供根路径,如果是文件路径,提示该路径下子文件夹的文件也会被做同样处理,做好文件备份隔离防护工作。如果是txt则按行读取,并且提示其中的路径有多少是有效的。
提供一个勾选框,决定是否要将路径中的各种图片格式转化为同名pdf。然后提供两个文本框指定图片转化线程数和水印添加线程数
然后再提供2个参数文本框,第一个文本框内数字为g(成为打印页边距)分别用来调节水印离两个方向页面边界的距离(%为单位的相对距离,实际距离取决于读取到的页面尺寸,长和宽的乘积取平方根再乘以g%),第2文本框用来指定相对字体大小f%%为单位,计算一个参考高度等于页面长宽乘积取平方根再乘以5%再乘以f%,然后计算选定字体显示高度与参考高度相等的字号),用标签提示最好在实验文件夹中测试好需要的相对字体大小
font_family根据系统可选提供下拉菜单,改为用户指定,前两个默认为Times New Roman和楷体
水印内容和示例代码中一样根据文件名、当前页数和总页数来确定
由于插入点是文本左上角,而四个角文本的方向不同,为了让文本更好贴合打印边界又不超出打印边界,该代码根据页面尺寸、打印边距和指定字体字号情况下文本显示所占矩形空间来确定插入点的具体位置
点击执行按钮,遍历一次路径如果有图片需要转化又未被转化,先转化图片为pdf(多线程执行),同时记录所有有待处理的pdf文件数(包括图片转化出来的)
再遍历一次路径,将每个pdf的按照设定参数添加水印(用多线程执行),并且替换原文件。按已处理文件数/总文件数显示进度条,完成后弹窗提示

import os
import re
import fitz
from PIL import ImageFont
def text_position(w,h,x,y,width,height,gap):
    if y<=height/2:
        if x<=width/2:
            x=max(x,gap)+h
            y=gap+w
            return [x,y]
        else:
            x=width-gap-w
            y=max(gap,y)+h
            return [x,y]
    else:
        if x<=width/2:
            x=gap+w
            y=height-max(gap,height-y)-h
            return [x,y]
        else:
            x=width-max(gap,width-x)-h
            y=height-gap-w
            return [x,y]
def text_size(line,font_family,font_size):
    font = ImageFont.truetype(font_family, font_size, 0)
    width, height = font.getsize(line)
    #DeprecationWarning: getsize is deprecated and will be removed in Pillow 10 (2023-07-01). Use getbbox or getlength instead.
    return [width,height]
def text_insert_once(x1,y1,x2,y2,x3,y3,x4,y4,text,fname,fsize,page):
    p = fitz.Point(x2,y2)#右上角
    page.insert_text(p,  # bottom-left of 1st char
                         text,  # the text (honors '\n')
                         fontname = fname,  # the default font
                         fontsize = fsize,  # the default font size
                         rotate = 0,  # also available: 90, 180, 270
                         )
    p = fitz.Point(x3,y3)#左下角,从右往左
    page.insert_text(p,  # bottom-left of 1st char
                         text,  # the text (honors '\n')
                         fontname = fname,  # the default font
                         fontsize = fsize,  # the default font size
                         rotate = 180,  # also available: 90, 180, 270
                         )
    p = fitz.Point(x1,y1)#左上角,从下到上
    page.insert_text(p,  # bottom-left of 1st char
                         text,  # the text (honors '\n')
                         fontname = fname,  # the default font
                         fontsize = fsize,  # the default font size
                         rotate = 90,  # also available: 90, 180, 270
                         )
    p = fitz.Point(x4,y4)#右下角,从上到下
    page.insert_text(p,  # bottom-left of 1st char
                         text,  # the text (honors '\n')
                         fontname = fname,  # the default font
                         fontsize = fsize,  # the default font size
                         rotate = 270,  # also available: 90, 180, 270
                         )
def pnum_print(pdf,file,flag=1):
    pagenum=pdf.page_count    
    i=0
    for page in pdf:
        content=[]
        #假定短边留白5%,长边留白3.3%
        i=i+1
        width=page.rect.width
        height=page.rect.height
        [wx,hx]=[0.06,0.04]
        if width>= height:
            #w=round(width*wx,0)
            h=round(height*wx,0)
            w=h
        else:
            w=round(width*wx,0)
            h=w
        fs=int(w/4)
        text=str(i)+'/'+str(pagenum)
        content.append(os.path.splitext(file)[0])
        content.append(text)       
        ff=page.insert_font(fontname="HT",fontfile=r"C:\Windows\Fonts\simhei.ttf", fontbuffer=None , set_simple=False )
        [x1,y1,x2,y2,x3,y3,x4,y4]=[0,0,width,0,0,height,width,height]
        for c in content:
            [w,h]=text_size(c,"simhei.ttf",fs)
            [x1,y1]=text_position(w,h,x1,y1,width,height,0*w)
            [x2,y2]=text_position(w,h,x2,y2,width,height,0*w)
            [x3,y3]=text_position(w,h,x3,y3,width,height,0*w)
            [x4,y4]=text_position(w,h,x4,y4,width,height,0*w)
            text_insert_once(x1,y1,x2,y2,x3,y3,x4,y4,c,"HT",fs,page)
    if pdf.can_save_incrementally():
        if flag==1:
            pdf.saveIncr()
        else:
            pdf.save(os.path.splitext(file)[0]+'(共'+str(pagenum)+'页)'+'.pdf')
        print(file+"***********processed")
        pdf.close()
        if flag!=1:
            os.remove(file)
        #os.remove(file)
    else:
        print("Can't save Incermentally")#增量保存的文件损坏和签名问题
def path_read(flag,source):
    path=[]
    if flag=="父节点":
        for p in os.listdir(source):
            if os.path.isdir(source+'\\'+p):
                path.append(source+'\\'+p)
        return path
    if flag=="列表文件":
        with open(source,'r') as f :
            for p in f.readlines():
                pp=p.replace('\n','')
                if os.path.isdir(pp):
                    path.append(pp)
        return path
    return None
def pic2pdf(file):
    img_file=['.png','.jpg',',jepg']
    title=os.path.splitext(file)[0]
    if os.path.splitext(file)[1] in img_file:
        imgdoc = fitz.open(file) # 打开图片
        pdfbytes = imgdoc.convert_to_pdf() # 使用图片创建单页的 PDF
        imgpdf = fitz.open("pdf", pdfbytes)
        doc=fitz.open()
        doc.insert_pdf(imgpdf) # 将当前页插入文档
        if os.path.exists(title+".pdf"):
            os.remove(title+".pdf")
        doc.save(title+".pdf") # 保存pdf文件
        doc.close()
        imgdoc.close()
        os.remove(file)
img_file=['.png','.jpg',',jepg']
img_convert=True #False  #True
#path=path_read(flag="列表文件",source=r'E:\huang\Desktop\路径列表.txt')
path=path_read(flag="父节点",source=r'E:\huang\Desktop\浙江通力传动科技股份有限公司\乐总底稿整理\新建文件夹\内控')
print(path)
for p in path:
    os.chdir(p)
    print(p)
    if img_convert:
        for file in os.listdir():
            if os.path.splitext(file)[1] in img_file:
                pic2pdf(file)
    for file in os.listdir():
        if os.path.splitext(file)[1]=='.pdf':
            print(file)
            if re.search(r'\(共\d+?页\)',file)==None:
                pdf_book=fitz.open(file)
                pnum_print(pdf_book,file,0)
                    

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

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

相关文章

电梯系统的UML文档05

Dispatcher 不控制实际的电梯组件&#xff0c;但它在软件系统中是重要的。每一个电梯有一个ispatcher&#xff0c;主要功能是计算电梯的移动方向、移动目的地以及保持门的打开时间。它和系统中除灯控制器以外的几乎所有控制对象交互。 安全装置也是一个环境对象&#xff0c;它…

各种获取数据接口

各种获取数据免费接口 1.音频接口 代理配置 /music-api:{target:https://api.cenguigui.cn/,changeOrigin:true,rewrite:(path)>path.replace(/^\/music-api/,),secure:false}axios全局配置 import axios from axios;const MusicClient axios.create({baseURL: /music-a…

外包公司名单一览表(成都)

大家好&#xff0c;我是苍何。 之前写了一篇武汉的外包公司名单&#xff0c;评论区做了个简单统计&#xff0c;很多人说&#xff0c;在外包的日子很煎熬&#xff0c;不再想去了。 有小伙伴留言说有些外包会强制离职&#xff0c;不行就转岗&#xff0c;让人极度没有安全感。 这…

第十一章 图论

#include <iostream> #include <cstdio> #include <vector>using namespace std;const int MAXN 1000;vector<int> graph[MAXN]; //用向量存储邻接表中的每个点及其连接的的其他点int main(){return 0; } #include <iostream> #include &…

大数据中 TopK 问题的常用套路

大数据中 TopK 问题的常用套路 作者 Chunel Feng&#xff0c;编程爱好者&#xff0c;阿里巴巴搜索引擎开发工程师。开源项目&#xff1a;Caiss 智能相似搜索引擎 对于海量数据到处理经常会涉及到 topK 问题。在设计数据结构和算法的时候&#xff0c;主要需要考虑的应该是当前算…

RabbitMQ基础篇

文章目录 1 RabbitMQ概述1.1 消息队列1.2 RabbitMQ体系结构 2 RabbitMQ工作模式2.1 简单模式&#xff08;Simple Queue&#xff09;2.2 工作队列模式&#xff08;Work Queues&#xff09;2.3 发布/订阅模式&#xff08;Publish/Subscribe&#xff09;2.4 路由模式&#xff08;R…

【人工智能】:搭建本地AI服务——Ollama、LobeChat和Go语言的全方位实践指南

前言 随着自然语言处理&#xff08;NLP&#xff09;技术的快速发展&#xff0c;越来越多的企业和个人开发者寻求在本地环境中运行大型语言模型&#xff08;LLM&#xff09;&#xff0c;以确保数据隐私和提高响应速度。Ollama 作为一个强大的本地运行框架&#xff0c;支持多种先…

从玩具到工业控制--51单片机的跨界传奇【3】

在科技的浩瀚宇宙中&#xff0c;51 单片机就像一颗独特的星辰&#xff0c;散发着神秘而迷人的光芒。对于无数电子爱好者而言&#xff0c;点亮 51 单片机上的第一颗 LED 灯&#xff0c;不仅仅是一次简单的操作&#xff0c;更像是开启了一扇通往新世界的大门。这小小的 LED 灯&am…

Linux 音视频入门到实战专栏(视频篇)视频编解码 MPP

文章目录 一、MPP 介绍二、获取和编译RKMPP库三、视频解码四、视频编码 沉淀、分享、成长&#xff0c;让自己和他人都能有所收获&#xff01;&#x1f604; &#x1f4e2;本篇将介绍如何调用alsa api来进行音频数据的播放和录制。 一、MPP 介绍 瑞芯微提供的媒体处理软件平台…

ScratchLLMStepByStep:训练自己的Tokenizer

1. 引言 分词器是每个大语言模型必不可少的组件&#xff0c;但每个大语言模型的分词器几乎都不相同。如果要训练自己的分词器&#xff0c;可以使用huggingface的tokenizers框架&#xff0c;tokenizers包含以下主要组件&#xff1a; Tokenizer: 分词器的核心组件&#xff0c;定…

深度学习项目--基于LSTM的火灾预测研究(pytorch实现)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 LSTM模型一直是一个很经典的模型&#xff0c;这个模型当然也很复杂&#xff0c;一般需要先学习RNN、GRU模型之后再学&#xff0c;GRU、LSTM的模型讲解将…

社区版Dify实现文生视频 LLM+ComfyUI+混元视频

社区版Dify实现文生视频 LLMComfyUI混元视频 一、 社区版Dify实现私有化混元视频效果二、为什么社区版Dify可以在对话框实现文生视频&#xff1f;LLMComfyUI混元视频 实现流程图&#xff08;重点&#xff09;1. 文生视频模型支持ComfyUI2. ComfyUI可以轻松导出API实现封装3. Di…

SpringBoot的Bean-中级-作用域

5个作用域&#xff1a; 初级演示的是第一种默认的singleton&#xff1a;SpringBoot的Bean-初级获取bean对象-CSDN博客 中级-1&#xff1a;Lazy注解使其在使用的时候再实例化 中级-2&#xff1a;Scope("prototype")使其每次需要注入的时候都实例化新的对象 测试程序&…

放大芯片参数阅读

一、芯片的增益能力 1. GBW&#xff08;增益带宽积&#xff09; 例如&#xff0c;GBW (typ) 1 MHz。 增益带宽积&#xff08;Gain Bandwidth Product&#xff09;是一个关键参数&#xff0c;用于计算在特定频率下的最大增益。 定义公式为&#xff1a; 增益带宽G…

蓝桥杯算法日常|枚举[*找到最多的数]

**找到最多的数** 重点疑问总结&#xff1a; 1、数组输入输出c一般会采用那种方便的方式&#xff1f;&#xff1f; 用的就是我想的那种&#xff0c;就是用的最大范围定义的。 2、怎样方便给数组中每个数出现的次数计数&#xff1f;&#xff1f; 刚开始想的是&#xff1a;每个数…

Docker安装PostGreSQL docker安装PostGreSQL 完整详细教程

Docker安装PostGreSQL docker安装PostGreSQL 完整详细教程 Docker常用命令大全Docker 运行命令生成Docker 上安装 PostGreSQL 14.15 的步骤&#xff1a;1、拉取 PostGreSQL 14.15 镜像2、创建并运行容器3、测试连接4、设置所有IP都可以运行连接进入容器内 修改配置文件关闭容器…

基于机器学习随机森林算法的个人职业预测研究

1.背景调研 随着信息技术的飞速发展&#xff0c;特别是大数据和云计算技术的广泛应用&#xff0c;各行各业都积累了大量的数据。这些数据中蕴含着丰富的信息和模式&#xff0c;为利用机器学习进行职业预测提供了可能。机器学习算法的不断进步&#xff0c;如深度学习、强化学习等…

Go 语言 select 的实现原理

介绍 select是Go在语言层面提供的I/O多路复用的机制&#xff0c;其专门用来让Goroutine同时等待多个channel是否准备完毕:可读或可写。在Channel状态改变之前&#xff0c;select会一直阻塞当前线程或者goroutine。 特性&#xff1a; case 必须是一个通信操作&#xff0c;主要是…

Java 视频处理:基于 MD5 校验秒传及 ffmpeg 切片合并的实现

本文介绍两种网络技术实现方法。一是 MD5 校验秒传&#xff0c;服务器端用数据库记上传文件 MD5 值及存储路径&#xff0c;Java 代码接收客户端 MD5 值并查询校验&#xff0c;返回状态码。二是用 ffmpeg 切片视频成 m3u8 上传&#xff0c;异步合并文件实现视频按需加载。 1. …

一文读懂iOS中的Crash捕获、分析以及防治

Crash系统性总结 Crash捕获与分析Crash收集符号化分析 Crash类别以及解法分析子线程访问UI而导致的崩溃unrecognized selector send to instance xxxKVO crashKVC造成的crashNSTimer导致的Crash野指针Watch Dog超时造成的crash其他crash待补充 参考文章&#xff1a; 对于iOS端开…