如何使用 Canvas 创建巨大的白色位图?

发布于 2025-01-05 01:40:59 字数 188 浏览 2 评论 0原文

我正在尝试弄清楚如何使用 Canvas 在大的白色表面上绘制一个小图形(实际上它是什么并不重要)。问题是,如果我从一个大的空位图开始,当我使用 ARGB_8888 创建它的可变副本时,Android 会立即耗尽内存。我很好奇我是否遗漏了一些东西,或者由于 Android 中的内存限制,是否实际上无法将小图形合成到大的白色表面上并将其保存为 PNG 或 JPG。

I'm trying to figure out how I can use Canvas to draw a small graphic (doesn't really matter what it is) onto a large white surface. The issue is that if I start with a large empty Bitmap, when I make a mutable copy of it using ARGB_8888 Android immediately runs out of memory. I'm curious if I'm missing something, or if it's actually not possible to composite a small graphic onto a large white surface and save it out as a PNG or JPG due to memory constraints in Android.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

北斗星光 2025-01-12 01:40:59

当然,当您想要创建巨大的位图时,您会受到内存的限制,但是您有足够的内存来创建相当大的位图。例如,1024*1024 ARGB_8888 位图将需要大约 4 MB 内存,如果您的应用程序通常使用内存比较节省,那么这不是问题。 Android 应用程序的正常堆大小通常在 16-32 MB 之间,具体取决于 Android 版本,只是为了让您了解必须使用的内容。

您说您制作了大位图的副本,这可能是您的主要问题。无需复制大位图,您只需要一个。下面是一个示例项目,它创建一个大的 (1024*1024) 白色位图,并在应用程序的中间绘制一个视图,然后将结果写入 PNG:

package com.example.android;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class WhitePngActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        findViewById(R.id.draw_to_bitmap).setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                Bitmap largeWhiteBitmap = Bitmap.createBitmap(1024, 1024, Bitmap.Config.ARGB_8888);

                // Make a canvas with which we can draw to the bitmap
                Canvas canvas = new Canvas(largeWhiteBitmap);

                // Fill with white
                canvas.drawColor(0xffffffff);

                // Draw the view to the middle of the big white bitmap. In this
                // case, it will be the button, but you can draw any View in
                // your view hierarchy to the bitmap like this. And of course
                // you can position the View anywhere you want
                canvas.save();
                canvas.translate(
                        largeWhiteBitmap.getWidth() / 2 - view.getWidth() / 2,
                        largeWhiteBitmap.getHeight() / 2 - view.getHeight() / 2);
                view.draw(canvas);
                canvas.restore();

                // Write the file (don't forget android.permission.WRITE_EXTERNAL_STORAGE)
                File pictureDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
                File pngFile = new File(pictureDir, "big-white-image-with-view.png");
                try {
                    largeWhiteBitmap.compress(Bitmap.CompressFormat.PNG, 0, new FileOutputStream(pngFile));
                } catch (FileNotFoundException e) {
                    Log.e("WhitePngActivity", "Could not write " + pngFile, e);
                }

                // Immediately release the bitmap memory to avoid OutOfMemory exception
                largeWhiteBitmap.recycle();
            }
        });
    }
}

与此主布局一起:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/draw_to_bitmap"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Click to draw to bitmap" />

</LinearLayout>

您将在某处获得位图就像 /mnt/sdcard/Pictures/big-white-image-with-view.png 看起来像这样:

在此处输入图像描述

Naturally, you are limited by memory when you want to create huge bitmaps, but you have enough memory to create quite big bitmaps. For example, a 1024*1024 ARGB_8888 bitmap will need roughly 4 MB of memory, which is not a problem if your app is frugal with memory in general. The normal heap size for an Android app is usually between 16-32 MB depending on Android version, just to give you a feeling for what you have to play with.

You say you make a copy of large bitmap, and that might be your main problem. There's no need to make a copy of a large bitmap, you need only one. Here's a sample project that creates a large (1024*1024) white bitmap and draws a View in your app in the middle of it, and then writes the result to a PNG:

package com.example.android;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class WhitePngActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        findViewById(R.id.draw_to_bitmap).setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                Bitmap largeWhiteBitmap = Bitmap.createBitmap(1024, 1024, Bitmap.Config.ARGB_8888);

                // Make a canvas with which we can draw to the bitmap
                Canvas canvas = new Canvas(largeWhiteBitmap);

                // Fill with white
                canvas.drawColor(0xffffffff);

                // Draw the view to the middle of the big white bitmap. In this
                // case, it will be the button, but you can draw any View in
                // your view hierarchy to the bitmap like this. And of course
                // you can position the View anywhere you want
                canvas.save();
                canvas.translate(
                        largeWhiteBitmap.getWidth() / 2 - view.getWidth() / 2,
                        largeWhiteBitmap.getHeight() / 2 - view.getHeight() / 2);
                view.draw(canvas);
                canvas.restore();

                // Write the file (don't forget android.permission.WRITE_EXTERNAL_STORAGE)
                File pictureDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
                File pngFile = new File(pictureDir, "big-white-image-with-view.png");
                try {
                    largeWhiteBitmap.compress(Bitmap.CompressFormat.PNG, 0, new FileOutputStream(pngFile));
                } catch (FileNotFoundException e) {
                    Log.e("WhitePngActivity", "Could not write " + pngFile, e);
                }

                // Immediately release the bitmap memory to avoid OutOfMemory exception
                largeWhiteBitmap.recycle();
            }
        });
    }
}

Together with this main layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/draw_to_bitmap"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Click to draw to bitmap" />

</LinearLayout>

You'll get a bitmap somewhere like /mnt/sdcard/Pictures/big-white-image-with-view.png that looks something like this:

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文