С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/30: Рейтинг темы: голосов - 30, средняя оценка - 4.80
0 / 0 / 0
Регистрация: 25.09.2013
Сообщений: 14
1

Как расшифровать цвета bmp изображения без таблицы?

18.11.2018, 13:27. Показов 6056. Ответов 14
Метки bmp (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте.
Прочитанный мною файл bmp имеет следующий заголовок InfoHeader

bitmapInfoHeader.biSize 40
bitmapInfoHeader.biWidth 8
bitmapInfoHeader.biHeight 8
bitmapInfoHeader.biPlanes 1
bitmapInfoHeader.biBitCount 8
bitmapInfoHeader.biClrUsed 0
bitmapInfoHeader.biClrImportant 0
bitmapInfoHeader.biSizeImage 64

То есть таблица цветов нулевая при поле biBitCount =8.
как расшифровать значения цветов?
я попытался преобразовать их из unsigned char в DOUBLE, но значения не совпадают с результатом, полученным в структуре Bitmap из C# System.Drawing.Imaging
Спасибо
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.11.2018, 13:27
Ответы с готовыми решениями:

Как нарисовать рамку из пикселей случайного цвета вокруг bmp изображения?
подробнее, вместе с прикрепленным проектом https://www.cyberforum.ru/cpp-builder/thread2391886.html

Не пк без Qt загружаются изображения, кроме PNG и BMP
Писал одну программку, которая выводит изображения и анимации, у меня работало стабильно, скинул на...

Как выделить определенный диапазон цвета RGB на картинке bmp?
всем доброго времени суток!помогите,пожалуйста, в написании кода.есть картинка bmp. Надо разложить...

Как происходит изменение разрешения изображения (bmp)
Мне нужно изменить разрешение изображения файла bmp, но я не понимаю как выбирается цвет для новых...

14
Злостный нарушитель
9613 / 5204 / 1187
Регистрация: 12.03.2015
Сообщений: 24,566
18.11.2018, 13:43 2
Цитата Сообщение от albertelena Посмотреть сообщение
я попытался преобразовать их из unsigned char в DOUBLE
Куда?!!!

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
typedef struct tagBITMAPINFOHEADER {
  DWORD biSize;
  LONG  biWidth;
  LONG  biHeight;
  WORD  biPlanes;
  WORD  biBitCount;
  DWORD biCompression;
  DWORD biSizeImage;
  LONG  biXPelsPerMeter;
  LONG  biYPelsPerMeter;
  DWORD biClrUsed;
  DWORD biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
0
2711 / 865 / 327
Регистрация: 10.02.2018
Сообщений: 2,045
18.11.2018, 13:52 3
Возможно стоит посмотреть какой формат компрессии у картинки.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
typedef struct tagBITMAPINFOHEADER {
  DWORD biSize; // 40
  LONG  biWidth; // 8
  LONG  biHeight; // 8
  WORD  biPlanes; // 1
  WORD  biBitCount; // 8
  DWORD biCompression; // чему равно вот это поле?
  DWORD biSizeImage; // 64
  LONG  biXPelsPerMeter; // ...
  LONG  biYPelsPerMeter; // ...
  DWORD biClrUsed; // 0
  DWORD biClrImportant; // 0
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
0
0 / 0 / 0
Регистрация: 25.09.2013
Сообщений: 14
18.11.2018, 17:37  [ТС] 4
biCompression =0 и biXPelsPerMeter=0, и biXPelsPerMeter=0, но они, наверное, точно не нужны

А из unsigned char в DOUBLE я преобразовал значения пикселей, скачанные из bmp-файла
Извините, плохо сформулировал, некоторые не поняли сильно
0
2711 / 865 / 327
Регистрация: 10.02.2018
Сообщений: 2,045
18.11.2018, 18:13 5
Лучший ответ Сообщение было отмечено albertelena как решение

Решение

Если заголовок картинки прочитан правильно, то могу предложить посмотреть на смещение до битов картинки, которое находится в первых 12 байтах файла. Если смещение дальше, чем (12+40), то возможно, что цвета всё же лежат после заголовка, а поле biClrUsed в некоторых случаях не обязательно для заполнения.
Какой размер у файла? 12 байт - первый заголовок, 40 - второй, 64 - пиксели. Если файл больше 116 байт, то можно искать таблицу цветов.
1
0 / 0 / 0
Регистрация: 25.09.2013
Сообщений: 14
18.11.2018, 18:48  [ТС] 6
заголовок прочитан.
Для эксперимента я взял картинку 4х4 пикселя, которую прочел командой fread

В буфере оказались символы
дддд
Ыддд
ддўд
дддд

после преобразования в double
164 164 164 164
155 164 164 164
164 164 247 164
164 164 164 164

в то время как C# для этой же картинки даёт значения
128 128 128 128
96 128 128 128
128 128 160 128
128 128 128 128

Я предположил, что перевод картинки в соответствии версии C# зависит от таблицы, содержащейся в biClrUsed.
Но там 0. Как бы выяснить принципы перевода цветов, используемые в System.Drawing.Imaging::Bitmap и перевести картинку в цифры правильно?
0
2711 / 865 / 327
Регистрация: 10.02.2018
Сообщений: 2,045
18.11.2018, 20:12 7
Для файлов сделанных в paint и сохранённых в формате 256 цветов можно так попробовать:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <fstream>
#include <Windows.h>
 
int main()
{
    std::ifstream f("d:\\test.bmp", std::ios_base::binary);
 
    BITMAPFILEHEADER fh;
    f.read((char*)&fh, sizeof(fh));
 
    BITMAPINFOHEADER ih;
    f.read((char*)&ih, sizeof(ih));
 
    if (ih.biBitCount != 8)
    {
        std::cout << "invalid bitcount" << std::endl;
        return -1;
    }
 
    RGBQUAD* colors = 0;
    int colorSize1 = (1 << 8) * sizeof(RGBQUAD);
    int colorSize2 = fh.bfOffBits - (sizeof(fh) + ih.biSize);
    int indexCount = colorSize2 / sizeof(RGBQUAD);
    if (indexCount > 0)
    {
        colors = new RGBQUAD[indexCount];
        f.read((char*)colors, colorSize2);
    }
 
    unsigned char *pixels = new unsigned char[ih.biSizeImage];
    f.read((char*)pixels, ih.biSizeImage);
 
    int lineSize = (ih.biWidth + 3) & ~0x3;
 
    for (int y=0; y<ih.biHeight; y++)
    {
        for (int x=0; x<ih.biWidth; x++)
        {
            unsigned index = pixels[y * lineSize + x];
            RGBQUAD color = colors[index];
            std::cout << index << "=(" << (unsigned)color.rgbRed << "," << (unsigned)color.rgbGreen << "," << (unsigned)color.rgbBlue << ") ";
        }
        std::cout << std::endl;
    }
 
    return 0;
}
1
0 / 0 / 0
Регистрация: 25.09.2013
Сообщений: 14
19.11.2018, 07:30  [ТС] 8
1. Спасибо, Ygg, сделать неизвестному программу- это показательно! Но хотелось бы понять, что делает эта программа в данном конкретном случае:
2. как то здесь выделяют код и цитаты, полагаю мне это напомнят, прошу извинить- не со зла.

3. пропуская понятное

RGBQUAD* colors = 0; // здесь создаём переменную для палитры- массив цветов

int colorSize1 = (1 << 8) * sizeof(RGBQUAD); // (1<<8)=256. Здесь реальный размер RGBQUAD в битах, вроде он не нужен

int colorSize2 = fh.bfOffBits - (sizeof(fh) + ih.biSize);
//от начала данных (1078) отступили 54 и осталось (в моём случае) аж 1024=256*4
// содержимого, которым мы воспользуемся как цветовой таблицей, независимо от значения bitmapInfoHeader.biClrUsed=0

а далее написано как это содержимое извлечь.
Правильно ли я понял Вашу программу?

4. еще один вопрос "вдогонку" f.read не надо указывать места начала и конца чтения?

Спасибо.
0
2711 / 865 / 327
Регистрация: 10.02.2018
Сообщений: 2,045
19.11.2018, 12:07 9
3. Да, вы правильно поняли основную идею. Смысл в том, что палитра в файле лежит, несмотря на нулевое значение в biClrUsed. Но как в этом случае понять, что она там есть и сколько она занимает? Можно предположить два способа определения размера. Первый заключается в том, что зная количество бит на индекс (8) можно утверждать, что для хранения палитры всех индексов потребуется 2^8 ячеек размера sizeof(RGBQUAD). Именно этот размер считается в colorSize1. Второй вариант заключается в чтении из файла смещения до пикселей картинки и вычитании из него размеров заголовков. Таким образом получается размер палитры на основании структуры файла colorSize2. Если все предположения верны и формат файла корректен, то теоретический размер палитры и фактический должны совпасть. Так и произошло.

4. Заголовки, палитра и пиксели лежат слитно друг за дружкой. Поэтому я не заморачивался с seek внутри файла. Но, теоретически, если файлы будут содержать в себе какие-то вариации, то алгоритм начнёт работать не правильно. Поэтому, для пущей надёжности, хорошо бы сделать проверки и, по необходимости, поиск нужной позиции внутри файла.
0
1355 / 854 / 365
Регистрация: 26.02.2015
Сообщений: 3,806
19.11.2018, 12:15 10
А может быть средства библиотеки для работы с BMP помогут?
0
0 / 0 / 0
Регистрация: 25.09.2013
Сообщений: 14
21.11.2018, 16:29  [ТС] 11
Просмотрел "библиотеки" на первый раз, спасибо.

Еще есть один вопрос, может Вы знаете где он есть в библиотеке.

Вопрос о формуле расшифровки цвета.
мою тестовую картинку
дддд
Ыддд
ддўд
дддд

которая, как выяснилось, имеет адреса в таблицу цветности
164 164 164 164
155 164 164 164
164 164 247 164
164 164 164 164

C# даёт значения
128 128 128 128
96 128 128 128
128 128 160 128
128 128 128 128

Если считать вклады цветовых каналов равновесными, то есть (R+G+B)/3, то получаем
128 128 128 128
106 128 128 128
128 128 161 128
128 128 128 128

по формуле "естественного ощущения" R*0.11+G*0.59+B*0.3 (Заметим, что 0.11+0.59+0.3=1)
93 93 93 93
71 93 93 93
93 93 116 93
93 93 93 93

"Равновесная" формула даёт значения, близкие к C#. Вопрос: по какой формуле считает C#?
0
2711 / 865 / 327
Регистрация: 10.02.2018
Сообщений: 2,045
21.11.2018, 17:12 12
"C# даёт значения" - значения чего, цвета? В большинстве цветовых моделей цвет трёхмерен. Это означает, что для задания цвета используются три значения (координаты цветового пространства). Поясните, что означают ваши числа, какими функциями на C# вы их получили.
0
0 / 0 / 0
Регистрация: 20.12.2015
Сообщений: 1
02.10.2019, 19:55 13
Можно ли как то на основе этой программы организовать чтобы оно обратно закидывала текстовые данные в .bmp?
0
Заблокирован
14.06.2020, 22:40 14
Здравствуйте,

Наверное немного не по теме, но подскажите пожалуйста:
В Paint`е есть возможность сохранения bmp файла, как 16-цветный рисунок, при прочтении заголовка этого bmp файла:
BITMAPINFOHEADER.biBitCount == 4

То есть я правильно понимаю, что 16-цветный рисунок - это не одно и тоже, что и 16 разрядный ?

Добавлено через 5 минут
Причем странность какая то, при том что этот рисунок состоит из 4пикселей: 2 на 2, но, если смотреть прочитанный параметр:
BITMAPINFOHEADER_biSizeImage == 8, то получаеся, что biBitCount все таки равен 16, а не 4, потому что 2*2*(16/8) = 8, то есть равно размеру изображения из biSizeImage.

Что то я совсем запутался с этими 16 битами или 16 цветами. С 24 и 32 битами - такой путаницы нет, так все четко.
0
2711 / 865 / 327
Регистрация: 10.02.2018
Сообщений: 2,045
15.06.2020, 09:38 15
Цитата Сообщение от Optimus11 Посмотреть сообщение
То есть я правильно понимаю, что 16-цветный рисунок - это не одно и тоже, что и 16 разрядный ?
16 цветный - это 16 цветов.
Есть отдельная табличка на 16 строчек (палитра).
В каждой строчке лежит цвет в привычном формате по 8 бит на компоненту: красный, зелёный, синий.
В самой картинке вместо цвета лежит индекс цвета в табличке цветов (0, 1, 2 ...).

BMP file format
Каждая строка картинки выравнена по 4 байта.
Размер строки может принимать значения только кратные 4 (4, 8, 12, 16, ...).
Это значит, что если данные для задания цветов строки имеют размер 1, 2, 3 или 4 байта, то в памяти под строку всё равно выделится 4 байта. В случае 16 цветов один пиксель занимает 4 бита, два пикселя - 8 бит, т.е. один байт. Но правила выравнивания вынуждают выделить под строку 4 байта и положить цвета пикселей в начало этого блока.
1
15.06.2020, 09:38
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
15.06.2020, 09:38
Помогаю со студенческими работами здесь

Как скачать все изображения со страницы сайта а затем конвертировать их в bmp?
Вопрос в названии. Как это сделать и сохранить всё в папку C:\ProgramData\DevArtWall\im\ при этом...

Как сделать загрузку изображения сразу же после его конвертации из jpeg в bmp?
Добрый день пользователи.Можно ли после конвертации изображения, сразу же загрузку изображения на...

Как сохранить bmp без сообщений об ошибках?
try fScreenCopy.SaveToFile(Owner.PathToDebugFiles + '\' + FName + '.bmp'); finally ...

Как графический bmp-файл вне зависимости от типа изображения привести к RGB изображению?
как графический *.bmp файл в не зависимости от типа изображения которое отрываю ( или серая шкала,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru