Android:将 ColorMatrixColorFilter 应用于 Paint 对象时出现异常,但仅限于某些位图

发布于 2024-12-29 19:39:42 字数 2780 浏览 1 评论 0原文

我是 Android 编程的初学者,但我花了很多时间来解决这个问题,所以希望有人知道发生了什么。我的应用程序有一堆 Thing 对象,每个对象都有一个位图,每个对象都会以某种方式更改位图(更改颜色、大小等)。对于我在 MS Paint 中制作的一些“测试”位图(另存为 .png 文件),这一切都运行良好。然而,当我用 GIMP 制作的更好的图片替换它们时,应用程序开始崩溃。

最终我发现,只有在 GIMP 中选中“保存背景颜色”来保存 .png 图像时,应用程序才会崩溃。我需要这个,因为其中一些图片需要部分透明,以便可以重叠。然而:疯狂的是,当我尝试覆盖图像或创建图像时,它并没有崩溃,而是当我将 ColorMatrixColorFilter 应用于 Paint 对象时,它崩溃了。

我不明白怎么会这样。它永远无法真正将 Paint 对象应用到任何东西,那么为什么一个图像文件可以工作,而另一个图像文件却不能呢?崩溃是 ActivityThread.performLauncActivity 中的 RuntimeException,我无法找到更多有关它的信息。

这是一些伪代码,准确地说明了我正在做的事情以及崩溃的地方。

问题: 1)为什么会崩溃? 2)如果我想加载透明图像并应用彩色滤镜,将它们相互叠加以创建新的位图等,我应该采取什么不同的做法?只要我的所有图像都没有背景,所有这些都可以正常工作。

public class ThingHolder {

Thing[] things;

public ThingHolder() {
    things = new Thing[3];
    things[0] = new Thing();  // The first one works fine
    things[1] = new Thing();  // The second fails, see below
    ...
    // Note: It never gets far enough to draw the bitmap 
      // to a Canvas, that occurs much later
    ...
    canvas.drawBitmap(things[0].bmp, null, rect, things[0].paint);
    canvas.drawBitmap(things[1].bmp, null, rect, things[1].paint);
    }
}

public class Thing {

Bitmap bmp;
Paint paint;

public Thing() {
    bmp = getBmp(1);  // this always returns resource file circle.png
    paint = new Paint();
    paint.setColorFilter(new ColorMatrixColorFilter(redMatrix()));
    // RuntimeException occurs here if circle.png has a background color
// But it works fine if circle.png was saved in MS Paint, or in 
      // Gimp without the background color option checked
}

private float[] redMatrix() {
    float[] matrix = { 
            1, 0, 0, 0, 0, //red
            0, 0, 0, 0, 0, //green
            0, 0, 0, 0, 0, //blue
            0, 0, 0, 1, 0  //alpha
        };
    return matrix;
}
}

编辑 1:这是跟踪,以防有帮助: DalvikVM[本地主机:8611]
线程 [<1> main](已挂起(异常 RuntimeException))
ActivityThread.performLaunchActivity(ActivityThread$ActivityRecord, Intent) 行:2663
ActivityThread.handleLaunchActivity(ActivityThread$ActivityRecord, Intent) 行:2679
ActivityThread.access$2300(ActivityThread, ActivityThread$ActivityRecord, Intent) 行:125 ActivityThread$H.handleMessage(Message) 行:2033
ActivityThread$H(Handler).dispatchMessage(Message) 行:99 Looper.loop()行:123 ActivityThread.main(String[]) 行:4627
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) 行:不可用 [本机方法]
Method.invoke(Object, Object...) 行:521
ZygoteInit$MethodAndArgsCaller.run() 行:868
ZygoteInit.main(String[]) 行:626 NativeStart.main(String[]) 行:不可用[本机方法]

编辑 2:使用 2.2 目标(特别是在 VirtualBox 中运行的 android-x86-2.2-eeepc)发生此情况。当针对 3.2 目标运行时,其他地方的位图处理似乎仍然存在一些问题,但它不再抛出 RuntimeException。所以看起来这可能只是一个错误。

I am kind of a beginner to Android programming, but I've spent a lot of time pinning this down, so hopefully someone knows what's going on. My app has a bunch of Thing objects, each of which has a bitmap, and each one changes the bitmap somehow (change the color, size, etc). This all worked fine with some "test" bitmaps I made in MS Paint (saved as .png files). However, when I replaced them with nicer pictures made in GIMP, the app started crashing.

Eventually I figured out that the app would only crash if the .png image is saved with "Save background color" checked in GIMP. I need this, as some of these pictures need to be partially transparent so they can be overlaid. However: the crazy thing is, it is not crashing when I try to overlay an image, or create one, it's crashing when I apply the ColorMatrixColorFilter to the Paint object.

I don't understand how that can be. It never gets far enough to actually apply the Paint object to anything, so why would one image file work, but another one wouldn't? The crash is a RuntimeException in ActivityThread.performLauncActivity and I haven't been able to find out anything more about it.

Here's some pseudocode of exactly what I'm doing and where it's crashing.

Questions:
1) Why is this crashing?
2) What should I be doing differently if I want to load transparent images and apply color filters, overlay them on each other to create new bitmaps, etc? All of this works fine as long as all of my images have no background.

public class ThingHolder {

Thing[] things;

public ThingHolder() {
    things = new Thing[3];
    things[0] = new Thing();  // The first one works fine
    things[1] = new Thing();  // The second fails, see below
    ...
    // Note: It never gets far enough to draw the bitmap 
      // to a Canvas, that occurs much later
    ...
    canvas.drawBitmap(things[0].bmp, null, rect, things[0].paint);
    canvas.drawBitmap(things[1].bmp, null, rect, things[1].paint);
    }
}

public class Thing {

Bitmap bmp;
Paint paint;

public Thing() {
    bmp = getBmp(1);  // this always returns resource file circle.png
    paint = new Paint();
    paint.setColorFilter(new ColorMatrixColorFilter(redMatrix()));
    // RuntimeException occurs here if circle.png has a background color
// But it works fine if circle.png was saved in MS Paint, or in 
      // Gimp without the background color option checked
}

private float[] redMatrix() {
    float[] matrix = { 
            1, 0, 0, 0, 0, //red
            0, 0, 0, 0, 0, //green
            0, 0, 0, 0, 0, //blue
            0, 0, 0, 1, 0  //alpha
        };
    return matrix;
}
}

Edit 1: Here's the trace, in case it's helpful:
DalvikVM[localhost:8611]
Thread [<1> main] (Suspended (exception RuntimeException))
ActivityThread.performLaunchActivity(ActivityThread$ActivityRecord, Intent) line: 2663
ActivityThread.handleLaunchActivity(ActivityThread$ActivityRecord, Intent) line: 2679
ActivityThread.access$2300(ActivityThread, ActivityThread$ActivityRecord, Intent) line: 125
ActivityThread$H.handleMessage(Message) line: 2033
ActivityThread$H(Handler).dispatchMessage(Message) line: 99
Looper.loop() line: 123
ActivityThread.main(String[]) line: 4627
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]
Method.invoke(Object, Object...) line: 521
ZygoteInit$MethodAndArgsCaller.run() line: 868
ZygoteInit.main(String[]) line: 626
NativeStart.main(String[]) line: not available [native method]

Edit 2: This occurred using a 2.2 target (specifically, android-x86-2.2-eeepc running in VirtualBox). When run against a 3.2 target, it looks like there are still some problems with Bitmap handling elsewhere, but it no longer throws a RuntimeException. So it would seem like maybe this is just a bug.

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文