当前位置: 首页 > wzjs >正文

福州哪家企业网站建设设计最高端seo优化托管

福州哪家企业网站建设设计最高端,seo优化托管,做网站退款怎么做会计分录,想做一个网站平台怎么做的文章目录0 引言1 解决思路与流程2 完整代码与测试效果参考0 引言 在之前的文章中,我们介绍了有关PDF文件图片去水印和文字颜色加深的方法,详情见如下链接: PDF图片去水印PDF图片文字加深 上述方法存在着一些不足之处,便是处理后…

文章目录

    • 0 引言
    • 1 解决思路与流程
    • 2 完整代码与测试效果
    • 参考

0 引言

在之前的文章中,我们介绍了有关PDF文件图片去水印和文字颜色加深的方法,详情见如下链接:

  • PDF图片去水印
  • PDF图片文字加深

上述方法存在着一些不足之处,便是处理后保存的PDF文件占用内存过大,比原本文件大好几倍。这篇文章的目的就是对处理后的PDF内存大小进行优化。

1 解决思路与流程

因为我们处理的PDF主要是由每页的图片组成的,因此图片的内存大小是影响PDF体量的主要因素。我们边看代码结果边分析,首先代入必要的库

import io # 用于字节流转换
import os # 用于查看文件内存占用情况
import sys # 用于查看变量字节数
import pymupdf # 用于操作PDF
from PIL import Image # 用于图片处理

这里import pymupdf而不是之前的import fitz,两者的区别参见官方文档说明1

为了兼顾调试分析的效率,我们先随便拿一个只有两页的PDF(example.pdf),该PDF由两张扫描图片组成。先读入文件,并打印内存大小。

doc = pymupdf.open("example.pdf")  # open a document
print(f"example.pdf [size]: {os.path.getsize('example.pdf') / 1024 / 1024:.2f} MB")

example.pdf [size]: 1.72 MB

接下来,我们以第一页的图片为例。get_image_info函数用于获取图片的信息,得到图像的尺寸信息,由于图像为彩色三通道,按像素矩阵保存的话需要24.80 MB的内存(1个通道值占1byte)。

page0 = doc.load_page(0)
image_list = page0.get_images()
xref0 = image_list[0][0]
img_info = page0.get_image_info(xrefs=xref0)[0]
print(f"img_array [size]: {(img_info['width'] * img_info['height'] * 3) / 1024 / 1024:.2f} MB")

img_array [size]: 24.80 MB

为了后续复用需要,我们定义函数print_size用于打印变量字节数。这里我们使用两种方法提取PDF页面内的图片,这两者方法的功能一样,但后者在速度和内层占用上都具有优势,这在官方文档中提及2。我们肯定是选用后者,这里只是对比一下。

print_size = lambda n, p: print(f"{n} [size]: {sys.getsizeof(p) / 1024 / 1024:.2f} MB")pix = pymupdf.Pixmap(doc, xref0)  # create a Pixmap
if pix.n - pix.alpha > 3:  # CMYK: convert to RGB firstpix = pymupdf.Pixmap(pymupdf.csRGB, pix)
print_size('Pixmap(doc, xref0)', pix.tobytes())imgdict = doc.extract_image(xref0)
imgdata = imgdict["image"]  # image data
print_size('imgdata(extract_image)', imgdata)

Pixmap(doc, xref0) [size]: 2.37 MB

imgdata(extract_image) [size]: 0.84 MB

我们发现extract_image函数提取出来的图像内存占用仅为0.84 MB,与我们计算的24.80 MB小得多,这是因为imgdata存储的是图像压缩后的字节信息,而不是原图像矩阵,图像压缩技术在存储上具备优势,不同的压缩格式所占用的内存大小也不同。页面图片原始的压缩标准可以通过imgdict["ext"]获取,示例中是jpeg格式(相较其他常见格式,该格式占用内存最小)。关于图片存储格式详情参见3

因为图像处理需要PIL(或OpenCV等),我们需要将提取到的图像数据转换为图像处理库支持的格式。

pil_imgdata = Image.open(io.BytesIO(imgdata))
print_size('pil_imgdata', pil_imgdata.tobytes())

pil_imgdata [size]: 24.80 MB

通过打印的内存大小我们可以得知,PIL.Image(24.80 MB)和之前计算的图像矩阵(24.80 MB)内存大小相同,猜测是因为PIL将压缩图像复原为矩阵了,方便后续的图像处理。pymupdf.Pixmap(2.37 MB)图像对象的内存占用大小比图像矩阵(24.80 MB)小,但是比imgdata(0.84 MB)大,通过调试,初步分析是因为imgdata为压缩后的字节串,而Pixmap为类对象,可能包含其他额外数据。无法直接对Pixmap对象进行图像处理操作,可能是因为其图像数据仍然是压缩格式?不知道。

