安卓系统中的高分辨率屏幕截图

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());
    }
}

1
为什么要截屏呢?在安卓上有许多库可以创建PDF文件。只需从Webview获取HTML页面的内容,然后使用任何库来创建PDF即可。这种截屏技术会带来更多新问题,而不是解决您原来的问题。 - mudit
我尝试了很多方法,但都没有找到一个完美的将HTML转换为PDF的方式。如果您有任何想法,请向我解释一下。 - Sniper
搜索相关内容时,偶然发现了pdfcrowd.com。我尝试将一些常见的网站如谷歌和雅虎进行转换,效果不错。他们似乎有一个API接口。虽然我不确定它是否可行,但值得一试。 - rahules
4个回答

11

更新:请参阅编辑3,以获得对原始问题的回答

有两种选择:

  1. 使用库将HTML转换为PDF。这绝对是最好的选择,因为它将(很可能)将文本保留为矢量。

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

对于HTML到PDF,wkhtmltopdf看起来是一个不错的选择,但它依赖于Qt,而您实际上不能在Android上使用Qt。还有一些其他库,但我怀疑它们对PDF渲染的支持不太好。

要获取高分辨率的webview,可以尝试创建自己的WebView,并调用onMeasure(...)onLayout(...)并传递适当的参数,以便视图真正大。然后调用onDraw(myOwnCanvas),Webview将向您的画布绘制自身,该画布可以由Canvas.setBitmap()支持的位图支持。

您可以使用类似以下内容将状态复制到新的WebView中:

screenshotterWebview.onRestoreInstanceState(mWebView.onSaveInstanceState());
Orrr甚至可能使用相同的 WebView ,只需暂时将其调整为大型尺寸,将其 onDraw()到您的画布上,然后再次调整其大小。 这变得非常狡猾! 如果它太大,您可能会遇到内存问题。
编辑1:
我想到了第三个选项,正是您想要的选项,但这有点强硬。 您可以创建一个自定义的 Canvas ,将其写入PDF。 实际上,这几乎是容易的,因为底层 Canvas 是Skia,它实际上包括PDF后端。 不幸的是,在Android上您无法访问它,因此您基本上必须在Android上构建自己的副本(有说明),并复制/覆盖所有 Canvas 方法,以指向您的Skia而不是Android的。 请注意,有一种诱人的 Picture.writeToStream()方法,可序列化Skia数据,但不幸的是,该格式不支持向前或向后兼容,因此如果您使用它,则代码可能仅适用于某些版本的Android。
如果我有完全可工作的代码,我会进行更新。
编辑2:
实际上不可能创建自己的“截取” Canvas 。 我开始做这件事,并经历了序列化所有函数调用的烦琐过程。 有些您无法做到,因为它们是隐藏的,但是这些看起来不重要。 但是在最后,我发现只有 Path 可以进行序列化,结果发现它是只写的。 对我来说,这似乎是个致命缺陷,因此唯一的选择是解释 Picture.writeToStream()的结果。 幸运的是,该格式仅有两个版本,并且几乎相同。
编辑3-获取视图的高分辨率位图的真正简单方法
好吧,事实证明,只需获取视图(可以是整个应用程序)的高分辨率位图就很容易。 这是如何获得双倍分辨率的方法。 显然,所有位图看起来有点垃圾,但文本以全分辨率呈现:
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倍分辨率渲染)。


对于Edit 3:为什么你上传0%质量的位图?猜测应该更像这样:bitmap.compress(Bitmap.CompressFormat.PNG, 100, myOutputStream); - Rappel
PNG的质量被忽略了。 - Timmmm

4
当您抓取视图时,只会捕获屏幕范围(由于控件重量和Android呈现管道)。
将截图捕获以转换为PDF是一种棘手的方法。我认为有两种更合理的解决方案。 解决方案1 编写解析器(很简单),将WebView内容(即HTML)转换为iText格式。
您可以参考这篇文章获取更多信息。
http://www.vogella.com/articles/JavaPDF/article.html 此外,您可以使用REGEX编写解析器并提供自己的方法,例如parseTableparseImage等。 解决方案2 需要互联网连接 提供一个通过PHP或C#将HTML转换为PDF的URL(或webservice),该语言拥有许多不错的库。接下来,您可以向客户端(Android设备)发送下载链接。
因此,您还可以从服务器端动态添加一些标记、横幅等到PDF中。

3
当然,使用这个:
Bitmap bitmap;
View v1 = MyView.getRootView();
v1.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);

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


2
这不是高分辨率。 - Timmmm

3

屏幕截图就是你设备显示屏的图片,通常取决于你手机的绝对像素,如果你的手机是480x800,则截图将相同,并且通常适用于所有情况。


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