Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: Firefox от Декабрь 06, 2011, 17:51



Название: прорисовка не успевает
Отправлено: Firefox от Декабрь 06, 2011, 17:51
доброго времени суток всем. у меня такая вот проблемка: рисую круговую развертку, но прорисовка не поспевает за таймером. то есть - есть картинка 800х800 пикселов.  от центра каждый 0,667 сек должен рисоваться круг радиусом R, причем радиус каждый цикл возрастает. но окружность внутри заполняется точками(drawPoint), так как точка каждая имеет свой цвет. воти получается, что при нарастании круга уже с 5-6 цикла никак обновление и прорисовка не укладываются в 0.667 сек, а под конец вообще доходит до 8-10 сек, что неприемлемо совершенно. рисую обыкновенно через QPainter в QImage потом отображаю. Может есть способы более быстрой прорисовки.  Буду рада идеям.


Название: Re: прорисовка не успевает
Отправлено: GreatSnake от Декабрь 06, 2011, 18:01
Какая платформа? Какой формат QImage? Включено ли сглаживание?


Название: Re: прорисовка не успевает
Отправлено: BRE от Декабрь 06, 2011, 18:02
но окружность внутри заполняется точками(drawPoint)
Вот так не надо заполнять, нужно работать напрямую с буфером QImage.


Название: Re: прорисовка не успевает
Отправлено: Igors от Декабрь 06, 2011, 18:24
Конечно если рисование не укладывается по времени - в первую очередь надо подумать как ee ускорить (о чем уже сказали выше).

Но так или иначе неизбежны ситуации когда нужно прервать отрисовку когда она уже не имеет смысла. Простой пример - пользователь тянет мышу. Если тянет "достаточно  медленно" - все хорошо, все 100K точек успели отрисоваться. Но если с бодуна или человек нервный - не успели. Нормальный софт должен это отрабатывать и выскакивать из paint если он уже потерял актуальность. Напр проверяя текущую позицию мыши через каждые N точек. Такого рода "маленькие тонкости" и есть отличия профессионального софта от "философии гну"  :)


Название: Re: прорисовка не успевает
Отправлено: Firefox от Декабрь 06, 2011, 22:04
Вот так не надо заполнять, нужно работать напрямую с буфером QImage.
а это не так разве??как тогда напрямую в QImage?
Код:
int Radiuse=20;
QImage *img;
img = new QImage(frame1);
frame1->installEventFilter(this);

QTimer *tm;
tm=new QTimer(this);
connect(tm,SIGNAL(timeout()),SLOT(DRAWW()));
tm->start(667);
...
eventFilter()
{
 ...
if(obj==frame1)
{
Qpainter pnt;
pnt->drawImage(0,0,*img,0,0,0);
}
}

void Draw_shum()
{
QPainter pnt2(img);
radiuse+=20;
if(radiuse>380)tm->stop();
// x, y - координаты точек в массиве
if(radiuse>=sqrt(x*x+y*y))
{
     pnt.setPen(QColor("из массива случайных чисел берется"));
     pnt.drawPoint(x,y);
}
}

void DRAWW()
{
Draw_shum();
frame1->update();
}

организация примерно такая. платформа VS2003 qt 4.4.3


Название: Re: прорисовка не успевает
Отправлено: BRE от Декабрь 06, 2011, 22:05
Я про то, как заполняется этот QImage. Не нужно использовать drawPoint - это очень медленно.



Название: Re: прорисовка не успевает
Отправлено: Firefox от Декабрь 06, 2011, 22:19
поясните на пальцах тогда как???функциями. я вроде рисуу на имежде но в паинтер.


Название: Re: прорисовка не успевает
Отправлено: GreatSnake от Декабрь 06, 2011, 22:21
Заполнять QImage нужно минимум через QImage::setPixel().

Код
C++ (Qt)
eventFilter()
{
     ...
     if(obj==frame1)
     {
           Qpainter pnt;
           pnt->drawImage(0,0,*img,0,0,0);
     }
}
При каких именно событиях делается pnt->drawImage()?
И почему нельзя было отнаследоваться от QFrame и не перегрузить QFrame::paintEvent() и уже в нём делать отрисовку.
eventFilter() как-то несеръёзно для этого использовать.


Название: Re: прорисовка не успевает
Отправлено: Firefox от Декабрь 06, 2011, 22:24
а это разве реально быстрее???


Название: Re: прорисовка не успевает
Отправлено: Firefox от Декабрь 06, 2011, 22:32
спасибо завтра обязательно попробую. просто сталкиваюсь с прорисовкой графики впервые и как в коллективе посоветовали(через eventFilter у нас работают многие) так и реализовала.


