You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 00:47:22