Comments (11)
就现状来看,请问我如何单独检测判断这种情况(每一个字是否有与字体相同颜色的描边),我应当使用什么技术方法,希望可以得到您的指点。
我也没有这个问题的通用解决方案,因为真实情况非常复杂,而且涉及很多PDF规范的基本知识。下面的分析过程,希望对你有所启发。开始之前,铺垫几点基础:
-
一个PDF文件可以类比一个为网页,通过源码格式可以看到背后的脚本。PDF规范(1.7版有1300多页)严格定义了如何渲染PDF页面,即你所看到的样式。
-
不同于标记语言,PDF通常用关键字表示内容,例如
x y l
表示从当前点连一条线到(x,y)
,x y w h re
表示以左下角(x,y)
为顶点画一个宽w
高h
的矩形 -
关于文字的定义在规范的第五章,关键点
- 文本包围在一组
BT
和ET
中 Tj
显示文本内容例如some text Tj
Tr
表示渲染模式,其中2 Tr
表示填充+描边模式,也就是我们关心的模拟加粗效果Td
、Tm
定义了文本的位置,以左下角点为参考
- 文本包围在一组
删除你的测试文件中多余部分,仅留下下图部分便于分析
借助PyMuPDF
库,读取PDF源码
import fitz
>>> doc = fitz.open('testfile.pdf')
>>> c = doc[0].getContents() # cross reference list in page 1
>>> c
[12]
>>> source = doc.xref_stream(12)
>>> for line in source.split(b'\n'): print(line)
b'/P<</MCID 27>> BDC'
b'q'
b'0 0 595.32 841.92 re W* n'
b'BT'
b'0 g 0 G .686 w 2 Tr/F0 24 Tf 116.9 589.66 Td'
b'<32C7> Tj'
b'ET'
b'Q'
b'EMC'
b'/P<</MCID 28>> BDC'
b'q'
b'0 0 595.32 841.92 re W* n'
b'BT'
b'0 g 0 G .686 w 2 Tr/F0 24 Tf 141.02 589.66 Td'
b'<32C7> Tj'
b'ET'
b'Q'
b'EMC'
b'/P<</MCID 29>> BDC'
b'q'
b'0 0 595.32 841.92 re W* n'
b'BT'
b'0 g 0 G .686 w 2 Tr/F0 24 Tf 165.14 589.66 Td'
b'<32C7> Tj'
b'ET'
b'Q'
b'EMC'
b'/P<</MCID 44>> BDC'
b'q'
b'0 0 595.32 841.92 re W* n'
b'BT'
b'0 g/F0 24 Tf 117.62 527.23 Td'
b'<34F634F634F6> Tj'
b'ET'
b'Q'
b'EMC'
b''
找出BT
、ET
之间的部分,一共4组,以第一组为例
b'BT'
b'0 g 0 G .686 w 2 Tr/F0 24 Tf 141.02 589.66 Td'
b'<32C7> Tj'
b'ET'
0 g 0 G
表示描边色和填充色都是黑色.686 w
描边粗细为0.686pt,也就是一开始我用PDF编辑器截图中的border width=0.7pt
2 Tr
渲染模式=2,即填充+描边24 Tf
字号24141.02 589.66 Td
左下角点坐标<32C7> Tj
文字内容
通过BT
和ET
,以及2 Tr
可以筛选出我们准备处理的模拟加粗的文本,但是光文本还不能唯一确定,还需要知道位置。注意PDF规范以页面左下角点为原点,而PyMUPDF
的原点在左上角,我们将PDF的(141.02 589.66)
转到PyMuPDF
坐标系得到(141.02, 252.34)
>>> doc[0].rect
Rect(0.0, 0.0, 595.3200073242188, 841.9199829101562) # 页面高度842
>>> y = 842-589.66
>>> y
252.34000000000003
以上得到了(141.02, 252.34)
位置处的文字需要加粗,同理处理其他位置。接下来对应到PyMuPDF
提取出的文本中去
>>> doc[0].getText('dict')
{
'width': 595.3200073242188,
'height': 841.9199829101562,
'blocks': [{
'number': 0,
'type': 0,
'bbox': (116.9000015258789, 231.635009765625, 189.13999938964844, 255.635009765625),
'lines': [{'
spans': [{
'size': 24.0,
'flags': 4,
'font': 'SimSun',
'color': 0,
'ascender': 0.859375,
'descender': -0.140625,
'text': '粗粗粗',
'origin': (116.9000015258789, 252.260009765625),
'bbox': (116.9000015258789, 231.635009765625, 189.13999938964844, 255.635009765625)
}],
'wmode': 0,
'dir': (1.0, 0.0),
'bbox': (116.9000015258789, 231.635009765625, 189.13999938964844, 255.635009765625)
}]},
{
'number': 1,
....
}]
}
以上可知粗粗粗
的边框矩形为(116.90, 231.64, 189.14, 255.64)
,而先前得到的位置点(141.02, 252.34)
正好在此范围内,可知这部分需要加粗,设置flags
属性为flags+=2**4
(具体参考此处的参数说明)。
pdf2docx
的Block
对象与上述getText('dict')
的字典结构比较类似,按上述步骤更新Block
后再创建docx,可以实现对这类文本的加粗。
from pdf2docx.
很好的一个问题,多谢提供测试文件。
我用PDF编辑器查看测试文件中“加粗”的字体,发现字体属性的粗体
其实是“否”——也就是说,字体上并非粗体的宋体,只是看起来比较粗。请看右侧属性的第三行和第五行,表示加了0.7pt的黑色描边,也就是在普通宋体的基础上描了一圈,使其看起来像粗体。pdf2docx
借助第三方库PyMuPDF
提取字体属性(字体/斜体/粗体、字号、颜色等),因为其本质上并非粗体,所以出现了你遇到的问题。
from pdf2docx.
再进一步,PDF文件出现这种描边“加粗”冒充粗体的原因是什么?
原因是当初从Word或其他格式转换到PDF的电脑缺少粗体宋体
这种字体,所以转换后的PDF无法保存粗体字体信息,而是替代以描边加粗这种补救方式来保证看起来是粗体。一个小常识,为何PDF随便到哪儿打印都能保证相同的样式?以字体为例,PDF会把所有用到的字体都嵌入到PDF文件中去,这样即便打印室电脑上没安装该字体,也能正确显示和打印。而这是MS Word无法做到的,例如对于这个测试文件,原来的电脑上没有宋体-粗体
这种字体,Word文档却能模拟显示出加粗的效果。
我的电脑上安装了粗体宋体SimSun Bold
,刚好可以做个对比试验:
- Word文档中选择宋体+加粗。无论有没有安装粗体字体,Word都会显示加粗的效果。
- 另存为PDF查看字体属性。因为有粗体字体加持,此时
Bold
属性显示为True
。
from pdf2docx.
那如果已经是测试文件这个样子了(通过描边模拟粗体),pdf2docx
如何正确转换粗体?
很抱歉,通过上面的分析可知,目前无法处理这种情况,并且考虑到这个问题的实际意义和优先级,短期内也不会进行修复。但理论上,可以通过检测每一个字是否有与字体相同颜色的描边来判断是否需要额外加粗。另外,斜体也是类似的情况。
from pdf2docx.
那如果已经是测试文件这个样子了(通过描边模拟粗体),
pdf2docx
如何正确转换粗体?很抱歉,通过上面的分析可知,目前无法处理这种情况,并且考虑到这个问题的实际意义和优先级,短期内也不会进行修复。但理论上,可以通过检测每一个字是否有与字体相同颜色的描边来判断是否需要额外加粗。另外,斜体也是类似的情况。
以上分析的非常精彩。
可能由于我们所处的地域不同,习惯有所不同。实际生产使用word过程中,字体选择后,在需要加粗时会直接使用word中的bold选项,而不会单独下载XX字体-粗体
的字体。我身边所有的同事,也包括我在内编辑word时也会这样。我猜国内朋友也是这样使用的。
就现状来看,请问我如何单独检测判断这种情况(每一个字是否有与字体相同颜色的描边),我应当使用什么技术方法,希望可以得到您的指点。
from pdf2docx.
可能由于我们所处的地域不同,习惯有所不同。实际生产使用word过程中,字体选择后,在需要加粗时会直接使用word中的bold选项,而不会单独下载XX字体-粗体的字体。我身边所有的同事,也包括我在内编辑word时也会这样。我猜国内朋友也是这样使用的。
是的,作为用户都是像你这样操作的。但是MS Word在接受了你的操作后,背后设置的实际是XX字体-粗体
、XX字体-斜体
,并且恰好系统已经安装了常见字体。而一旦不存在这样的字体,就出现了这种等效粗体的情况。举个例子,看一下我们熟悉的Times New Roman
字体(C:\Windows\Fonts
),你会发现常规
、粗体
、斜体
的每种组合都对应了一种字体,而不仅仅只是Times New Roman
。
from pdf2docx.
上游库PyMuPDf
与本问题相关的两个issue:
from pdf2docx.
暂时关闭,如有问题欢迎继续探讨。
from pdf2docx.
请问这个工具叫什么名字
from pdf2docx.
一个PDF编辑器:PDF-XChange
,选择对象(文本、图片、形状)后可以显示基本属性
from pdf2docx.
非常感谢
from pdf2docx.
Related Issues (20)
- 这个项目最大的问题在于数据结构设计 HOT 4
- PDF转docx时文档中带链接的文字全部丢失 HOT 1
- pdf2docx-0.5.8版,将附件"深入浅出强化学习01.pdf"转docx后,每段首句被移到末尾了 HOT 1
- 转word速度太慢了,怎么设置只转换部分内容?比如只转换pdf中表格到word,不要页眉页脚段落,也许这样指定内容更快
- 2 tests fail
- transfer error:unsupported colorspace for '{output}' HOT 1
- [WARNING] Ignore Line "<image>" due to overlap
- 无法复原pdf文件中表格的框线 HOT 1
- How to save highlight in table after convert pdf to docx HOT 4
- Negative ref_dif in Blocks.py causing paragraph splitting
- 转化后存在页面超出的问题
- ValueError: unsupported colorspace for 'png' HOT 2
- Any support for ANDROID? HOT 1
- 转换时遇到字体名为中文(比如“宋体”)时,发生错误 HOT 1
- language support
- pdf2docx.Converter将某些特殊pdf转word时,某个子进程会卡住 HOT 3
- Table is broken when the table is displayed on 2 pages HOT 1
- 关于行高分配的逻辑疑问
- 转换docx表格中文本不全,请问这个可以解决吗
- Resource Han Rounded CN Light rendered as "Resource"
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pdf2docx.