Russian Qt Forum
Ноябрь 23, 2024, 07:06 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: [РЕШЕНО]↑ Искажается BMP при выводе из массива  (Прочитано 7585 раз)
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);

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



Будьте добры подскажите в чем ошибка. Бьюсь весь день. Подставлял все возможные и невозможные значения. Сохранял во всех мыслимых и немыслимых форматах. Ничего не помогает. Буду благодарен за любые подсказки, примеры кодов и замечания.
« Последнее редактирование: Апрель 07, 2013, 12:46 от Hrundel » Записан
_OLEGator_
Гость
« Ответ #1 : Апрель 06, 2013, 21:37 »

Очевидно неправильно вычисляется размер (ширина) картинки и ошибка накапливается.
Ширина как минимум больше необходимой. Это легко проверяется подсчетом числа квадратов на первом и втором изображении.
« Последнее редактирование: Апрель 06, 2013, 21:42 от _OLEGator_ » Записан
Hrundel
Гость
« Ответ #2 : Апрель 06, 2013, 21:43 »

Ширну получаю из header'a

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

Может так быть, что по какой-то причине возвращает неправильное значение?
Записан
_OLEGator_
Гость
« Ответ #3 : Апрель 06, 2013, 21:49 »

Тем не менее, ты потом еще ширину увеличиваешь зачем то:
Код
C++ (Qt)
img = new QImage(widthBMP+1, heightBMP+1, QImage::Format_RGB32);
И похоже я слегка попутал. Ты же снизу вверх изображение выводишь?
« Последнее редактирование: Апрель 06, 2013, 21:52 от _OLEGator_ » Записан
Hrundel
Гость
« Ответ #4 : Апрель 06, 2013, 22:20 »

Да, снизу вверх.

Вот на счет ширины как раз и проблема. Это еще самый оптимальный вариант. В других вариантах искажения еще больше получаются. Это просто тупая подгонка, чтобы хоть как-то ближе понять откуда ноги у проблемы растут.
Записан
_OLEGator_
Гость
« Ответ #5 : Апрель 06, 2013, 22:38 »

Если снизу вверх, то тогда наоборот получается, что такое смещение возникает, когда ширину меньше берешь.
Прикрепи нормальный компилируемый проект со всеми данными, чтобы можно было потестить.
Так будет проще найти ошибку.
Записан
Hrundel
Гость
« Ответ #6 : Апрель 06, 2013, 23:24 »

Прикрепил. Надеюсь сможете разобраться в этом нагромождении. Событие обрабатывается в BitmapWidget.
Для того, чтобы загрузилось рабочее пространство необходимо открыть файл bmp или wav. Они там есть в проекте.
« Последнее редактирование: Апрель 07, 2013, 15:34 от Hrundel » Записан
Hrundel
Гость
« Ответ #7 : Апрель 06, 2013, 23:25 »

Правильнее всего заточен файл testbild_16Bit copy.bmp там точно 8 bit на цвет = 24 на канал.
Записан
Hrundel
Гость
« Ответ #8 : Апрель 07, 2013, 11:15 »

Кстати, я тут посмотрел картинку в увеличении и мне стало казаться что смещение из-за сдвига в битах цвета. Смотри какой яркий красный пиксель.
Значит он имеет значение rgb(255, 0, 0)

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

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



Может я все-таки заголовок неправильно вычитываю. И смещаюсь в нем.
Ну вроде все проверил - не похоже на то.
« Последнее редактирование: Апрель 07, 2013, 11:44 от Hrundel » Записан
_OLEGator_
Гость
« Ответ #9 : Апрель 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++;
}
Записан
Hrundel
Гость
« Ответ #10 : Апрель 07, 2013, 12:27 »

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

Большое спасибо !!!
Записан
_OLEGator_
Гость
« Ответ #11 : Апрель 07, 2013, 12:31 »

Переименуй свое первое сообщение и добавь в начало темы [РЕШЕНО].
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.143 секунд. Запросов: 21.