PDFBox 2.0如何获取白色文本及背景色?文本RGB值获取错误
问题描述
我尝试提取PDF中的白色文本及其背景色,但获取到的文本RGB值是(0,0,0),和实际应有的(255,255,255)不符,没法正确获取白色文本和背景色。
我的Scala代码
override def processTextPosition(text: TextPosition): Unit = { super.processTextPosition(text) val color: PDColor = getGraphicsState.getNonStrokingColor val components: Array[Float] = color.getComponents val r: Int = Math.round(components(0) * 255) val g: Int = Math.round(components(1) * 255) val b: Int = Math.round(components(2) * 255) linePos.append((r, g, b)) if(r!=0||g!=0||b!=0) bad.append(text.getUnicode) val color2: PDColor = getGraphicsState.getStrokingColor val components2: Array[Float] = color2.getComponents if (components2.size >= 3){ val r2: Int = Math.round(components2(0) * 255) val g2: Int = Math.round(components2(1) * 255) val b2: Int = Math.round(components2(2) * 255) if (r2 != 0 || g2 != 0 || b2 != 0) bad.append(text.getUnicode) } }
问题分析与解决方案
- 颜色空间不匹配:你直接将
PDColor的组件按RGB处理,但PDF可能使用灰度、CMYK等其他颜色空间,导致值转换错误。必须先判断颜色空间类型,再做对应转换。 - 文本渲染模式忽略:文本可能同时使用填充+描边模式,或者仅用描边,你当前的判断逻辑没考虑渲染模式对最终颜色的影响,需要先通过
getGraphicsState.getTextRenderingMode()确认渲染模式。 - 背景色获取逻辑缺失:当前代码只处理了文本颜色,PDF的背景色不属于文本属性,需要监听图形绘制操作(如矩形填充)来捕获背景区域和颜色。
- ExtGState属性影响:部分PDF会用
ExtGState设置颜色反相、透明度等,可能导致获取的原始颜色和显示颜色不一致,需要检查相关属性。
修正后的代码示例
override def processTextPosition(text: TextPosition): Unit = { super.processTextPosition(text) val gs = getGraphicsState // 处理非描边颜色,先转换为RGB val nonStrokingRGB = convertToRGB(gs.getNonStrokingColor) linePos.append(nonStrokingRGB) // 这里改为判断是否不是白色,按需调整逻辑 if (nonStrokingRGB != (255, 255, 255)) { bad.append(text.getUnicode) } // 处理描边颜色 val strokingRGB = convertToRGB(gs.getStrokingColor) if (strokingRGB != (255, 255, 255)) { bad.append(text.getUnicode) } } // 新增颜色空间转换函数,兼容多种颜色类型 private def convertToRGB(color: PDColor): (Int, Int, Int) = { val colorSpace = color.getColorSpace val components = color.getComponents colorSpace match { case _: PDDeviceRGB => (Math.round(components(0)*255), Math.round(components(1)*255), Math.round(components(2)*255)) case _: PDDeviceGray => val gray = Math.round(components(0)*255) (gray, gray, gray) case _: PDDeviceCMYK => // CMYK转RGB公式 val c = components(0) val m = components(1) val y = components(2) val k = components(3) val r = Math.round((1 - c) * (1 - k) * 255) val g = Math.round((1 - m) * (1 - k) * 255) val b = Math.round((1 - y) * (1 - k) * 255) (r, g, b) case _ => // 其他颜色空间默认返回黑色,可按需扩展 (0, 0, 0) } }
补充说明
- 若要获取背景色,需重写
processPaintingOperator方法,监听re(填充矩形)等操作,记录填充的颜色和区域,再与文本位置匹配判断。 - 如果PDF使用了透明度,还需结合
gs.getExtGState().getAlphaConstant()等属性调整颜色计算逻辑。
内容的提问来源于stack exchange,提问作者li peng
相关产品推荐
相关产品推荐

