Формат bmp

Содержание

Слайд 2

Структура BITMAPINFO Данная структура в файле windows.h определена следующим образом: typedef

Структура BITMAPINFO
Данная структура в файле windows.h определена следующим образом:
typedef struct tagBITMAPINFO

{ BITMAPINFOHEADER bmiHeader;
RGBQUARD bmiColors[1];
} BITMAPINFO;
т.е. внутри структуры находятся заголовок bmiHeader и способ задания цвета в битовом изображении.
Структура заголовка BITMAPINFOHEADER
Размер данной структуры всегда 40 байт.
typedef struct tagBITMAPINFOHEADER
{ DWORD biSize; //размер структуры в байтах
LONG biWidth; //ширина битового изображения в пикселах;
LONG biHeight; //высота битового изображения в пикселах
WORD biPlanes; //количество плоскостей изображения (обычно 1) WORD biBitCount; //количество бит на один пиксел. Может быть 1,2,4,8,16,24,32
DWORD biCompression; //метод сжатия изображения
DWORD biSizeImage; // размер несжатого изображения в байтах
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed; //количество используемых цветов, т.е. размер таблицы RGBQUARD
DWORD biClrImportant; //количество важных цветов. Если 0, все цвета считаются важными. } BITMAPINFOHEADER, *PBITMAPINFOHEADER;
biCompression - метод сжатия изображения,
BI_RGB(значение - 0)- нет сжатия,
BI_JPEG (значение - 4) - сжатие используемое в jpeg-изображениях,
BI_PNG (значение - 5) - сжатие используемое в png-изображениях и др.
Слайд 3

biXPelsPerMeter, biYPelsPerMeter - необходимое разрешение устройства для вывода битового изображения без

biXPelsPerMeter, biYPelsPerMeter - необходимое разрешение устройства для вывода битового изображения без

искажения, задается в пикселах на метр по горизонтальи вертикали. Формат bmp - это по сути аппаратно-независимый растр. Но разрешение у устройств разное, и для того, чтобы построить наиболее подходящее изображение используют эти параметры. Если параметры имеют нулевые значения, используются параметры устройства, определяемые по умолчанию.
Сразу после структуры BITMAPINFOHEADER в файле может находиться таблица цветов. Эта таблица содержит массив структур типа RGBQUAD:

typedef struct tagRGBQUAD
{ BYTE rgbBlue ;
BYTE rgbGreen;
BYTE rgbRed ;
BYTE rgbReserved;
} RGBQUAD;
Первые три поля содержат красную, зеленую и синюю составляющую цвета. Последнее поле зарезервиро-вано, не используется.
Все разновидности формата bmp условно можно разделить на два типа: палитровые и беспалитровые в зависимости от того, используется в данном формате палитра или нет. Палитра может быть даже в беспалитровых форматах, но там она не используется.

Слайд 4

Изображение в битовой матрице записано по строкам: значения пикселов первой строки,

Изображение в битовой матрице записано по строкам: значения пикселов первой строки,

значения пикселов второй строки, третьей и т д. Первая строка пикселов - НИЖНЯЯ строка изображения. Рисунок ниже показывает, как выглядит одно и тоже изображение в формате bmp с разной глубиной изображения.

Пример 1. Разбор графического файла с глубиной изображения 24 бита.

Слайд 5

#pragma once #include #include #include #include #include using namespace std; void

#pragma once
#include
#include
#include
#include
#include
using namespace std;
void Test()
{ setlocale(LC_ALL, "RUSSIAN");
TCHAR

title[128];
::GetConsoleTitle(title, 80);
HWND hWnd = ::FindWindow(NULL, title);
SetWindowPos(hWnd, 0, 0, 0, 750, 600, 0);
HDC hdc = ::GetDC(hWnd);
TCHAR fileName[] = L"C:\\Users\\Public\\DZ\\App_CPP\\Graph\\BMP24.bmp";
wprintf(L"Попытка открытия файла  %s  \n", fileName, fileName);
HANDLE hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{ wprintf(L"Не могу открыть файл %s\n", fileName); return;
}
DWORD fSizeHigh = 0,
fSize = GetFileSize(hFile, &fSizeHigh);
BYTE* mmttrr = new BYTE[fSize];
DWORD nread;
ReadFile(hFile, mmttrr, fSize, &nread, NULL);
wprintf(L"Файл  %s  открыт, размер= %u байтов, получено =%d \n", fileName,
fSize, nread);
Слайд 6

//1. Разбор первого сегмента файла void * ptr = mmttrr; BITMAPFILEHEADER*

//1. Разбор первого сегмента файла  
void * ptr = mmttrr;
BITMAPFILEHEADER* fi

= (BITMAPFILEHEADER*)mmttrr;
DWORD offbits = fi->bfOffBits;
char * p1 = (char*)(&fi->bfType);
printf("Параметры заголовков \n1) Type = %c%c  OffBits = %d  size(Header)= %d\n",
p1[0], p1[1], offbits, sizeof(BITMAPFILEHEADER));
//2  Разбор второго сегмента файла
ptr = mmttrr + sizeof(BITMAPFILEHEADER); //начало 2-го сегмента
BITMAPINFO * pbi = (BITMAPINFO*)ptr;
BITMAPINFOHEADER* pbh = (BITMAPINFOHEADER*)ptr;
int w = pbh->biWidth;
int h = pbh->biHeight;
printf("2) %d  %d  %d  %d   w*h*3 = %d\n",
pbh->biSizeImage, pbh->biBitCount, w, h, w*h*3);
//3   offbits - смещение битовой матрицы относительно начала файла
//   Изображение выводится дважды - прямое изображение и повернутое на 90 град. 
int X1 = 50; // Горизонтальные координаты в пикселах для 1-го и 2-го изображений
int X2 = 400;
int Y = 150 + 256; // Вертикальная координата экрана первой (нижней строки изображений)
int ind_ = offbits; // Начало битовой матрицы 
int rest = 4-(3*w)%4; // Число пикселов в строке всегда кратно 4(адрес строки // выранивается по двойному слову
if (rest == 4) rest = 0; //число пустых пикселов для выравнивания строк
int r, g, b; // Перемнные будут использованы для обозначения цветовых
//составляющих
Слайд 7

while (1) { ind_ = offbits; //ind_ - номер начального байта

while (1)
{ ind_ = offbits; //ind_ - номер начального байта очередного

пиксела
for (int is = 0; is < h; is++) // is - номер строки битовой матрицы
{ for (int ic = 0; ic < w; ic++) // iс- номер столбца битовой матрицы
{ r = mmttrr[ind_]; // выделение цветовых составляющих пиксела
g = mmttrr[ind_ + 1];
b = mmttrr[ind_ + 2];
ind_ += 3; // переход к следующему пикселу (следующей тройке
//байтов в матрице )
::SetPixel(hdc, ic+X1, -is+Y, COLORREF(RGB(b,g,r)));
// вывод на экран очередного пиксела в позицию
// (ic+X1, -is+Y)
::SetPixel(hdc, is + X2, -ic + Y, COLORREF(RGB(r, g, b)));
// вывод на экран очередного пиксела повернутого
//изображения. Кроме того, в повернутом изображени
//поменялись цвета
}ind_ += rest;
}
::Sleep(500); // Циклический вывод картинки для сохранения нормального } // вида, иначе при выполнении каких-либо действий (например, } // щелчок мышью по экрану и т.д.) картинка ломается или
// пропадает
Слайд 8

Слайд 9

Пример 2. Разбор и вывод графического файла с глубиной изображения 256

Пример 2. Разбор и вывод графического файла с глубиной изображения 256

цветов

#pragma once
#include
#include
#include
#include
void Test()
{ setlocale(LC_ALL, "RUSSIAN");
TCHAR title[128];
::GetConsoleTitle(title, 80);
HWND hWnd = ::FindWindow(NULL, title);
SetWindowPos(hWnd, 0, 50, 50, 600, 600, 0);
HDC hdc = ::GetDC(hWnd);
TCHAR fileName[] = L"C:\\Users\\Public\\DZ\\App_CPP\\Graph\\BMP256.bmp";
wprintf(L"Попытка открытия файла %s \n", fileName);
HANDLE hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{ wprintf(L"Не могу открыть файл %s\n", fileName); return;
}
DWORD fSizeHigh, fSize= GetFileSize(hFile, &fSizeHigh);
BYTE* mtr = new BYTE[fSize];
DWORD nread;
ReadFile(hFile, mtr, fSize, &nread, NULL);
wprintf(L"Файл %s открыт, размер %u байтов, получено %d \n", fileName, fSize,
nread);

Слайд 10

//1. Разбор первого сегмента файла void * ptr = mtr; BITMAPFILEHEADER*

//1. Разбор первого сегмента файла  
void * ptr = mtr;
BITMAPFILEHEADER*

fi = (BITMAPFILEHEADER*)mtr;
DWORD offbits = fi->bfOffBits;
char * p1 = (char*)(&fi->bfType);
printf("Параметры заголовков \n1) Type=%c%c OffBits=%d size(Header)= %u\n",
p1[0], p1[1], offbits, sizeof(BITMAPFILEHEADER));
//2  Разбор второго сегмента файла
ptr = mtr + sizeof(BITMAPFILEHEADER);
BITMAPINFO * pbi = (BITMAPINFO*)ptr;
BITMAPINFOHEADER* pbh = (BITMAPINFOHEADER*)(&pbi->bmiHeader);
RGBQUAD * bmCol = (RGBQUAD*)(&pbi->bmiColors);
long w =(long)pbh->biWidth;
long h =(long)pbh->biHeight;
printf("2) w=%d h=%d SizeImage=%d biBitCount=%d \n", w , h, pbh->biSizeImage,
pbh->biBitCount);
int X1 = 20;
int Y = 500; // координата  экрана первой (нижней) строки изображения
int ind_ = offbits; // начало битовой матрицы 
BYTE r, g, b;
int color;
int w4 = w % 4;
printf("Смещение в конце строк битовой матрицы %d\n", w4);
Слайд 11

for (int is = 0; is { for (int ic =

for (int is = 0; is < h; is++)
{ for (int ic

= 0; ic < w; ic++)
{ int num_col = mtr[ind_]; ind_++;
RGBQUAD col = bmCol[num_col];
r = col.rgbRed;
g = col.rgbGreen;
b = col.rgbBlue;
SetPixel(hdc, ic+X1, -is+Y,
COLORREF(RGB(r,g,b))
);
}
ind_ += (4 - w4)%4;
}
_getche();
//Нажать любую клавишу для продолжения
}
Слайд 12

Пример 3. Разбор и вывод графического файла с глубиной изображения 1

Пример 3. Разбор и вывод графического файла с глубиной изображения 1

(черно-белое изображение). Один пиксел занимает 1 бит. Бит равен 1 -белый цвет, бит=0 - черный. Таким образом, один байт битовой матрицы хранит 8 пикселов изображения.
#pragma once
#include
#include
#include
#include
void Test()
{ setlocale(LC_ALL, "RUSSIAN");
TCHAR title[128];
::GetConsoleTitle(title, 80);
HWND hWnd = ::FindWindow(NULL, title);
SetWindowPos(hWnd, 0, 50, 50, 600, 600, 0);
HDC hdc = ::GetDC(hWnd);
TCHAR fileName[] = L"C:\\Users\\Public\\DZ\\App_CPP\\Graph\\BMP2.bmp";
wprintf(L"Попытка открытия файла  %s  \n", fileName, fileName);
HANDLE hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{ wprintf(L"Не могу открыть файл %s\n", fileName); return;
}
DWORD fSizeHigh, fSize = GetFileSize(hFile, &fSizeHigh);
BYTE* mtr = new BYTE[fSize];
DWORD nread;
ReadFile(hFile, mtr, fSize, &nread, NULL);
wprintf(L"File %s open, size=%u nread=%d \n", fileName, fSize, nread);
Слайд 13

//1. Разбор первого сегмента файла void * ptr = mtr; BITMAPFILEHEADER*

//1. Разбор первого сегмента файла 
void * ptr = mtr;
BITMAPFILEHEADER* fi =

(BITMAPFILEHEADER*)mtr;
DWORD offbits = fi->bfOffBits;
char * p1 = (char*)(&fi->bfType);
printf("1) Type=%c%c OffBits=%d size(Header)= %u\n",
p1[0], p1[1], offbits, sizeof(BITMAPFILEHEADER));
//2  Разбор второго сегмента файла
ptr = mtr + sizeof(BITMAPFILEHEADER);
BITMAPINFO * pbi = (BITMAPINFO*)ptr;
BITMAPINFOHEADER* pbh = (BITMAPINFOHEADER*)(&pbi->bmiHeader);
RGBQUAD * bmCol = (RGBQUAD*)(&pbi->bmiColors);
long w = (long)pbh->biWidth;
long h = (long)pbh->biHeight;
printf("2) w=%d h=%d SizeImage=%d biBitCount=%d\n",w,h,pbh->biSizeImage,pbh->biBitCount);
int X1 = 20;
int Y = 550; // координата  экрана первой(нижней) строки изображения
int ind_ = offbits; // начало битовой матрицы 
int w4 = w%4;
printf("Смещение в конце строк битовой матрицы %d\n", w4)
for (int is = 0; is < h; is++)
{ for (int ic = 0; ic < w; ic+=8)
{ int num_col = mtr[ind_];
ind_++;
int bb = 1;
for ( int ic1=0; ic1<8; ic1++)
{ int bi = num_col & bb; bb *= 2;
if (bi==0) SetPixel(hdc, ic+(7-ic1)+ X1, -is+Y, COLORREF(RGB(0,0, 0)));
else SetPixel(hdc, ic+(7-ic1)+ X1, -is+Y, COLORREF(RGB(255, 255, 255)));
}
}
Слайд 14

ind_ += (4-w4)%4; } }

ind_ += (4-w4)%4;
}
}