使用itext对pdf指定文字位置插入图片_Java_知北行的博客-CSDN博客

创建时间:2020/4/15 14:21
来源:https://blog.csdn.net/qq_35077107/article/details/102653651


使用java开源itext库对pdf进行操作,分主要分两步先查找指定文字位置,然后再在指定位置插入图片。

1.查找指定文字的坐标位置

这里主要通过实现类RenderListener来完成查找坐标位置

代码如下:

  1. 1
    package com.anyu.PDFUtils;
  2. 2
  3. 3
    import java.io.File;
  4. 4
    import java.io.FileInputStream;
  5. 5
    import java.io.IOException;
  6. 6
    import java.util.ArrayList;
  7. 7
    import java.util.Arrays;
  8. 8
    import java.util.List;
  9. 9
  10. 10
  11. 11
    import com.itextpdf.awt.geom.Rectangle2D.Float;
  12. 12
    import com.itextpdf.text.Rectangle;
  13. 13
    import com.itextpdf.text.pdf.PdfDictionary;
  14. 14
    import com.itextpdf.text.pdf.PdfName;
  15. 15
    import com.itextpdf.text.pdf.PdfReader;
  16. 16
    import com.itextpdf.text.pdf.parser.ContentByteUtils;
  17. 17
    import com.itextpdf.text.pdf.parser.ImageRenderInfo;
  18. 18
    import com.itextpdf.text.pdf.parser.PdfContentStreamProcessor;
  19. 19
    import com.itextpdf.text.pdf.parser.RenderListener;
  20. 20
    import com.itextpdf.text.pdf.parser.TextRenderInfo;
  21. 21
  22. 22
  23. 23
    public class PdfKeywordFinder {
  24. 24
  25. 25
  26. 26
    public static void main(String[] args) throws IOException {
  27. 27
  28. 28
    String keyword = "甲方签字:";
  29. 29
    List<float[]> positions = findKeywordPostions("E:\\Desktop\\pdftest.pdf", keyword);
  30. 30
  31. 31
    System.out.println("total:" + positions.size());
  32. 32
    if (positions != null && positions.size() > 0) {
  33. 33
    for (float[] position : positions) {
  34. 34
    System.out.print("pageNum: " + (int) position[0]);
  35. 35
    System.out.print("\tx: " + position[1]);
  36. 36
    System.out.println("\ty: " + position[2]);
  37. 37
    System.out.println("\tcharWidth:" + position[3]);//每个字符的宽度
  38. 38
    }
  39. 39
    }
  40. 40
    }
  41. 41
  42. 42
    /**
  43. 43
    * @description: 查找插入签名图片的最终位置,因为是插入签名图片,所以之前的关键字应只会出现一次
  44. 44
    * 这里直接使用了第一次查找到关键字的位置,并返回该关键字之后的坐标位置
  45. 45
    * @return: float[0]:页码,float[1]:最后一个字的x坐标,float[2]:最后一个字的y坐标
  46. 46
    */
  47. 47
    public static float[] getAddImagePositionXY(String pdfName, String keyword) throws IOException {
  48. 48
    float[] temp = new float[3];
  49. 49
    List<float[]> positions = PdfKeywordFinder.findKeywordPostions(pdfName, keyword);
  50. 50
    // PdfReader pdfReader = new PdfReader(pdfName);
  51. 51
    // Rectangle pageSize = pdfReader.getPageSize(1);
  52. 52
    // temp[0]=positions.get(0)[0];
  53. 53
    // temp[1]=positions.get(0)[1]*pageSize.getWidth();
  54. 54
    // temp[2]=positions.get(0)[2]*pageSize.getHeight();
  55. 55
    temp[0] = positions.get(0)[0];
  56. 56
    temp[1] = positions.get(0)[1] + (keyword.length() * positions.get(0)[3]);
  57. 57
    temp[2] = positions.get(0)[2] - positions.get(0)[3];
  58. 58
  59. 59
    return temp;
  60. 60
    }
  61. 61
  62. 62
    /**
  63. 63
    * findKeywordPostions
  64. 64
    *  返回查找到关键字的首个文字的左上角坐标值
  65. 65
    *
  66. 66
    * @param pdfName
  67. 67
    * @param keyword
  68. 68
    * @return List<float [ ]> : float[0]:pageNum float[1]:x float[2]:y
  69. 69
    * @throws IOException
  70. 70
    */
  71. 71
    public static List<float[]> findKeywordPostions(String pdfName, String keyword) throws IOException {
  72. 72
    File pdfFile = new File(pdfName);
  73. 73
    byte[] pdfData = new byte[(int) pdfFile.length()];
  74. 74
    FileInputStream inputStream = new FileInputStream(pdfFile);
  75. 75
    //从输入流中读取pdfData.length个字节到字节数组中,返回读入缓冲区的总字节数,若到达文件末尾,则返回-1
  76. 76
    inputStream.read(pdfData);
  77. 77
    inputStream.close();
  78. 78
  79. 79
    List<float[]> result = new ArrayList<>();
  80. 80
    List<PdfPageContentPositions> pdfPageContentPositions = getPdfContentPostionsList(pdfData);
  81. 81
  82. 82
  83. 83
    for (PdfPageContentPositions pdfPageContentPosition : pdfPageContentPositions) {
  84. 84
    List<float[]> charPositions = findPositions(keyword, pdfPageContentPosition);
  85. 85
    if (charPositions == null || charPositions.size() < 1) {
  86. 86
    continue;
  87. 87
    }
  88. 88
    result.addAll(charPositions);
  89. 89
    }
  90. 90
    return result;
  91. 91
    }
  92. 92
  93. 93
  94. 94
    private static List<PdfPageContentPositions> getPdfContentPostionsList(byte[] pdfData) throws IOException {
  95. 95
    PdfReader reader = new PdfReader(pdfData);
  96. 96
  97. 97
  98. 98
    List<PdfPageContentPositions> result = new ArrayList<>();
  99. 99
  100. 100
  101. 101
    int pages = reader.getNumberOfPages();
  102. 102
    for (int pageNum = 1; pageNum <= pages; pageNum++) {
  103. 103
    float width = reader.getPageSize(pageNum).getWidth();
  104. 104
    float height = reader.getPageSize(pageNum).getHeight();
  105. 105
  106. 106
  107. 107
    PdfRenderListener pdfRenderListener = new PdfRenderListener(pageNum, width, height);
  108. 108
  109. 109
  110. 110
    //解析pdf,定位位置
  111. 111
    PdfContentStreamProcessor processor = new PdfContentStreamProcessor(pdfRenderListener);
  112. 112
    PdfDictionary pageDic = reader.getPageN(pageNum);
  113. 113
    PdfDictionary resourcesDic = pageDic.getAsDict(PdfName.RESOURCES);
  114. 114
    try {
  115. 115
    processor.processContent(ContentByteUtils.getContentBytesForPage(reader, pageNum), resourcesDic);
  116. 116
    } catch (IOException e) {
  117. 117
    reader.close();
  118. 118
    throw e;
  119. 119
    }
  120. 120
  121. 121
  122. 122
    String content = pdfRenderListener.getContent();
  123. 123
    List<CharPosition> charPositions = pdfRenderListener.getcharPositions();
  124. 124
  125. 125
  126. 126
    List<float[]> positionsList = new ArrayList<>();
  127. 127
    for (CharPosition charPosition : charPositions) {
  128. 128
    float[] positions = new float[]{charPosition.getPageNum(), charPosition.getX(), charPosition.getY(), charPosition.getCharWidth()};
  129. 129
    positionsList.add(positions);
  130. 130
    }
  131. 131
  132. 132
  133. 133
    PdfPageContentPositions pdfPageContentPositions = new PdfPageContentPositions();
  134. 134
    pdfPageContentPositions.setContent(content);
  135. 135
    pdfPageContentPositions.setPostions(positionsList);
  136. 136
  137. 137
  138. 138
    result.add(pdfPageContentPositions);
  139. 139
    }
  140. 140
    reader.close();
  141. 141
    return result;
  142. 142
    }
  143. 143
  144. 144
  145. 145
    private static List<float[]> findPositions(String keyword, PdfPageContentPositions pdfPageContentPositions) {
  146. 146
  147. 147
  148. 148
    List<float[]> result = new ArrayList<>();
  149. 149
  150. 150
  151. 151
    String content = pdfPageContentPositions.getContent();
  152. 152
    List<float[]> charPositions = pdfPageContentPositions.getPositions();
  153. 153
  154. 154
  155. 155
    for (int pos = 0; pos < content.length(); ) {
  156. 156
    int positionIndex = content.indexOf(keyword, pos);
  157. 157
    if (positionIndex == -1) {
  158. 158
    break;
  159. 159
    }
  160. 160
    float[] postions = charPositions.get(positionIndex);
  161. 161
    result.add(postions);
  162. 162
    pos = positionIndex + 1;
  163. 163
    }
  164. 164
    return result;
  165. 165
    }
  166. 166
  167. 167
    private static class PdfPageContentPositions {
  168. 168
    private String content;
  169. 169
    private List<float[]> positions;
  170. 170
  171. 171
  172. 172
    public String getContent() {
  173. 173
    return content;
  174. 174
    }
  175. 175
  176. 176
  177. 177
    public void setContent(String content) {
  178. 178
    this.content = content;
  179. 179
    }
  180. 180
  181. 181
  182. 182
    public List<float[]> getPositions() {
  183. 183
    return positions;
  184. 184
    }
  185. 185
  186. 186
  187. 187
    public void setPostions(List<float[]> positions) {
  188. 188
    this.positions = positions;
  189. 189
    }
  190. 190
    }
  191. 191
  192. 192
    private static class PdfRenderListener implements RenderListener {
  193. 193
    private int pageNum;
  194. 194
    private float pageWidth;
  195. 195
    private float pageHeight;
  196. 196
    private StringBuilder contentBuilder = new StringBuilder();
  197. 197
    private List<CharPosition> charPositions = new ArrayList<>();
  198. 198
  199. 199
  200. 200
    public PdfRenderListener(int pageNum, float pageWidth, float pageHeight) {
  201. 201
    this.pageNum = pageNum;
  202. 202
    this.pageWidth = pageWidth;
  203. 203
    this.pageHeight = pageHeight;
  204. 204
    }
  205. 205
  206. 206
  207. 207
    @Override
  208. 208
    public void beginTextBlock() {
  209. 209
  210. 210
  211. 211
    }
  212. 212
  213. 213
  214. 214
    @Override
  215. 215
    public void renderText(TextRenderInfo renderInfo) {
  216. 216
    List<TextRenderInfo> characterRenderInfos = renderInfo.getCharacterRenderInfos();
  217. 217
    for (TextRenderInfo textRenderInfo : characterRenderInfos) {
  218. 218
    String word = textRenderInfo.getText();
  219. 219
    if (word.length() > 1) {
  220. 220
    word = word.substring(word.length() - 1, word.length());
  221. 221
    }
  222. 222
    Float rectangle = textRenderInfo.getAscentLine().getBoundingRectange();
  223. 223
    float x = (float) rectangle.getMinX();
  224. 224
    float y = (float) rectangle.getMinY();
  225. 225
    float charWidth = (float) (rectangle.getMaxX() - rectangle.getMinX());
  226. 226
    //也可以返回坐标相对于pdf页面大小的百分比
  227. 227
    float xPercent = Math.round(x / pageWidth * 10000) / 10000f;
  228. 228
    float yPercent = Math.round((1 - y / pageHeight) * 10000) / 10000f;
  229. 229
  230. 230
    CharPosition charPosition = new CharPosition(pageNum, x, y, charWidth);
  231. 231
    charPositions.add(charPosition);
  232. 232
    contentBuilder.append(word);
  233. 233
    }
  234. 234
    }
  235. 235
  236. 236
  237. 237
    @Override
  238. 238
    public void endTextBlock() {
  239. 239
  240. 240
  241. 241
    }
  242. 242
  243. 243
  244. 244
    @Override
  245. 245
    public void renderImage(ImageRenderInfo renderInfo) {
  246. 246
  247. 247
  248. 248
    }
  249. 249
  250. 250
  251. 251
    public String getContent() {
  252. 252
    return contentBuilder.toString();
  253. 253
    }
  254. 254
  255. 255
  256. 256
    public List<CharPosition> getcharPositions() {
  257. 257
    return charPositions;
  258. 258
    }
  259. 259
    }
  260. 260
  261. 261
  262. 262
    private static class CharPosition {
  263. 263
    private int pageNum = 0;
  264. 264
    private float x = 0;
  265. 265
    private float y = 0;
  266. 266
    private float charWidth = 0;//单个文字的宽度
  267. 267
  268. 268
    public CharPosition(int pageNum, float x, float y, float charWidth) {
  269. 269
    this.pageNum = pageNum;
  270. 270
    this.x = x;
  271. 271
    this.y = y;
  272. 272
    this.charWidth = charWidth;
  273. 273
    }
  274. 274
  275. 275
  276. 276
    public int getPageNum() {
  277. 277
    return pageNum;
  278. 278
    }
  279. 279
  280. 280
  281. 281
    public float getX() {
  282. 282
    return x;
  283. 283
    }
  284. 284
  285. 285
  286. 286
    public float getY() {
  287. 287
    return y;
  288. 288
    }
  289. 289
  290. 290
    public float getCharWidth() {
  291. 291
    return charWidth;
  292. 292
    }
  293. 293
  294. 294
    @Override
  295. 295
    public String toString() {
  296. 296
    return "[pageNum=" + this.pageNum + ",x=" + this.x + ",y=" + this.y + "]";
  297. 297
    }
  298. 298
    }
  299. 299
    }
  300. 300
  301. 301