图像处理后,需要替换掉原PDF中的图像,在这之前需要将PIL.Image转换为压缩格式字节流,方便放入PDF文件中。调用save函数,其中format参数是压缩标准,我们就使用原PDF中的jpeg;quality参数是压缩质量,取100会比原图像占用内存更大,取95占用内存更小(图像压缩效果再可接受范围内,以小内存为优);progressive参数是保存渐进式jpeg(该格式相比默认格式内存更小,选它);dpi参数设置越大,图像内存越大,我们和原图像dpi取值一致。

bio = io.BytesIO()
pil_imgdata.save(bio, format=imgdict["ext"], quality=95, progressive=True, dpi=(imgdict['xres'], imgdict['yres']))
print_size('pil_imgdata_save', bio)

72, 72

pil_imgdata_save [size]: 0.63 MB

很好,处理插入PDF的图像内存(0.63 MB)甚至比提取出的图像内存(0.84 MB)更小!可能是因为压缩(quality=95)的原因。

接下来的步骤是用处理后的图像替换原页面图像,采用之前文章中的方法(replace_image),该示例的完整代码如下

import io
import os
import pymupdf
from PIL import Imagedoc = pymupdf.open("example.pdf")  # open a document
print(f"example.pdf [size]: {os.path.getsize('example.pdf') / 1024 / 1024:.2f} MB")for page_index in range(len(doc)):  # iterate over pdf pagespage = doc[page_index]  # get the pageimage_list = page.get_images()print(f"Find {len(image_list)} images on page {page_index}")for image_index, img in enumerate(image_list, start=1):  # enumerate the image listxref = img[0]  # get the XREF of the imageimg_info = page.get_image_info(xrefs=xref)[0]imgdict = doc.extract_image(xref)imgdata = imgdict["image"]  # image datapil_imgdata = Image.open(io.BytesIO(imgdata))# TODO:图像处理操作pix_imgdata = pymupdf.Pixmap(imgdata)bio = io.BytesIO()pil_imgdata.save(bio, format=imgdict["ext"], quality=95, progressive=True,dpi=(pix_imgdata.xres, pix_imgdata.yres))# 页面图像替换page.replace_image(xref, stream=bio)print(f"Processed {image_index} images on page {page_index}")# 保存PDF
doc.save('output.pdf')
doc.close()
print(f"output.pdf [size]: {os.path.getsize('output.pdf') / 1024 / 1024:.2f} MB")

example.pdf [size]: 1.72 MB
Find 1 images on page 0
Processed 1 images on page 0
Find 1 images on page 1
Processed 1 images on page 1
output.pdf [size]: 2.64 MB

可以看到,输出PDF比原PDF更大了,这不行。

image-20250713123732879

后来发现这是个坑啊,官方文档中的描述如上,为了证实我的猜想,写个测试脚本

import pymupdfdoc = pymupdf.open("output.pdf")  # open a documentfor page_index in range(len(doc)):  # iterate over pdf pagespage = doc[page_index]  # get the pageimage_list = page.get_images()print(f"Find {len(image_list)} images on page {page_index}")for image_index, img in enumerate(image_list, start=1):  # enumerate the image listxref = img[0]  # get the XREF of the imageimg_info = page.get_image_info(xrefs=xref)[0]imgdict = doc.extract_image(xref)imgdata = imgdict["image"]  # image datapix_imgdata = pymupdf.Pixmap(imgdata)print_size("imgdata", imgdata)

Find 2 images on page 0
imgdata [size]: 0.63 MB
imgdata [size]: 0.63 MB
Find 2 images on page 1
imgdata [size]: 0.68 MB
imgdata [size]: 0.68 MB

我还以为是将新图片从内存上替换原图片呢,没想到逻辑是把新图像放到原图像显示的位置,原图像不显示,但数据仍在页面中,占着内存呢!

经翻阅文档函数,我尝试先将原图像删除,再插入新的图像,也就是把原来的page.replace_image(xref, stream=bio)替换为

page.delete_image(xref)
page.insert_image(rect=img_info['bbox'], stream=bio)

example.pdf [size]: 1.72 MB
Find 1 images on page 0
Processed 1 images on page 0
Find 1 images on page 1
Processed 1 images on page 1
output.pdf [size]: 1.33 MB

继续查看页面图像组成

Find 3 images on page 0
imgdata [size]: 0.00 MB
imgdata [size]: 0.00 MB
imgdata [size]: 0.63 MB
Find 3 images on page 1
imgdata [size]: 0.00 MB
imgdata [size]: 0.00 MB
imgdata [size]: 0.68 MB

