LINUX.ORG.RU

QT RGB или BGR ? Не могу разобраться.

 char2qimg, ,


0

2

Что-то я не пойму как из char* получить Картинку в Qt? Сделал тест:


    unsigned char* array = new unsigned char[10*10*3];
    for(int i =0;i<300;i++){
        array[i]=0xFF;
    }
    array[0]=0;
    array[1]=0;
    array[2]=0xFF;

    QImage* img = new QImage(array,10,10,QImage::Format_RGB32);

ПО идее, он должен вывести синий первый пиксель, а остальные белые. но не тут то было:

http://hostingkartinok.com/show-image.php?id=1796d7cd69325174c3df00c3bc846907

Может я чего-то не понимаю? если я устанавливаю array[0]=0xFF; То пиксель - синий. Так что там формат BGR? А ещё, как вы заметили, белым закрашивается не всё изображение, а до определённого момента. Эмпирически я выяснил, что пикселы кратные 3 вообще никак не влияют и никак не учитываются.

Так как блин работать? Вроде нормальный формат RGB32, если я правильно понял - это 0xRRGGBB или нет? По 8 бит на цвет?

Мне, изначально надо вывести ЧБ картинку которая записана в short на экран QT.Я так посмотрел, что все опреции производятся в char*. Поэтому, я каждый пиксель short* поделил на 256 и перенёc в char*. Не нашел формата в QImage для отображения ЧБ картинок, так что решил сделать алгоритм - что-то типа

 unsigned char* color = new unsigned char[h*v*3];
   for(int i =0;i<h*v;i++){
     color[i*3]=data[i];
     color[i*3+1]=data[i];
     color[i*3+2]=data[i];
   }
 QImage* img = new QImage(array,w,h,QImage::Format_RGB32);



по моим соображениям  оно должно вывести ЧБ картинку. но выводило какой-то бред. И я поставил вышеизложенный эксперимент, который провалился. Подскажите. в чём там дело? И, может, как оптимальней решить задачу?

В большинстве архитектур, включая народные интеловские процы, порядок байт в числе обратный (big endian, в отличие от архитектур с little endian). Формат-то RGB, но первым идёт синий пиксель.

quiet_readonly ★★★★
()

Просто диву с таких даюсь, неужели так сложно прочитать документацию?

QImage::Format_RGB32

The image is stored using a 32-bit RGB format (0xffRRGGBB).

Deleted
()
Ответ на: комментарий от quiet_readonly

В большинстве популярных как раз little endian.

note173 ★★★★★
()
Ответ на: комментарий от Deleted

Само собой читал, и меня ввели в заблуждение эти 2 ff , но ведь порядок байт там всё-равно RGB, даже если между пикселами по двум FF-кам, это не объясняет обратный порядок байт. Тогда 0 пиксел ни на что бы не влиял, а первый отвечал бы за красный цвет - но это не так. Видимо из за обратного порядка , как раз, каждый 3 пиксел ни на что не влияет, но тогда за чем он?

quiet_readonly

Надеялся обойтись без SetPixel, а про scalLine() ещё не слышал - почитаю. Про обратный порядок байт тоже не слышал - Почитаю.

QImage::Format_RGB888

Поробовал. Там прямой порядок байт и вроде нет промежуточных, но цикл всё-равно не заполняет картинку целиком. Обратите внимание

    unsigned char* array = new unsigned char[10*10*3];
    for(int i =0;i<300;i++){
        array[i]=0xFF;
    }

    array[0]=0xFF;
    array[1]=0x00;
    array[2]=0x00;

    array[3]=0;
    array[4]=0xFF;
    array[5]=0x00;

    array[6]=0;
    array[7]=0x00;
    array[8]=0xFF;
    QImage* img = new QImage(array,10,10,QImage::Format_RGB888);
Результат http://s002.radikal.ru/i199/1211/8f/0a4265f9f4d7.png

Теперь меня терзает странное чувство, что где-то меня обманывают. Разве в картинке HxV по 3 байта на пиксел не H*V*3 байт?

И вы не ответили про монохромные изображения. Неужели нету методов для их вывода и необходимо переводить их в RGB? И адекватно ли я перевожу каждый short описывающий пиксел в каждый char описывающий пиксел

vsrmis
() автор топика
Ответ на: комментарий от vsrmis

Само собой читал, и меня ввели в заблуждение эти 2 ff , но ведь порядок байт там всё-равно RGB, даже если между пикселами по двум FF-кам, это не объясняет обратный порядок байт. Тогда 0 пиксел ни на что бы не влиял, а первый отвечал бы за красный цвет - но это не так. Видимо из за обратного порядка , как раз, каждый 3 пиксел ни на что не влияет, но тогда за чем он?

Не-а. Формат там по факту BGR с паддингом (на интелевской архитектуре). 0xffRRGGBB в little-endian представлении будет BB GG RR ff. Размер пикселя, заметь, 4 байта. Ты выделяешь слишком мало памяти под исходный массив, поэтому внизу изображения мусор.

Deleted
()
Ответ на: комментарий от Deleted

Хорошо, пусть будет так. Меня не сильно волнует цвет. Всё-равно буду запихивать во все 3 канала 1 значение. Сейчас меня слегка смутило другое. Перевод из short в char

Сделал такой код

   read();// читает из файла и заносит в contents
   //contents это valarray 

   short*data =  new short[contents.size()];
   for(int i = 0;i<contents.size();i++){
       data[i]=contents[i];// перевод из valarray в указатель на массив
   }
   unsigned char* chardata  = new unsigned char[image->axis(0)*image->axis(1)*4];// создание массива байтов для RGB32
   for(int i =1;i<contents.size();i+=1){
       chardata[i*4]=data[i]/255; // конвертироование short в char
       chardata[i*4+1]=data[i]/255;
       chardata[i*4+2]=data[i]/255;
   }
     QImage* img= new  QImage(chardata,image->axis(0),image->axis(1),QImage::Format_RGB32);

Результат вышел ну оооочень тёмный. http://s017.radikal.ru/i405/1211/91/57bd85258fae.jpg ( слева моя программа, справа эта-же картинка, открытая Gimp-ом) Адекватная яркость достигается при делении каждого пиксела на 50( выяснено эмперически). Но, так нельзя я не уверен на 100% что там информация хранится в short, но уверен что не в byte. Да и если бы она хранилась там в int,long — при делении, я бы получил картинку ещё темнее. А вот результат без деления http://img13.imageshost.ru/img/2012/11/10/image_509ea7996d13c.png Совсем туфта. И ещё, я заметил, что картинка инвертирована зеркалирована относительно Ох. Я думал, что это изза порядка записи и изменил его на chardata[i*4]=data[contents.size()-i] Но в результате получил картинку не только вверх ногами, а ещё и зеркальную относительно Oy

vsrmis
() автор топика

Используем повсеместно формат QImage::Format_ARGB32_Premultiplied, как рекомендуемый тролями формат для быстрых операций, а для него и для QImage::Format_RGB32 можно использовать следующие заготовки:

1) Read

QRgb *rgbline = reinterpret_cast<QRgb*>(image.scanLine(y));
int red = qRed(rgbline[x]);
// ...

2) Read-write

quint8* pix = image.scanLine(y);
for ( int x = 0; x < width; ++x, pix += 4 ) {
  pix [ 0 ] = blue;
  pix [ 1 ] = green;
  pix [ 2 ] = red;
  pix [ 3 ] = alpha
}

nikitos ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.