我在Java中使用iText从大型PDF文档中选择几页并保存为新的较小的PDF。与此同时,我想改变他们的颜色。
例如,假设我的页面都使用灰色阴影,我想将其设为绿色。使用的所有颜色都是灰色阴影。我想用绿色的相应颜色替换每种颜色。
Mark Storer问道:
你到底想要完成什么?
将此...改为:
我有some documents,我已经使用iText根据用户输入从文档中选择一组较小的页面 - 将页面减少到100页以下,大约为5页。同时我希望生产绿色,蓝色,黄色,粉红色等版本。不是每个页面都是灰度级的,而是所有重要的页面,所以如果需要,我可以强制它们的颜色空间。
更新
按照Mark Storer关于混合模式的建议,这就是我所拥有的:
val reader = new PdfReader(file.toURL)
val document = new Document
val writer = PdfWriter.getInstance(document, outputStream)
document.open()
/* draw a white background behind the page, so the
blend always has something to transform, otherwise
it just fills. */
val canvas = writer.getDirectContent
canvas.setColorFill(new CMYKColor(0.0f, 0.0f, 0.0f, 0.0f))
canvas.rectangle(10f, 0f, 100f, 100f)
canvas.fill
/* Put the imported page on top of that */
val page = writer.getImportedPage(reader, 1)
canvas.addTemplate(page, 0, 0)
/* Fill a box with colour and a blending mode */
canvas.setColorFill(new CMYKColor(0.6f,0.1f,0.0f,0.5f))
val gstate = new PdfGState
gstate.setBlendMode(PdfGState.BM_SCREEN)
canvas.setGState(gstate)
canvas.rectangle(0f, 0f, 100f, 100f)
canvas.fill
document.close()
(它在Scala中,但iText库与Java中的相同)
问题是,iText提供的所有混合模式都是“可分离”模式:它们独立地在每个颜色通道上运行。这意味着我可以单独调整青色,品红色,黄色或黑色值,但我不能将灰色变为绿色。
要做到这一点,我需要使用颜色混合模式,即“不可分离”,即颜色通道相互影响。据我所知,iText没有提供 - PdfGState
中的常量中没有列出任何非分离混合模式。我正在使用iText 5.0.5,这是写这篇文章时的最新版本。
有没有办法在iText中访问这些混合模式,甚至是黑客入侵?还有另一种方法可以达到结果吗?
更新
即使将混合模式设置为“颜色”也不起作用。我在代码中这样做是为了强制它:
val gstate = new PdfGState
gstate.put(PdfName.BM, new PdfName("Color"))
canvas.setGState(gstate)
我在文本编辑器中检查了生成的PDF,以确保它说得对。可悲的是,屏幕上的结果不起作用。我不知道为什么,根据PDF规范应该是正确的混合模式。
Mark Storer问道:
“颜色”不起作用?质朴。我们能看到PDF吗?
将它放在网络上,我现在可以看到“颜色”模式在Chrome中正常工作,但在Acrobat 9 Pro(CS4)中不起作用。所以这项技术是正确的,但Adobe在渲染时失败了!
我想知道是否没有某种方法可以“展平”混合模式的效果,因此PDF直接包含所需的颜色对象,而不是用于产生正确颜色的混合。
想法:将其颠倒过来。将现有页面用作填充页面上的Alpha通道 完全用所需的颜色而不是相反的方式。
如何?我不确定GState是否适用于添加模板?
此外,导入的页面首先需要添加白色背景,或者只有在没有对象而不是混合的情况下,它只会泛起颜色。
我试过这样做:
val canvas = writer.getDirectContent
canvas.setColorFill(new CMYKColor(0.6f,0.1f,0.0f,0.0f))
canvas.rectangle(10f, 0f, 500f, 500f)
canvas.fill
val template = canvas.createTemplate(500f, 500f)
template.setColorFill(new CMYKColor(0f, 0f, 0f, 0f))
template.rectangle(0f, 0f, 500f, 500f)
template.fill
val page = writer.getImportedPage(reader, 1)
template.addTemplate(page, 0, 0)
val gstate = new PdfGState
gstate.put(PdfName.BM, new PdfName("Color"))
canvas.setGState(gstate)
canvas.addTemplate(template, 0, 0)
here's the PDF it produced。在Chrome或Acrobat中不太对劲:)
编辑:傻傻的我。我将模式更改为“Luminosity”,producing this file。和以前一样,这在Chrome中看起来不正确,但在Acrobat中看起来不正确。
我刚检查过,甚至Adobe Reader X都没有正确呈现它。这可能意味着我所要求的是不可能的。 :(
解决方案
来自Adobe的Leonard Rosenthal回复了我,并澄清了问题:“颜色”混合模式仅在转换空间为RGB而非CMYK时才有效。我的PDF没有指定空间,因此Adobe产品默认为CMYK,而其他产品默认为RGB。iText中的解决方案是将此行添加到顶部附近:
writer.setRgbTransparencyBlending(true)
当然,为了颜色准确性,您不需要比绝对必要的颜色空间转换更多,所以如果您确实需要使用RGB混合模式,请仅使用此行。
从Photoshop用户的角度来看,制作的彩色页面看起来有点奇怪:看起来浅灰色比黑色灰色更饱满。我正在研究组合过滤器以调整输出的方法。
非常感谢Mark Storer帮助我实现这一解决方案。
答案 0 :(得分:5)
如果你一直想从“灰色阴影”变为“颜色X阴影”,你可以在一些时髦的混合模式下使用透明度。
如果您想浏览所有内容流并编辑现有的颜色命令,这是一个非常高的顺序。你必须考虑各种各样的colo(u)r空间。 DeviceGray,DeviceRGB,DeviceCMYK,ICC配置文件,校准RGB和CMYK,专色,以及此类。
你到底想要完成什么?
“颜色”不起作用?质朴。我们能看到PDF吗?
想法:将其颠倒过来。将现有页面用作完全填充所需颜色的页面上的Alpha通道,而不是相反。
再试一次。而不是混合,使用传递函数。您需要构建一个Function字典。您坚持使用CMYK,因此将任何和所有输入填充到特定输出中应该相当简单。
类似的东西:
C:[0 1] - > [0 0.6]
M:[0 1] - > [0 0.1]
Y:[0 1] - > [0 0]
K:[0 1] - > [0 0]
(我从你的PDF中刷了0.6 0.1 0 0)
Urgh ...只有你现有的页面都是deviceGray,对吧?不...... CMYK也只是K's。你需要一个带有K值的传递函数,并根据你想要的颜色输出将它们映射到CMYK。
然后我看了你如何在PDF中定义一个函数。这么简单。域名和范围和样本哦,我的!不完全是微不足道的。
不过,这可能会奏效。
(虽然我仍然认为你应该找到一个适用于Acrobat的混合PDF,看看有什么不同之处)
最后的努力: PM Leonard Rosenthol。他在这里有一个账号。他是Adobe的Acrobat开发者关系人员。告诉他Mark Storer很难过。这应引起他的注意。 ;)