Android: эффективно прокручиваете содержимое холста? - PullRequest
5 голосов
/ 30 мая 2009

Я хочу нарисовать график, который обновляется в режиме реального времени (растет справа). Самый эффективный способ сделать это - скопировать все из x [0 .. width-2], оставленного на 1 пиксель, а затем нарисовать новое значение в x [width-1].

У меня мало опыта с Android, но, насколько я могу судить, Canvas вообще не работает с его содержимым. Нужно ли перекрашивать весь экран каждый раз? Это включает масштабирование и сглаживание, поэтому я боюсь, что это будет медленно.

Стоит ли рисовать в байт [] [], а затем использовать его для рисования на экране (каждый раз сдвигая содержимое моего буфера влево)?

Ответы [ 4 ]

1 голос
/ 09 июня 2009

Если ваш график ограничен, попробуйте отрисовать все это один раз в изображение, а затем перетащите соответствующие части из этого изображения в свой холст. Старайтесь избегать «движущихся» пикселей в буфере, так как это может привести к зависимости между чтением и записью и может реально снизить производительность. На самом деле может быть лучше скопировать из одного буфера в другой и чередовать, какой из них будет скрыт на экране. Наконец, если вам в конечном итоге придется работать с пикселями вручную, убедитесь, что вы запускаете изображение в строках, а не в столбцах, и начинаете с начала строки, чтобы помочь с кэшированием.

1 голос
/ 09 июня 2009

По поводу производительности, без профилирования мы не можем сказать.

Возможно, на целевом телефоне рисование линий аппаратно ускорено, и вы должны рисовать график с нуля, используя примитивы рисования линий в каждом кадре.

С другой стороны, простое управление пикселями буфера изображения будет:

Создайте изображение нужного размера и очистите его до «background_color». Это изображение должно иметь функцию setpixel ().

Иметь массив значений, которые записывают y каждого времени x, поэтому для любого столбца вы знаете, где вы в последний раз строили график.

Обрабатывайте эти "chart_image" и "chart_array" как циклический буфер. Для каждого временного шага:

Y = ...;
X = time_since_start % chart_width;
chart_image.setpixel(X,chart_array[X],background_color); // clear previous line
chart_array[X] = Y;
chart_image.setpixel(X,chart_array[X],foreground_color); // draw new plot

А теперь вам нужно это уничтожить. Вам нужно дважды пролистать изображение:

X = time_since_start % chart_width;
// the newest data is on the left of the chart_image but gets drawn on the right side of the output
blit(out_x+X,out_y, // destination coordinates
    chart_image,
    0,0, // top left of part of chart_image to blit
    X,chart_height); // bottom right of chart_image part
// the oldest data is on the right of the chart_image but gets drawn on the left side of the output
blit(out_x,out_y,
    chart_image,
    X,0,
    chart_width,chart_height);

Ситуация усложняется, если вы хотите использовать линии, а не отдельные пиксели, но drawline() вместо setpixel() может сделать эту работу и с этим подходом.

(Прошу прощения за то, что не знал API-интерфейсы Android; но подход является общим.)

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

Поскольку я могу считать само собой разумеющимся, что вы храните данные графика в памяти, перерисовка не должна быть проблемой. Перерисовывать набор точек в каждом кадре совсем не сложно. Сдвиг памяти будет интенсивным, он двигает все, а не просто рисует только то, что вам нужно. В худшем случае, поскольку это функция времени, только одно значение на столбец дисплея, приблизительно 800 пикселей / значения в альбомной ориентации, которую должна нарисовать система. Это тривиально. Вы профилировали это? РЕДАКТИРОВАТЬ: Помните, это не то, что система должна рисовать каждую точку, она только опирается на память, а затем использует свои примитивы. Не думайте, что это повторяет рисование точки, сброс в видеопамять, а затем снова.

0 голосов
/ 08 июня 2009

Просто мысль, которую вы, возможно, уже рассмотрели, но я бы не стал сдвигать содержимое буфера - я бы просто попытался использовать его как кольцевой буфер. Сохраняйте индекс для текущего столбца, и после того, как вы снова обернетесь к крайнему левому столбцу, вы можете нарисовать пункт назначения в двух сегментах - что находится справа от текущего столбца, а затем - слева, последний заполненный столбец. Таким образом, вам не нужно ничего сдвигать, и каждое обновление экрана составляет всего два бита (растровые копии) для двух сегментов. Если этот бит слишком медленный, вы все равно всегда можете нарисовать их во второй внеэкранный буфер, прежде чем за один раз выбросить все это на экран. Конечно, один большой удар на экран довольно быстро, не так ли?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...