使用muPDF实现curl/flip效果

11
我将使用muPDF来阅读我的应用程序中的PDF文件。我不喜欢它默认的动画效果(水平切换)。在另一方面,我发现this是一个出色的图像翻页库,以及this项目能够实现布局的翻转效果。
在翻页示例项目中,在CurlActivity中,所有数据都是图像,并像这样在PageProvider中设置:
private class PageProvider implements CurlView.PageProvider {

    // Bitmap resources.
    private int[] mBitmapIds = { R.drawable.image1, R.drawable.image2,
            R.drawable.image3, R.drawable.image4};

并像这样使用它:

private CurlView mCurlView;
mCurlView = (CurlView) findViewById(R.id.curl);
mCurlView.setPageProvider(new PageProvider());

CurlView继承自GLSurfaceView并实现了View.OnTouchListener, CurlRenderer.Observer

但在muPDF中,如果我没记错的话,数据存储在core对象中。 coreMuPDFCore类的实例。可以像这样使用:

MuPDFReaderView mDocView;
MuPDFView pageView = (MuPDFView) mDocView.getDisplayedView();
mDocView.setAdapter(new MuPDFPageAdapter(this, this, core));

MuPDFReaderView继承自ReaderView,而ReaderView则继承自AdapterView<Adapter>并实现了GestureDetector.OnGestureListener, ScaleGestureDetector.OnScaleGestureListener, Runnable

我的问题是在MuPDF中如何使用卷曲效果?我应该从哪里逐页获取页面并将其转换为位图?然后更改MuPDF中Adapter的方面以CurlView为例。

在翻转示例项目中,在FlipHorizontalLayoutActivity中(我也喜欢这种效果),我们有以下内容:

private FlipViewController flipView;
flipView = new FlipViewController(this, FlipViewController.HORIZONTAL);
flipView.setAdapter(new TravelAdapter(this));
setContentView(flipView);

FlipViewController扩展了AdapterView<Adapter>,并在TravelAdapter中设置数据,该适配器扩展了BaseAdapter

之前没有人做过吗?或者有人可以帮我完成这个任务吗?!

编辑:

我发现另一个名为fbreaderJ的带卷曲效果的开源PDF阅读器。它的开发者说:“一个允许在FBReader中打开PDF文件的附加模块。基于radaee pdf库。

我感到困惑!因为radaeepdf是闭源的,而downloadable project仅用于演示,并且插入的用户名和密码是为此软件包而设定的。 人们想要更改整个fbreader项目,例如软件包名称。

另一个让我困惑的问题是,这个附加模块的源代码在哪里?!

无论如何,如果有人想帮助我,fbreader做得非常好。

编辑:

我与开发muPDF(或其中一位开发者)的Robin Watts进行了交谈,他说:

你读过platform/android/ClassStructure.txt吗?MuPDF主要是一个C库。标准API因此是C API。我们没有将该API完全暴露给Java(这将是最好的解决方案,我已经做了一些工作,但由于时间不足而未完成),而是实现了MuPDFCore来封装我们需要的部分。MuPDFCore处理打开PDF文件并从中获取位图以在视图中使用的部分,或者更确切地说,MuPDFCore返回“视图”,而不是“位图”。如果您需要位图,则需要在MuPDFCore中进行更改。

更改MuPDFReaderView类的一小部分时会出现太多错误。我感到困惑!这些彼此相关。

请回答更加精确。

编辑:

赏金已过期。


你有没有解决方案? - Anand Savjani
@AnandSavjani 我没有测试过被勾选的答案,但它似乎可以工作。 - Dr.jacky
2个回答

2
如果muPDF不支持将渲染输出为位图,那么你只能将其渲染到常规视图并截屏成位图,如下所示:
View content = findViewById(R.id.yourPdfView);
Bitmap bitmap = content.getDrawingCache();

然后将此位图用作您其他库的输入。

谢谢DKIT,我知道如何将视图转换为位图,但我想要更详细的答案。请参见编辑后的问题。 - Dr.jacky

1
我应该从哪里获取页面并将其转换为位图?
在我们的应用程序(报纸应用程序)中,我们使用MuPDF来呈现PDF文件。 工作流程如下:
1. 下载PDF文件(每个报纸页面有一个PDF文件) 2. 使用MuPDF进行渲染 3. 将位图保存到文件系统 4. 从文件系统加载位图作为视图的背景图像
因此,最终我们使用的是MuPDFCore.java及其方法drawPage(...)和onDestroy()。
这就是你想知道的吗?还是我错过了什么?
编辑: 1. 我认为没有必要发布如何下载文件的代码。但是,在下载后,我会向Renderqueue添加一个RenderTask(扩展自Runnable),并触发该队列。 RenderTask需要一些用于渲染的信息:
/**
 * constructs a new RenderTask instance
 * @param context: you need Context for MuPdfCore instance
 * @param pageNumber
 * @param pathToPdf 
 * @param renderCallback: callback to set bitmap to the view after    
 * rendering
 * @param heightOfRenderedBitmap: this is the target height
 * @param widthOfRenderedBitmap: this is the target width
 */
public RenderTask (Context context, Integer pageNumber, String pathToPdf, IRenderCallback,    
                   renderCallback, int heightOfRenderedBitmap, 
                   int widthOfRenderedBitmap) {

    //store things in fields
}

2.) + 3.) 渲染队列将RenderTask封装在一个新线程中并启动它。因此,RenderTask的run方法将被调用:

@Override
public void run () {

    //do not render it if file exists
    if (exists () == true) {

        finish();
        return;
    }


    Bitmap bitmap = render();

    //if something went wrong, we can't store the bitmap
    if (bitmap == null) {

        finish();
        return;
    }

    //now save the bitmap
    // in my case i save the destination path in a String field
    imagePath = save(bitmap, new File("path/to/your/destination/folder/" + pageNumber + ".jpg"));

    bitmap.recycle();
    finish();
}

/**
 * let's trigger the callback
 */
private void finish () {

    if (renderCallback != null) {

        // i send the whole Rendertask to callback
        // maybe in your case it is enough to send the pageNumber or path to    
        // renderend bitmap   
        renderCallback.finished(this); 
    }

}

/**
 * renders a bitmap
 * @return
 */
private Bitmap render() {

    MuPDFCore core = null;
    try {
        core = new MuPDFCore(context, pathToPdf);
    } catch (Exception e) {

        return null;
    }

    Bitmap bm = Bitmap.createBitmap(widthOfRenderedBitmap, heightOfRenderedBitmap, Config.ARGB_8888);
    // here you render the WHOLE pdf cause patch-x/-y == 0
    core.drawPage(bm, 0, widthOfRenderedBitmap, heightOfRenderedBitmap, 0, 0, widthOfRenderedBitmap, heightOfRenderedBitmap, core.new Cookie());
    core.onDestroy();
    core = null;
    return bm;
}

/**
 * saves bitmap to filesystem
 * @param bitmap
 * @param image
 * @return
 */
private String save(Bitmap bitmap, File image) {

    FileOutputStream out = null;
    try {
        out = new FileOutputStream(image.getAbsolutePath());
        bitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
        return image.getAbsolutePath();

    } catch (Exception e) {

        return null;
    }

    finally {
        try {
            if (out != null) {
                out.close();
            }
        } catch(Throwable ignore) {}

    }
}  

}

4.) 我认为没有必要发布代码来设置位图作为视图的背景。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接