Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: Hrundel от Апрель 06, 2013, 21:32



Название: [РЕШЕНО]↑ Искажается BMP при выводе из массива
Отправлено: Hrundel от Апрель 06, 2013, 21:32
Всем привет!

Пишу курсовую с задачей вывода 1D и 2D сигналов с их последующей трансформацией.

Проблему вывода 1D решил. Теперь перешел к 2D. В качестве формата сигнала выбрал *.bmp
Читаю сигнал и загружаю в массив так:

Код:
    FILE *BMPFile = fopen(FileName.toAscii().data(), "rb");

        // Read Header

        fileHeader.TypeBMP          = read_u16(BMPFile);
        fileHeader.SizeDataBMP      = read_u32(BMPFile);
        fileHeader.Reserved1BMP     = read_u16(BMPFile);
        fileHeader.Reserved2BMP     = read_u16(BMPFile);
        fileHeader.OffBitsBMP       = read_u32(BMPFile);

        fileHeader.SizeInfoBMP      = read_u32(BMPFile);
        fileHeader.WidthBMP         = read_s32(BMPFile);
        fileHeader.HeightBMP        = read_s32(BMPFile);
        fileHeader.PlanesBMP        = read_u16(BMPFile);
        fileHeader.BitCountBMP      = read_u16(BMPFile);
        fileHeader.CompressionBMP   = read_u32(BMPFile);
        fileHeader.SizeImageBMP     = read_u32(BMPFile);
        fileHeader.XPelsPerMeterBMP = read_s32(BMPFile);
        fileHeader.YPelsPerMeterBMP = read_s32(BMPFile);
        fileHeader.ClrUsedBMP       = read_u32(BMPFile);
        fileHeader.ClrImportantBMP  = read_u32(BMPFile);

        // Pixel Array
        pixelArray = new rgbQuad[fileHeader.HeightBMP * fileHeader.WidthBMP];

        // Read Bytes
        for (int i = 0; i < fileHeader.HeightBMP * fileHeader.WidthBMP; i++) {
            pixelArray[i].rgbBlue = getc(BMPFile);
            pixelArray[i].rgbGreen = getc(BMPFile);
            pixelArray[i].rgbRed = getc(BMPFile);
        }
        fclose(BMPFile);

Дальше передаю массив в виджет отображения и пытаюсь вывести так:

Код:
    pixArray = bitmapData->getPixelArray();

    widthBMP = bitmapData->getBitmapWidth();
    heightBMP = bitmapData->getBitmapHeight();

    img = new QImage(widthBMP+1, heightBMP+1, QImage::Format_RGB32);

QRgb rgb;
    int x = 0;
    int y = 0;

    for(int i = 0; i < widthBMP * heightBMP; i++)
    {
        rgb = qRgb(pixArray[i].rgbRed, pixArray[i].rgbGreen, pixArray[i].rgbBlue);
        if(x >= widthBMP)
        {
            x = 0;
            ++y;
        }
        else x++;

        img->setPixel(x, heightBMP-y, rgb);
    }

    QPainter painter(this);
    painter.drawImage(0,0,*img,0,0,-1,-1,Qt::AutoColor);

В итоге получаю такую тупую картинку:

