Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Gdiplus - проблема с анимацией

263
07 февраля 2007 года
koltaviy
816 / / 16.12.2004
В общем ситуация следующая:
Работаю с Gdiplus.
Мне нужно вывести анимацию. Причем вопрос не в том как отобразить анимированный *.gif, а как вывести последовательность кадров, чтобы получилась анимация.
Как это сделать - я, в принципе знаю, но возникла следующая проблема:
Имеем:
Сама анимация загружается в небольшой по размеру PaintBox1:
Код:
void __fastcall TForm1::PaintBox1Paint(TObject *Sender)
{
  static int N = 20;
  N++;
  Gdiplus::Graphics *grphics = new Gdiplus::Graphics(PaintBox1->Canvas->Handle);
  AnsiString Fname = ExtractFilePath(Application->ExeName) + "loop_animation\\loop_000" + IntToStr(N) + ".png";
  WCHAR* buf = new WCHAR[ Fname.WideCharBufSize() ];
  Gdiplus::Image *imge = new Gdiplus::Image( Fname.WideChar(buf, Fname.WideCharBufSize()) );
  grphics->DrawImage(imge,
                   Gdiplus::Rect(0, 0,imge->GetWidth(), imge->GetHeight()));
  if( N >= 56 ) N = 21;
  delete grphics;
  delete imge;
  delete [] buf;
}

Изображение фона загружается в PaintBox2, растянутый на всю форму:
 
Код:
void __fastcall TForm1::PaintBox2Paint(TObject *Sender)
{
 graphics = new Gdiplus::Graphics(PaintBox2->Canvas->Handle);
 graphics->DrawImage(image,
       Gdiplus::Rect(0, 0,image->GetWidth(), image->GetHeight()));
  delete graphics;
}

Ну и таймер конечно:
 
Код:
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
 //this->PaintBox2->OnPaint = NULL;
 this->PaintBox1->Repaint();
 //this->PaintBox2->OnPaint = PaintBox2Paint;
}

Проблема в том, что при такой организации при отображении анимации прога хавает порядка 70% проца.
Комментарии в таймере - то, что я пытался сделать. Просто при вызове Repaint'a PaintBox1 происходит прежде событие OnPaint PaintBox2.
Не спасло - получается, что область под PaintBox1 у PaintBox2(изображение прозрачное) не отрисовывается.
Проблема усугубляется тем, что пользователь имеет возможность изменять скорость анимации(таймера) в программе. А при такой работе ни о какой скорости и речи быть не может!..
1
09 февраля 2007 года
kot_
7.3K / / 20.01.2000
Цитата: koltaviy
В общем ситуация следующая:
Работаю с Gdiplus.
Мне нужно вывести анимацию. Причем вопрос не в том как отобразить анимированный *.gif, а как вывести последовательность кадров, чтобы получилась анимация.
Как это сделать - я, в принципе знаю, но возникла следующая проблема:
Имеем:
Сама анимация загружается в небольшой по размеру PaintBox1:
Код:
void __fastcall TForm1::PaintBox1Paint(TObject *Sender)
{
  static int N = 20;
  N++;
  Gdiplus::Graphics *grphics = new Gdiplus::Graphics(PaintBox1->Canvas->Handle);
  AnsiString Fname = ExtractFilePath(Application->ExeName) + "loop_animation\\loop_000" + IntToStr(N) + ".png";
  WCHAR* buf = new WCHAR[ Fname.WideCharBufSize() ];
  Gdiplus::Image *imge = new Gdiplus::Image( Fname.WideChar(buf, Fname.WideCharBufSize()) );
  grphics->DrawImage(imge,
                   Gdiplus::Rect(0, 0,imge->GetWidth(), imge->GetHeight()));
  if( N >= 56 ) N = 21;
  delete grphics;
  delete imge;
  delete [] buf;
}

Изображение фона загружается в PaintBox2, растянутый на всю форму:
 
Код:
void __fastcall TForm1::PaintBox2Paint(TObject *Sender)
{
 graphics = new Gdiplus::Graphics(PaintBox2->Canvas->Handle);
 graphics->DrawImage(image,
       Gdiplus::Rect(0, 0,image->GetWidth(), image->GetHeight()));
  delete graphics;
}

Ну и таймер конечно:
 
Код:
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
 //this->PaintBox2->OnPaint = NULL;
 this->PaintBox1->Repaint();
 //this->PaintBox2->OnPaint = PaintBox2Paint;
}

Проблема в том, что при такой организации при отображении анимации прога хавает порядка 70% проца.
Комментарии в таймере - то, что я пытался сделать. Просто при вызове Repaint'a PaintBox1 происходит прежде событие OnPaint PaintBox2.
Не спасло - получается, что область под PaintBox1 у PaintBox2(изображение прозрачное) не отрисовывается.
Проблема усугубляется тем, что пользователь имеет возможность изменять скорость анимации(таймера) в программе. А при такой работе ни о какой скорости и речи быть не может!..



Для начала - определи наиболее узкое место в программе. Кроме того - в форме включи двойную буферизацию, загрузку файла лучше делать заранее и возможно в потоке, и я бы отказался от использования PaintBox - я так понял фон у тебя постоянный - не проще ли рисовать анимацию непосредственно на нем?

