Данные битмап-файла отображаются неправильно [закрыто]

Вопрос или проблема

У меня есть BMP-файл изображения луны из оригинальной аркадной игры Space Invaders. Я отображаю это на TFT-дисплее 240×320 с использованием RPi Pico. Я не могу заставить его отображаться правильно, поэтому я задаюсь вопросом, правильно ли я извлек данные из файла или это что-то другое.

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

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

Обратите внимание, что так как мой дисплей всего 240 пикселей в ширину, я отображаю только первые 240 пикселей данных изображения. С учетом того, что изображение шириной 327 пикселей, я ожидаю увидеть примерно 3/4 изображения, так что луна уже должна изгибаться вниз с правой стороны. А у меня нет никаких данных о том, что находится слева, похоже на картошку. Небольшой артефакт, который выглядит как МКС, на самом деле находится на правой стороне луны в оригинальном изображении.

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

Скрипт на Python для извлечения данных:

#!/bin/python3

# 327 Ш x 150 В пикселей
# данные начинаются с 138 (0x8a)

with open("moon24.bmp", "rb") as inp, open("moon24_data.txt", "w") as out:
    data = inp.read()
    out.write("const char moon[150][981] = {\n")
    x = 0
    for i in range(138, 138+147150-1):
        if x==0:
            out.write("    {")
        out.write('0x%02X' % data[i])
        x = x + 1
        if (x==327*3):
            out.write("},\n")
            x = 0
        else:
            out.write(",")
    out.write('0x%02X' % data[138+147150-1])
    out.write("}")
    out.write("\n};")

Код для RPi Pico, чтобы отобразить данные:

void draw_moon(PIO pio, uint sm) {
    uint16_t r, c;
    uint8_t red, green, blue;
    uint16_t R, G, B, val;
    
    set_window(pio, sm, 0, 165, SCREEN_WIDTH-1, 165+150-1);
    st7789_lcd_wait_idle(pio, sm);
    lcd_set_dc_cs(1, 0);

    for (r = 0; r < 150; r++) {
        for (c = 0; c < 240*3; c+=3) {
            blue = moon[149-r][c];
            green = moon[149-r][c+1];
            red = moon[149-r][c+2];

            B =  (blue  >> 3)        & 0x001F;
            G = ((green >> 2) <<  5) & 0x07E0;
            R = ((red   >> 3) << 11) & 0xF800;

            val = (R | G | B);
            
            st7789_lcd_put(pio, sm, val >> 8);
            st7789_lcd_put(pio, sm, val & 0xff);
        }
    }
}

Битмап:
moon24.bmp

Что я получаю:
введите описание изображения здесь

.

Ответ или решение

Проблема с неправильным отображением растрового файла BMP на дисплее TFT 240×320 с использованием Raspberry Pi Pico может быть вызвана несколькими факторами, включая неправильный считывание данных пикселей, некорректное обращение к данным изображения или ошибки в коде отображения. Давайте рассмотрим основные моменты, которые могут помочь в решении этой проблемы.

1. Проверка структуры файла BMP

Формат файла BMP хранит данные изображения в определенной последовательности. Вам нужно убедиться, что вы правильно интерпретируете этот формат.

  • Заголовок: Файлы BMP имеют заголовок, который содержит информацию о размере и свойствах изображения. Обратите внимание на поле, указывающее на ширину и высоту изображения, а также на количество бит на пиксель.
  • Порядок байтов: Данные пикселей в BMP часто хранятся в формате BGR (сначала синий, затем зеленый, затем красный). Это отличается от ожидаемой последовательности RGB.

2. Правильное чтение данных пикселей

В вашем коде вы начинаете считывать данные пикселей с оффсета 138. Проверьте, правильно ли вы определяете этот оффсет. Убедитесь, что в заголовке файла BMP указаны правильные размеры и порядок данных.

3. Обработка данных для отображения

Обратите внимание на код, отвечающий за обработку данных для отображения:

blue = moon[149-r][c];
green = moon[149-r][c+1];
red = moon[149-r][c+2];

Ваша логика инверсии по вертикали (149-r) может быть верной, но стоит убедиться в порядке цвета (BGR вместо RGB) перед преобразованием в 16-битное значение.

4. Дисплей и преобразование цвета

При преобразовании пикселей в 16-битный формат (RGB565) вы используете следующий код:

B =  (blue  >> 3)        & 0x001F;
G = ((green >> 2) <<  5) & 0x07E0;
R = ((red   >> 3) << 11) & 0xF800;

Убедитесь, что все битовые сдвиги и маскировка выполняются корректно. Не забудьте, что ваши значения B, G и R должны соответствовать максимальному диапазону для каждого цвета.

5. Проверка первого 240 пикселей

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

6. Ручное тестирование и отладка

Если результаты все еще не удовлетворительные, попробуйте:

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

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...