(http://i53.fastpic.ru/big/2013/0406/52/22176d2eeb859287bea1f8bbd67e6a52.jpg)

Будьте добры подскажите в чем ошибка. Бьюсь весь день. Подставлял все возможные и невозможные значения. Сохранял во всех мыслимых и немыслимых форматах. Ничего не помогает. Буду благодарен за любые подсказки, примеры кодов и замечания.


Название: Re: Искажается BMP при выводе из массива
Отправлено: _OLEGator_ от Апрель 06, 2013, 21:37
Очевидно неправильно вычисляется размер (ширина) картинки и ошибка накапливается.
Ширина как минимум больше необходимой. Это легко проверяется подсчетом числа квадратов на первом и втором изображении.


Название: Re: Искажается BMP при выводе из массива
Отправлено: Hrundel от Апрель 06, 2013, 21:43
Ширну получаю из header'a

Код:
fileHeader.WidthBMP  = read_s32(BMPFile);

Может так быть, что по какой-то причине возвращает неправильное значение?


Название: Re: Искажается BMP при выводе из массива
Отправлено: _OLEGator_ от Апрель 06, 2013, 21:49
Тем не менее, ты потом еще ширину увеличиваешь зачем то:
Код
C++ (Qt)
img = new QImage(widthBMP+1, heightBMP+1, QImage::Format_RGB32);
И похоже я слегка попутал. Ты же снизу вверх изображение выводишь?


Название: Re: Искажается BMP при выводе из массива
Отправлено: Hrundel от Апрель 06, 2013, 22:20
Да, снизу вверх.

Вот на счет ширины как раз и проблема. Это еще самый оптимальный вариант. В других вариантах искажения еще больше получаются. Это просто тупая подгонка, чтобы хоть как-то ближе понять откуда ноги у проблемы растут.


Название: Re: Искажается BMP при выводе из массива
Отправлено: _OLEGator_ от Апрель 06, 2013, 22:38
Если снизу вверх, то тогда наоборот получается, что такое смещение возникает, когда ширину меньше берешь.
Прикрепи нормальный компилируемый проект со всеми данными, чтобы можно было потестить.
Так будет проще найти ошибку.


Название: Re: Искажается BMP при выводе из массива
Отправлено: Hrundel от Апрель 06, 2013, 23:24
Прикрепил. Надеюсь сможете разобраться в этом нагромождении. Событие обрабатывается в BitmapWidget.
Для того, чтобы загрузилось рабочее пространство необходимо открыть файл bmp или wav. Они там есть в проекте.


Название: Re: Искажается BMP при выводе из массива
Отправлено: Hrundel от Апрель 06, 2013, 23:25
Правильнее всего заточен файл testbild_16Bit copy.bmp там точно 8 bit на цвет = 24 на канал.


Название: Re: Искажается BMP при выводе из массива
Отправлено: Hrundel от Апрель 07, 2013, 11:15
Кстати, я тут посмотрел картинку в увеличении и мне стало казаться что смещение из-за сдвига в битах цвета. Смотри какой яркий красный пиксель.
Значит он имеет значение rgb(255, 0, 0)

Код:
img->setPixel(x, heightBMP-y, rgb);

а в этом участке есть только белые линии и черные квадраты. Значит он тащит два нуля из черного цвета и один 255 из белого.
Но как этот сдвиг получается - не могу понять.

(http://i33.fastpic.ru/big/2013/0407/9f/a433a04efddfa47cdcccd7f9009b429f.jpg)

Может я все-таки заголовок неправильно вычитываю. И смещаюсь в нем.
Ну вроде все проверил - не похоже на то.


Название: Re: Искажается BMP при выводе из массива
Отправлено: _OLEGator_ от Апрель 07, 2013, 11:46
Ну, во-первых, надо внимательно читать описание формата BMP: http://ru.wikipedia.org/wiki/BMP
Цитировать
Последовательность пикселей, записанных в том или ином виде. Пиксели хранятся построчно, снизу вверх. Каждая строка изображения дополняется нулями до длины, кратной четырём байтам.

И если уже используешь Qt, то лучше пользоваться инструментарием, например читать файл QFile+QDataStream:
Код
C++ (Qt)
QFile file(FileName);
file.open(QIODevice::ReadOnly);
 
QDataStream data(&file);
 
...
 
int skipBites = 0;
while ((fileHeader.WidthBMP * fileHeader.BitCountBMP / 8 + skipBites) % 4 != 0) skipBites++;
 
for (int i = 0; i < fileHeader.HeightBMP * fileHeader.WidthBMP; i++) {
data >> pixelArray[i].rgbBlue;
data >> pixelArray[i].rgbGreen;
data >> pixelArray[i].rgbRed;
 
if (skipBites > 0 && ((i + 1) % fileHeader.WidthBMP == 0))
{
data.skipRawData(skipBites);
}
}
 
file.close();

И в-третьих, не надо формировать изображение каждый раз в отрисовке, генерируй его только один раз:
Код
C++ (Qt)
widthBMP = bitmapData->getBitmapWidth();
heightBMP = bitmapData->getBitmapHeight();
img = new QImage(widthBMP, heightBMP, QImage::Format_RGB32);
 
QRgb rgb;
int x = 0;
int y = 0;
 
for(int i = 0; i < widthBMP * heightBMP; i++)
{
rgb = qRgb(pixArray[i].rgbRed, pixArray[i].rgbGreen, pixArray[i].rgbBlue);
 
img->setPixel(x, heightBMP-y-1, rgb);
 
if(x >= widthBMP - 1)
{
x = 0;
++y;
}
else x++;
}


Название: Re: Искажается BMP при выводе из массива
Отправлено: Hrundel от Апрель 07, 2013, 12:27
Ах вот оно откуда смещается   :D
А для меня эта строка была вообще пустым звуком. Я даже не думал, что подобные ситуации надо еще как-то предусматривать и отдельно их обрабатывать.
Причем, понял что сдвиг есть, а что его надо предусматривать - даже мысли не возникло.

Большое спасибо !!!


Название: Re: Искажается BMP при выводе из массива
Отправлено: _OLEGator_ от Апрель 07, 2013, 12:31
Переименуй свое первое сообщение и добавь в начало темы [РЕШЕНО].