263
10 февраля 2007 года
koltaviy
816 / / 16.12.2004
1) :D Двойная буферизация естественно включена. К тому же неиспользование двойной буферизации не приводит к ситуации, которую я описал выше.
Более того при неиспользовании двойной буферизации прога хавает лишь 10 процентов проца - что тоже ненормально. Так что двойная буферизация тут вообще ни при чем!!
2) Загрузка файла происходит в конструкторе формы, удаление - в деструкторе - аналогичная ситуация. В данной случае в таком количестве ест проц не загрузка файла, а его рисование - и только это!!
3) А что делать если фон непостоянный? Приведенный мною код 'немного' отличается от кода моей программы. Это лишь пример, который отражает возникшую проблему!
1
10 февраля 2007 года
kot_
7.3K / / 20.01.2000
Цитата: koltaviy
1) :D Двойная буферизация естественно включена. К тому же неиспользование двойной буферизации не приводит к ситуации, которую я описал выше.
Более того при неиспользовании двойной буферизации прога хавает лишь 10 процентов проца - что тоже ненормально. Так что двойная буферизация тут вообще ни при чем!!
2) Загрузка файла происходит в конструкторе формы, удаление - в деструкторе - аналогичная ситуация. В данной случае в таком количестве ест проц не загрузка файла, а его рисование - и только это!!
3) А что делать если фон непостоянный? Приведенный мною код 'немного' отличается от кода моей программы. Это лишь пример, который отражает возникшую проблему!



Для начала определи - что именно тормозит программу - тем более что в приведенном тобой коде загрузка файла происходит при рисовании

 
Код:
AnsiString Fname = ExtractFilePath(Application->ExeName) + "loop_animation\\loop_000" + IntToStr(N) + ".png";
263
10 февраля 2007 года
koltaviy
816 / / 16.12.2004
Я же сказал - прогу тормозит именно рисование фона!! Загрузка изображения фона в OnPaint и загрузка в конструкторе формы приводят к одному и тому же результату, который я объяснил выше!
Загрузка и рисование самого кадра - не приводит к съеданию проца. Если фон не рисуется - проц вообще не хавается(смотрю в диспетчере)!!
Я уже который раз объясняю, что тормозит прогу!! - РИСОВАНИЕ ФОНА, а ты меня не слушаешь!!
1
10 февраля 2007 года
kot_
7.3K / / 20.01.2000
Цитата: koltaviy
Я же сказал - прогу тормозит именно рисование фона!! Загрузка изображения фона в OnPaint и загрузка в конструкторе формы приводят к одному и тому же результату, который я объяснил выше!
Загрузка и рисование самого кадра - не приводит к съеданию проца. Если фон не рисуется - проц вообще не хавается(смотрю в диспетчере)!!
Я уже который раз объясняю, что тормозит прогу!! - РИСОВАНИЕ ФОНА, а ты меня не слушаешь!!


Не кричи, бл%, не дома. И дома не кричи.
Русским языком тебе говорят - используй старый способ, работавший еще в досе - рисуешь картинку заранее - а потом ее копируешь на форму. Зачем использовать два пайтбокса, если полностью достаточно одного? А можно просто рисовать на канве формы - нафига цеплять лишние компоненты? Для анимации характерен последовательный вывод - т.е. ты можешь готовить сразу 20-30 картинок в отдельных потоках - но правда если нужна анимация с хорошей частотой - то лучше юзать DX - в противном случае тормоза при частоте порядка 10-25 кадров/сек. все равно будут - так как видеопамять напрямую не доступна.

263
10 февраля 2007 года
koltaviy
816 / / 16.12.2004
Извини, если накричал.. А ты не матерись) Я же не со зла! Я же объяснил ситуацию..А ты мне все мимо советуешь - типа используй двойную буферизацию, загрузи статический Image в TImage..
Насчет двух и более PaintBox - а если произошли какие-либо изменения, результат которых отображается изображением меньшим изображения фона раз в 20. Например графическое выделение какого-либо объекта на фоне при наведении курсора!! По прежнему предлагаешь использовать один PaintBox-фон(загрузить сначала фон, а потом этот маленький Image)?? Не легче перерисовывать этот маленький PaintBox!!
Насчет DX - уже практически пришел к этому и сам!!
Интересует реализация именно на Gdiplus!! Считаю, что эта либа может с этим справиться!!
1
11 февраля 2007 года
kot_
7.3K / / 20.01.2000
Цитата: koltaviy
Извини, если накричал.. А ты не матерись) Я же не со зла! Я же объяснил ситуацию..А ты мне все мимо советуешь - типа используй двойную буферизацию, загрузи статический Image в TImage..
Насчет двух и более PaintBox - а если произошли какие-либо изменения, результат которых отображается изображением меньшим изображения фона раз в 20. Например графическое выделение какого-либо объекта на фоне при наведении курсора!! По прежнему предлагаешь использовать один PaintBox-фон(загрузить сначала фон, а потом этот маленький Image)?? Не легче перерисовывать этот маленький PaintBox!!
Насчет DX - уже практически пришел к этому и сам!!
Интересует реализация именно на Gdiplus!! Считаю, что эта либа может с этим справиться!!


Ни PaintBox ни Image не годятся для нормальной анимации. Если картинка большая - ее нужно загонять напрямую в видиопамять - иначе тормоза обеспечены.

263
11 февраля 2007 года
koltaviy
816 / / 16.12.2004
Спасибо!
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог