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

Ваш аккаунт

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

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

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

Оптимизация кода

17K
05 июня 2010 года
neWManAlex
15 / / 20.10.2006
Здравствуйте, уважаемые. У меня есть программа, которая загружает изображение в компонент TImage и потом через канву делает анимацию "волны" над этим изображением. Но работает алгоритм очень медленно. Помогите, пожалуйста, оптимизировать код. Скриншот работы программы приведён ниже. Заранее спасибо!

Код:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
        Image1->Picture->LoadFromFile("C:\\CONTENT.BMP");
        TColor temp;
}

void __fastcall TForm1::Button2Click(TObject *Sender)
{
        int b;
        for(int a=-100;a<Image1->Picture->Width;a+=5)
        {
                b=0;
                for(int i=a;i<a+100;i++)
                {
                        for (int j=0;j<Image1->Picture->Height;j++)
                        {
                                Image1->Canvas->Pixels[j]=Image1->Canvas->Pixels[j+50*sin(M_PI*b/100)];
                        }
                        b++;
                }
                Image1->Refresh();
                Sleep(10);
                Image1->Picture->LoadFromFile("C:\\CONTENT.BMP");

        }
}
307
05 июня 2010 года
Artem_3A
863 / / 11.04.2008
Код:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
        Image1->Picture->LoadFromFile("C:\\CONTENT.BMP");
        TColor temp;
}

void __fastcall TForm1::Button2Click(TObject *Sender)
{
        int b;
        [COLOR="Red"]int imagen_widht = Image1->Picture->Width;
        int imagen_height = Image1->Picture->Height;
        float pi_sot = M_PI/100;
        int offset;[/COLOR]
        for(int a(-100);a<imagen_widht;a+=5)
        {
                b=0;
                for(int i(a);i<a+100;i++)
                {
                        [COLOR="Red"]offset = 50*int(sin(pi_sot*b));[/COLOR]
                        for (int j=0;j<imagen_height;j++)
                        {
                                Image1->Canvas->Pixels[j]=Image1->Canvas->Pixels[j+offset];
                        }
                        ++b;
                }
                Image1->Refresh();
                Sleep(10);
                Image1->Picture->LoadFromFile("C:\\CONTENT.BMP");

        }
}


мог опечататься. еще можно отправить все это дело в отдельный поток.
2.1K
05 июня 2010 года
Norgat
452 / / 12.08.2009
Цитата:
50*sin(M_PI*b/100)



а нельзя ли заранее рассчитать весь массив значений синусов, которые нужны? и потом просто подставлять нужное значение из массива?

немного набросаю...

Код:
float pi_sot = M_PI/100;
float sin_mas[100];//b у нас изменяется от 0 до 100 же?
for(int i = 0;i < 100; ++i)
    sin_mas = 50*sin(pi_sot*i/100);
...
...
b=0;
                for(int i=a;i<a+100;i++)
                {
                        for (int j=0;j<Image1->Picture->Height;j++)
                        {
                                Image1->Canvas->Pixels[j]=Image1->Canvas->Pixels[j+sin_mas];
                        }
                        b++;
                }


таким образом будет всего 100 вычислений синусов, вместо

for(int a(-100);a<imagen_widht;a+=5)*for(int i=a;i<a+100;i++) //лень считать сколько раз он тут подсчитается
5
05 июня 2010 года
hardcase
4.5K / / 09.08.2005
В любом случае больше всего "тормозит" алгоритм обращение к Pixels. Вместо Pixels лучше использовать ScanLine.
307
05 июня 2010 года
Artem_3A
863 / / 11.04.2008
Цитата: Norgat
а нельзя ли заранее рассчитать весь массив значений синусов, которые нужны? и потом просто подставлять нужное значение из массива?



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

5
05 июня 2010 года
hardcase
4.5K / / 09.08.2005
Еще замечания. Использование Sleep(10) не здорово - таймером пользоваться нужно.
Кроме этого лучше один раз загрузить картинку в память и манипуляции производить над ее клоном, который и отображать на Image, но я бы не пользовался компонентом и руками ее отрисовывал.
2.1K
05 июня 2010 года
Norgat
452 / / 12.08.2009
Цитата: Artem_3A
можно, но это будет не гибко, бо будет только для конкретного размера изображения, да и размер массива то не хилый получается.



ну в примере всего 100 значений синуса нужно...

 
Код:
b=0;
for(int i(a);i<a+100;i++){... ++b;}


