#c# #performance #image #user-interface
#c# #Производительность #изображение #пользовательский интерфейс
Вопрос:
По сути, я создаю анимированный пользовательский интерфейс с нуля. Все в пользовательском интерфейсе является производным от базового класса ScreenThing, который может хранить растровое изображение, используемое для рисования этого объекта, а также его положение. Когда я хочу нарисовать пользовательский интерфейс, я создаю новое пустое растровое изображение нужного размера, создаю графический объект из этого растрового изображения, затем передаю этот графический объект во все методы ScreenThings Draw (), чтобы они рисовали сами. Когда это будет сделано, я выведу растровое изображение на экран с помощью элемента управления PictureBox.
Все это отлично работает, но слишком медленно. Я хочу, чтобы это происходило не менее 30 раз в секунду, чтобы анимация была плавной, но для всего этого требуется более 33 миллисекунд. Я видел, что причиной этой медлительности является блокировка и разблокировка памяти растровых изображений. Я попробовал некоторый код, который нашел в Интернете, который разблокирует растровые изображения и создает новые функции GetPixel и SetPixel, и попробовал комбинировать изображения попиксельно, как показано ниже, но это заняло еще больше времени. (приведенный ниже код был просто тестовым, он не помещает изображение в нужное место)
for (int i = 0; i < images.Count; i )
{
FastBitmap foreground = new FastBitmap(images[i]);
foreground.LockImage();
for (int x = 0; x < images[0].Width; x )
{
for (int y = 0; y < images[0].Height; y )
{
output.SetPixel(x, y, foreground.GetPixel(x, y));
}
}
foreground.UnlockImage();
}
Итак, каков наилучший способ сделать это? Возможно ли использовать C # для рисования довольно большого изображения (например, 1024х768) в режиме реального времени, подобного этому? Если ничего другого не получится, я думаю, я мог бы придумать способ рисовать только те части, которые были изменены, но я бы хотел избежать этого, если возможно перерисовывание всего методом перебора. Большое спасибо!
Комментарии:
1. Есть ли какая-либо причина, по которой вы не рисуете свои изображения на растровом изображении, а не используете попиксельный подход?
Ответ №1:
Использование растровых изображений для рисования анимации в реальном времени очень неэффективно. После этого создайте CustomControl и переопределите его метод OnPaint следующим образом:
protected override void OnPaint(PaintEventArgs pe)
{
}
там вы можете использовать pe.Графика для создания любого рисунка, который вы хотите, и копирование на экран не требуется.
Я использовал это, и если вы рисуете процедуры достаточно быстро, это будет гладко.
Также не забудьте вызвать SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
в конструкторе control, чтобы получить двойную буферизацию
Комментарии:
1. Звучит как лучший способ. После публикации я вспомнил, что однажды делал нечто подобное с XNA Framework для отображения 3D-модели в приложении forms. Я собирался рассмотреть возможность создания этого как «2d игры» в XNA, но сначала я рассмотрю ваш подход. Спасибо!
Ответ №2:
Подход «попиксель за пикселем» — это худшее, что вы можете сделать. Вместо этого вы должны профилировать свое приложение. Это просто: запустите его при полной рабочей нагрузке (100% cpu) и приостановите отладчик 10 раз. Посмотрите, где это чаще всего останавливается, это ваша точка доступа, которую вам нужно оптимизировать.
Комментарии:
1. Как насчет простого использования профилировщика, который может точно показать вам, где ваша программа проводит сколько времени?
2. Еще лучше! Вам просто нужно иметь один. Отладчик всегда рядом.
3. У меня было ощущение, что пиксель за пикселем было хуже всего, но подумал, что стоит попробовать после графики. Метод drawImage был слишком медленным. Спасибо за совет по профилированию, я никогда раньше этого не пробовал и изучу его.