k2pdfopt是一个文本重排库,Willus.com's K2pdfopt 这是主页.提供多平台的程序.
mupdf的文本重排,对于非扫描版pdf,可以直接得到文本.但它是按行获取的,虽然可以得到html,要得到一个较好的可视文本,还要处理行的合并.对于扫描版的pdf,它就做不了了.
kindle有一个文本重排,它用的就是k2pdfopt,可以将扫描版的pdf重新排版,效果不错.
在使用中,发现,对于一些程序较长的行,或者公式,它的截取就没有那么智能了,毕竟它是按行处理的,一个程序的pdf书,通常一个方法很长,分割后不容易看.但是对于其它的pdf分割效果不错.
官方提供多平台的app,可以将pdf进行分割,组合,重新生成pdf,适用不同的页面.
对于android平台,axet / android-k2pdfopt · GitLab 这个大侠提供了相应的库,mvn上可以直接获取,aar只有300多k.使用方便.在千元机上,2500*3000的图片,生成dpi150,高宽是720*1500左右的新图片要600多毫秒,效率还行
多说无益,直接上代码:
private void testPdfOpt(CustomView customView) {
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.test1);
DisplayMetrics d = getResources().getDisplayMetrics();
test(bmp, customView.getWidth(), customView.getHeight(), d.densityDpi);
}
先解析一个测试图片
private void test(Bitmap bitmap, int viewWidth, int viewHeight, int densityDpi) {
long start = System.currentTimeMillis();
K2PdfOpt opt = new K2PdfOpt();
//最终会形成,以viewWidth为基准的竖长图片,dpi=272/2时纸的大小是:9.4 x 10.2
//dpi越大,时间越久,
//count:2, dpi:272, view.w-h:720-1555, bmp.w-h:2550-2781, cos:640
opt.create(viewWidth, viewHeight, densityDpi / 2);
opt.load(bitmap);
int count = opt.getCount();
List<Bitmap> bitmaps = new ArrayList<>();
for (int i = 0; i < opt.getCount(); i++) {
Bitmap bmp = opt.renderPage(i);
bitmaps.add(bmp);
}
System.out.printf("count:%s, dpi:%s, view.w-h:%s-%s, bmp.w-h:%s-%s, cos:%s%n",
count, densityDpi, viewWidth, viewHeight, bitmap.getWidth(), bitmap.getHeight(), (System.currentTimeMillis() - start));
for (Bitmap bmp : bitmaps) {
BitmapUtils.saveBitmapToFile(bmp, new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + System.currentTimeMillis() + ".png"));
bmp.recycle();
}
}
关键四步:
opt.create(viewWidth, viewHeight, densityDpi / 2); opt.load(bitmap); opt.getCount(); opt.renderPage(i);
创建一个画布的大小,我以手机当前的view全屏的大小为基准,dpi取手机dpi的一半就可以了,这样字不会太大,时间也不会很长.
然后加载原图.
得到分割的数量.
然后针对每一个分割的图片,渲染出来即可.
至于渲染后的图片,是直接显示,还是先存文件,生成新的pdf,都可以,直接显示的话,考虑到机器的性能,并不是一个很好的效果.像这样的一张图片,时间在600多毫秒,而解析pdf的图片,mupdf10毫秒足够,滚动的效果可想而知了.
生成的图片可以使用前面文章生成pdf的方式,直接生成新的.
也可以通过前面的图片目录浏览进行显示.