Название: Re: прорисовка не успевает
Отправлено: Firefox от Декабрь 07, 2011, 10:54
Что-то у меня не отображается. Подскажите ошибку. Сделала вот как
Код:
// конструктор
img_obp1 = new QImage( frame_obp->width(), frame_obp->height(), QImage::Format_RGB32);
void pr::paintEvent(QPaintEvent *pe)
{
frame_obp->paintEvent(pe); // РУГАЕТСЯ НА ЭТУ СТРОЧКУ  error C2248: 'QFrame::paintEvent' : cannot access protected member declared in class 'QFrame'
// если убрать верхнюю строчку не рисуется ничего
QPainter p(frame_obp);
p.drawImage(0,0,*img_obp1,0,0,0,0);

}
//слот таймера 0.6 сек
// старт таймера по кнопке происходит
void pr::Krug()
{
Draw_shum();
frame_obp->update();
}
// функция прорисовки
void pr::Draw_shum()
{
QRgb rgb_col;
int col=0,r_col=0,g_col=0,b_col=0,rez=0;
acc_d->Detection_account();

// расчет радиуса прорисовки на 1 цикл
if(D_shkala>0)
Radius+=4*48/D_shkala;
if(Radius>=384 && T_obmen->isActive()==true)
{
KRUG_DRAW_SHUM->stop();
return;
}

float Rez1=0;
int count_r=0, count_g=0;
QString str;
int Num_col=0;
int i,j;
for (i=0;i<384;i++)
{
for(j=0;j<384;j++)
{

Rez1=sqrt((float)((i)*(i)+(j)*(j)));
if(Radius>Rez1 )//условие попадет ли точка в сектор окружности радиуса Radius
{
// верхний правый сектор отображается
Num_col=acc_d->OUT_STR.Rastr[i+384][384-j];
if(Num_col>=255) r_col=255;
if(Num_col<=0)r_col=0;
if(Num_col>0 && Num_col<255)r_col=byr_colors[Num_col][0];
if(Num_col>=255)g_col=255;
if(Num_col<=0)g_col=0;
if(Num_col>0 && Num_col<255)g_col=byr_colors[Num_col][1];
if(Num_col>=255)b_col=255;
if(Num_col<=0)b_col=0;
if(Num_col>0 && Num_col<255)b_col=byr_colors[Num_col][2];
img_obp1->setPixel(i,-j,qRgb(r_col,g_col,b_col));
// проверка
if(r_col>0)
count_r++;
LE_1->setText(str.setNum(count_r));
if(g_col>0)
count_g++;
LE_2->setText(str.setNum(count_g));
//

// нижний правый сектор окружности отображается
Num_col=acc_d->OUT_STR.Rastr[i+384][384+j];
if(Num_col>=255)r_col=255;
if(Num_col<=0)r_col=0;
if(Num_col>0 && Num_col<255)r_col=byr_colors[Num_col][0];
if(Num_col>=255)g_col=255;
if(Num_col<=0)g_col=0;
if(Num_col>0 && Num_col<255)g_col=byr_colors[Num_col][1];
if(Num_col>=255)b_col=255;
if(Num_col<=0)b_col=0;
if(Num_col>0 && Num_col<255)b_col=byr_colors[Num_col][2];
img_obp1->setPixel(i,j,qRgb(r_col,g_col,b_col));

// проверка
if(r_col>0)
count_r++;
LE_1->setText(str.setNum(count_r));
if(g_col>0)
count_g++;
LE_2->setText(str.setNum(count_g));
//


// нижний левый сектор окружности отображается
Num_col=acc_d->OUT_STR.Rastr[384-i][384-j];
if(Num_col>=255)r_col=255;
if(Num_col<=0)r_col=0;
if(Num_col>0 && Num_col<255)r_col=byr_colors[Num_col][0];
if(Num_col>=255)g_col=255;
if(Num_col<=0)g_col=0;
if(Num_col>0 && Num_col<255)g_col=byr_colors[Num_col][1];
if(Num_col>=255)b_col=255;
if(Num_col<=0)b_col=0;
if(Num_col>0 && Num_col<255)b_col=byr_colors[Num_col][2];
img_obp1->setPixel(-i,-j,qRgb(r_col,g_col,b_col));


// проверка
if(r_col>0)
count_r++;
LE_1->setText(str.setNum(count_r));
if(g_col>0)
count_g++;
LE_2->setText(str.setNum(count_g));
//


// верхний левый сектор окружности отображается
Num_col=acc_d->OUT_STR.Rastr[384-i][384+j];
if(Num_col>=255)r_col=255;
if(Num_col<=0)r_col=0;
if(Num_col>0 && Num_col<255)r_col=byr_colors[Num_col][0];
if(Num_col>=255)g_col=255;
if(Num_col<=0)g_col=0;
if(Num_col>0 && Num_col<255)g_col=byr_colors[Num_col][1];
if(Num_col>=255)b_col=255;
if(Num_col<=0)b_col=0;
if(Num_col>0 && Num_col<255)b_col=byr_colors[Num_col][2];
img_obp1->setPixel(-i,j,qRgb(r_col,g_col,b_col));

// проверка
if(r_col>0)
count_r++;
LE_1->setText(str.setNum(count_r));
if(g_col>0)
count_g++;
LE_2->setText(str.setNum(count_g));
//

Count_cel_obn=0;
int R1=0,R2=0;//расстояние до цели от центра окружности

for(int t=0;t<2;t++)
{
if(acc_d->OUT_STR.Mass_obn[t][0]==1)
{
Count_cel_obn++;

R1=(int)sqrt((float)((acc_d->OUT_STR.Otmetka[t][0]-384)*(acc_d->OUT_STR.Otmetka[t][0]-384) +(acc_d->OUT_STR.Otmetka[t][1]-384)*(acc_d->OUT_STR.Otmetka[t][1]-384)));
R2=(int)sqrt((float)((acc_d->OUT_STR.Otmetka[t][2]-384)*(acc_d->OUT_STR.Otmetka[t][2]-384) +(acc_d->OUT_STR.Otmetka[t][3]-384)*(acc_d->OUT_STR.Otmetka[t][3]-384)));
if(R1<=Radius && R2<=Radius && R1>0 && R2>0)
{
QRect rec1(acc_d->OUT_STR.Otmetka[t][0]-384,acc_d->OUT_STR.Otmetka[t][1]-384,3,3);
QRect rec2(acc_d->OUT_STR.Otmetka[t][2]-384,acc_d->OUT_STR.Otmetka[t][3]-384,3,3);
rgb_col=qRgb(255,255,255);
img_obp1->setPixel(acc_d->OUT_STR.Otmetka[t][0]-384,acc_d->OUT_STR.Otmetka[t][1]-384,rgb_col);
img_obp1->setPixel(acc_d->OUT_STR.Otmetka[t][0]-384+1,acc_d->OUT_STR.Otmetka[t][1]-384,rgb_col);
img_obp1->setPixel(acc_d->OUT_STR.Otmetka[t][0]-384-1,acc_d->OUT_STR.Otmetka[t][1]-384,rgb_col);
img_obp1->setPixel(acc_d->OUT_STR.Otmetka[t][0]-384,acc_d->OUT_STR.Otmetka[t][1]-384+1,rgb_col);
img_obp1->setPixel(acc_d->OUT_STR.Otmetka[t][0]-384+1,acc_d->OUT_STR.Otmetka[t][1]-384+1,rgb_col);
img_obp1->setPixel(acc_d->OUT_STR.Otmetka[t][0]-384-1,acc_d->OUT_STR.Otmetka[t][1]-384+1,rgb_col);
img_obp1->setPixel(acc_d->OUT_STR.Otmetka[t][0]-384,acc_d->OUT_STR.Otmetka[t][1]-384-1,rgb_col);
img_obp1->setPixel(acc_d->OUT_STR.Otmetka[t][0]-384+1,acc_d->OUT_STR.Otmetka[t][1]-384-1,rgb_col);
img_obp1->setPixel(acc_d->OUT_STR.Otmetka[t][0]-384-1,acc_d->OUT_STR.Otmetka[t][1]-384-1,rgb_col);

img_obp1->setPixel(acc_d->OUT_STR.Otmetka[t][2]-384,acc_d->OUT_STR.Otmetka[t][3]-384,rgb_col);
img_obp1->setPixel(acc_d->OUT_STR.Otmetka[t][2]-384+1,acc_d->OUT_STR.Otmetka[t][3]-384,rgb_col);
img_obp1->setPixel(acc_d->OUT_STR.Otmetka[t][2]-384-1,acc_d->OUT_STR.Otmetka[t][3]-384,rgb_col);
img_obp1->setPixel(acc_d->OUT_STR.Otmetka[t][2]-384,acc_d->OUT_STR.Otmetka[t][3]-384+1,rgb_col);
img_obp1->setPixel(acc_d->OUT_STR.Otmetka[t][2]-384+1,acc_d->OUT_STR.Otmetka[t][3]-384+1,rgb_col);
img_obp1->setPixel(acc_d->OUT_STR.Otmetka[t][2]-384-1,acc_d->OUT_STR.Otmetka[t][3]-384+1,rgb_col);
img_obp1->setPixel(acc_d->OUT_STR.Otmetka[t][2]-384,acc_d->OUT_STR.Otmetka[t][3]-384-1,rgb_col);
img_obp1->setPixel(acc_d->OUT_STR.Otmetka[t][2]-384+1,acc_d->OUT_STR.Otmetka[t][3]-384-1,rgb_col);
img_obp1->setPixel(acc_d->OUT_STR.Otmetka[t][2]-384-1,acc_d->OUT_STR.Otmetka[t][3]-384-1,rgb_col);
}
}
}
}
}

}
End_radius=Radius-1;
Count_krug++;
if(End_radius>=384)
LE_4->setText("end");
}