复制

参考:Java 在pdf中通过关键字定位 

2.在查找到的坐标位置插入图片

  1. 1
    package com.anyu;
  2. 2
  3. 3
    import com.anyu.PDFUtils.PdfKeywordFinder;
  4. 4
    import com.itextpdf.text.*;
  5. 5
    import com.itextpdf.text.pdf.PdfContentByte;
  6. 6
    import com.itextpdf.text.pdf.PdfReader;
  7. 7
    import com.itextpdf.text.pdf.PdfStamper;
  8. 8
    import com.itextpdf.text.pdf.PdfWriter;
  9. 9
  10. 10
    import java.io.FileOutputStream;
  11. 11
    import java.io.IOException;
  12. 12
    import java.net.URL;
  13. 13
    import java.util.Arrays;
  14. 14
    import java.util.List;
  15. 15
  16. 16
    /**
  17. 17
    * @author :fan
  18. 18
    * @description: TODO
  19. 19
    * @date :2019/10/20 15:10
  20. 20
    */
  21. 21
    public class PDFImageTest1 {
  22. 22
    public static void main(String[] args) throws IOException, DocumentException {
  23. 23
    String pdfname="E:\\Desktop\\pdftest.pdf";
  24. 24
    //查找签名位置
  25. 25
    float[] position= PdfKeywordFinder.getAddImagePositionXY(pdfname,"甲方签字:");
  26. 26
    //Read file using PdfReader
  27. 27
    PdfReader pdfReader = new PdfReader(pdfname);
  28. 28
    System.out.println("x:"+position[1]+" y:"+position[2]);
  29. 29
    // float pageNum=positions.get(0)[0];
  30. 30
    // float x=positions.get(0)[1];
  31. 31
    // float y=positions.get(0)[2];
  32. 32
    // float charWidth=positions.get(0)[3];
  33. 33
  34. 34
    // System.out.println(Arrays.toString(positions.get(0)));
  35. 35
    // float temp[]=PdfKeywordFinder.getKeywordPositionXY(pdfname,"甲方签字");
  36. 36
    // for(int i=0;i<temp.length;i++){
  37. 37
    // System.out.println(temp[i]);
  38. 38
    // }
  39. 39
  40. 40
  41. 41
    //Modify file using PdfReader
  42. 42
    PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileOutputStream("E:\\Desktop\\modified.pdf"));
  43. 43
  44. 44
    Image image = Image.getInstance("E:\\Desktop\\SignaturePicture\\testlogo.jpg");
  45. 45
    //Fixed Positioning
  46. 46
    image.scaleAbsolute(100, 50);
  47. 47
    //Scale to new height and new width of image
  48. 48
    image.setAbsolutePosition(position[1], position[2]);
  49. 49
  50. 50
    System.out.println("pages:"+pdfReader.getNumberOfPages());
  51. 51
  52. 52
  53. 53
    PdfContentByte content = pdfStamper.getUnderContent((int) position[0]);
  54. 54
    content.addImage(image);
  55. 55
  56. 56
  57. 57
    pdfStamper.close();
  58. 58
    }
  59. 59
    }

参考:使用iText库创建PDF文件 

测试结果:

关键字(keyword):“甲方签名:”

插入图片:

插入结果:

 

查找位置的另一种参考:

java提取PDF文字坐标

发布了79 篇原创文章 · 获赞 13 · 访问量 2万+