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.rgb
的 None
值表示 运行 从其样式层次结构(例如段落默认值、形状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 演示文稿中每个母版只需要一次。所以真正的代码最好分成适合您需要的顺序。
我想从给定的文本框中读取字体颜色。我可以提取字体名称和粗体但不能提取颜色(或字体名称)。
这是我的代码:
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.rgb
的 None
值表示 运行 从其样式层次结构(例如段落默认值、形状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 演示文稿中每个母版只需要一次。所以真正的代码最好分成适合您需要的顺序。