Название: Re: прорисовка не успевает
Отправлено: GreatSnake от Декабрь 07, 2011, 11:00
Что такое pr и frame_obp и зачем такой hack ???
Код
C++ (Qt)
frame_obp->paintEvent(pe);


Название: Re: прорисовка не успевает
Отправлено: BRE от Декабрь 07, 2011, 11:35
Firefox, не нужно использовать и setPixel. :) Ты при каждом вызове рассчитываешь адрес в буфере для указанных координат, а этого можно не делать.
Смотри небольшой пример:

Код
C++ (Qt)
#include <QImage>
#include <QColor>
 
const int ImageWidth  = 512;
const int ImageHeight = 512;
 
int main( int, char *[] )
{
       QImage img( ImageWidth, ImageHeight, QImage::Format_RGB32 );
 
       // Заливаем картинку Qt::Green
       QRgb *p = reinterpret_cast<QRgb *>( img.bits() );       // получаем указатель на начало буфера
       QRgb fillColor = QColor( Qt::green ).rgb();
       for( int i = 0; i < ImageWidth * ImageHeight; ++i )
               *p++ = fillColor;
 
       // Устанавливаем точку по координатам 10, 10
       int x = 10;
       int y = 10;
 
       QRgb *point = reinterpret_cast<QRgb *>( img.scanLine( y ) ) + x;        // другой способ получения адреса в буфере картинки
       QRgb pointColor = QColor( 20, 40, 60 ).rgb();           // r=20 g=40 b=60
       *point = pointColor;
 
       // Для того, что бы переместиться к следующей точке достаточно инкрементировать указатель point:
       // ++point
       // предыдущей:
       // --point
 
       // Для того, что бы переместиться к точке под текущей достаточно к указателю прибавить длину строки
       point += ImageWidth;
       *point = pointColor;
 
       img.save( "test.png" );
 
       return 0;
}
 

