iText PDF:替换/转换颜色

Mar*_*ing 6 pdf colors itext

我正在使用Java中的iText从一个大的PDF文档中选择一些页面并保存为一个新的较小的PDF.与此同时,我想改变他们的颜色.

例如,假设我的页面都使用灰色阴影,我想将其设为绿色.使用的所有颜色都是灰色阴影.我想用绿色的相应颜色替换每种颜色.


Mark Storer问道:

你到底想要完成什么?

把这个...变成这个:

灰页绿页

我有一些文件,我已经在使用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()
Run Code Online (Sandbox Code Playgroud)

(它在Scala中,但iText库与Java中的相同)

问题是,iText提供的所有混合模式都是"可分离"模式:它们独立地在每个颜色通道上运行.这意味着我可以单独调整青色,品红色,黄色或黑色值,但我不能将灰色变为绿色.

要做到这一点,我需要使用颜色混合模式,这是"不可分离",即颜色通道相互影响.据我所知,iText没有提供 - 没有任何非分离混合模式列在常量中PdfGState.我正在使用iText 5.0.5,这是写这篇文章时的最新版本.

有没有办法在iText中访问这些混合模式,甚至是黑客入侵?还有另一种方法可以达到效果吗?


更新:

即使将混合模式设置为Color也不起作用.我在代码中这样做是为了强制它:

    val gstate = new PdfGState
    gstate.put(PdfName.BM, new PdfName("Color"))
    canvas.setGState(gstate)
Run Code Online (Sandbox Code Playgroud)

我在文本编辑器中检查了生成的PDF,以确保它说得对.可悲的是,屏幕上的结果不起作用.我不知道为什么,根据PDF规范应该是正确的混合模式.


Mark Storer问道:

"颜色"不起作用?质朴.我们能看到PDF吗?

这是一个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)
Run Code Online (Sandbox Code Playgroud)

而且这里是它产生的PDF.在Chrome或Acrobat中不太对劲:)

编辑:傻我.我将模式更改为"Luminosity",生成此文件.和以前一样,这在Chrome中看起来是正确的,但在Acrobat中却看不到.


我刚检查过,甚至Adobe Reader X都没有正确呈现它.这可能意味着我所要求的是不可能的.:(


来自Adobe的伦纳德罗森塔尔回到我身边,澄清了问题:"颜色"混合模式仅在变换空间为RGB而非CMYK时才有效.我的PDF没有指定空间,因此Adobe产品默认为CMYK,而其他默认为RGB.

iText中的解决方案是在顶部附近添加此行:

    writer.setRgbTransparencyBlending(true)
Run Code Online (Sandbox Code Playgroud)

当然,为了颜色准确性,您不需要比绝对必要的颜色空间转换更多,因此如果您确实需要使用RGB混合模式,请仅使用此行.

从Photoshop用户的角度来看,制作的彩色页面看起来有点奇怪:看起来浅灰色比黑色灰色更饱满.我正在研究组合过滤器以调整输出的方法.

这是结果!

非常感谢Mark Storer帮助我实现这一解决方案.

Mar*_*rer 5

如果您一直想要从"灰色阴影"变为"颜色X的阴影",您可以使用透明度和一些时髦的混合模式.

如果您想浏览所有内容流并编辑现有的颜色命令,这是一个非常高的顺序.你必须考虑各种各样的colo(u)r空间.DeviceGray,DeviceRGB,DeviceCMYK,ICC配置文件,校准RGB和CMYK,专色和So Forth.

你到底想要完成什么?


"颜色"不起作用?质朴.我们能看到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)

呃...只有你现有的页面都是deviceGray,对吧?不...... CMYK也只是K's.您需要一个采用K值的传递函数,并根据您想要的颜色输出将它们映射到CMYK.

然后我看了你如何在PDF中定义一个函数.这么简单.域名和范围和样本哦,我的!不完全是微不足道的.

不过,这可能会奏效.

(虽然我仍然认为你应该找到一个可以在Acrobat中运行的混合PDF,看看有什么区别)


最后的努力:PM Leonard Rosenthol.他在这里有一个账号.他是Adobe的Acrobat开发者关系人员.告诉他Mark Storer很难过.这应引起他的注意.;)