不可複製的PDF轉成雙層可複製PDF

小樹禾小央發表於2023-11-01

有些PDF是透過掃描或者虛擬印表機生成的,這些PDF不可複製裡邊的內容

市面上的工具一般都是收費或者有水印,所以就萌生了自己搞一個的想法:

使用了以下三個開源庫

  • PdfiumViewer PDF預覽及可編輯PDF的提取
  • PDFsharp 生成PDF
  • PaddleSharp 對圖片OCR識別

 

大概思路是:

用PdfiumViewer 渲染顯示,並轉PDF為圖片;

使用PaddleSharp 對提取圖片的內容及bbox座標;

把座標根據縮放比轉成相對於PDF的座標,並使用PDFsharp 重新生成PDF,如需要保持原有格式需要把1轉成的圖片重新回寫到生成的pdf,文字層為ocg層;

實現雙層pdf的效果;

讀取PDF到到記憶體流:

  private PdfDocument OpenDocument(string fileName)
  {
      try
      {
          return PdfDocument.Load(this, new MemoryStream(File.ReadAllBytes(fileName)));
      }
      catch (Exception ex)
      {
          MessageBox.Show(this, ex.Message, Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
          return null;
      }
  }

 

PDF轉圖片:

//圖片dpi要相對大些,這樣ocr識別的更清晰
int dpiX = 96 * 5; int dpiY = 96 * 5; var pdfWidth = (int)document.PageSizes[page].Width * 4 / 3; var pdfHeight = (int)document.PageSizes[page].Height * 4 / 3; var rotate = PdfRotation.Rotate0; var flags = PdfRenderFlags.Annotations | PdfRenderFlags.CorrectFromDpi; using (var image = document.Render(page, pdfWidth, pdfHeight, dpiX, dpiY, rotate, flags)){}

OCR識別:

  byte[] sampleImageData = ImageToByte(image);
  FullOcrModel model = LocalFullModels.ChineseV3;
  using (PaddleOcrAll all = new PaddleOcrAll(model, PaddleDevice.Mkldnn())
  {
      AllowRotateDetection = true, /* 允許識別有角度的文字 */
      Enable180Classification = false, /* 允許識別旋轉角度大於90度的文字 */
  })
  {
     // Load local file by following code:
     using (Mat src = Cv2.ImDecode(sampleImageData, ImreadModes.Color))
      {
          PaddleOcrResult result = all.Run(src);
          return result;
      }
  }

圖片轉成流:

 private byte[] ImageToByte(System.Drawing.Image image)
 {
     MemoryStream ms = new MemoryStream();
     if (image == null)
         return new byte[ms.Length];
     image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
     byte[] BPicture = new byte[ms.Length];
     BPicture = ms.GetBuffer();
     return BPicture;
 }

轉換bbox座標到PDF座標:bbox座標是相對於圖片的座標,所以縮放比是pdf和圖片的之間的轉換,圖片大小變化,此函式需跟著調整

 private System.Drawing.RectangleF ConvertToPDFSize(System.Drawing.RectangleF rectangle, float dpiX, float dpiY, PdfRotation rotate, PdfRenderFlags flags)
 {
     var width = rectangle.Width;
     var height = rectangle.Height;
     var x = rectangle.X;
     var y = rectangle.Y;
     if ((flags & PdfRenderFlags.CorrectFromDpi) != 0)
     {
         width = (width / dpiX * 72);
         height = (height / dpiY * 72);
         x = (x / dpiX * 72);
         y = (y / dpiY * 72);
     }
     return new RectangleF(x, y, width, height);
 }

bbox座標框選示例:

由於OCR的限制:轉雙層pdf只能在x64系統執行,不使用OCR可執行x86和x64,

工具功能:

  1. 可提取和框選提取可複製和不可複製pdf;
  2. 可轉換不可複製的pdf為雙層可複製pdf;
  3. 可轉換不可複製的pdf為可複製pdf;
  4. 載入圖片並提取標註提取內容;

直接下載地址:
https://cloud.189.cn/web/share?code=MZvMb2ZNRbMn(訪問碼:y9st)
也可按照下放程式碼自己編譯使用,遵循MIT協議
歡迎Start、PR
原始碼地址:https://github.com/1000374/HM.PdfOcr

相關文章