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

通过分离有色和无色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页面减少打印费

前言 该工具是我认识的一位中科大的大佬在本科毕业的时候做的一个小工具&#xff0c;去打印店打印全彩的毕业论文的话会比较贵&#xff0c;他想到有没有一种方案可以实现有彩色页面的pdf和没有彩色页面的pdf分开打印&#xff0c;前者打印彩色&#xff0c;后者打印黑白&#xf…...

c语言--指针

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理c语言中指针的相关知识点。 指针概念 指针存储的就是数据的地址。 直观理解: 李华家是北洋路130号1单元101 用变量处理数据: 我们去李华家拿数据。 用指针处理数据: 我们去北洋路130号1单元101拿数据…...

python-九九乘法表(对齐式1)

[题目描述] 输出九九乘法表&#xff0c;输出格式见样例。输入格式&#xff1a; 无输出格式&#xff1a; 输出乘法表&#xff0c;对齐方式见样例输出。样例输入 无样例输出 来源/分类&#xff08;难度系数&#xff1a;一星&#xff09; 完整代码展示&#xff1a; #对齐式1 a[] …...

thinkphp单独为某个接口设置缓存

参考 官方文档 $this->request->cache(__URL__,600);只需要在接口方法的开头添加这个代码即可...

OpenCV视觉--视频人脸微笑检测(超详细,附带检测资源)

目录 概述 具体实现 1.加载分类器 2.打开摄像头并识别人脸 3.处理人脸并检测是否微笑 效果 总结 概述 OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉和机器学习库&#xff0c;广泛应用于图像处理和视频分析等领…...

docker 搭建 AI大数据模型 --- 使用GPU

docker 搭建 AI大数据模型 — 使用GPU方式 搭建本地大模型&#xff0c;最简单的方法&#xff01;效果直逼GPT 服务器GPU系统HP580 G8P40Rocky9.2 安装程序AnythingLLM前端界面Open WebUIChatOllamaollama 一、AnythingLLM 介绍 AnythingLLM 是 Mintplex Labs Inc. 开发的一…...

面向对象, 常用类, 集合, 异常, JDBC, mysql数据库 复习

1.面向对象 &#xff08;1&#xff09;面向过程和面向对象 ● 面向过程的程序设计思想 &#xff08;procedure -Oriented Programming)&#xff0c;简称POP ● 关注的焦点是过程&#xff1a;过程就是操作数据的步骤。如果某个过程的实现代码重复出 现&#xff0c;那么就可…...

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) 支持传递多个参数&#xff0c;带有较大的值的那个数 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 函数注册字符设备的时候只需要给定一个主设备号即可&#xff0c;但是这样会 带来两个问题 需要我们事先确定好哪些主设备号没有使用 会将一个主设备号下的所有次设备号都使用掉&#xff0c;比如现在设置 LED 这个主设备号为200&…...

MCU的最佳存储方案CS创世 SD NAND

大家都知道MCU是一种"麻雀"虽小&#xff0c;却"五脏俱全"的主控。它的应用领域非常广泛&#xff0c;小到手机手表&#xff0c;大到航空航天的设备上都会用到MCU.市面上目前几个主流厂商有意法半导体&#xff08;其中最经典的一款就是STM32系列&#xff09;…...

40岁学习java是否需要报班学习?

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「java的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“666”之后私信回复“666”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;应该不需要。各种公开免费的…...

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 …...

加固三防平板如何提高轨道交通系统的运营效率?

在当今快节奏的社会中&#xff0c;轨道交通系统作为城市交通的重要组成部分&#xff0c;其运营效率的提升对于缓解交通拥堵、满足人们的出行需求以及促进城市的发展具有至关重要的意义。而加固三防平板作为一种先进的技术设备&#xff0c;正逐渐在轨道交通领域发挥着关键作用&a…...

Django 靓号管理系统:实现登录功能

本文将详细介绍如何在 Django 靓号管理系统中实现登录功能,包括用户认证、验证码生成、以及中间件的使用。我们将逐步展示所有相关代码,并附带详细注释。 1. 项目结构 首先,让我们看一下项目的基本结构: number ├── manage.py ├── monaco.ttf ├── number │ …...

【Solr 学习笔记】Solr 源码启动教程

Solr 源码启动教程 本教程记录了如何通过 IDEA 启动并调试 Solr 源码&#xff0c;从 Solr9 开始 Solr 项目已由 ant 方式改成了 gradle 构建方式&#xff0c;本教程将以 Solr 9 为例进行演示&#xff0c;IDE 选择使用 IntelliJ IDEA。 Solr github 地址&#xff1a;https://gi…...

Java中的事件驱动编程模型

Java中的事件驱动编程模型 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我将为大家介绍Java中的事件驱动编程模型。事件驱动编程模型是一种以事件为核心驱…...

Python 语法基础一

1.变量 python 中变量很简单&#xff0c;不需要指定数据类型&#xff0c;直接使用等号定义就好。python变量里面存的是内存地址&#xff0c;也就是这个值存在内存里面的哪个地方&#xff0c;如果再把这个变量赋值给另一个变量&#xff0c;新的变量通过之前那个变量知道那个变量…...

从零开始:Spring Boot 中使用 Drools 规则引擎的完整指南

规则引擎作用 规则引擎主要用于将业务逻辑从应用程序代码中分离出来&#xff0c;提高系统的灵活性和可维护性。规则引擎通过预定义的规则来处理输入数据并做出相应的决策&#xff0c;从而实现业务逻辑的自动化和动态调整。 例如 门店信息校验&#xff1a;美团点评在门店信息…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...

Ubuntu系统复制(U盘-电脑硬盘)

所需环境 电脑自带硬盘&#xff1a;1块 (1T) U盘1&#xff1a;Ubuntu系统引导盘&#xff08;用于“U盘2”复制到“电脑自带硬盘”&#xff09; U盘2&#xff1a;Ubuntu系统盘&#xff08;1T&#xff0c;用于被复制&#xff09; &#xff01;&#xff01;&#xff01;建议“电脑…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...

0x-3-Oracle 23 ai-sqlcl 25.1 集成安装-配置和优化

是不是受够了安装了oracle database之后sqlplus的简陋&#xff0c;无法删除无法上下翻页的苦恼。 可以安装readline和rlwrap插件的话&#xff0c;配置.bahs_profile后也能解决上下翻页这些&#xff0c;但是很多生产环境无法安装rpm包。 oracle提供了sqlcl免费许可&#xff0c…...