由于孩子在学校经常会发一些作业,或者自己在网上找一些试卷,很多都是A3幅面的,由于手上没有A3打印机,如果直接缩放打印,字体会非常小,孩子看不清。
WORD、Adobe Acrobat和WPS等都没有直接将A3幅面的试卷裁剪生成为A4幅面的功能。手动倒是可以操作,但是太复杂,有时候还会弄错顺序。
因此,想自己动手,丰衣足食。手撸一个A3到A4的PDF转换工具。记录下来,方便有需要的友友们自取使用。
(PS:好久没有写文章了,主要是没有太好的素材,又不想水。今天冒个泡^_^)
1、准备工作
(注意,这部分是在说明我开发的过程,不需要粉丝自己有这样的环境,如果有需要打包好的执行程序,我在文章最后会告诉大家如何获取。)
1)机器上要有Python环境,
2)机器上有一个IDE编程环境,我这里用VSCode
开发环境
3)界面部分我采用的是PySide2,用QtCreator画的
最后的界面长这样
2、需求分析
为了同时满足一些日常可能碰到的PDF处理工作。顺便添加了PDF转WORD,PDF转JPG,JPG转PDF。当然最重要的是A3幅面的试卷自动转成A4可打印的PDF。
1)PDF转WORD,将PDF转成可编辑的WORD文件,亲测效果还可以。但是请注意,PDF有几种形式,一种是Word等办公软件直接生成的PDF,这种PDF好转。另一种PDF本身就是存的图片,这种转成WROD后也是图片。并不能将其中的内容转成可编辑的内容。以后有空了可以研究一下。
2)PDF转JPG,将一个PDF转成一系列JPG文件
3)JPG转PDF,将一个目录中有顺序编号的JPG转成一个PDF
4)A3幅面的试卷自动转A4幅面
A3打印机,手撸一个将A3试卷PDF裁剪输出成A4幅面的PDF,
3、相关依赖
经过网上学习,决定使用pdf2docx包和fitz包,这两个包的功能强大,具体的介绍这里就不赘述了,有兴趣的同学可以自己搜索。
4、核心代码
这一部分是准备给有Python编程基础的同学的,没有编程经验的同学可以直接跳过。
由于头条上的文章中显示代码
```
def pdf2jpg(pdf_path, jpgPath, zoom_x, zoom_y, rotate_angle):
# zoom_x x方向的缩放系数
# zoom_y y方向的缩放系数
# rotation_angle 旋转角度
# open pdf File
pdf = fitz.open(pdf_path)
(filepath, tempfilename) = os.path.split(pdf_path)
(filename, extension) = os.path.splitext(tempfilename)
i=1 # 当前页码
save_roi_name=''
for page in pdf:
# 设置缩放和旋转系数
trans = fitz.Matrix(zoom_x, zoom_y).prerotate(rotate_angle) # .preRotate(rotate_angle)
pix = page.get_pixmap(matrix=trans, alpha=False)
save_roi_name = os.path.join(jpgPath, filename '_d.jpg'%i)
i = i 1
pix .save(save_roi_name)
pdf.close()
def imgInsert2Pdf(imgFileName, pdf):
imgdoc = fitz.open(imgFileName)
pdfbytes = imgdoc.convert_to_pdf()
imgpdf = fitz.open("pdf", pdfbytes)
pdf.insert_pdf(imgpdf)
imgdoc.close()
imgpdf.close()
# 将文件夹中所有jpg图片全部转换为一个指定名称的pdf文件,并保存至指定文件夹
def jpg2pdf(img_path, pdf_pathname):
doc = fitz.open()
for img in sorted(glob.glob(img_path "\*.jpg")):
imgdoc = fitz.open(img)
pdfbytes = imgdoc.convert_to_pdf()
imgpdf = fitz.open("pdf", pdfbytes)
doc.insert_pdf(imgpdf)
doc.save(pdf_pathname)
doc.close()
# 如何设置边线,增加空白的参考代码
# addleft True——在页面左边增加空白宽度,反之,False——在页面右边增加空白宽度
def addBlankWide(pixSrc, addWidth, addleft=True):
tar_pix = None
if pixSrc is None:
return tar_pix
tar_w = pixSrc.width addWidth
tar_h = pixSrc.height
if addleft:
tar_pix = fitz.Pixmap(pixSrc.colorspace, (addWidth, 0, tar_w addWidth, tar_h), pixSrc.alpha) # create target pixmap
pixSrc.set_origin(addWidth, 0)
else:
tar_pix = fitz.Pixmap(pixSrc.colorspace, (-addWidth, 0, tar_w-addWidth, tar_h), pixSrc.alpha) # create target pixmap
pixSrc.set_origin(-addWidth, 0)
tar_pix.set_rect(tar_pix.irect, (255,255,255)) # fill it with some background color
tar_pix.copy(pixSrc, pixSrc.irect) # 要求拷贝前后的alpha值一致
return tar_pix
# 思路是,先裁剪输出成4页A4幅面的的图片,然后合并图片成一个PDF文件,最后删除过程图片文件
def pdfA3toA4(openedPdf, pdfPage, pdf_path, savFile, zoom_x, zoom_y, add_Width, seal_width):
# zoom_x x方向的缩放系数
# zoom_y y方向的缩放系数
# rotation_angle 旋转角度
# seal_width 密封区域宽度
# pdfPage 需要转换的页码
# open pdf file
# pdf = fitz.open(pdf_path)
# 新建一个PDF,然后把这几个JPG按顺序插入到新的PDF中
pdf2 = fitz.open() # new empty PDF
(filepath, tempfilename) = os.path.split(pdf_path)
(filename, extension) = os.path.splitext(tempfilename)
save_roi_name=''
# 设置缩放和旋转系数
trans = fitz.Matrix(zoom_x, zoom_y).prerotate(0) # .preRotate(rotate_angle)
pdfpageCount = openedPdf.page_count
if pdfPage>=pdfpageCount or pdfpageCount<=0:
pass
clip = None
for i in range(pdfpageCount):
# 第一页,密封区域在左边,先单页模式
page1 = openedPdf.load_page(pdfPage i)
rect = page1.rect # 页面大小
if i%2==0:
clip = fitz.Rect(rect.x0 add_Width seal_width,rect.y0, rect.x0 (rect.x1-rect.x0-seal_width)/2,rect.y1) # 想要截取的区域
else:
clip = fitz.Rect(rect.x0 add_Width, rect.y0, rect.x0 (rect.x1-rect.x0-seal_width)/2,rect.y1) # 想要截取的区域
pix = page1.get_pixmap(matrix=trans, alpha=False, clip=clip) # 将页面转换为图像
tarpix = addBlankWide(pix, add_Width, False)
str1 = '_clip_' str(i) '.png'
save_roi_name = os.path.join(filepath, filename str1)
tarpix .save(save_roi_name)
imgInsert2Pdf(save_roi_name,pdf2)
os.remove(save_roi_name)
if i%2==0:
# 奇数页
clip = fitz.Rect(rect.x0 (rect.x1-rect.x0-seal_width)/2,rect.y0, rect.x1-add_Width,rect.y1) # 想要截取的区域
else:
# 偶数页
clip = fitz.Rect(rect.x0 (rect.x1-rect.x0-seal_width)/2,rect.y0, rect.x1-seal_width-add_Width,rect.y1) # 想要截取的区域
pix = page1.get_pixmap(matrix=trans, alpha=False, clip=clip) # 将页面转换为图像
tarpix = addBlankWide(pix, add_Width, True)
str1 = '_clip_' str(i 1) '.png'
save_roi_name = os.path.join(filepath, filename str1)
tarpix .save(save_roi_name)
imgInsert2Pdf(save_roi_name,pdf2)
os.remove(save_roi_name)
pdf2.save(savFile)
pdf2.close()
def getAppPath():
application_path = ""
# determine if application is a script file or frozen exe
if getattr(sys, 'frozen', False):
application_path = os.path.dirname(sys.executable)
elif __file__:
application_path = os.path.dirname(__file__)
return application_path
```
5、效果
(1)A3试卷这样的
六年级的数学试卷,有兴趣的同学可以做一下试试!^_^
(2)转成A4之后这样的
包括顺序,都自动调整好了,直接打印即可。
7、关于源代码、执行程序与下载
(1)源代码,如果有粉丝需要完整的源代码,这里可以免费提供,暂时没有放到Git上去;
(2)执行程序,为了方便粉丝使用。我这里特意将Python脚本打包成可执行程序,我准备放到云盘上去,有需要的可以自行下载。打包过程遇到了很多坑,有兴趣的同学可以交流。执行程序中已经包含了Python相关的依赖环境,因此会比较大,但不需要下载后额外安装其他依赖。
需要的同学可以加我关注,然后私信我,我会一一回复。
(声明:本文中采用的开发语言为Python,采用了一些网上已经公开的公共组件,并没有从零开始,但核心代码原创编写。出发点只是为了自己方便,同时,如果有需要帮助的粉丝可以自取。本文全网首发,已签约平台自动维权,转载请注明。本文中的软件不做商用!)
,