Android 位图多线程处理 - 不是线程安全的?
Android Bitmap multithreaded processing - not thread-safe?
我想在我的 Android 应用程序中处理位图 - 位图可能很大,所以我使用多线程来执行更快的操作。这是我的代码(Runnable child 的一部分):
@Override
public void run() {
int imageHeight = filter.getBitmap().getHeight();
int start = threadNumber * imageHeight / threadCount;
int stop = (threadNumber + 1) * imageHeight / threadCount;
for (int j = start; j < stop; j++) {
filter.processLine(j);
}
}
//...
protected void processLine(int lineNumber)
{
int width = bitmap.getWidth();
int pixels[] = new int[width];
bitmap.getPixels(pixels, 0, width, 0, lineNumber, width, 1);
for (int i = 0; i < width; i++) {
pixels[i] = processPixel(pixels[i]);
}
bitmap.setPixels(pixels, 0, width, 0, lineNumber, width, 1);
}
当我在池中只使用 1 个线程时,一切正常。不幸的是,当我使用的线程数等于处理器的内核数(我的设备中为 4 个)时,结果如下(对于灰度过滤器):
有时看起来像:
- bitmap.getPixels(...) 不起作用,因为输出中有黑线
- bitmap.setPixels(...) 不起作用,因为输出中有未更改的行
我说的对吗?这些函数是线程不安全的吗?我应该如何执行多线程位图过滤才能快速且线程安全?
Android 中的 2D 图像处理由 Skia 库提供,Chrome 也使用。
很难找到明确的答案。 "Skia is not thread-safe, although SkBitmap [used by Bitmap] is thread-safe..." 不知道怎么想的。我仔细阅读了一堆难以理解的 JNI/C++ 代码,这是我能提供的最好的代码(这似乎比其他任何人都多):
我认为你应该在 整个位图 上调用 bitmap.getPixels()
。然后划分结果数组并线程化处理。当所有线程完成后,重新assemble结果并调用bitmap.setPixels()
看起来 bitmap.getPixels()
和 bitmap.setPixels()
应该只不过是 memcpy()
s,但在引用计数、图像缓存、颜色等方面还有很多事情要做space 转换、预乘以及谁知道还有什么。将 Bitmap
方法从并发处理中取出应该可以让您远离麻烦。
我想在我的 Android 应用程序中处理位图 - 位图可能很大,所以我使用多线程来执行更快的操作。这是我的代码(Runnable child 的一部分):
@Override
public void run() {
int imageHeight = filter.getBitmap().getHeight();
int start = threadNumber * imageHeight / threadCount;
int stop = (threadNumber + 1) * imageHeight / threadCount;
for (int j = start; j < stop; j++) {
filter.processLine(j);
}
}
//...
protected void processLine(int lineNumber)
{
int width = bitmap.getWidth();
int pixels[] = new int[width];
bitmap.getPixels(pixels, 0, width, 0, lineNumber, width, 1);
for (int i = 0; i < width; i++) {
pixels[i] = processPixel(pixels[i]);
}
bitmap.setPixels(pixels, 0, width, 0, lineNumber, width, 1);
}
当我在池中只使用 1 个线程时,一切正常。不幸的是,当我使用的线程数等于处理器的内核数(我的设备中为 4 个)时,结果如下(对于灰度过滤器):
有时看起来像:
- bitmap.getPixels(...) 不起作用,因为输出中有黑线
- bitmap.setPixels(...) 不起作用,因为输出中有未更改的行
我说的对吗?这些函数是线程不安全的吗?我应该如何执行多线程位图过滤才能快速且线程安全?
Android 中的 2D 图像处理由 Skia 库提供,Chrome 也使用。
很难找到明确的答案。 "Skia is not thread-safe, although SkBitmap [used by Bitmap] is thread-safe..." 不知道怎么想的。我仔细阅读了一堆难以理解的 JNI/C++ 代码,这是我能提供的最好的代码(这似乎比其他任何人都多):
我认为你应该在 整个位图 上调用 bitmap.getPixels()
。然后划分结果数组并线程化处理。当所有线程完成后,重新assemble结果并调用bitmap.setPixels()
看起来 bitmap.getPixels()
和 bitmap.setPixels()
应该只不过是 memcpy()
s,但在引用计数、图像缓存、颜色等方面还有很多事情要做space 转换、预乘以及谁知道还有什么。将 Bitmap
方法从并发处理中取出应该可以让您远离麻烦。