Джава. Какой самый быстрый способ запустить и обработать каждый пиксель на растровом изображении? - PullRequest
1 голос
/ 04 января 2012

У меня есть image_source, который является исходным растровым изображением с некоторым изображением и image_new - временное растровое изображение

Я делаю этот код, который делает image_source фоновым слоем анаглифа:

int [] pixel = {0x0, 0x0, 0x0};
int [] image_params = {image_source.getWidth() - 2 * anaglyph_amplitude, image_source.getHeight()};
Bitmap image_new = Bitmap.createScaledBitmap(image_source, image_params[0], image_params[1], false);
for(int i = 0; i < image_params[0]; ++i)
    for(int j = 0; j < image_params[1]; ++j) {
        pixel[0] = image_source.getPixel(i, j);
        pixel[1] = image_source.getPixel(i + 2 * anaglyph_amplitude, j);
        pixel[2] = pixel[0] + pixel[1] % 0x10000 - pixel[0] % 0x10000;
        image_new.setPixel(i, j, pixel[2]);
    }
image_source = Bitmap.createBitmap(image_new);
image_new = null;

Затем image_source рисуется на холсте (рисование на холсте у них недоступно).

Проблема в том, что этой программе требуется около 5 секунд для обработки изображения размером 1000x1000 на интеллектуальном устройстве Android.

Есть ли другие способы запуска растровых пикселей?

Ответы [ 4 ]

0 голосов
/ 05 января 2012

Вот решение: я получил массив пикселей и работал с ним.

int [] pixel = {0x0, 0x0, 0x0};
int [] pixels_old, pixels_new;
int [] params = {image_source.getWidth(), image_source.getHeight()};
int [] image_params = {image_source.getWidth() - 2 * anaglyph_amplitude, image_source.getHeight()};
pixels_old = new int[params[2] * params[3]];
pixels_new = new int[image_params[0] * image_params[1]];
image_source.getPixels(pixels_old, 0, params[2], 0, 0, params[2], params[3]); 
image_source = null;
for(int i = 0; i < image_params[0]; ++i)
    for(int j = 0; j < image_params[1]; ++j) {
        pixel[0] = pixels_old[i + j * params[2]];
        pixel[1] = pixels_old[i + (anaglyph_amplitude<<1) + j * params[2]];
        pixel[2] = pixel[0] + (pixel[1] & 0xFFFF) - (pixel[0] & 0xFFFF);
        pixels_new[i + j * image_params[0]] = pixel[2];
    }
pixels_old = null;
image_source = Bitmap.createBitmap(pixels_new, image_params[0], image_params[1], Bitmap.Config.ARGB_8888);
pixels_new = null;
0 голосов
/ 04 января 2012

Еще один незначительный твик. Во внутреннем цикле нет причин использовать массив для пикселя [1] и т. Д. Имеется три целых числа: p0, p1 и p2.

РЕДАКТИРОВАТЬ ДОБАВЛЕНО

Я менее знаком с Android, чем Swing, но я надеялся, что в растровом изображении Android есть метод «получи мне кучу пикселей за раз», похожий на растр. Это делает.

Я думаю, вы должны использовать растровый метод Ссылка Javadocs здесь

public void getPixels (int[] pixels, int offset, int stride, int x, int y, int width, int height)

Если у вас есть доступная память, получите все 1 000 000 одновременно.

0 голосов
/ 04 января 2012

Вы можете кэшировать вычисление 2 * anaglyph_amplitude, поэтому его не нужно вычислять на каждой итерации.

0 голосов
/ 04 января 2012

В коде фрагмента есть некоторое улучшение производительности. Я не уверен, что вам этого достаточно.

Первое изменение

pixel[2] = pixel[0] + (pixel[1] & 0xFFFF) - (pixel[0] & 0xFFFF);

вместо

pixel[2] = pixel[0] + pixel[1] % 0x10000 - pixel[0] % 0x10000;

-

pixel[1] = image_source.getPixel(i + (anaglyph_amplitude<<1), j);

вместо

pixel[1] = image_source.getPixel(i + 2 * anaglyph_amplitude, j);
...