简体   繁体   English

Android中的高分辨率屏幕截图

[英]High resolution screen shot in Android

Is there any way to get a high resolution screen shot of a certain view in an activity. 有什么方法可以获取活动中某个视图的高分辨率屏幕截图。

I want to convert html content of my webview to PDF. 我想将Webview的html内容转换为PDF。 For that I tried to take screen shot of the webview content and then converted it to PDF using itext. 为此,我尝试拍摄Webview内容的屏幕截图,然后使用itext将其转换为PDF。 The resulted PDF is not in much more clarity. 生成的PDF不够清晰。

My code: 我的代码:

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

Update: See Edit 3 for an answer to op's original question 更新:请参阅编辑3,以获取op原始问题的答案

There are two options: 有两种选择:

  1. Use a library to convert the HTML to PDF. 使用库将HTML转换为PDF。 This is by far the best option, since it will (probably) preserve text as vectors. 到目前为止,这是最好的选择,因为它将(可能)将文本保留为矢量。

  2. Get a high resolution render of the HTML and save it as a PNG (not PDF surely!). 获取高分辨率的HTML渲染,并将其另存为PNG(当然不是PDF!)。

For HTML to PDF, wkhtmltopdf looks like a good option, but it relies on Qt which you can't really use on Android. 对于HTML到PDF, wkhtmltopdf看起来是一个不错的选择,但是它依赖于Qt,而您实际上无法在Android上使用它。 There are some other libraries but I doubt they do the PDF rendering very well. 还有其他一些库,但我怀疑它们能否很好地呈现PDF。

For getting a high-res webview, you could try creating your own WebView and calling onMeasure(...) and onLayout(...) and pass appropriate parameters so the view is really big. 为了获得高分辨率的webview,您可以尝试创建自己的WebView并调用onMeasure(...)onLayout(...)并传递适当的参数,以使视图确实很大。 Then call onDraw(myOwnCanvas) and the webview will draw itself to your canvas, which can be backed by a Bitmap using Canvas.setBitmap() . 然后调用onDraw(myOwnCanvas)onDraw(myOwnCanvas)将自己绘制到画布上,可以使用Canvas.setBitmap()Bitmap支持。

You can probably copy the state into the new WebView using something like 您可能可以使用以下方式将状态复制到新的WebView

screenshotterWebview.onRestoreInstanceState(mWebView.onSaveInstanceState());

Orrr it may even be possible to use the same WebView , just temporarily resize it to be large, onDraw() it to your canvas, and resize it back again. 或者,甚至可以使用相同的WebView ,只是暂时将其调整为较大的大小,然后将其onDraw()应用于画布,然后再次调整其大小。 That's getting very hacky though! 不过,这变得非常骇人听闻!

You might run into memory issues if you make it too big. 如果太大,可能会遇到内存问题。

Edit 1 编辑1

I thought of a third, exactly-what-you-want option, but it's kind of hardcore. 我想到了第三个完全您想要的选项,但这有点难。 You can create a custom Canvas , that writes to a PDF. 您可以创建自定义的Canvas ,将其写入PDF。 In fact, it is almost easy, because underlying Canvas is Skia, which actually includes a PDF backend. 实际上,这几乎很容易,因为底层的Canvas是Skia,它实际上包括一个PDF后端。 Unfortunately you don't get access to it on Android, so you'll basically have to build your own copy of it on Android (there are instructions), and duplicate/override all the Canvas methods to point to your Skia instead of Androids. 不幸的是,您无法在Android上访问它,因此,您基本上必须在Android上构建自己的副本(有说明),并复制/覆盖所有Canvas方法以指向Skia(而不是Android)。 Note that there is a tempting Picture.writeToStream() method which serializes the Skia data, but unfortunately this format is not forwards or backwards compatible so if you use it your code will probably only work on a few versions of Android. 请注意,有一个诱人的Picture.writeToStream()方法可对Skia数据进行序列化,但不幸的是,此格式不兼容向前或向后兼容,因此,如果使用它,您的代码可能仅在少数版本的Android上有效。

I'll update if/when I have fully working code. 如果有完整的代码,我会更新。

Edit 2 编辑2

