如何为PdfDocument生成的位图PDF添加可选文本?
问题解答:让Bitmap生成的PDF支持文本选中
可以实现。你当前生成的PDF无法选中文本,是因为PdfDocument绘制Bitmap后,页面仅包含位图数据,没有可被编辑器识别的文本对象。解决思路是:通过OCR识别Bitmap中的文本内容和位置,在PDF页面的Bitmap上方叠加一层透明的可选中文本层——这层文本不会影响视觉效果,但会被PDF编辑器识别为可选中的文本元素。
现有代码分析与优化
1. OCR文本识别(mlkitforembededtext)
你已经用MLKit完成了文本内容、边界框的提取,但文本大小计算逻辑存在问题,需调整为更合理的行高匹配逻辑:
// 原错误逻辑:用边界框宽度除以单个symbol数量,不符合字体大小对应关系 // float textSize = ( (float) boundingBoxforsave.width() /FORCOUNT.size()); // 修改为:取行边界框高度作为初始文本大小(字体高度与行高匹配更准确) float textSize = boundingBoxforsave != null ? boundingBoxforsave.height() : 0; pageTextSizes.add(textSize);
同时简化代码层级,无需遍历到Symbol级别:
for (Text.TextBlock block : visionText.getTextBlocks()) { for (Text.Line line : block.getLines()) { Rect boundingBox = line.getBoundingBox(); String textValue = line.getText(); if (boundingBox != null && textValue != null) { pageBoundingBoxes.add(boundingBox); pageTextValues.add(textValue); pageTextSizes.add(boundingBox.height()); Log.i("MLKIT", "Text and bounding box added: " + textValue + " " + boundingBox.toString()); } else { Log.e("MLKitError", "BoundingBox or Text is null"); } } }
2. PDF生成(createpdf)
当前代码绘制了可见文本,会干扰原Bitmap视觉,需改为透明文本层,同时优化对齐逻辑:
public void createpdf() throws IOException { PdfDocument document = new PdfDocument(); for (int i = 0; i < pdfBitmaps.size(); i++) { Bitmap bitmap = pdfBitmaps.get(i); PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(bitmap.getWidth(), bitmap.getHeight(), i + 1).create(); PdfDocument.Page page = document.startPage(pageInfo); Canvas canvas2 = page.getCanvas(); // 1. 直接绘制原Bitmap(去掉多余的压缩解码步骤) canvas2.drawBitmap(bitmap, 0f, 0f, null); // 2. 准备绘制透明文本层 List<String> textValues = allPageTextValues.get(i); List<Rect> boundingBoxes = allPageBoundingBoxes.get(i); List<Float> textSizes = allPageTextSizes.get(i); Paint textPaint = new Paint(); textPaint.setStyle(Paint.Style.FILL); // 设置文本为透明,不干扰原Bitmap显示 textPaint.setColor(Color.TRANSPARENT); textPaint.setTypeface(Typeface.DEFAULT); // 可替换为匹配原文本的字体 textPaint.setAntiAlias(true); textPaint.setTextAlign(Paint.Align.LEFT); for (int p = 0; p < boundingBoxes.size(); p++) { String text = textValues.get(p); Rect box = boundingBoxes.get(p); float textSize = textSizes.get(p); textPaint.setTextSize(textSize); // 计算缩放因子,让文本适配边界框宽度 float textWidth = textPaint.measureText(text); float scaleFactor = box.width() / textWidth; // 限制缩放范围,避免文本变形 scaleFactor = Math.min(Math.max(scaleFactor, 0.8f), 1.2f); textPaint.setTextSize(textSize * scaleFactor); // 计算文本绘制位置:对齐边界框左上角,适配字体基线确保垂直居中 float x = box.left; float y = box.bottom - textPaint.descent(); // 绘制透明文本,提供可选中的文本数据 canvas2.drawText(text, x, y, textPaint); } document.finishPage(page); } // 补充PDF保存逻辑 File outputFile = new File(getExternalFilesDir(null), "output.pdf"); document.writeTo(new FileOutputStream(outputFile)); document.close(); }
关键优化点
- 透明文本层:将文本颜色设为
Color.TRANSPARENT,既不影响原Bitmap显示,又能让PDF编辑器识别文本。 - 字体适配:基于边界框宽度调整缩放因子,确保文本与原Bitmap中的文本位置完全对齐。
- 性能优化:去掉多余的Bitmap压缩解码步骤,直接绘制原Bitmap提升效率。
内容的提问来源于stack exchange,提问作者Tndstn
相关产品推荐
相关产品推荐

