文本pdf转epub的一点体会(续)

如果同时提取文本和图片,需要实现IRenderListener接口里的RenderImage和RenderText方法。

RenderImage方法:

        public void RenderImage(ImageRenderInfo info)
        {
            PdfImageObject image = info.GetImage();
            Matrix matrix = info.GetImageCTM();
            var fileType = image.GetFileType();
            fileType = string.IsNullOrWhiteSpace(fileType) ? "png" : fileType.ToLower();
            var pic = image.GetDrawingImage();
            var x = matrix[Matrix.I31];
            var y = matrix[Matrix.I32];
            var width = matrix[Matrix.I11];
            var height = matrix[Matrix.I22];
            //排除页眉页脚的无用图片,数据是调试出来的
            if (width > 126f && width < 128f && height > 140f && height < 142f)
            {
                File.WriteAllBytes("foo."+fileType, image.GetImageAsBytes());
            }
        }    

提取文本时,可能会碰到一个问题:如何识别“换行”?Pdf里是不存在回车符这样的东西的,只能利用坐标来判断。在RenderText方法里:

        private int _lastOrientationMagnitude;
        private int _lastDistPerpendicular; 
       public void RenderText(TextRenderInfo info)
        {
            LineSegment segment = info.GetBaseline();
            var start = segment.GetStartPoint();
            var end = segment.GetEndPoint();

            Vector oVector = end.Subtract(start);
            if (oVector.Length == 0)
            {
                oVector = new Vector(1, 0, 0);
            }
            var orientationVector = oVector.Normalize();
            var orientationMagnitude = (int)(Math.Atan2(orientationVector[Vector.I2], orientationVector[Vector.I1]) * 1000);

            Vector origin = new Parser.Vector(0, 0, 1);
            var distPerpendicular = (int)(start.Subtract(origin)).Cross(orientationVector)[Vector.I3];

            if (orientationMagnitude != _lastOrientationMagnitude
                   || Math.Abs(distPerpendicular - _lastDistPerpendicular) > 10//这个10是调试出来的
               )
           {//换行了
              //做些什么
              _lastOrientationMagnitude = orientationMagnitude;
              _lastDistPerpendicular = distPerpendicular;
           }
         }

调用的代码:

            PdfReader reader = new PdfReader(pdf);
            int pages = reader.NumberOfPages;
            PdfReaderContentParser parser = new PdfReaderContentParser(reader);
            MyPdfRenderListener listener = new MyPdfRenderListener();
            for (int i = 1; i <= pages; i++)
            {
                parser.ProcessContent(i, listener);
            }

提取文本后,比较麻烦的是根据章节切割成单独的html。这个主要是用正则表达式来判断,但是很多书里的章节标志并不统一。比如前面是第一章,第一节这样,后面第N节后忽然又多了个(一),(二),(三)这样的章节标志,而第N+1节后又变成A, B, C这样的标志。所以只能反复调试。

如果pdf中有表格,用Acrobat另存为html的方法,提取效果最好,能够完整地保存表格的框格线。但是表格里的内容往往需要编程填入。

html和图片准备好后,可以用epub的制作软件制作,也可以编程生成epub需要的元数据。这个只需要查看一下随便哪个已有的epub的文件结构,不难实现。顺便提一下,epub所用css不支持display: flex,只好用display: inline-block,display:table-cell等代替。

总之,将文本pdf转成epub,虽可利用各种工具和编程实现一定程度的自动化,但因为每本书的情况都不同,没有统一的方法,代码也需要根据每本书的情况量身定做,可重用性比较差。

posted @ 2023-02-10 22:06  平静寄居者  阅读(146)  评论(0编辑  收藏  举报