Для интереса можно сравнить скорость заливки картинки через буфер и через drawPoint/setPixe.


Название: Re: прорисовка не успевает
Отправлено: GreatSnake от Декабрь 07, 2011, 11:44
Firefox, не нужно использовать и setPixel. :)
На самом деле QImage::setPixel() тоже довольно-таки оптимизирован. И если пользоваться твоим способом, имхо, выигрыш будет минимальным)


Название: Re: прорисовка не успевает
Отправлено: BRE от Декабрь 07, 2011, 11:48
На самом деле QImage::setPixel() тоже довольно-таки оптимизирован. И если пользоваться твоим способом, имхо, выигрыш будет минимальным)
Я веду к тому, что нужно изменять сам алгоритм формирования картинки и постараться сделать его линейным, т.е. выполнять заполнение по строкам.
А если прыгать от точки к точки, то мой вариант ничем не будет отличаться от setPixel или drawPixel. :)


Название: Re: прорисовка не успевает
Отправлено: GreatSnake от Декабрь 07, 2011, 12:01
А если прыгать от точки к точки, то мой вариант ничем не будет отличаться от setPixel или drawPixel. :)
Для изменения цвета в QImage, если не нужен composing, QPainter ни в коем случае вообще не нужен.


Название: Re: прорисовка не успевает
Отправлено: Firefox от Декабрь 07, 2011, 13:06
frame_obp -фрейм, на котором я рисую. pe - QPainEvent событие


Название: Re: прорисовка не успевает
Отправлено: GreatSnake от Декабрь 07, 2011, 13:09
frame_obp -фрейм, на котором я рисую. pe - QPainEvent событие
Ещё раз внимательно читаем вопрос (http://www.prog.org.ru/index.php?topic=20274.msg137787#msg137787).


Название: Re: прорисовка не успевает
Отправлено: Igors от Декабрь 07, 2011, 20:10
А если прыгать от точки к точки, то мой вариант ничем не будет отличаться от setPixel или drawPixel. :)
Смотря что заложено в обработку пикселя. Напр если простейшие операции (напр вырезать красный цвет) - то прямой доступ все равно ощутимо быстрее. Или если картинка масштабируется (и нужно взять 9 пикселей) - прирост по скорости хороший.


Название: Re: прорисовка не успевает
Отправлено: Firefox от Декабрь 07, 2011, 20:30
спасибо за пример))все сделала. круто очень. все успевает)) :D