在 Android 中从 HTML 生成位图

Posted

技术标签:

【中文标题】在 Android 中从 HTML 生成位图【英文标题】:Generate bitmap from HTML in Android 【发布时间】:2011-06-05 18:15:47 【问题描述】:

如何?

可以使用WebView 还是有更好的方法(比如直接使用WebView 渲染引擎)?怎么样?

我想实现以下方法...

public Bitmap toBitmap(Context context, String html, Rect rect);

...html 是要渲染的 html,rect 是所需位图的框架。

【问题讨论】:

您可以考虑再添加几百个词来解释“从 HTML 生成动态位图”的含义。 简而言之,我想从呈现的 HTML 生成位图。我删除了“动态”并重新措辞以防令人困惑。 FWIW,这是我的解决方案尝试:***.com/a/41354684/6684508 【参考方案1】:

一种使用 WebView 从 HTML 字符串生成位图的同步方法,可以在 AsyncTask 中使用:

public Bitmap getBitmap(final WebView w, int containerWidth, int containerHeight, final String baseURL, final String content) 
    final CountDownLatch signal = new CountDownLatch(1);
    final Bitmap b = Bitmap.createBitmap(containerWidth, containerHeight, Bitmap.Config.ARGB_8888);
    final AtomicBoolean ready = new AtomicBoolean(false); 
    w.post(new Runnable() 

        @Override
        public void run() 
            w.setWebViewClient(new WebViewClient() 
                @Override
                public void onPageFinished(WebView view, String url) 
                    ready.set(true);
                
            );
            w.setPictureListener(new PictureListener() 
                @Override
                public void onNewPicture(WebView view, Picture picture) 
                    if (ready.get()) 
                        final Canvas c = new Canvas(b);
                        view.draw(c);
                        w.setPictureListener(null);
                        signal.countDown();
                    
                
            );
            w.layout(0, 0, rect.width(), rect.height());
            w.loadDataWithBaseURL(baseURL, content, "text/html", "UTF-8", null);
        );
    try 
        signal.await();
     catch (InterruptedException e) 
        e.printStackTrace();
    
    return b;

它有一些限制,但这是一个开始。

【讨论】:

一个复杂的开始。【参考方案2】:

您可以使用 draw 方法让它在您选择的位图中绘制。我举了一个例子,不要忘记清单的互联网和外部存储权限:


public class MainActivity extends Activity 
    private WebView mWebView;
    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        mWebView = new WebView(this);
        setContentView(mWebView);
        mWebView.loadUrl("http://tea.ch");
    
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) 
      if (keyCode != KeyEvent.KEYCODE_BACK) return super.onKeyDown(keyCode, event);
      Bitmap bm = Bitmap.createBitmap(200, 300, Bitmap.Config.ARGB_8888);
      Canvas c = new Canvas(bm);
      mWebView.draw(c);
      OutputStream stream = null;
      try 
        stream = new FileOutputStream(Environment.getExternalStorageDirectory() +"/teach.png");
        bm.compress(CompressFormat.PNG, 80, stream);
        if (stream != null) stream.close();
       catch (IOException e) 
       finally 
        bm.recycle();
      
      return super.onKeyDown(keyCode, event);
    

【讨论】:

那么有没有办法跳过WebView直接使用它的渲染引擎呢? 它是一个视图,你只能保留它的一个实例作为渲染引擎。您必须自己设置渲染为Layout参数的大小,例如:LayoutParams params = new LayoutParams(500,500); mWebView.setLayoutParams(params); mWebView.layout(0, 0, 500, 500); 我刚测试过,只需要设置mWebView.layout(0, 0, 500, 500); +1 用于测试。 :) 如果可行,将尝试接受答案。 不幸的是,此解决方案仅适用于活动内部。你知道如何在工作线程中实现它吗?【参考方案3】:

为什么不使用 WebView 方法:capturePicture(),它返回一个图片并且从 API 级别 1 开始可用?

它返回整个文档的图片。

然后您可以使用矩形裁剪结果并从那里保存位图。

【讨论】:

请注意,capturePicture() 在 API 级别 19 中已弃用:developer.android.com/reference/android/webkit/…【参考方案4】:

这个例子展示了如何抓取webView内容的最后一张图片(等待webview完成渲染图片),它是一个使用Android将HTML转换为PNG的例子

活动代码

public class HtmlViewer extends Activity 
private String HTML; 
private Context ctx;
private Picture pic = null;
private int i=0; suppose this is the last pic
private int oldi = 0; 
private Timer myTimer; // timer for waiting until last picture loaded
@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_html_viewer);
    Intent intent = getIntent();
    HTML = intent.getStringExtra("HTML");
    ctx = this;
    WebView wv = (WebView)findViewById(R.id.webView1);
    wv.setPictureListener(new PictureListener()

        public void onNewPicture(WebView view, Picture picture) 
            Log.w("picture", "loading.." + String.valueOf(view.getProgress()));
            pic = picture;
            i++;


            

        );
    wv.loadData(HTML, "text/html; charset=utf-8", null);

    wv.setWebViewClient(new WebViewClient()     
    
        public void onPageFinished(WebView wv, String url)
        
            Picture p = wv.capturePicture();
            myTimer = new Timer();
            myTimer.schedule(new TimerTask()           
                @Override
                public void run() 
                    if (i > oldi)
                        oldi = i;
                        else
                            if (i != 0)
                        
                            Log.w("picture", "finished");
                            cancel();
                            Picture picture = pic;

                            Log.w("picture", "onNewPicture- Height"+ picture.getHeight());
                            Log.w("picture", "onNewPicture- Width"+ picture.getWidth());

                            File sdCard = Environment.getExternalStorageDirectory();
                            if (picture != null)
                            
                                Log.w("picture", " P OK");
                            Bitmap image = Bitmap.createBitmap(picture.getWidth(),picture.getHeight(), Config.ARGB_8888);
                            Canvas canvas = new Canvas(image);
                            picture.draw(canvas);
                            Log.w("picture", "C OK");

                            if (image != null) 
                                Log.w("picture", "I OK");
                                ByteArrayOutputStream mByteArrayOS = new ByteArrayOutputStream();
                                image.compress(Bitmap.CompressFormat.PNG, 90, mByteArrayOS);
                                try 
                                    File file = new File(sdCard, "AccountView.PNG");
                                    FileOutputStream fos = new FileOutputStream(file);
                                    fos.write(mByteArrayOS.toByteArray());
                                    fos.flush();
                                    fos.close();                                        
                                    Log.w("picture", "F OK " + String.valueOf(mByteArrayOS.size()) + " ? " + String.valueOf(file.length()));
                                    Intent sharingIntent = new Intent(Intent.ACTION_SEND);
                                    Uri screenshotUri = Uri.fromFile(file);                      
                                    sharingIntent.setType("image/png");
                                    sharingIntent.putExtra(Intent.EXTRA_STREAM, screenshotUri);
                                    startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.ACCOUNT_VIEW_TITLE)));                      
                                    ((Activity)ctx).finish();
                                 catch (FileNotFoundException e) 
                                    e.printStackTrace();
                                 catch (IOException e) 
                                    e.printStackTrace();
                                
                                           
                            

                        
                

            , 0, 1000);

            Log.w("picture", "done");

            loadcompleted = true;
        
    );





@Override
public boolean onCreateOptionsMenu(Menu menu) 
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.activity_html_viewer, menu);
    return true;





布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
android:orientation="vertical"
tools:context=".HtmlViewer" >

<WebView
    android:id="@+id/webView1"
    android:layout_
    android:layout_ />

【讨论】:

【参考方案5】:

这是一个很好的库,可用于将任何 HTML 内容转换为位图。

同时支持 URL 和 HTML 字符串

https://github.com/iZettle/android-html2bitmap

【讨论】:

以上是关于在 Android 中从 HTML 生成位图的主要内容,如果未能解决你的问题,请参考以下文章

当我在我的 android 应用程序中从图库中加载图像时,为啥位图返回较小的图像?

在 Android Studio 中从用户那里获取图片并进行编码,以便可以将其存储在数据库中

在mfc中从中心缩放位图图像

Android:位图、软引用和书籍?

如何在 C# 中从位图中读取文本? [关闭]

在 Adob​​e Animate 中从矢量保存高分辨率位图