PPT对图片进行重新着色和设置透明颜色这两个行为,并不会对原图进行修改,而是通过将修改信息直接存入xml中,并在加载图片时通过计算将效果渲染出来。由于PPT不会存储一张经过该效果处理后的图片,所以第三方应用需要主动获取相关的存储信息,解析后将原图进行修改或通过着色器处理渲染效果。
通过本篇内容,我们将介绍重新着色的存储相关,并将说明我们如何实现相同的效果。
原文: [PPTX解析] 图片效果算法篇:重新着色 - 仙尘阁
存储解析
首先,让我们来看一下PPTX提供了哪些重新着色的选项:
可以看到,PPT的着色选项大体分为以下几类:
效果类型 | 包含的选项 | 原理 |
---|
GrayScaleEffect | 灰度 | 将图片修改为灰度图 |
ErosionEffect | 冲蚀 | 修改图片的亮度和对比度 |
Black/WhiteEffect | 黑白:25%、黑白:50%、黑白:75%、 | 根据指定阈值将像素设为黑色或白色 |
DuotoneEffect | 上述效果外的选项(包含其他变体) | 对于每个像素,通过线性插值组合 clr1 和 clr2 以确定该像素的新颜色 |
需要注意的是,实际上重新着色是需要根据选择的类型不同,其存储方案也是不同的!(根据规范都是存储在<a:blip />
节点中的)
图像处理矩阵
在讲解如何解析PPTX图像存储前,我们先来说明一下如何处理图片,将其按照我们的想法和输入数据将其进行转换。
在图像处理中,我们通常使用矩阵来进行图像的像素处理,下面是一些常见的C#图像处理矩阵:
在获取到这些处理的矩阵后,我们可以将其应用到图片上,代码如下(C#):
存储属性解析
接下来,就让我们逐一的对存储节点进行分析吧~
GrayScaleEffect
该属性的标记非常简单和清晰,使用了一个单一的节点**<a:grayscl />
**表明是否应用了该效果:
所以只要在解析PPTX节点的过程之中,发现存在节点**<a:grayscl />
,就可以通过灰度滤波器矩阵**对图片做灰阶处理即可。
Black/WhiteEffect
该属性通过节点**<a:biLevel />
**进行存储,如下:
该节点属性解析:
属性名称 | 属性含义 | 值含义 | 补充说明 |
---|
thresh | 阈值 | 颜色的亮度(即像素点的灰度值)大于或等于给定的阈值将显示白色,否则显示黑色 | 单位:千倍百分比(如:50000实际值代表50%) |
可以参考下面的代码,将指定Bitmap
的颜色进行黑白效果的设置:
DuotoneEffect
这个效果是PPT重新着色中最复杂的效果。
该属性通过节点**<a:duotone />
**进行存储,如下:
[A] 你可能会看到如下的存储格式(选择预设的效果选项)
[B] 你还可能会看到如下的存储格式(选择其他变体->主题颜色选项):
[C] 甚至,你还可能会看到如下的存储格式(选择其他变体->其他颜色选项):
**<a:duotone />
**节点解析:
子节点名称 | 含义 | 值含义 | 补充说明 |
---|
a | RGB颜色 | 实际颜色值,表示为十六进制数字 RRGGBB 的序列 | 实际上就是一个颜色 |
a | 预设颜色 | 指定实际的预设颜色值 | 实际上就是一个颜色 |
a | 预设方案(主题)颜色 | 用户定义或预设的主题色 | 实际上就是一个颜色 |
**<a:srgbClr />
**节点解析:
子节点名称 | 含义 | 值含义 | 补充说明 |
---|
a | 明色调 | 指定输入颜色,其按给定百分比值进行加白减淡变亮。 | 单位:千倍百分比(如:50000实际值代表50%) |
a | 暗色调 | 指定输入颜色,其按给定百分比值进行加黑增深变暗。 | 单位:千倍百分比(如:50000实际值代表50%) |
a | 饱和度调制 | 指定输入颜色,其饱和度按给定百分比进行调制。 | 单位:千倍百分比 (50%将饱和度降低一半,200%使饱和度加倍) |
a | 亮度调制 | 指定输入颜色,其亮度按给定百分比调制。 | 单位:千倍百分比(如:50000实际值代表50%) |
a | 亮度偏移 | 指定输入颜色,其亮度发生变化,但色调和饱和度不变。 | 单位:千倍百分比(如:50000实际值代表50%) |
实践出真知
看过上面的解析,是不是觉得它的解析很复杂,请忘掉上面的内容!看下面经过实践验证的解析:
经过实践验证,节点**<a:duotone />
**实际存放并支持的是两个颜色,下面称为A
,B
下面我们使用色相环和和进行过灰度转换的灰阶图去检测颜色和颜色顺序对最终效果的影响:
序列 | 颜色A | 颜色B | 转换结果(原图:色相环) | 转换结果(原图:灰阶图) |
---|
1 | 白 | 白 | 全白 | 全白 |
2 | 黑 | 黑 | 全黑 | 全黑 |
3 | 红 | 红 | 全红 | 全红 |
4 | 白 | 黑 | | |
5 | 黑 | 白 | | |
6 | 白 | 红 | | |
7 | 红 | 白 | | |
8 | 黑 | 红 | | |
9 | 红 | 黑 | | |
通过色环图实际的应用效果,可以论证我们的猜想,下面我们可以通过两种方式实现该效果
实现方案一:像素级处理
下面的参考代码是将图片中某一个颜色应用DuotoneEffect效果的代码(C#):
实现方案二:使用灰度滤波器矩阵
我们曾介绍了如何通过图像处理矩阵进行图像的处理,所以我们可以先通过灰度滤波器矩阵将图片转为灰度图,因为在灰度图像中,亮度等于灰度。我们可以根据亮度的值0~1
对图像进行处理。
DuotoneColor = (1 - Brightness) * ColorB + Brightness * ColorB;
ErosionEffect
该属性通过节点**<a:lum />
**进行存储,如下:
该节点属性解析:
属性名称 | 属性含义 | 值含义 | 补充说明 |
---|
bright | 亮度 | 正值表示增加亮度,负值表示降低亮度 | 单位:千倍百分比(如:70000实际值代表70%) |
contrast | 对比度 | 正值表示增加对比度,负值表示降低对比度 | 单位:千倍百分比(如:-70000实际值代表-70%) |
所以只要在解析PPTX节点的过程之中,发现存在节点**<a:lum />
,就可以通过亮度滤波器矩阵和对比度滤波器矩阵**对图片做处理,然后你就会发现“怎么样子还不一样呢?”。
效果不一致问题:
在实际转换后,你可能会发现:当使用一个同样的图片,将它的亮度和对比度设为解析出的亮度(-70%)和对比度(-70%),此时图片的效果和通过亮度滤波器矩阵和对比度滤波器矩阵做处理的图片是一样的,所以不是我们的处理矩阵算错了,而是PPTX不是仅仅修改亮度和对比度达到的冲蚀效果,因此如果拿不到PPTX冲蚀算法的我们需要模拟一个可以实现相似效果的算法。这里我们通过一个简单的算法,让转换效果基本和PPT保持一致一致,代码如下(C#):
例如,我们在处理亮度时,如果解析出bright=70000,那么根据千倍百分比可以得出bright实际效果值应该为0.7,我们将0.7传入**GetNearlyAmount()**即可获得一个和PPT亮度修改效果近似的转化比例。接下来调用CreateBrightnessMatrix(),就可以获得亮度转换矩阵了。(注意:当bright=100000时,我们直接创建一个纯白的图即可)。
GitHub项目仓库:
如果希望参考完整案例,请参考下面的项目:
设置重新着色案例
小知识
RGB 转为灰度值的心理学公式 Gray = 0.30R + 0.59G + 0.11B
原文链接: http://blog.lindexi.com/post/%E3%80%90%E8%BD%AC%E3%80%91--PPTX%E8%A7%A3%E6%9E%90-%E9%87%8D%E6%96%B0%E7%9D%80%E8%89%B2
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。
欢迎转载、使用、重新发布,但务必保留文章署名 林德熙 (包含链接: https://blog.lindexi.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我 联系。