发现每页变成三张图像了,只不过除了新插入的图像外,其他两张都是小的透明Pixmap("虚拟"图像),占用内存可忽略不计。

对于强迫症来说受不了,于是翻阅文档,发现可以在保存时执行垃圾回收和清理,如下图所示

image-20250713132042319

经尝试,发现只要在保存时设置doc.save('output.pdf', garbage=2, clean=True)即可。同时,也解决了使用替换页面图片page.replace_image(xref, stream=bio)带来的内存增大问题。测试结果如下:

example.pdf [size]: 1.72 MB
Find 1 images on page 0
Processed 1 images on page 0
Find 1 images on page 1
Processed 1 images on page 1
output.pdf [size]: 1.32 MB

Find 1 images on page 0
imgdata [size]: 0.63 MB
Find 1 images on page 1
imgdata [size]: 0.68 MB

以上便是我解决这一问题的思路。

2 完整代码与测试效果

示例最终完整代码如下:

import io
import os
import pymupdf
from PIL import Imagedoc = pymupdf.open("example.pdf")  # open a document
print(f"example.pdf [size]: {os.path.getsize('example.pdf') / 1024 / 1024:.2f} MB")for page_index in range(len(doc)):  # iterate over pdf pagespage = doc[page_index]  # get the pageimage_list = page.get_images()print(f"Find {len(image_list)} images on page {page_index}")for image_index, img in enumerate(image_list, start=1):  # enumerate the image listxref = img[0]  # get the XREF of the imageimgdict = doc.extract_image(xref)imgdata = imgdict["image"]  # image datapil_imgdata = Image.open(io.BytesIO(imgdata))# TODO:图像处理操作bio = io.BytesIO()pil_imgdata.save(bio, format=imgdict["ext"], quality=95, progressive=True,dpi=(imgdict['xres'], imgdict['yres']))page.replace_image(xref, stream=bio)print(f"Processed {image_index} images on page {page_index}")# 保存PDF
doc.save('output.pdf', garbage=2, clean=True)
doc.close()
print(f"output.pdf [size]: {os.path.getsize('output.pdf') / 1024 / 1024:.2f} MB")

对前两篇文章的方法进行优化,结果如下:

  • 文章1中示例

    example.pdf [size]: 48.48 MB
    Processing: 100%|████████████████████████████████████████████████| 55/55 [04:11<00:00, 4.57s/ Page]

    PDF处理完成!输出文件: output.pdf
    output.pdf [size]: 69.04 MB

  • 文章2中示例

    image-20250713183423968

参考


  1. 关于名称fitz的说明 - PyMuPDF 1.26.0 文档 ↩︎

  2. extract_image函数说明 - PyMuPDF 1.26.0 文档 ↩︎

  3. JPEG 图片存储格式与元数据解析 ↩︎

http://www.dtcms.com/wzjs/240433.html

相关文章:

  • 怎样做网站ppt培训机构连锁加盟
  • 做装修的网站篮网目前排名
  • 网站建设 选择题小程序模板
  • 徐汇网站设计软文批发网
  • 苏州门户网站有哪些seo赚钱方式
  • 东莞整合网站建设公司在线seo优化
  • 网络直播网站建设龙岗seo优化
  • 做网站用ui好还是ps北京seo业务员
  • 做网站怎么不被找到世界杯32强排名
  • 网站已过期怎么办理qq群引流推广平台免费
  • 做网站能收多少广告费百度网址导航
  • cdn接入wordpress出错上海网络seo
  • wordpress 优化 插件南宁seo推广外包
  • 网站域名费用怎么做分录百度指数峰值查询
  • 滨州内做网站的公司邯郸百度推广公司
  • 织梦的网站数据还原怎么做制作网站需要什么技术
  • ps网站CAD做PS地砖贴图网络营销的基本方法
  • 互联网网站基础济南seo网站排名优化工具
  • anker 网站建设网盟推广平台
  • 莱芜金点子招聘网最新招聘福州seo推广服务
  • 经济与政府网站建设建网站需要多少钱
  • 成都网站建设小公司企业互联网推广
  • 交互设计师主要是做什么的呢网络优化工作应该怎么做
  • 番禺网站 建设信科网络什么网站都能打开的浏览器
  • 淘宝网站建设的主要工作河北网站建设制作
  • 广东一站式网站建设推荐推广普通话的宣传内容
  • 做seo时网站发文目的在线seo推广软件
  • PHP网站开发案例12源代码网络推广营销
  • 做赌石网站客服的经验百度搜索排名怎么收费
  • 网站制作合作协议百度品牌广告收费标准