通过分离有色和无色pdf页面减少打印费
前言
该工具是我认识的一位中科大的大佬在本科毕业的时候做的一个小工具,去打印店打印全彩的毕业论文的话会比较贵,他想到有没有一种方案可以实现有彩色页面的pdf和没有彩色页面的pdf分开打印,前者打印彩色,后者打印黑白,这样做的话可以节约很多打印彩色pdf页面的钱,然后这位大佬就做了这样一个小工具,省了一笔打印费,代码和原文链接在文末,我这里介绍下其大致的代码逻辑
1. is_color_image 函数
功能: 检查给定图像是否为彩色图像。
逻辑:
- 将图像转换为 RGB 模式。
- 将图像转换为 NumPy 数组,并归一化像素值到
[0,1]范围。 - 计算每个像素的最大和最小 RGB 值。
- 计算每个像素的饱和度 (saturation)。
- 统计饱和度大于阈值 (
saturation_threshold) 的像素占总像素的比例 (color_fraction)。 - 如果
color_fraction大于设定的阈值 (color_fraction_threshold),则认为图像是彩色的。
def is_color_image(image, saturation_threshold=0.35, color_fraction_threshold=0.001):image = image.convert('RGB')pixels = np.array(image) / 255.0max_rgb = np.max(pixels, axis=2)min_rgb = np.min(pixels, axis=2)delta = max_rgb - min_rgbsaturation = delta / (max_rgb + 1e-7) # 防止除以零color_pixels = saturation > saturation_thresholdcolor_fraction = np.mean(color_pixels)return color_fraction > color_fraction_threshold
2. is_color_page 函数
功能: 检查 PDF 页面是否为彩色页面。
逻辑:
- 将页面渲染为 pixmap 对象。
- 将 pixmap 转换为 PNG 格式的字节数据。
- 使用 PIL 库将字节数据转换为图像对象。
- 调用
is_color_image函数检查图像是否为彩色图像。
def is_color_page(page):pix = page.get_pixmap()img = pix.tobytes("png")from PIL import Imagefrom io import BytesIOimage = Image.open(BytesIO(img))return is_color_image(image)
3. split_pdf 函数
功能: 将输入的 PDF 分割为彩色页面和黑白页面两个 PDF。
逻辑:
- 打开输入 PDF。
- 创建新的 PDF 对象来保存彩色页面和黑白页面。
- 遍历输入 PDF 的每一页,检查页面是否为彩色页面。
- 如果设置了双面打印 (
is_double_sized_printing),确保彩色页面的前后页也包括在内。 - 将彩色页面和黑白页面分别插入到新的 PDF 对象中。
- 保存新的彩色和黑白 PDF。
- 关闭所有文档对象。
def split_pdf(input_pdf_path, output_color_pdf_path, output_bw_pdf_path, is_double_sized_printing):doc = fitz.open(input_pdf_path)color_doc = fitz.open()bw_doc = fitz.open()color_pages = []bw_pages = []for page_num in tqdm(range(len(doc))):page = doc.load_page(page_num)if is_color_page(page):color_pages.append(page_num)if is_double_sized_printing:for page_num in color_pages:if page_num % 2 == 0 and page_num + 1 not in color_pages and page_num + 1 < len(doc):color_pages.append(page_num + 1)if page_num % 2 == 1 and page_num - 1 not in color_pages and page_num - 1 > 0:color_pages.append(page_num - 1)for page_num in range(len(doc)):if page_num not in color_pages:bw_pages.append(page_num)for page_num in sorted(color_pages):color_doc.insert_pdf(doc, from_page=page_num, to_page=page_num)for page_num in sorted(bw_pages):bw_doc.insert_pdf(doc, from_page=page_num, to_page=page_num)color_doc.save(output_color_pdf_path)bw_doc.save(output_bw_pdf_path)doc.close()color_doc.close()bw_doc.close()
主程序部分
功能: 定义输入、输出文件路径和是否双面打印的参数,并调用 split_pdf 函数。
if __name__ == '__main__':INPUT_PDF_PATH = '1.pdf'OUTPUT_COLOR_PDF_PATH = 'color_pages.pdf'OUTPUT_BW_PDF_PATH = 'bw_pages.pdf'IS_DOUBLE_SIZED_PRINTING = Truesplit_pdf(INPUT_PDF_PATH, OUTPUT_COLOR_PDF_PATH, OUTPUT_BW_PDF_PATH, IS_DOUBLE_SIZED_PRINTING)
完整代码
import pymupdf as fitz
import numpy as np
from tqdm import tqdmdef is_color_image(image, saturation_threshold=0.35, color_fraction_threshold=0.001):image = image.convert('RGB')pixels = np.array(image) / 255.0 # 归一化像素值到[0,1]范围# 将RGB转换为HSVmax_rgb = np.max(pixels, axis=2)min_rgb = np.min(pixels, axis=2)delta = max_rgb - min_rgb# 饱和度saturation = delta / (max_rgb + 1e-7) # 防止除以零# 判断饱和度大于阈值的彩色像素color_pixels = saturation > saturation_thresholdcolor_fraction = np.mean(color_pixels)return color_fraction > color_fraction_thresholddef is_color_page(page):"""Check if a page is a color page."""# Render page to a pixmappix = page.get_pixmap()# Convert pixmap to an imageimg = pix.tobytes("png")# Create an image object using PILfrom PIL import Imagefrom io import BytesIOimage = Image.open(BytesIO(img))return is_color_image(image)def split_pdf(input_pdf_path, output_color_pdf_path, output_bw_pdf_path, is_double_sized_printing):# Open the input PDFdoc = fitz.open(input_pdf_path)# Create new PDFs for color and black & white pagescolor_doc = fitz.open()bw_doc = fitz.open()# Save color and bw pages numbercolor_pages = []bw_pages = []# Iterate over each page in the input PDFfor page_num in tqdm(range(len(doc))):page = doc.load_page(page_num)# Check if the page is a color pageif is_color_page(page):color_pages.append(page_num)# Handle double sized printingif is_double_sized_printing:for page_num in color_pages:if page_num % 2 == 0 and page_num + 1 not in color_pages and page_num + 1 < len(doc):color_pages.append(page_num + 1)if page_num % 2 == 1 and page_num - 1 not in color_pages and page_num - 1 > 0:color_pages.append(page_num - 1)# Insert BW Pagesfor page_num in range(len(doc)):if page_num not in color_pages:bw_pages.append(page_num)# Insert PDF pagesfor page_num in sorted(color_pages):color_doc.insert_pdf(doc, from_page=page_num, to_page=page_num)for page_num in sorted(bw_pages):bw_doc.insert_pdf(doc, from_page=page_num, to_page=page_num)# Save the new PDFscolor_doc.save(output_color_pdf_path)bw_doc.save(output_bw_pdf_path)# Close all documentsdoc.close()color_doc.close()bw_doc.close()if __name__ == '__main__':INPUT_PDF_PATH = '1.pdf' # 待转换的PDF路径OUTPUT_COLOR_PDF_PATH = 'color_pages.pdf' # 彩色部分PDF输出路径OUTPUT_BW_PDF_PATH = 'bw_pages.pdf' # 黑白部分PDF输出路径IS_DOUBLE_SIZED_PRINTING = True # 是否双面打印split_pdf(INPUT_PDF_PATH, OUTPUT_COLOR_PDF_PATH, OUTPUT_BW_PDF_PATH, IS_DOUBLE_SIZED_PRINTING)
原文链接:http://t.csdnimg.cn/VY0dE
代码链接:https://github.com/RicePasteM/Color-BW-Separator-for-PDF.git
相关文章:
通过分离有色和无色pdf页面减少打印费
前言 该工具是我认识的一位中科大的大佬在本科毕业的时候做的一个小工具,去打印店打印全彩的毕业论文的话会比较贵,他想到有没有一种方案可以实现有彩色页面的pdf和没有彩色页面的pdf分开打印,前者打印彩色,后者打印黑白…...
c语言--指针
前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理c语言中指针的相关知识点。 指针概念 指针存储的就是数据的地址。 直观理解: 李华家是北洋路130号1单元101 用变量处理数据: 我们去李华家拿数据。 用指针处理数据: 我们去北洋路130号1单元101拿数据…...
python-九九乘法表(对齐式1)
[题目描述] 输出九九乘法表,输出格式见样例。输入格式: 无输出格式: 输出乘法表,对齐方式见样例输出。样例输入 无样例输出 来源/分类(难度系数:一星) 完整代码展示: #对齐式1 a[] …...
thinkphp单独为某个接口设置缓存
参考 官方文档 $this->request->cache(__URL__,600);只需要在接口方法的开头添加这个代码即可...
OpenCV视觉--视频人脸微笑检测(超详细,附带检测资源)
目录 概述 具体实现 1.加载分类器 2.打开摄像头并识别人脸 3.处理人脸并检测是否微笑 效果 总结 概述 OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习库,广泛应用于图像处理和视频分析等领…...
docker 搭建 AI大数据模型 --- 使用GPU
docker 搭建 AI大数据模型 — 使用GPU方式 搭建本地大模型,最简单的方法!效果直逼GPT 服务器GPU系统HP580 G8P40Rocky9.2 安装程序AnythingLLM前端界面Open WebUIChatOllamaollama 一、AnythingLLM 介绍 AnythingLLM 是 Mintplex Labs Inc. 开发的一…...
面向对象, 常用类, 集合, 异常, JDBC, mysql数据库 复习
1.面向对象 (1)面向过程和面向对象 ● 面向过程的程序设计思想 (procedure -Oriented Programming),简称POP ● 关注的焦点是过程:过程就是操作数据的步骤。如果某个过程的实现代码重复出 现,那么就可…...
js取数组最大值之Math.max、Math.max.apply
js取数组最大值之Math.max、Math.max.apply Math.maxMath.max.applyapply()第一个参数为什么可以是null 最小值同理 Math.max Math.max(n1,n2,n3,…,nX) 支持传递多个参数,带有较大的值的那个数 Math.max(2,5,3,6,2,4,2,15,9,6,0,1)Math.max.apply apply() 语法&a…...
各种中间件的安装
文章目录 20232306mysql的wondows安装 2023 2306 mysql的wondows安装 常用mysql教程 springboot整合druid连接池SpringBoot配置Druid连接池 mysql的wondows安装 MySQL学习笔记 01、MySQL安装 这个是安装的具体思路 win10 安装 mysql 5.7 msi版的教程图文详解 这个是安装的…...
【Mysql】多表查询、隐式内链接、显式内连接、左外连接、右外连接
多表查询 什么是多表查询 •DQL: 查询多张表,获取到需要的数据 •比如 我们要查询家电分类下 都有哪些商品,那么我们就需要查询分类与商品这两张表 数据准备 创建db3_2 数据库 -- 创建 db3_2 数据库,指定编码 CREATE DATABASE db3_2 CHARACTER SET utf8;创建分类表与商品表 …...
Linux驱动开发(三)--新字符设备驱动开发 LED驱动开发升级
1、新字符设备驱动原理 使用 register_chrdev 函数注册字符设备的时候只需要给定一个主设备号即可,但是这样会 带来两个问题 需要我们事先确定好哪些主设备号没有使用 会将一个主设备号下的所有次设备号都使用掉,比如现在设置 LED 这个主设备号为200&…...
MCU的最佳存储方案CS创世 SD NAND
大家都知道MCU是一种"麻雀"虽小,却"五脏俱全"的主控。它的应用领域非常广泛,小到手机手表,大到航空航天的设备上都会用到MCU.市面上目前几个主流厂商有意法半导体(其中最经典的一款就是STM32系列)…...
40岁学习java是否需要报班学习?
在开始前刚好我有一些资料,是我根据网友给的问题精心整理了一份「java的资料从专业入门到高级教程」, 点个关注在评论区回复“666”之后私信回复“666”,全部无偿共享给大家!!!应该不需要。各种公开免费的…...
Vitis Accelerated Libraries 学习笔记--OpenCV 运行测试
目录 1. 简介 2. 实例测试 2.1 实例介绍 2.2 创建工程 2.2.1 创建工程 2.2.2 获取路径 2.2.3 设置路径 2.2.4 打开工程 2.2.5 添加文件 2.2.6 启动 GUI 2.2.7 配置 csim 参数 3 常见错误 3.1 核心共享库报错 4. 总结 1. 简介 在《Vitis Accelerated Libraries …...
加固三防平板如何提高轨道交通系统的运营效率?
在当今快节奏的社会中,轨道交通系统作为城市交通的重要组成部分,其运营效率的提升对于缓解交通拥堵、满足人们的出行需求以及促进城市的发展具有至关重要的意义。而加固三防平板作为一种先进的技术设备,正逐渐在轨道交通领域发挥着关键作用&a…...
Django 靓号管理系统:实现登录功能
本文将详细介绍如何在 Django 靓号管理系统中实现登录功能,包括用户认证、验证码生成、以及中间件的使用。我们将逐步展示所有相关代码,并附带详细注释。 1. 项目结构 首先,让我们看一下项目的基本结构: number ├── manage.py ├── monaco.ttf ├── number │ …...
【Solr 学习笔记】Solr 源码启动教程
Solr 源码启动教程 本教程记录了如何通过 IDEA 启动并调试 Solr 源码,从 Solr9 开始 Solr 项目已由 ant 方式改成了 gradle 构建方式,本教程将以 Solr 9 为例进行演示,IDE 选择使用 IntelliJ IDEA。 Solr github 地址:https://gi…...
Java中的事件驱动编程模型
Java中的事件驱动编程模型 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我将为大家介绍Java中的事件驱动编程模型。事件驱动编程模型是一种以事件为核心驱…...
Python 语法基础一
1.变量 python 中变量很简单,不需要指定数据类型,直接使用等号定义就好。python变量里面存的是内存地址,也就是这个值存在内存里面的哪个地方,如果再把这个变量赋值给另一个变量,新的变量通过之前那个变量知道那个变量…...
从零开始:Spring Boot 中使用 Drools 规则引擎的完整指南
规则引擎作用 规则引擎主要用于将业务逻辑从应用程序代码中分离出来,提高系统的灵活性和可维护性。规则引擎通过预定义的规则来处理输入数据并做出相应的决策,从而实现业务逻辑的自动化和动态调整。 例如 门店信息校验:美团点评在门店信息…...
别再踩坑了!Windows 10下Mamba-SSM 2.2.2 + CUDA 12.4保姆级安装指南(附已修复依赖包)
Windows 10下Mamba-SSM 2.2.2与CUDA 12.4终极配置指南 在深度学习领域,Mamba-SSM因其高效的状态空间模型架构而备受关注。然而,对于Windows用户而言,配置一个可用的Mamba-SSM环境往往是一场噩梦。本文将带你一步步避开所有陷阱,完…...
8个Illustrator自动化脚本解决方案,彻底改变设计师工作流程
8个Illustrator自动化脚本解决方案,彻底改变设计师工作流程 【免费下载链接】illustrator-scripts Adobe Illustrator scripts 项目地址: https://gitcode.com/gh_mirrors/il/illustrator-scripts illustrator-scripts项目提供了一套专业的Adobe Illustrator…...
Fish Speech-1.5多语种支持实战:阿拉伯语右向文本语音生成注意事项
Fish Speech-1.5多语种支持实战:阿拉伯语右向文本语音生成注意事项 1. 引言 语音合成技术正在改变我们与数字世界的交互方式,而多语言支持更是让这项技术真正走向全球化。Fish Speech-1.5作为一款强大的文本转语音模型,支持包括阿拉伯语在内…...
效率倍增:用快马平台智能优化你的openclaw更新工作流
最近在折腾openclaw的更新命令时,发现每次手动输入各种参数和检查依赖实在太费时间了。经过一番摸索,我发现用InsCode(快马)平台可以大幅优化这个流程,今天就把我的经验分享给大家。 智能参数补全 以前最头疼的就是记不住各种参数组合&#x…...
ReadMe.md
一、先告诉你:这个项目是干嘛的? 这是一套网页自动化 E2E 测试框架用来自动打开浏览器 → 自动点页面 → 自动校验功能是否正常 二、最关键:你必须先做的 1 件事(否则跑不起来) 在项目根目录创建 .env 文件 项目根目录…...
Git-RSCLIP与YOLOv8结合:遥感图像目标检测实战指南
Git-RSCLIP与YOLOv8结合:遥感图像目标检测实战指南 遥感图像目标检测一直是地理信息系统和城市规划领域的重要技术需求。传统的检测方法在面对复杂多变的遥感场景时,往往表现不佳,特别是在处理不同尺度、不同角度的目标时存在明显局限性。 …...
从L298到自举H桥:深入聊聊直流电机驱动方案的演进与选型心得
从L298到自举H桥:直流电机驱动方案的技术演进与工程实践 在机器人底盘、自动化产线和智能硬件开发中,直流电机驱动电路的设计往往决定着整个系统的性能天花板。十年前我们可能还在用L298这类经典驱动芯片,如今工程师们的工具箱里已经出现了IR…...
SJA1105Q升级踩坑记:RGMII V2.0时序下,33Ω串阻为何成了千兆通信的‘隐形杀手’?
SJA1105Q升级中的RGMII V2.0时序陷阱:33Ω串阻如何摧毁千兆通信稳定性 当NXP SJA1105Q这款号称"增强版"的工业交换机芯片落到我们硬件工程师手中时,谁曾想PCB上那些看似无害的33Ω小电阻,竟会成为千兆通信系统的阿喀琉斯之踵。这不…...
Phi-3-mini-128k-instruct实战案例:中小企业技术文档自动解析与结构化提取
Phi-3-mini-128k-instruct实战案例:中小企业技术文档自动解析与结构化提取 1. 项目背景与价值 对于中小企业而言,技术文档管理一直是个令人头疼的问题。工程师们经常需要从大量PDF、Word文档中提取关键信息,手动整理成结构化数据。这个过程…...
精准匹配歌词:Foobar2000歌词插件配置完全指南
精准匹配歌词:Foobar2000歌词插件配置完全指南 【免费下载链接】ESLyric-LyricsSource Advanced lyrics source for ESLyric in foobar2000 项目地址: https://gitcode.com/gh_mirrors/es/ESLyric-LyricsSource 3分钟完成版本适配检测 如何确定你的Foobar20…...
