Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: ecspertiza от Октябрь 11, 2011, 10:20



Название: Оптимизация конвертации
Отправлено: ecspertiza от Октябрь 11, 2011, 10:20
Как можно оптимизировать следующий код ?

Код:
QImage *ResizePreview::nv21torgb(CameraFrame *frame) {

    QByteArray *data = frame->data;
    int width = frame->width;
    int height = frame->height;

    QImage *img = new QImage(width,height,QImage::Format_ARGB32);


    int frameSize = width * height;

    int uvp = 0;
    int u = 0;
    int v = 0;
    int y = 0;
    int r = 0;
    int g = 0;
    int b = 0;

       for (int j = 0, yp = 0; j < height; ++j) {
           uvp = frameSize + (j >> 1) * width;
           u = 0;
           v = 0;

           for (int i = 0; i < width; ++i, ++yp) {
               y = (0xff & (int)data->at(yp));

               if ((i & 1) == 0) {
                   v = (0xff & ((int)data->at(uvp++)) - 128;
                   u = (0xff & ((int)data->at(uvp++)) - 128;
               }

               r = y + 1.402f * v;
               g = y - 0.34414f * u - 0.71414f * v;
               b = y + 1.772f * u;

               if (r < 0) r = 0; else if (r > 255) r = 255;
               if (g < 0) g = 0; else if (g > 255) g = 255;
               if (b < 0) b = 0; else if (b > 255) b = 255;

               img->setPixel(i,j,qRgba(r,g,b,255));
           }
       }

   return img;
}

этот код конвертирует изображения из nv21 в rgb и работает не сильно шустро 4 - 7 раз в секунду, хотелось бы оптимизировать до 12 -14. что здесь можно изменить?


Название: Re: Оптимизация конвертации
Отправлено: Igors от Октябрь 11, 2011, 12:40
1) Ну конечно работать с пикселями напрямую вместо setPixel. Учитывая что число байт в строке может быть больше числа пикселей * размер пикселя, надо использовать scanLine. Полагается что выходной имедж 32 бита на пиксель (ну может 24). Для остальных (редко используемых) - то что сейчас

2) Объявление int r, g, b ощутимо снижает качество, а скорость сильно не поднимает. Лучше считать все во float, а также добавить бухгалтерское округление

Edit: at тоже (возможно) что-то отгрызает, лучше взять (const char *) - стоить проверить.


Название: Re: Оптимизация конвертации
Отправлено: ecspertiza от Октябрь 11, 2011, 14:25
насчет r,g,b уже пробовал разницу почти не заметил, тоже с const char*. А вот как работать с пикселями напрямую ? я то думал что setPixel - это напрямую :)


Название: Re: Оптимизация конвертации
Отправлено: BRE от Октябрь 11, 2011, 15:41
насчет r,g,b уже пробовал разницу почти не заметил, тоже с const char*. А вот как работать с пикселями напрямую ? я то думал что setPixel - это напрямую :)
Картинка храниться в одном непрерывном куске памяти как последовательность точек, строка за строкой, начиная с верхней, слева направо.
Ты задал формат QImage::Format_ARGB32, значит каждая точка будет состоять из 4 байт в порядке: Alpha, Red, Green, Blue.
Начало этого возвращает метод:
uchar * QImage::bits ()

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


Название: Re: Оптимизация конвертации
Отправлено: Igors от Октябрь 11, 2011, 17:19
Код:
       for (int j = 0, yp = 0; j < height; ++j) {
           uvp = frameSize + (j >> 1) * width;
В последующем цикле не увидел какая еще разница между j = 0 и j = 1 (кроме записи выходных пикселей). Так может сделать цикл j +=2 и писать по 2 пикселя