Actually it is impossible to make your own "intercepting" Canvas . 实际上,不可能制作自己的“拦截” Canvas I started doing it and went through the tedious process of serializing all function calls. 我开始这样做,并经历了所有函数调用序列化的乏味过程。 A few you can't do because they are hidden, but those didn't look important. 一些您无法执行,因为它们是隐藏的,但是看起来并不重要。 But right at the end I came to serializing Path only to discover that it is write-only. 但是,最后,我来对Path进行序列化只是为了发现它是只写的。 That seems like a killer to me, so the only option is to interpret the result of Picture.writeToStream() . 在我看来,这似乎是一个杀手er,所以唯一的选择是解释Picture.writeToStream()的结果。 Fortunately there are only two versions of that format in use, and they are nearly identical. 幸运的是,仅使用了该格式的两个版本,它们几乎相同。

Edit 3 - Really simple way to get a high resolution Bitmap of a view 编辑3-真正简单的方法来获取视图的高分辨率Bitmap

Ok, it turns out just getting a high res bitmap of a view (which can be the entire app) is trivial. 好的,事实证明,获取视图的高分辨率位图(可以是整个应用程序)是微不足道的。 Here is how to get double resolution. 这是获得双分辨率的方法。 Obviously all the bitmaps look a bit crap, but the text is rendered at full resolution: 显然,所有位图看起来都有些废话,但文本以全分辨率呈现:

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

Works like a charm. 奇迹般有效。 I've now given up on getting a PDF screenshot with vector text. 我现在已经放弃了获取带有矢量文本的PDF屏幕截图的方法。 It's certainly possible, but very difficult. 当然有可能,但是非常困难。 Instead I am working on getting a high-res PSD where each draw operation is a separate layer, which should be much easier. 相反,我正在努力获得高分辨率PSD,其中每个绘制操作都是一个单独的层,这应该容易得多。

Edit 4 编辑4

Woa this is getting a bit long, but success! 哇,这有点长了,但是成功了! I've generated an .xcf (GIMP) and PDF where each layer is a different canvas drawing operation. 我生成了一个.xcf (GIMP)和PDF,其中每一层都是一个不同的画布绘制操作。 It's not quite as fine-grained as I was expecting, but still, pretty useful! 它不像我期望的那么细,但是仍然非常有用!

Actually my code just outputs full-size PNGs and I used "Open as layers..." and "Autocrop layer" in GIMP to make these files, but of course you can do that in code if you like. 实际上,我的代码只是输出完整尺寸的PNG,我在GIMP中使用“打开为图层...”和“自动裁剪图层”来制作这些文件,但是当然,如​​果愿意,也可以在代码中完成。 I think I will turn this into a blog post. 我想我会将其转变为博客文章。

Download the GIMP or Photoshop demo file (rendered at 3x resolution). 下载GIMPPhotoshop演示文件(以3倍分辨率渲染)。

When you capture the view, just screen bound will capture ( due to control weight and android render pipeline ). 捕获视图时,将捕获屏幕边界(由于控件权重和android渲染管道)。

Capturing screenshot for converting to PDF is tricky way. 捕获屏幕快照以转换为PDF是棘手的方法。 I think two way is more reasonable solutions. 我认为两种方式是更合理的解决方案。

Solution #1 解决方案1

Write a parser ( it's simple ) to convert webview content ( that is HTML ) to iText format. 编写一个解析器(很简单)以将Webview内容(即HTML)转换为iText格式。
You can refer to this article for more information. 您可以参考本文以获取更多信息。
http://www.vogella.com/articles/JavaPDF/article.html http://www.vogella.com/articles/JavaPDF/article.html

Also to write a parser you can use REGEX and provide your own methods like parseTable , parseImage , ... 同样要编写一个解析器,您可以使用REGEX并提供您自己的方法,例如parseTableparseImage ,...

Solution #2 Internet Required 解决方案2 需要互联网

Provide a URL ( or webservice ) to convert HTML to PDF using PHP or C# that has a lot of nice libraries. 提供一个URL(或webservice),以使用具有许多不错的库的PHP或C#将HTML转换为PDF。 Next you can send download link to the Client ( Android Device ). 接下来,您可以将下载链接发送到客户端(Android设备)。

So you can also dynamically add some Tags, Banners, ... to the PDF from server side. 因此,您还可以从服务器端向PDF动态添加一些标签,横幅等。

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

Sure, Use this: 当然可以,使用这个:

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

Here MyView is the View you need a screenshot of. 这里MyView是您需要其屏幕截图的View。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM