安卓端itextpdf:5.5.12实现PdfContentByte添加模糊文本的方案问询
安卓端itextpdf 5.5.12实现PDF模糊文本的方案
方案一:iText原生实现(优先推荐,无图片失真问题)
你不需要通过生成图片实现模糊,iText5支持直接对PdfContentByte的内容应用高斯模糊效果,核心是通过透明度组+高斯模糊滤镜处理文本,属于矢量级效果,不会出现分辨率问题:
PdfWriter pdfWriter=PdfWriter.getInstance(document, new FileOutputStream(file)); PdfContentByte cb = pdfWriter.getDirectContent(); cb.saveState(); // 第一步:创建高斯模糊滤镜 PdfDictionary filterDic = new PdfDictionary(PdfName.FILTER); filterDic.put(PdfName.SUBTYPE, PdfName.GAUSSIANBLUR); filterDic.put(new PdfName("Radius"), new PdfNumber(2)); // 调整这个值控制模糊程度 // 第二步:创建图形状态,应用模糊滤镜 PdfGState gs = new PdfGState(); gs.put(PdfName.BM, PdfName.NORMAL); gs.put(new PdfName("FILTER"), filterDic); cb.setGState(gs); // 第三步:正常绘制文本即可 cb.beginText(); cb.setColorFill(baseCol); cb.setFontAndSize(myBaseFontArialNarrowBold,7); cb.showTextAligned(PdfContentByte.ALIGN_LEFT,"需要模糊的文本内容",297,638,rotation); cb.endText(); cb.restoreState();
这个方案是矢量效果,不管放大多少都不会失真,性能也远高于生成图片的方案,兼容性符合PDF标准。
方案二:Canvas生成图片方案的问题修复
字体效果差的核心原因
- 生成的Bitmap分辨率不足:PDF默认打印精度为300DPI,而你当前生成的Bitmap是按屏幕分辨率(一般72/160DPI)创建的,插入PDF缩放后会出现锯齿、字体发虚
- 未做超采样处理:直接按实际显示尺寸绘制文本,模糊效果和字体边缘的精度不够
- 画布参数适配问题:Canvas的子像素渲染、抗锯齿参数是针对屏幕显示优化的,不适合打印场景的PDF输出
优化代码
// 第一步:按300DPI生成超采样Bitmap,比如你需要的PDF中显示尺寸是50x50pt,就生成50*4=200x200px的Bitmap // 4倍超采样,保证缩放后精度足够 int scaleFactor = 4; int bitmapWidth = 50 * scaleFactor; int bitmapHeight = 50 * scaleFactor; Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); canvas.drawColor(Color.TRANSPARENT); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); // 所有尺寸都乘以缩放系数 paint.setTextSize(8 * scaleFactor); paint.setTypeface(typeface); paint.setColor(Color.argb(190,0,0,0)); paint.setTextAlign(Paint.Align.LEFT); paint.setMaskFilter(new BlurMaskFilter(1 * scaleFactor, BlurMaskFilter.Blur.NORMAL)); // 关闭针对屏幕的子像素优化 paint.setSubpixelText(false); paint.setLinearText(false); // 坐标也乘以缩放系数 canvas.rotate(-0.9876f); canvas.drawText(textAr[0],6.8f * scaleFactor,11.78f * scaleFactor,paint); paint.setTextSize(7 * scaleFactor); canvas.drawText(textAr[1],6.8f * scaleFactor,20 * scaleFactor,paint); canvas.drawText(textAr[2],6.8f * scaleFactor,45 * scaleFactor,paint); // 插入PDF的时候按原尺寸设置宽高,不要按Bitmap像素大小设置 ByteArrayOutputStream stream2 = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream2); byte[] byteArray2 = stream2.toByteArray(); Image img2 = Image.getInstance(byteArray2); // 这里设置成你需要的实际尺寸,不要用Bitmap的宽高 img2.scaleAbsolute(50,50); cb.addImage(img2,290,398);
调整后生成的图片插入PDF后精度会提升4倍,基本不会出现字体发虚的问题。
内容的提问来源于stack exchange,提问作者slodeveloper
相关产品推荐
相关产品推荐

