如何使用PDFsharp提取PDF中已绘制矩形的颜色信息
如何使用PDFsharp提取PDF中已绘制矩形的颜色信息
嘿,我完全懂你的需求——你用PDFsharp在PDF页面角落画了个带唯一颜色的小矩形做标记,现在想重新打开文件读取这个颜色对吧?咱们来一步步解决这个问题。
首先得说清楚为什么你之前找/XObject没结果:你用XGraphics.DrawRectangle绘制的矩形,并不是作为独立的XObject存储的,而是直接被转换成了PDF页面内容流里的一系列绘图指令,所以在页面的Resources字典里找不到对应的条目。
接下来给你两种解决方案,按需选择:
方案一:生成PDF时记录颜色元数据(最简单)
如果你能控制PDF的生成过程,那直接在绘制矩形后给页面添加自定义元数据是最省心的办法,完全不用解析复杂的内容流:
绘制时添加元数据
// 你的绘制代码 var brush = new XSolidBrush(XColor.FromArgb(255, colorArray.R, colorArray.G, colorArray.B)); XGraphics gfx = XGraphics.FromPdfPage(document.Pages[0]); gfx.DrawRectangle(brush, xRect); // 添加自定义元数据,记录矩形颜色 PdfPage page = document.Pages[0]; page.Elements.Add("/MyMarkerColor", new PdfString($"RGB({colorArray.R},{colorArray.G},{colorArray.B})"));
读取时获取颜色
PdfDocument document = PdfReader.Open("your-file.pdf"); PdfPage page = document.Pages[0]; // 读取自定义元数据 PdfString colorEntry = page.Elements.GetValue("/MyMarkerColor") as PdfString; if (colorEntry != null) { string colorStr = colorEntry.Value; // 解析字符串得到RGB值,比如按逗号分割 string[] rgbParts = colorStr.Replace("RGB(", "").Replace(")", "").Split(','); if (rgbParts.Length == 3 && int.TryParse(rgbParts[0], out int r) && int.TryParse(rgbParts[1], out int g) && int.TryParse(rgbParts[2], out int b)) { Console.WriteLine($"标记矩形颜色: RGB({r}, {g}, {b})"); } }
方案二:解析页面内容流提取颜色(适用于无法修改生成逻辑的情况)
如果没法在生成时加元数据,那就得直接解析PDF页面的内容流,提取绘图指令里的颜色信息。PDFsharp没有提供现成的高级解析API,所以需要手动处理:
步骤1:获取页面内容流
PdfDocument document = PdfReader.Open("your-file.pdf"); PdfPage page = document.Pages[0]; // 获取扁平化后的内容流字节 byte[] contentBytes = page.Contents.Flatten(); string content = Encoding.ASCII.GetString(contentBytes);
步骤2:解析颜色指令
你用XSolidBrush填充矩形,对应的PDF指令会是:先通过rg指令设置填充颜色(格式为r g b rg,其中r/g/b是0-1之间的归一化值),然后用re定义矩形路径,最后用f执行填充。
我们可以遍历内容流的指令,找到对应的颜色值:
string[] tokens = content.Split(new[] {' ', '\n', '\r'}, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < tokens.Length; i++) { // 寻找填充颜色指令 "rg" if (tokens[i] == "rg" && i >= 3) { // 尝试解析前三个token为RGB归一化值 if (double.TryParse(tokens[i-3], out double normR) && double.TryParse(tokens[i-2], out double normG) && double.TryParse(tokens[i-1], out double normB)) { // 转换为0-255的RGB值 int r = (int)Math.Round(normR * 255); int g = (int)Math.Round(normG * 255); int b = (int)Math.Round(normB * 255); // 如果你知道矩形在角落,可以结合坐标指令进一步筛选,比如找附近的位置参数 Console.WriteLine("找到填充颜色: RGB({0}, {1}, {2})", r, g, b); } } }
注意事项
- 内容流里可能有多个
rg指令,所以你需要结合矩形的位置(比如你知道标记在页面角落,可以找对应坐标附近的颜色指令)来确认哪个是你要的颜色。 - PDF的坐标系统和PDFsharp的可能有差异,需要注意坐标转换。
备注:内容来源于stack exchange,提问作者Nikolas McRain
相关产品推荐
相关产品推荐