как бы от размера картинки там выбор a зависел, а не кол-во проходов цикла, где меняется b.
307
05 июня 2010 года
Artem_3A
863 / / 11.04.2008
омг, пропустил я это дело, но при таком оформлении кода и не мудрено... теперь убедил!:D

тогда конечный резалт.

Код:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
        Image1->Picture->LoadFromFile("C:\\CONTENT.BMP");
        TColor temp;
}

void __fastcall TForm1::Button2Click(TObject *Sender)
{
        int b;
        int imagen_widht = Image1->Picture->Width;
        int imagen_height = Image1->Picture->Height;
        float pi_sot = M_PI/100;
        int offset[100];
        int b;
        int temp_size;

        for(b = 0; b<100; b++)
            offset = 50*int(sin(pi_sot*b));

        for(int a(-100);a<imagen_widht;a+=5)
        {
                temp_size = a + 100;
                for(int i(a);i<temp_size;i++)
                {
                        b = 0;
                        for (int j=0;j<imagen_height;j++)
                        {
                                Image1->Canvas->Pixels[j]=Image1->Canvas->Pixels[j+offset];
                        }
                        ++b;
                }
                Image1->Refresh();
                Sleep(10);
                Image1->Picture->LoadFromFile("C:\\CONTENT.BMP");

        }
}


топикавтор - проверяй, бо мы тут сие на коленке писали.
5
05 июня 2010 года
hardcase
4.5K / / 09.08.2005
Цитата: Artem_3A
можно, но это будет не гибко, бо будет только для конкретного размера изображения, да и размер массива то не хилый получается.

Недавно тут уже советовали как с помощью школьной математики выполнить достаточно точное вычисление синусов.

5
05 июня 2010 года
hardcase
4.5K / / 09.08.2005
Цитата: Norgat
ну в примере всего 100 значений синуса нужно...

Верно, но как я уже писал, проблема не только в них.

307
05 июня 2010 года
Artem_3A
863 / / 11.04.2008
ну уж синусы я думаю мы трогать не будем, пусть сами потихоньку считаются!=)))

Цитата: hardcase
В любом случае больше всего "тормозит" алгоритм обращение к Pixels. Вместо Pixels лучше использовать ScanLine.



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

5
05 июня 2010 года
hardcase
4.5K / / 09.08.2005
Цитата: Artem_3A

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


Есть смутная мысль, что Хардкейз с этим сам неоднократно сталкивался. ;)

307
05 июня 2010 года
Artem_3A
863 / / 11.04.2008
Цитата: hardcase
Есть смутная мысль, что Хардкейз с этим сам неоднократно сталкивался. ;)



Тогда есть смутная мысль, что предыдущая смутная мысль отпадает.:D

17K
07 июня 2010 года
neWManAlex
15 / / 20.10.2006
Спасибо всем отписавшимся! Попробовал код, предложенный Artem_3A. Программа стала работать немного быстрее.

Со ScanLine я сейчас разберусь.

Может ещё есть какие-то идеи?

Исправленный код:

Код:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
        Image1->Picture->LoadFromFile("C:\\CONTENT.BMP");
        TColor temp;
}

void __fastcall TForm1::Button2Click(TObject *Sender)
{
        int b;
        int imagen_widht = Image1->Picture->Width;
        int imagen_height = Image1->Picture->Height;
        float pi_sot = M_PI/100;
        int offset[100];

        for(b = 0; b<100; b++)
            offset = 50*sin(pi_sot*b);


        for(int a=-100;a<imagen_widht;a+=5)
        {
                b=0;

                for(int i=a;i<a+100;i++)
                {
                        for (int j=0;j<imagen_height;j++)
                        {
                                Image1->Canvas->Pixels[j]=Image1->Canvas->Pixels[j+offset];
                        }
                        b++;
                }
                Image1->Refresh();
                Sleep(10);
                Image1->Picture->LoadFromFile("C:\\CONTENT.BMP");

        }

}
307
08 июня 2010 года
Artem_3A
863 / / 11.04.2008
 
Код:
Image1->Picture->LoadFromFile("C:\\CONTENT.BMP");


вот это очень узкое место. на каждой итерации с жестяка грузим в память картинку. в билдере я думаю есть какой нить клас тип TPicture(я как бы на билдере не очень кодил, так что в его библиотеках не особо), так вот, загрузить в него картинку и постоянно хранить. когда нужен будет новый экземпляр, то просто копировать ее. при чем все манипуляции по созданию волны лучше производить именно в этом классе, а не в компоненте формы.

так же вместо слипа используйте таймер.

ЗЫ: а вообще обо всем этом писал уважаемый hardcase ниже, читайте внимательней.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог