python-pptx: 读取字体颜色

python-pptx: read font color

我想从给定的文本框中读取字体颜色。我可以提取字体名称和粗体但不能提取颜色(或字体名称)。

这是我的代码:

text_frame = shape.text_frame
paragraph = text_frame.paragraphs[0]

for run in paragraph.runs:
    font = run.font
    try:
        font_size = font.size.pt
        print(font_size)
        font_bold = font.bold
        print(font_bold)
        font_name = font.name
        print(font_name)
        color = font.color.rgb
        print(color)
    except:
        pass

returns:

36.0
True
None

谢谢

在 PowerPoint 中(在这方面与 CSS 大致相同),字体属性可以在所谓的(至少某些人认为)样式层次结构.这些的底层覆盖了上面的任何级别,将样式直接应用于特定 运行。使用 .bold.color.

等属性只能检索像这样的 直接应用的 属性

可能 是像 .effective_bold.effective_color 这样的属性,它们导航样式层次结构以计算将在渲染时应用的值,但是有还没有。

因此 font.color.rgbNone 值表示 运行 从其样式层次结构(例如段落默认值、形状default, theme, or presentation default, 等等)但不幸的是没有遍历样式层次来确定它的有效颜色设置是什么。

我也有同样的填充需求。区别不是那么大。它以类似的方式工作。简化就是把“fill.fore_color”改成“font.color”。

首先要检查给定的颜色是否是特定的(rgb 不是None)。如果是的话,你已经得到了它。如果不是,请按照主题颜色路径从那里获取 RGB 值。

srgb = font.color.rgb
if srgb == None:
    theme_color = font.color.theme_color
    brightness = font.color.brightness

现在你拥有的是theme_color和亮度。主题颜色实际上是一个数值,定义了 PowerPoint 中使用的“强调”颜色。它可以通过 MSO_THEME_COLOR 解析,通过私有字典“_member_to_xml”,您可以使用它来定义提取它所需的 xml 路径:

from pptx.enum.dml import MSO_THEME_COLOR
accent = MSO_THEME_COLOR._member_to_xml[theme_color]
xpath = 'a:themeElements/a:clrScheme/a:{}/a:srgbClr/@val'.format(accent)

要进行提取,您需要提供适当的主题信息,您可以通过从您所在的当前幻灯片使用的布局定义的 slide_master 中提取主题信息来获得这些信息。为此需要更多进口:

from pptx.opc.constants import RELATIONSHIP_TYPE as RT
from pptx.oxml import parse_xml
slide_master_part = slide.slide_layout.slide_master.part
theme_part = slide_master_part.part_related_by(RT.THEME)
theme = parse_xml(theme_part.blob)  # theme here is an <a:theme> element

现在,您终于有了找出使用的 PPT 强调色所需的一切,回到我们之前定义的 xpath,并使用我们刚刚找到的主题对其进行翻译:

hex_color = theme.xpath(xpath)[0]

如果没有亮度(亮度为零),您的 hex_color 不仅定义了使用的重音,还定义了真正的 RGB 颜色。这是使用您想要的任何方法从十六进制颜色值中提取的。例如图像颜色:

from PIL import ImageColor
import numpy as np
srgb = np.array(ImageColor.getcolor('#{}'.format(hex_color), 'RGB'))

但是,如果亮度(我们在开始时找到主题颜色时发现的亮度)不为零,我们还有更多工作要做。然后,真实颜色比由亮度值定义的强调色更暗或更亮。获得真正的 RGB 所需的额外步骤需要使用该亮度进行调整。以与 PowerPoint 中类似的方式使颜色更亮需要转换为 HSL。然后改变亮度,再转换回RGB:

import colorsys
srgb = srgb / 255
h, luminance, s = colorsys.rgb_to_hls(*srgb)
lum_mod = 100000 * (1 - brightness)
lum_off = 100000 * brightness
luminance = luminance * (lum_mod / 100000) + (lum_off / 100000)
srgb = np.array(colorsys.hls_to_rgb(h, luminance, s))
srgb = (srgb * 255).round(0).astype(int)

我根据需要在上面展示了做一种颜色的步骤。每张幻灯片只需要查找一次幻灯片母版主题,实际上在 PPT 演示文稿中每个母版只需要一次。所以真正的代码最好分成适合您需要的顺序。