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を参照してください。

2つのオプションがあります。

  1. ライブラリを使用してHTMLをPDFに変換します。これは(おそらく)テキストをベクトルとして保存するため、これが断然最良のオプションです。

  2. HTMLの高解像度レンダリングを取得し、PNGとして保存します(PDFではありません!)。

HTMLからPDFの場合、wkhtmltopdfは適切なオプションのように見えますが、Androidでは実際には使用できないQtに依存しています。他にもいくつかのライブラリがありますが、PDFレンダリングがうまく機能しているとは思えません。

高解像度のWebビューを取得するには、独自のWebビューを作成してWebView呼び出しonMeasure(...)onLayout(...)適切なパラメーターを渡して、ビューが非常に大きくなるようにすることができます。次にを呼び出すonDraw(myOwnCanvas)と、Webビューがキャンバスに描画されます。これは、Bitmapを使用してバックアップできますCanvas.setBitmap()

WebView次のようなものを使用して、状態を新しい状態にコピーできます。

screenshotterWebview.onRestoreInstanceState(mWebView.onSaveInstanceState());

または、同じものを使用してWebView、一時的にサイズを大きくonDraw()してキャンバスに合わせ、サイズを元に戻すことも可能です。しかし、それは非常にハッキーになっています!

大きくしすぎると、メモリの問題が発生する可能性があります。

編集1

私は3番目の、まさにあなたが望むオプションを考えましたが、それは一種のハードコアです。CanvasPDFに書き込むカスタムを作成できます。実際、基になるのはSkiaであり、実際にはPDFバックエンドが含まれているため、ほとんど簡単です。Canvas残念ながら、Androidではアクセスできないため、基本的にAndroidで独自のコピーを作成し(手順があります)、AndroidCanvasではなくSkiaを指すようにすべてのメソッドを複製/オーバーライドする必要があります。Skiaデータをシリアル化する魅力的なPicture.writeToStream()方法がありますが、残念ながら、この形式は下位互換性または下位互換性がないため、使用する場合、コードはおそらくAndroidのいくつかのバージョンでのみ機能します。

完全に機能するコードがある場合は更新します。

編集2

実際、独自の「インターセプト」を作成することは不可能Canvasです。私はそれを始め、すべての関数呼び出しをシリアル化するという面倒なプロセスを経ました。それらが隠されているためにできないいくつかのことですが、それらは重要に見えませんでした。しかし、最後に私はPathそれが書き込み専用であることを発見するためだけにシリアル化するようになりました。それは私にはキラーのように思えるので、唯一のオプションはの結果を解釈することですPicture.writeToStream()。幸い、使用されているその形式のバージョンは2つだけであり、それらはほぼ同じです。

Bitmap編集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

これは少し長くなっていますが、成功です!(GIMP)とPDFを生成しました.xcf。各レイヤーは、異なるキャンバス描画操作です。思っていたほどきめ細かくはありませんが、それでもかなり便利です!

実際、私のコードはフルサイズのPNGを出力するだけで、GIMPで「レイヤーとして開く...」と「レイヤーの自動トリミング」を使用してこれらのファイルを作成しましたが、もちろん、必要に応じてコードでそれを行うこともできます。これをブログ投稿に変えたいと思います。

GIMPまたはPhotoshopのデモファイル(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 (または webservice ) を提供して、多くの便利なライブラリがある 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 に答える