18

有没有办法获得活动中某个视图的高分辨率屏幕截图。

我想将我的 webview 的 html 内容转换为 PDF。为此,我尝试截取 webview 内容的屏幕截图,然后使用 itext 将其转换为 PDF。生成的 PDF 不是更清晰。

我的代码:

    protected void takeimg() {
    Picture picture = mWebView.capturePicture();
    Bitmap b = Bitmap.createBitmap(picture.getWidth(), picture.getHeight(),
            Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);
    picture.draw(c);

    // byte[] bt = b.getNinePatchChunk();

    // Bitmap b;
    // View v1 = mWebView.getRootView();
    // v1.setDrawingCacheEnabled(true);
    // b = Bitmap.createBitmap(v1.getDrawingCache());
    // v1.setDrawingCacheEnabled(false);

    FileOutputStream fos = null;
    try {
        File root = new File(Environment.getExternalStorageDirectory(),
                "Sample");

        if (!root.exists()) {
            root.mkdir();
        }
        String sdcardhtmlpath = root.getPath().toString() + "/"
                + "temp_1.png";

        fos = new FileOutputStream(sdcardhtmlpath);
        // fos = openFileOutput("samsp_1.jpg", MODE_WORLD_WRITEABLE);
        if (fos != null) {
            b.compress(Bitmap.CompressFormat.PNG, 100, fos);

            // fos.write(bt);
            fos.close();
        }
    } catch (Exception e) {
        Log.e("takeimg", e.toString());
        e.printStackTrace();

    }
}


protected void pdfimg() {
    Document mydoc = new Document(PageSize.A3);
    try {
        File root = new File(Environment.getExternalStorageDirectory(),
                "Sample");

        if (!root.exists()) {
            root.mkdir();
        }
        String sdcardhtmlpath = root.getPath().toString() + "/";
        mydoc.setMargins(0, 0, 0, 0);
        PdfWriter.getInstance(mydoc, new FileOutputStream(sdcardhtmlpath
                + PDFfilename));
        mydoc.open();
        Image image1 = Image.getInstance(sdcardhtmlpath + "temp_1.jpg");
        image1.scalePercent(95f);

        mydoc.add(image1);
        // mydoc.newPage();

        mydoc.close();
    } catch (Exception e) {
        Log.e("pdi name", e.toString());
    }
}
4

4 回答 4

11

更新:有关 op 原始问题的答案,请参阅编辑 3

有两种选择:

  1. 使用库将 HTML 转换为 PDF。这是迄今为止最好的选择,因为它将(可能)将文本保存为向量。

  2. 获取 HTML 的高分辨率渲染并将其保存为 PNG(当然不是 PDF!)。

对于 HTML 到 PDF,wkhtmltopdf看起来是一个不错的选择,但它依赖于 Qt,而您无法在 Android 上真正使用它。还有其他一些库,但我怀疑它们是否能很好地渲染 PDF。

为了获得高分辨率的 web 视图,您可以尝试创建自己的WebView并调用onMeasure(...)onLayout(...)传递适当的参数,以便视图非常大。然后调用onDraw(myOwnCanvas),webview 将自己绘制到您的画布上,这可以由Bitmapusing支持Canvas.setBitmap()

您可能可以WebView使用类似的方式将状态复制到新的

screenshotterWebview.onRestoreInstanceState(mWebView.onSaveInstanceState());

或者甚至可以使用相同的WebView,只是暂时将其调整为大,onDraw()将其调整到您的画布,然后再次调整大小。但这变得非常hacky!

如果你把它做得太大,你可能会遇到内存问题。

编辑 1

我想到了第三种,正是你想要的选择,但它有点硬核。您可以创建一个Canvas写入 PDF 的自定义文件。事实上,这几乎很容易,因为底层Canvas是 Skia,它实际上包括一个 PDF 后端。不幸的是,您无法在 Android 上访问它,因此您基本上必须在 Android 上构建自己的副本(有说明),并复制/覆盖所有Canvas方法以指向您的 Skia 而不是 Android。请注意,有一种诱人的Picture.writeToStream()方法可以序列化 Skia 数据,但不幸的是,这种格式不能向前或向后兼容,因此如果您使用它,您的代码可能只能在少数几个版本的 Android 上运行。

如果/当我有完整的工作代码时,我会更新。

编辑 2

其实自己做“拦截”是不可能的Canvas。我开始这样做并经历了序列化所有函数调用的繁琐过程。有些你不能做,因为它们是隐藏的,但那些看起来并不重要。但是最后我开始序列化Path只是发现它是只写的。这对我来说似乎是一个杀手,所以唯一的选择是解释Picture.writeToStream(). 幸运的是,该格式只有两个版本在使用,而且几乎完全相同。

编辑 3 - 获得高分辨率Bitmap视图的非常简单的方法

好的,事实证明只是获得视图的高分辨率位图(可以是整个应用程序)是微不足道的。这是获得双分辨率的方法。显然所有的位图看起来都有点垃圾,但文本以全分辨率呈现:

View window = activity.getWindow().getDecorView()

Canvas bitmapCanvas = new Canvas();
Bitmap bitmap = Bitmap.createBitmap(window.getWidth()*2, window.getHeight()*2, Bitmap.Config.ARGB_8888);

bitmapCanvas.setBitmap(bitmap);
bitmapCanvas.scale(2.0f, 2.0f);
window.draw(bitmapCanvas);

bitmap.compress(Bitmap.CompressFormat.PNG, 0, myOutputStream);

奇迹般有效。我现在已经放弃了获取带有矢量文本的 PDF 屏幕截图。这当然是可能的,但非常困难。相反,我正在努力获得一个高分辨率 PSD,其中每个绘制操作都是一个单独的图层,这应该更容易。

编辑 4

哇,这有点长,但是成功了!我生成了一个.xcf(GIMP) 和 PDF,其中每一层都是不同的画布绘图操作。它不像我预期的那么细粒度,但仍然非常有用!

实际上,我的代码只输出全尺寸的 PNG,我在 GIMP 中使用“作为图层打开...”和“自动裁剪图层”来制作这些文件,但当然,如果您愿意,您可以在代码中执行此操作。我想我会把它变成一篇博客文章。

下载GIMPPhotoshop演示文件(以 3 倍分辨率渲染)。

于 2012-11-28T10:11:52.993 回答
4

当您捕获视图时,只会捕获屏幕绑定(由于控制权重和 android 渲染管道)。

捕获屏幕截图以转换为 PDF 是一种棘手的方法。我认为两种方式是更合理的解决方案。

解决方案#1

编写一个解析器(很简单)将 webview 内容(即 HTML)转换为 iText 格式。
您可以参考这篇文章了解更多信息。
http://www.vogella.com/articles/JavaPDF/article.html

此外,要编写解析器,您可以使用 REGEX 并提供您自己的方法,如parseTable, parseImage, ...

解决方案#2 需要互联网

提供一个 URL(或 web 服务)以使用 PHP 或 C# 将 HTML 转换为 PDF,其中包含许多不错的库。接下来,您可以将下载链接发送到客户端(Android 设备)。

因此,您还可以从服务器端向 PDF 动态添加一些标签、横幅等。

于 2012-11-28T05:59:04.567 回答
3

屏幕截图只不过是设备显示的图片,通常取决于您手机的绝对像素,如果您的手机是 480x800 屏幕截图将是相同的,并且通常适用于所有场景。

于 2012-11-20T06:58:53.657 回答
3

当然,使用这个:

Bitmap bitmap;
View v1 = MyView.getRootView();
v1.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);

这里 MyView 是您需要截屏的视图。

于 2012-11-20T07:00:04.697 回答