#android #image #android-canvas #draw #pixel
#Android #изображение #android-холст #рисовать #пиксель
Вопрос:
Я пытаюсь перенести эмулятор, который я написал на Java, на Android. Все шло хорошо, я смог перенести большую часть своих кодов с незначительными изменениями, однако из-за того, как работает эмуляция, мне нужно отображать изображение на уровне пикселей.
Что касается настольной Java, я использую
int[] pixelsA = ((DataBufferInt) src.getRaster().getDataBuffer()).getData();
что позволяет мне получать ссылку на пиксельный буфер и обновлять его на лету (минимизировать создание объектов)
В настоящее время это то, что мой эмулятор для Android делает для каждого кадра
@Override
public void onDraw(Canvas canvas)
{
buffer = Bitmap.createBitmap(pixelsA, 256, 192, Bitmap.Config.RGB_565);
canvas.drawBitmap(buffer, 0, 0, null);
}
pixelsA — это массив int[], pixelsA содержит всю информацию о цвете, поэтому для каждого кадра он должен будет создавать растровый объект, выполняя
buffer = Bitmap.createBitmap(pixelsA, 256, 192, Bitmap.Config.RGB_565);
я считаю, что это довольно дорого и медленно.
Есть ли какой-нибудь способ эффективно рисовать пиксели с помощью canvas?
Комментарии:
1. Правда, CreateBitmap работает медленно, это копирование в память и даже преобразование формата пикселей в вашем случае!
Ответ №1:
Один довольно низкоуровневый метод, но для меня он работает нормально (с собственным кодом):
Создайте Bitmap
объект размером с ваш видимый экран. Также создайте View
объект и реализуйте onDraw
метод.
Затем в машинном коде вы загружаете libjnigraphics.итак, встроенная библиотека, функции поиска AndroidBitmap_lockPixels
и. AndroidBitmap_unlockPixels
Эти функции определены в исходном коде Android в bitmap.h.
Затем вы вызываете блокировку / разблокировку растрового изображения, получая адрес в необработанных пикселях. Вы должны интерпретировать формат пикселей RGB в соответствии с тем, что он есть на самом деле (16-разрядный 565 или 32-разрядный 8888).
После изменения содержимого растрового изображения вы хотите отобразить это на экране. Вызовите View.invalidate()
свой View
. В its onDraw
превратите ваше растровое изображение в заданное Canvas
.
Этот метод очень низкоуровневый и зависит от фактической реализации Android, однако он очень быстрый, вы можете получить 60 кадров в секунду без проблем.
bitmap.h является частью Android NDK с версии платформы 8, так что это официальный способ сделать это с Android 2.2.
Ответ №2:
Вы можете использовать метод drawBitmap, который позволяет избежать создания растрового изображения каждый раз или даже в крайнем случае рисовать пиксели один за другим с помощью drawPoint.
Комментарии:
1. Я попробовал метод drawBitmap, который принимает int[] в качестве своего параметра, это дает хороший прирост производительности по сравнению с созданием растровых объектов. Кажется, это единственный способ (я думаю) достичь приемлемой производительности, не прибегая к машинному коду.
2. Приятно знать, что это сработало. Как вы говорите, нет ничего быстрее, чем переход на родной язык, но это намного сложнее.
Ответ №3:
Не воссоздавайте растровое изображение каждый раз. Попробуйте что-то вроде этого:
Bitmap buffer = null;
@Override
public void onDraw(Canvas canvas)
{
if(buffer == null) buffer = Bitmap.createBitmap(256, 192, Bitmap.Config.RGB_565);
buffer.copyPixelsFromBuffer(pixelsA);
canvas.drawBitmap(buffer, 0, 0, null);
}
РЕДАКТИРОВАТЬ: как указывалось, вам необходимо обновить буфер пикселей. И растровое изображение должно быть изменяемым, чтобы это произошло.
Комментарии:
1. Это не сработает. Bitmap инициализирует свой собственный пиксельный буфер в CreateBitmap, его вызов не приведет к обновлению пикселей Bitmap.
Ответ №4:
если pixelsA уже представляет собой массив пикселей (что я бы сделал из вашего заявления о содержании цветов), то вы можете просто отображать их напрямую, не конвертируя с помощью:
canvas.drawBitmap(pixelsA, 0, 256, 0, 0, 256, 192, false, null);