I want to create a pdf with partially transparent polygons as the ellipse in the below image using libharu. The polygons come as RGBA, but libharu only has these fill methods:
HPDF_Page_SetCMYKFill()
HPDF_Page_SetGrayFill()
HPDF_Page_SetRGBFill()
Run Code Online (Sandbox Code Playgroud)
There is no "A" channel for rgb. (There is a transparency mask for the whole image, but as I understand, this only makes a range of colors invisible in the whole image, which is not what I want.)
I am new to libharu, and not an expert in color schemes or PDF, so solutions on all these levels might work...
以下代码可作为通用解决方案,经 Duke(原始海报)证明。
在 PDF 文件中添加可变性的通用方法是,首先声明一组可选的“图形状态”,并在版本 5 (%PDF-1.4) 中添加透明度作为通常分配给 /GS0 的扩展图形状态 (/ExtGState) /GS1 /GS2...但声明性命名方案是可选的。
因此,在 PDF 内部文档资源中,您可以根据需要添加例如 <</ExtGState<</GS0 0.25/GS1 0.5 /GS...>>>>。然后,在构建页面时,可以引入这些状态(通常视为q /GS0 gs任何后续对象,直到后续页面对象需要时重置(通常为 Q 表示上一个)。
每个 PDF 生成器都会有一些类似的方法,在讨论过程中,提出了以下方法作为使用 LibHaru 的最小示例的方法。使用HPDF_CreateExtGState(pdf_document_)和HPDF_Page_SetExtGState(pdf_page_, gstate)
#include ".../hpdf.h"
#include <vector>
int main(int argc, char* argv[])
{
std::vector<std::pair<float, float>> pol1{ {100, 100}, {900, 900}, {900, 100} };
std::vector<std::pair<float, float>> pol2{ {10, 10}, {10, 900}, {900, 10} };
auto pdf_document_ = HPDF_New([](HPDF_STATUS error_no, HPDF_STATUS detail_no, void* user_data) {
// Do some error handling
}, NULL);
auto pdf_page_ = HPDF_AddPage(pdf_document_);
HPDF_Page_SetHeight(pdf_page_, 1000);
HPDF_Page_SetWidth(pdf_page_, 1000);
// Polygon 1 (no transparency)
HPDF_Page_SetRGBFill(pdf_page_, 1, 1, 0); // Set color to yellow
HPDF_Page_MoveTo(pdf_page_, pol1[0].first, pol1[0].second);
for (int i = 1; i < pol1.size(); i++) {
HPDF_Page_LineTo(pdf_page_, pol1[i].first, pol1[i].second);
}
HPDF_Page_ClosePathFillStroke(pdf_page_);
// Polygon 2 (opacity 0.45)
HPDF_Page_SetRGBFill(pdf_page_, 1, 0, 1); // Set color to purple - because... why not ;-)
HPDF_ExtGState gstate{ HPDF_CreateExtGState(pdf_document_) }; // Create extended graphics state
HPDF_ExtGState_SetAlphaFill(gstate, 0.45); // Set the opacity
HPDF_Page_SetExtGState(pdf_page_, gstate); // Apply the gstate property to the page
HPDF_Page_MoveTo(pdf_page_, pol2[0].first, pol2[0].second);
for (int i = 1; i < pol2.size(); i++) {
HPDF_Page_LineTo(pdf_page_, pol2[i].first, pol2[i].second);
}
HPDF_Page_ClosePathFillStroke(pdf_page_);
HPDF_SaveToFile(pdf_document_, "my.pdf");
}
Run Code Online (Sandbox Code Playgroud)
结果将是带有/ExtGState标签 /E1 的页面定义
4 0 obj
<</Type/Page/MediaBox [ 0 0 1000 1000 ]/Contents 5 0 R
/Resources<</ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
/ExtGState <</E1 7 0 R>>>>
/Parent 2 0 R>>
endobj
Run Code Online (Sandbox Code Playgroud)
/E1 指向扩展图形状态,在本例中只是颜色lpha的更改,但可以具有其他扩展属性
7 0 obj
<</Type/ExtGState/ca 0.45>>
endobj
Run Code Online (Sandbox Code Playgroud)
然后在稍后的页面内容中,可以在那时应用该命名状态,就好像包含了 /ca 0.45 一样
5 0 obj
<</Length 6 0 R>>
stream
% set color to yellow
1 1 0 rg
% draw solid state triangle diagonally right and up from bottom left
100 100 m
900 900 l
900 100 l
% close and fill
b
% Change colour to magenta
1 0 1 rg
% set gs to Extended Graphic State (Opacity 45%)
/E1 gs
10 10 m
10 900 l
900 10 l
b
Run Code Online (Sandbox Code Playgroud)
我在这里压缩了真实的 PDF 结果,以更少的行数显示它们。因此,记事本中的对象 7 的布局如下,可以轻松地从 0.45 编辑到 0.75 不透明度进行实验,如右上实时预览(不是 Acrobat)中所示。
7 0 obj
<<
/Type /ExtGState
/ca 0.75
>>
endobj
Run Code Online (Sandbox Code Playgroud)
注意:我使用术语“不透明度”来表示 alpha 通道,因为具有无限浮点数的 0 到 1 的范围是从完全透明 (0) 到完全不透明 (1)。
这在 RGBA 术语中意味着 [0 0 0 0] 根本没有颜色(完全半透明),而 [1 1 1 1] 是全色(完全纯白色)。但更令人困惑的是,它意味着单个“颜色”透明度是 [# # # 0] 到 [# # # 1],因此在图像中 256 字节的范围内,在存储和提取时,所有内容实际上都显示为单色黑色软蒙版独立,但这是一个不同的非常广泛的话题!