Що означає bmp. Що таке розширення файлу BMP? Якою програмою відкрити розширення bmp

BMP(Від англ. Bitmap Picture) - формат зберігання растрових зображень, розроблений компанією Microsoft.

З форматом BMP працює безліч програм, оскільки його підтримка інтегрована в операційні системи Windows і OS/2 . Файли формату BMP можуть мати розширення .bmp, .dib та .rle. Крім того, дані цього формату включаються в двійкові файли ресурсів RES і PE-файли .

Компанія Microsoft також розробила для своїх потреб формати ICO та CUR, які мають схожу на BMP структуру. Крім цього, структури цього формату використовуються деякими WinAPI-функціями підсистеми GDI .

Глибина кольору в даному форматі може бути 1, 2, 4, 8, 16, 24, 32, 48 біт на піксель, але глибина 2 біта на піксель офіційно не підтримується. При цьому для глибини кольору менше 16 бітів використовується палітра з повнокольоровими компонентами глибиною 24 біти.

У форматі BMP зображення можуть зберігатися як є або із застосуванням деяких поширених алгоритмів стиснення. Зокрема, формат BMP підтримує RLE-стиск без втрати якості, а сучасні операційні системи та програмне забезпечення дозволяють використовувати JPEG та PNG (ці формати вбудовуються в BMP як у контейнер).

DIB та DDB

При використанні формату DIB (англ. Device Independent Bitmap, Апаратно-незалежний растр) програміст може отримати доступ до всіх елементів структур, що описують зображення, за допомогою звичайного покажчика. Але ці дані не використовуються для безпосереднього керування екраном, так як вони завжди зберігаються в системній пам'яті, а не спеціалізованої відеопам'яті. p align="justify"> Формат пікселя в оперативній пам'яті може відрізнятися від того формату, який повинен заноситись у відеопам'ять для індикації точки такого ж кольору. Наприклад, у DIB-форматі може використовуватися 24 біти для завдання пікселя, а графічний адаптер може працювати в режимі HiColor з колірною глибиною 16 біт. При цьому яскраво-червона точка в апаратно-незалежному форматі задаватиметься трьома байтами 0x0000ff, а у відеопам'яті - словом 0xF800. При копіюванні картинки на екран система витрачатиме додатковий час на перетворення кодів кольору з 24-бітного формату у формат відеобуфера.

Огляд структури файлу

BMP-файл складається із чотирьох частин:

  1. Заголовок файлу (BITMAPFILEHEADER)
  2. Заголовок зображення (BITMAPINFOHEADER, може бути відсутнім). BITMAPV4HEADER (Win95, NT4.0) BITMAPV5HEADER (Win98/Me, 2000/XP)
  3. Палітра (може бути відсутнім)
  4. Саме зображення

BITMAPFILEHEADER

Ця структура містить інформацію про тип, розмір та подання даних у файлі. Розмір 14 байт.

Typedef struct tagBITMAPFILEHEADER ( WORD bfType; // Зміщення 0 байт від початку файлу DWORD bfSize; // Зміщення 2 байти від початку файлу, довжина 4 байти WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; // Зміщення 10 байт від початку файлу, довжина 4 байти) BITMAPFILEHEADER, * PBITMAPFILEHEADER;

Тип WORD повинен мати розмір 16 біт, типи DWORD і LONG - 32 біти, тип LONG - знаковий, порядок байтів мається на увазі little endian.

  • bfType - тип файлу, символи BM (в HEX: 0x42 0x4d).
  • bfSize - розмір файлу в байтах.
  • bfReserved1 та bfReserved2 - зарезервовані, повинні містити нулі.
  • bfOffBits - містить зміщення в байтах від початку структури BITMAPFILEHEADER до безпосередньо бітів зображення.

Після заголовка файлу

BITMAPINFOHEADER

Найпростіший варіант заголовка. Програми для Windows NT3.51 і раніше можуть використовувати тільки цю структуру. Розмір 40 байт.

Typedef struct tagBITMAPINFOHEADER( DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORTM INFOHEADER, * PBITMAPINFOHEADER;

BiSize Розмір цієї структури в байтах. Формат BMP згодом доповнювався і значення цього поля визначається версія формату. biWidth Ширина зображення в пікселях. Для Win98/Me та Win2000/XP: якщо поле biCompression містить BI_JPEG або BI_PNG, тут вказано ширину розпакованого зображення. biHeight Висота зображення в пікселях. Якщо містить позитивне значення – зображення записане в порядку знизу-вгору (нульовий піксель у нижньому лівому кутку). Якщо значення негативне – зображення записано зверху-вниз (нульовий піксель у верхньому лівому куті зображення). Поле biCompression має містити значення BI_RGB чи BI_BITFIELDS. Таке зображення не може бути стисло. biPlanes Кількість кольорових площин та у форматі BMP містить одиницю. biBitCount Кількість біт на піксель. Може приймати такі значення:

  • 0 – має сенс для Win98/Me/2000/XP. Кількість біт пікселів визначає формат JPEG або PNG.
  • 1 - монохромне зображення. Член bmiColors структури BITMAPINFO містить два елементи. Кожен біт зображення представляє один піксель; якщо біт дорівнює нулю – піксель має колір першого елемента таблиці bmiColors, інакше – колір другого.
  • 4 - шістнадцятикольорове зображення. Пікселі визначаються 4-х бітними індексами, кожен байт зображення містить інформацію про два пікселі - старші 4 біти для першого, що залишилися - для другого.
  • 8 - панель містить до 256 кольорів, кожен байт зображення зберігає індекс в палітрі для одного пікселя.
  • 16 - якщо поле biCompression містить BI_RGB, файл не містить палітри. Кожні два байти зображення зберігають інтенсивність червоної, зеленої та синьої компоненти одного пікселя. У цьому старший біт немає, на кожну компоненту відведено 5 біт: 0RRRRRGGGGGBBBBBBB.
    Якщо поле biCompression містить значення BI_BITFIELDS, палітра зберігає три чотирибайтові значення, що визначають маску для кожної з трьох компонентів кольору. Кожен піксель зображення представлений двобайтним значенням, з якого масками витягуються колірні компоненти. Для WinNT/2000/XP - послідовності біт кожної компоненти повинні слідувати безперервно, не перекриваючись і не перетинаючи послідовності інших компонентів. Для Win95/98/Me - підтримуються лише такі маски: 5-5-5, де маска синьої компоненти 0х001F, зеленої 0x03E0, червоної 0x7C00; та 5-6-5, де маска синьої компоненти 0x001F, зеленої 0x07E0, червоної 0xF800.
  • 24 - палітра не використовується, кожна трійка байт зображення представляє один піксель, байт для інтенсивності синього, зеленого і червоного каналу відповідно.
  • 32 - Якщо поле biCompression містить значення BI_RGB, зображення не містить панелі. Кожні чотири байти зображення представляють один піксель, по байти для інтенсивності синього, зеленого та червоного каналу відповідно. Старший байт кожної четвірки зазвичай не використовується, проте дозволяє зберігати дані альфа-каналу.
    Якщо поле biCompression містить значення BI_BITFIELDS, на панелі зберігаються три чотирибайтні кольорові маски - для червоної, зеленої та синьої компоненти. Кожен піксель зображення представлений чотирма байтами. WinNT/2000: маски компонентів не повинні перекриватися або перетинатися. Windows 95/98/Me: система підтримує лише один режим стиснення, повністю аналогічний режиму без компресії BI_RGB - старший байт кожної четвірки використовується як альфа-канал, наступні три відведені для синього, зеленого та червоного каналу відповідно: 0xAARRGGBB.
biCompression Тип стиснення для стиснених зображень:
Значення Ідентифікатор Компресія
0 BI_RGB стиснене зображення
1 BI_RLE8 стиск RLE для 8-бітних зображень
2 BI_RLE4 стиск RLE для 4-бітних зображень
3 BI_BITFIELDS зображення не стисло, палітра містить три 4-байтні маски для червоної, зеленої та синьої компонент кольору. Використовується для 16- та 32-бітних зображень
4 BI_JPEG Win98/Me/2000/XP: JPEG-стиск
5 BI_PNG Win98/Me/2000/XP: PNG-стиск
6 BI_ALPHABITFIELDS WinCE: зображення не стисло, палітра містить чотири 4-байтні маски для червоної, зеленої, синьої та прозорої (альфа-канал) компонент кольору. Використовується для 16- та 32-бітних зображень
biSizeImage Розмір зображення в байтах. Може містити нуль для BI_RGB-зображень. Win98/Me/2000/XP: якщо biCompression містить BI_JPEG або BI_PNG, biSizeImage вказує розмір BI_JPEG або BI_PNG буфера зображення. biXPelsPerMeter Горизонтальна роздільна здатність у пікселях на метр для цільового пристрою. Програма може використовувати це значення для вибору з групи ресурсів зображення, найбільше підходить для поточного пристрою. Для DPI 96, яке прийнято в Microsoft для моніторів, воно дорівнюватиме 3780 (якщо вважати за формулою (96 / 25,4) * 1000). biYPelsPerMeter Вертикальна роздільна здатність у пікселях на метр для цільового пристрою. biClrUsed Кількість використовуваних індексів кольорів на панелі. Якщо значення дорівнює нулю - зображення використовує максимально доступну кількість індексів, відповідно до значення biBitCount і методу стиснення, зазначеного в biCompression.
Якщо містить ненульове значення і biBitCount менше 16, biClrUsed вказує кількість кольорів, до яких буде звертатися драйвер пристрою або додаток. Якщо biBitCount більше або дорівнює 16, biClrUsed розмір палітри, що використовується для оптимізації роботи системних палітр. Якщо biBitCount дорівнює 16 або 32, оптимальна палітра слідує відразу після трьох чотирьохбайтних масок.
У упакованому зображенні масив пікселів слід відразу після структури BITMAPINFO, biClrUsed повинен містити нуль або реальний розмір палітри. biClrImportant Кількість елементів палітри, необхідних для відображення зображення. Якщо містить нуль – всі індекси однаково важливі.

Структура BITMAPINFO поєднує BITMAPINFOHEADER і палітру, надаючи повний опис розмірів та кольорів зображення.

Щоб знайти палітру в структурі BITMAPINFO, додаток повинен використовувати інформацію, що зберігається в biSize, так:

PColor = ((LPSTR) pBitmapInfo + (WORD) (pBitmapInfo-> bmiHeader.biSize ) ) ;

Растр зазвичай зберігається у вертикально дзеркальному вигляді. Але є також можливість зберігати растр над вертикально дзеркальному вигляді. Ознака того, що растр BMP не у вертикально дзеркальному вигляді задається параметром biHeight.

BITMAPV4HEADER

Розширена версія описаної вище структури. Win NT 3.51 і раніше повинні використовувати структуру BITMAPINFOHEADER. Win98/Me/2000/XP можуть використовувати замість структури BITMAPV4HEADER структуру BITMAPV5HEADER.

Typedef struct (DWORD bV4Size; LONG bV4Width; LONG bV4Height; WORD bV4Planes; WORD bV4BitCount; DWORD bV4V4Compression; DWORD bV4SizeImage; LONG bV4XPelsPerMeter; LONG bV4Y 4ClrImportant; DWORD bV4RedMask; ; CIEXYZTRIPLE bV4Endpoints; DWORD bV4GammaGreen;

Поля від початку структури до bV4ClrImportant включно мають те саме призначення, що і відповідні поля структури BITMAPINFOHEADER.

  • bV4RedMask - колірна маска червоної компоненти кожного пікселя, використовується лише якщо bV4Compression містить значення BI_BITFIELDS.
  • bV4GreenMask - колірна маска зеленої компоненти кожного пікселя, використовується лише якщо bV4Compression містить значення BI_BITFIELDS.
  • bV4BlueMask - колірна маска синіх компонентів кожного пікселя, використовується тільки якщо bV4Compression містить значення BI_BITFIELDS.
  • bV4AlphaMask – маска, що визначає компоненту альфа-каналу.
  • bV4CSType – визначає колірний простір зображення.
  • bV4Endpoints - структура CIEXYZTRIPLE, що вказує на x, y і z координати трьох кольорів, які відповідають кінцевим точкам (endpoints) колірного простору, визначеного для зображення. Це поле ігнорується, якщо bV4CSType не містить значення LCS_CALIBRATED_RGB.
  • bV4GammaRed – крива тону червоної компоненти. Ігнорується, якщо bV4CSType не містить значення LCS_CALIBRATED_RGB. Вказується у форматі 16×16.
  • bV4GammaGreen – крива тону зеленої компоненти. Ігнорується, якщо bV4CSType не містить значення LCS_CALIBRATED_RGB.
  • bV4GammaBlue – крива тону синьої компоненти. Ігнорується, якщо bV4CSType не містить значення LCS_CALIBRATED_RGB.

BITMAPV5HEADER

Win95/NT 4.0: програми можуть використовувати BITMAPV4HEADER. Win NT 3.51 і раніше повинні використовувати структуру BITMAPINFOHEADER.

Typedef struct ( DWORD bV5Size; LONG bV5Width; LONG bV5Height; WORD bV5Planes; WORD bV5BitCount; DWORD bV5Compression; DWORD bV5SizeImage; LONG bV5XPelsPerMeter; LONG bV5YPel rImportant; DWORD bV5RedMask; ; CIEXYZTRIPLE bV5End; DWORD bV5 * PBITMAPV5HEADER;

Для полів від початку структури до bV5GammaBlue включно будуть описані лише відмінності від попередніх версій - BITMAPINFOHEADER і BITMAPV4HEADER.

  • bV5CSType - визначає колірний простір зображення, може приймати такі значення:
LCS_CALIBRATED_RGB LCS_sRGB LCS_WINDOWS_COLOR_SPACE PROFILE_LINKED PROFILE_EMBEDDED
  • bV5Intent - може приймати такі значення:
LCS_GM_ABS_COLORIMETRIC LCS_GM_BUSINESS LCS_GM_GRAPHICS LCS_GM_IMAGES
  • bV5ProfileData - зміщення в байтах від початку структури до початку даних профілю (ім'я файлу профілю, рядок складається виключно з символів кодової таблиці 1252 і нульовим байтом, що закінчується). Ігнорується, якщо bV5CSType містить значення, відмінне від PROFILE_LINKED та PROFILE_EMBEDDED.
  • bV5ProfileSize – розмір даних профілю в байтах.
  • bV5Reserved – зарезервовано. Містить нуль.

Палітра

Палітра може містити послідовність чотирьохбайтових полів за кількістю доступних кольорів (256 для 8-бітного зображення). Три молодші байти кожного поля визначають інтенсивність червоної, зеленої та синьої компоненти кольору, старший байт не використовується. Кожен піксель зображення описаний у разі одним байтом, що містить номер поля палітри, у якому збережено колір цього пікселя.

Якщо піксель зображення описується 16-бітним числом, палітра може зберігати три двобайтні значення, кожне з яких визначає маску для вилучення з 16-бітного пікселя червоної, зеленої та синьої компонент кольору.

Файл BMP може не містити палітри, якщо в ньому зберігається повне кольорове зображення.

Дані зображення

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

У bmp-файлах з глибиною кольору 24 біти, байти кольору кожного пікселя зберігаються в порядку BGR (Blue, Green, Red)

B bmp-файлах з глибиною кольору 32 біта, байти кольору кожного пікселя зберігаються в порядку BGRA (Blue, Green, Red, Alpha)

Бітність зображення

Залежно від кількості квітів, на кожну точку відводиться від 1 до 48 бітів:

  • 1 біт - монохромне зображення (два кольори).
  • 2 біти - 4 можливі кольори (режими роботи CGA) (2-бітовий режим офіційно не стандартизований, але використовується).
  • 4 біти - 16-колірне зображення (режими роботи EGA).
  • 8 біт (1 байт) - 256 кольорів, останній із режимів, що підтримували індексовані кольори (див. нижче).
  • 16 біт (2 байти) - режим HiColor, Для 5-6-5 = 65536 можливих відтінків, для 5-5-5 = 32768 можливих відтінків.
  • 24 біти (3 байти) - TrueColor. У зв'язку з тим, що 3 байти не дуже добре співвідносяться зі ступенями двійки (особливо при зберіганні даних у пам'яті, де вирівнювання даних по межі слова має значення), замість нього часто використовують 32-бітове зображення. У режимі TrueColor на кожен із трьох каналів (в режимі RGB) відводиться по 1 байти (256 можливих значень), загальна кількість кольорів дорівнює .
  • 32 біти (4 байти) - цей режим практично аналогічний TrueColor, четвертий байт зазвичай не використовується, або в ньому розташовується альфа-канал (прозорість).
  • 48 біт (6 байт) - формат, що рідко використовується, з підвищеною точністю передачі кольору (16 біт на канал), підтримується відносно малою кількістю програм і обладнання.

Індексовані кольори

При кількості біт 1 (2 кольори), 2 (4 кольори), 4 (16 кольорів) або 8 (256 кольорів) на кожен піксель може використовуватися спеціальний режим індексованих кольорів. У цьому випадку число, яке відповідає кожному пікселю, вказує не на колір, а на номер кольору на панелі. Завдяки використанню палітри можна адаптувати зображення до кольорів, присутніх на зображенні. У такому випадку зображення обмежене не заданими кольорами, а максимальною кількістю кольорів, що одночасно використовуються.

Приклад програми

Наступна програма відкриває 24 бітний BMP файл у вікні XWindow, глибина кольору повинна становити 32 біти, на меншій передачі кольору не працює, так як це ускладнює приклад:

/* Компілюється рядком: cc -o xtest xtest.c -I/usr/X11R6/include -L/usr/X11R6/lib -lX11 -lm */#include #include #include #include #include #include #include #include #include #include #include #include "bitmap.h" /* Тут визначення заголовків BMP як було описано вище в цій статті */ static XImage * CreateImageFromBuffer(Display*, unsigned char *, int, int); main(int argc, char * argv ) ( Display * dis; Window win; /* Наше вікно */ XEvent event; /* Події */ GC gc; /* Графічний контекст */ XImage * image; int n, width, height, fd, size; unsigned char * data; BITMAPFILEHEADER bmp; BITMAPINFOHEADER inf; char*buf; if (argc< 2 ) { perror ("use: xtest file.bmp\n "); exit (1); ) if ((fd = open(argv[1] , O_RDONLY) ) == - 1 ) ( printf ("Error open bitmap \n "); exit (1); ) read(fd, & bmp, sizeof (BITMAPFILEHEADER)); read(fd, & inf, sizeof (BITMAPINFOHEADER)); width = inf.biWidth; height = inf.biHeight; if ((dis = XOpenDisplay(getenv ("DISPLAY" ) ) ) == NULL) ( printf ( "Can"t connect X server: %s\n ", strerror (errno)); exit (1); ) win = XCreateSimpleWindow(dis, RootWindow(dis, DefaultScreen(dis) ) , 0 , 0 , width, height, 5 , BlackPixel(dis, DefaultScreen(dis) ) , WhitePixel(dis, DefaultScreen(dis) ) ) XSetStandardProperties(dis, win, argv[1], argv[0], None, argv, argc, NULL); gc = DefaultGC(dis, DefaultScreen(dis)); /* Іноді у структурі це місце не заповнено */ if (inf.biSizeImage == 0 ) ( /* Обчислимо розмір */ size = width * 3 + width % 4; size = size * height; ) else ( size = inf.biSizeImage ; ) buf = malloc ( size ) ; if (buf == NULL) ( perror ("malloc" ) ; exit (1 ) ; ) printf ( "size = %d байтів виділено\n ", size); /* Змістимось на початок самого зображення */ lseek(fd, bmp.bfOffBits, SEEK_SET); /* Читаємо в буфер */ n = read(fd, buf, size); printf ( "size = %d байт прочитано\n ", n); image = CreateImageFromBuffer(dis, buf, width, height) ; /* Видалимо буфер - він нам більше не потрібен */ free (buf); XMapWindow(dis, win); XSelectInput(dis, win, ExposureMask | KeyPressMask) ; while (1 ) ( XNextEvent(dis, & event) ; if (event.xany .window == win) ( switch (event.type ) ( case Expose: XPutImage(dis, win, gc, image, 0 , 0 , 0) , 0 , image-> width, image-> height) ; break ; exit (EXIT_SUCCESS) ; ) break ; /* Створює Ximage з файлу BMP, тому що зображення BMP зберігається первернутим * і дзеркальним-у циклі це виправляється */ XImage * CreateImageFromBuffer(Display * dis, unsigned char * buf, int width, int height) ( int depth, screen; XImage * img = NULL; int i, j; int numBmpBytes; size_t numImgBytes; int32_t * ;int line; int temp; /* Номери рядка та стовпця для відображення */ int new_ind; /* Новий індекс */ screen = DefaultScreen(dis); depth = DefaultDepth(dis, screen); temp = width * 3; line = temp + width % 4; /* Довжина рядка з урахуванням вирівнювання */ numImgBytes = (4 * (width * height)) ; imgBuf = malloc (numImgBytes); /* Розмір, відведений на BMP у файлі з урахуванням вирівнювання */ numBmpBytes = line * height; for (i = 0; i< numBmpBytes; i++ ) { unsigned int r, g, b; /* Пропускаємо padding */ if (i >= temp && (i % line) >= temp) continue; b = buf [i]; i++; g = buf [i]; i++; r = buf [i]; /* Обчислюємо новий індекс для відображення по вертикалі */ iw = ind % width; ih = ind/width; new_ind = iw + (height - ih - 1) * width; imgBuf [new_ind] = (r | g<< 8 | b << 16 ) << 8 ; ind++; } img = XCreateImage(dis, CopyFromParent, depth, ZPixmap, 0 , (char * ) imgBuf, width, height, 32 , 0 ) ; XInitImage(img) ; /* Порядок бітів та байтів на PC повинен бути таким */ img-> byte_order = MSBFirst; img->bitmap_bit_order = MSBFirst; return img; )

Формат файлу BMP (скорочено від BitMaP) - це "рідний" формат растрової графіки для Windows, оскільки він найближче відповідає внутрішньому формату Windows, в якому ця система зберігає свої растрові масиви. Для імені файлу, представленого в форматі BMP, найчастіше використовується розширення BMP, хоча деякі файли мають розширення RLE, що означає run length encoding (кодування довжини серій). Розширення RLE імені файлу зазвичай вказує на те, що стиснення растрової інформації файлу одним з двох способів стиснення RLE, які допустимі для файлів BMP-формату.

У BMP інформація про колір кожного пікселя кодується 1, 4, 8, 16 або 24 біт (біт/піксель). Числом біт/піксель, званим також глибиною подання кольору, визначається максимальна кількість кольорів у зображенні. Зображення при глибині 1 біт/піксель може мати лише два кольори, а при глибині 24 біт/піксель - понад 16 млн. різних кольорів.

На наведеній схемі показано структуру типового BMP-файлу, що містить 256-кольорове зображення (з глибиною 8 біт/піксель). Файл розбитий на чотири основні розділи: заголовок файлу растрової графіки, інформаційний заголовок растрового масиву, таблиця кольорів і дані растрового масиву. Заголовок файлу растрової графіки містить інформацію про файл, у тому числі адресу, з якої починається область даних растрового масиву. В інформаційному заголовку растрового масиву містяться відомості про зображення, що зберігається у файлі, наприклад, його висоту та ширину в пікселях. У таблиці кольорів представлені значення основних кольорів RGB (червоний, зелений, синій) для зображень кольорів. Програми, що зчитують та відображають BMP-файли, у разі використання відеоадаптерів, які не дозволяють відображати більше 256 кольорів, для точної передачі кольорів можуть програмно встановлювати такі значення RGB в колірних палітрах адаптерів.

Формат даних растрового масиву у файлі BMP залежить від кількості біт, що використовуються для кодування даних про колір кожного пікселя. При 256-колірному зображенні кожен піксель у тій частині файлу, де містяться дані растрового масиву, описується одним байтом (8 біт). Цей опис пікселя не представляє значення кольорів RGB, а служить покажчиком для входу до таблиці кольорів файлу. Таким чином, якщо в якості першого значення кольору RGB у таблиці кольорів файлу BMP зберігається R/G/B=255/0/0, то значенню пікселя 0 у растровому масиві буде поставлений у відповідність яскраво-червоний колір. Значення пікселів зберігаються в порядку їх розташування ліворуч, починаючи (як правило) з нижнього рядка зображення. Таким чином, у 256-колірному BMP-файлі перший байт даних растрового масиву являє собою індекс для кольору пікселя, що знаходиться в лівому нижньому куті зображення; другий байт представляє індекс для кольору сусіднього праворуч пікселя і т. д. Якщо число байт у кожному рядку непарне, то до кожного рядка додається додатковий байт, щоб вирівняти дані растрового масиву по 16-біт кордонів.


Не всі файли BMP мають структуру, подібну до показаної на схемі. Наприклад, файли BMP з глибиною 16 та 24 біт/піксель не мають таблиць кольорів; у цих файлах значення пікселів растрового масиву безпосередньо характеризують значення RGB кольорів. Також можуть відрізнятися внутрішні формати зберігання окремих розділів файлів. Наприклад, інформація растрового масиву в деяких 16 і 256-кольорових BMP-файлах може стискатися за допомогою алгоритму RLE, який замінює послідовності ідентичних пікселів зображення на лексеми, що визначають кількість пікселів у послідовності та їх колір. У Windows допускається робота з BMP-файлами стилю OS/2, у яких використовуються різні формати інформаційного заголовка растрового масиву та таблиці кольорів.

Ця стаття про те, як виглядає графічний формат bmp. Хоча це і один із простих форматів, але через те, що існує багато варіацій цього формату, то не всі моменти очевидні. Отже, годі лити воду, почнемо.

Структури формату

Формат bmp (від слів BitMaP - бітова карта, або, говорячи російською, бітовий масив) являє собою несжате (в основному) зображення, яке досить легко читається і виводиться в ОС Windows, в якій є спеціальні функції API, які в цьому допомагають.

Для початку наведемо графічне представлення даних у bmp (картинка взята з MSDN).

На початку стоїть заголовок файлу (BITMAPFILEHEADER). Він описаний так:

bfTypeвизначає тип файлу. Тут він має бути BM. Якщо Ви відкриєте будь-який файл BMP у текстовому (а краще у 16-річному редакторі), то побачите, що перші два символи - це BM (від слова BitMap, як ви вже, мабуть, здогадалися).
bfSize- це розмір файлу в байтах. Строго кажучи, ви повинні його вираховувати (що рекомендується), але я ставив розмір файлу неправильно (правда, не навмисне:)) і ніяких проблем не було (ACDSee читало без проблем, моя програма працювала), але я вам не рекомендую писати його свідомо неправильно раптом з'явиться сумлінна програма, яка звірить цей розмір зі справжнім і вирішить, що це не bmp, а щось інше. В ідеалі всі програми для того, щоб переконатися, що перед ними дійсно bmp, а не підробка, повинні, по-перше, перевірити, що bfType містить "BM" (без лапок), а по-друге, що bfSize дорівнює розміру файлу .
bfReserved1 та bfReserved2зарезервовані та мають бути нулями.
bfOffBits. Це один із найважливіших полів у цій структурі. Він показує, де починається сам бітовий масив щодо початку файлу (або, як написано в MSDN, "від початку структури BITMAPFILEHEADER"), який описує картинку. Тобто щоб гарантовано потрапляти на початок масиву ви повинні писати:

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;

biSize- Це розмір самої структури. Її потрібно ініціалізувати так: bih.biSize = sizeof (BITMAPINFOHEADER);
Знову тут і далі вважатимемо, що bih оголошено наступним чином: BITMAPINFOHEADER bih;
biWidth та biHeightзадають відповідно ширину та висоту картинки в пікселях.
biPlanesзадає кількість площин. Поки що воно завжди встановлюється в 1.
biBitCount- кількість біт на один піксель. Докладніше про це поговоримо нижче.
biCompressionпозначає тип стиснення. Не дивуйтеся і не лякайтеся, що в bmp і раптом стиск. Я особисто не бачив жодної стисненої bmp (але я не кажу, що таких не існує). Якщо стиснення немає, цей прапор треба встановлювати в BI_RGB. У цій статті ми говоримо про стислий формат, тому інші прапори я навіть не перераховуватиму. Схоже, що ця ж структура використовується і в файлах JPEG і PNG, тому що, починаючи з Windows 98, тут з'явилися варіанти BI_JPEG, яка показує, що ця картинка - JPEG і BI_PNG, що це PNG (про формат Jpeg я нічого не знаю, я тільки зробив ці висновки, виходячи з того, що написано в MSDN).
biSizeImageпозначає розмір картинки в байтах. Якщо зображення не стисло (тобто попереднє поле встановлено в BI_RGB), то тут має бути записано нуль. biXPelsPerMeterі biYPelsPerMeterпозначають відповідно горизонтальну та вертикальну роздільну здатність (у пікселях на метр) кінцевого пристрою, на який буде виводитися бітовий масив (растр). Програма може використовувати це значення для того, щоб вибирати з групи ресурсів найбільш підходящий бітовий масив для потрібного пристрою. Справа в тому, що формат bmp - це по суті апаратно-незалежний растр, тобто коли зовнішній вигляд того, що виходить, не залежить від того, на що цей растр проектується (якщо можна так висловиться). Наприклад, зображення виглядатиме однаково незалежно від того, малюється вона на екрані монітора або друкується на принтері. Але дозвіл у пристроїв різний, і саме для того, щоб вибрати найбільш підходящу картинку з наявних і використовують ці параметри.
biClrUsedвизначає кількість кольорів, що використовуються з таблиці. Якщо це значення дорівнює нулю, то в растрі використовується максимально можлива кількість кольорів, які мають значення biBitCount. Це актуально лише для стислих картинок. Якщо biClrUsed не нуль і biBitCount менше 16, biClrUsed визначає поточне число кольорів графічного движка або доступного драйвера пристрою. Якщо biBitCount більше або дорівнює 16, biClrUsed визначає розмір таблиці кольорів, що використовується для оптимізації поточної системної палітри.
biClrImportant– це кількість важливих кольорів. Визначає кількість кольорів, які потрібні для того, щоб зобразити малюнок. Якщо це значення дорівнює 0 (як це зазвичай і буває), всі кольори вважаються важливими.

Види формату BMP

Усі різновиди формату bmp умовноможна розділити на два типи: палітрові та безпалітрові. Тобто використовується в даному форматі палітра чи ні. Зауважте, що палітра може бути навіть у безпалітрових форматах, тільки там вона не використовується. У безпалітрових bmp колір вираховується прямо з тих бітів, які йдуть у файлі, починаючи з деякого місця. А в палітрових кожен байт описує один або кілька пікселів, причому значення байта (або бітів) – це індекс кольору на палітрі. Спочатку наведу таблицю, яка порівнює можливі варіанти. Вигляд картинки (палітрова чи безпалітрова) залежить від того, скільки біт віддається на один піксель, тобто від значення biBitCount структури BITMAPINFOHEADER.

biBitCountПалітровий або безпалітровий форматМаксимально можлива кількість кольорівПримітки 1 Палітровий2 Двоколірна, зауважте, не обов'язково чорно-біла, палітрова картинка. Якщо біт растру (що це таке трохи нижче) скинутий (рівний 0), то це означає, що на цьому місці має бути перший колір з палітри, а якщо встановлений (рівний 1), то другий. 4 Палітровий16 Кожен байт описує 2 пікселі. Ось приклад з MSDN. Якщо перший байт в картинці 0x1F, то він відповідає двом пікселям, колір першого - другий колір з палітри (оскільки відлік йде від нуля), а другий піксель - 16-й колір палітри. 8 Палітровий256 Один із найпоширеніших варіантів. Але водночас і найпростіших. Палітра займає один кілобайт (але на це краще не розраховувати). Один байт – це один колір. Причому його значення – це номер кольору на палітрі. 16 Безпалітровий2^16 або 2^15Це найзаплутаніший варіант. Почнемо з того, що він безпалітровий, тобто кожні два байти (одне слово WORD) у растрі однозначно визначають один піксель. Але ось що виходить: бітів 16, а компонентів кольорів - 3 (Червоний, Зелений, Синій). А 16 ніяк на 3 ділитися не хоче. Тому тут є два варіанти. Перший використовувати не 16, а 15 бітів, тоді на кожну компоненту кольору виходить по 5 біт. Таким чином, ми можемо використовувати максимум 2^15 = 32768 кольорів і виходить трійка R-G-B = 5-5-5. Але тоді даремно втрачається цілий біт з 16. Але так вже сталося, що наші очі серед усіх кольорів краще сприймають зелений колір, тому і вирішили цей один біт віддавати на зелену компоненту, тобто тоді виходить трійка R-G-B = 5-6-5, і тепер ми можемо використовувати 2^16 = 65536 кольорів. Але що найнеприємніше, що використовують обидва варіанти. У MSDN пропонують для того, щоб розрізняти скільки ж кольорів використовується, заповнювати цим значенням поле biClrUsed із структури BITMAPINFOHEADER. Щоб виділити кожну компоненту, треба використовувати наступні маски. Для формату 5-5-5: 0x001F для синьої компоненти, 0x03E0 для зеленої та 0x7C00 для червоної. Для формату 5-6-5: 0x001F – синя, 0x07E0 – зелена та 0xF800 червона компоненти відповідно. 24 Безпалітровий2^24 А це найпростіший формат. Тут 3 байти визначають 3 компоненти кольору. Тобто за компонентом на байт. Просто читаємо за структурою RGBTRIPLE і використовуємо його поля rgbtBlue, rgbtGreen, rgbtRed. Вони йдуть саме так. 32 Безпалітровий2^32 Тут 4 байти визначають 3 компоненти. Але, щоправда, байт не використовується. Його можна віддати, наприклад, для альфа-каналу (прозорості). Читати растр у даному випадку зручно структурами RGBQUAD, яка описана так:

Зберігання даних у форматі bmp

Ну ось і підійшли до найцікавішого. Після структур BITMAPFILEHEADER та BITMAPINFOHEADER йде палітра. Причому, якщо формат безпалітровий, то його може й не бути, проте на це не треба розраховувати. Справа в тому, що коли я тільки починав розбиратися з форматом bmp, в одній книжці я вичитав, що, нібито, якщо формат безпалітровий, то взагалі немає палітри. Там навіть були дві картинки – схеми формату: одна з палітрою, інша без. А я тим часом писав програму, яка старанно оперує з bmp-шками. І мені треба було перетворювати вхідні картинки з 256 кольорів на 24-бітові (якщо такі були) у тимчасові файли. І я в 24-бітних палітру просто не створював (bfOffBits зі структури BITMAPFILEHEADER у мене дорівнював сумі sizeof(BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER), а вхідні 24-розрядні залишав без змін. З 256-кольоровими растрами мені не попалася 24-розрядна картинка, у якої внизу замість потрібної частини відображалося сміття. Я не відразу зрозумів у чому справа. 1024 байта).Там була палітра. Використовуючи bfOffBits, Палітра являє собою масив структур RGBQUAD, що йдуть один за одним Навіть якщо в палітрі використовуються не всі кольори (а тільки, наприклад, 16), то часто все одно під палітру відводять 256 полів. 4 - розмір структури RGBQUAD, тобто і виходить той самий кілобайт.

Відразу за палітрою йде сам растр. Тут уже заплутаніше. По-перше, пікселі тут описуються так, як написано в таблиці вище залежно від формату. І можуть самі містити значення компонентів кольору (для безпалітрових), а можуть бути індексами масиву-палітри. Сама картинка записується рядково. По-друге, картинка йде як би перевернута догори ногами. Тобто спочатку записано нижній рядок, потім передостанній і так далі до самого верху. І, по-третє, як написано в , якщо розмір рядка растру не кратен 4, то вона доповнюється від 1 до 3 порожніми (нульовими) байтами, щоб довжина рядка виявилася кратною параграфу. Ось це і є найнеприємніше. Справа в тому, що для кожного формату доводиться підлаштовувати це число порожніх байтів (правда, я люблю туди записувати частину палітри, просто мені не хочеться заводити зайві "нульові" змінні, якщо все одно ці байти пропускають і нікому вони не потрібні). Я наводжу таблицю з формулами, які показують для якого формату скільки байт треба дописувати до кінця рядка. Там під змінною Width, як можна здогадатися, мається на увазі ширина картинки. Усі ці формули були встановлені експериментально. Я наведу приклад тільки для форматів, що найбільш використовуються. Для решти ви можете написати самі.

Приклади програм

Всі вихідники ви можете скачати .Я особливо не буду багато писати. Просто наведу функції із коментарями.

Привіт 1. Створення зображення у форматі bmp.
Тут створюється однотонна картинка. У прикладах таких функцій три: створення bmp 8, 16 та 24 біт. Я наведу лише для 16-бітних.

// Створимо картинку у форматі bmp 16 біт типу 5-5-5, яка буде просто однотонною
void CreateBmp555 (char * fname, WORD color)
{
HANDLE hFile;
DWORD RW;
int i, j;

// Оголосимо необхідні структури
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
BYTE Palette [1024]; // Палітра

// Нехай у нас буде картинка розміром 35 x 50 пікселів
int Width = 35;
int Height = 50;

memset (Palette, 0, 1024); // У палітрі у нас нулі заповнимо їх
memset (& bfh, 0, sizeof (bfh));

Bfh.bfType = 0x4D42; // Позначимо, що це bmp "BM"
bfh.bfOffBits = sizeof (bfh) + sizeof (bih) + 1024; // Палітра займає 1Kb, але ми його використовувати не будемо
bfh.bfSize = bfh.bfOffBits +
sizeof (color) * Width * Height +
Height * ((sizeof (color) * Width) % 4); // Порахуємо розмір кінцевого файлу
memset (& bih, 0, sizeof (bih));
bih.biSize = sizeof (bih); // Так належить
bih.biBitCount = 16; // 16 біт на піксель
bih.biClrUsed = 32768; // Ми використовуємо 5-5-5
bih.biCompression = BI_RGB; // Без стиснення
bih.biHeight = Height;
bih.biWidth = Width;
bih.biPlanes = 1; // Має бути 1
// А інші поля залишаються 0

HFile = CreateFile (fname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return;

// Запишемо заголовки
WriteFile (hFile, & bfh, sizeof (bfh), & RW, NULL);
WriteFile (hFile, & bih, sizeof (bih), & RW, NULL);

// Запишемо палітру
WriteFile (hFile, Palette, 1024, & RW, NULL);
for (i = 0; i< Height; i++ )
{
for (j = 0; j< Width; j++ )
{
WriteFile (hFile, & color, sizeof (color), & RW, NULL);
}

// Вирівняємо за кордоном
WriteFile (hFile, Palette, (sizeof (color) * Width) % 4 & RW, NULL ) ;
}
CloseHandle(hFile) ;
}

color - колір картинки. Значення цієї змінної має бути заповнене відповідно до першої таблиці. Отриману картинку ви можете подивитися в ACDSee, наприклад. Просто я пробував її відкрити у Photoshop'і, виявилося, що у цьому форматі він їх читати не вміє. А ви можете:).

Приклад 2. Перетворення картинки з формату 8 біт (256 кольорів) на 24 біт.

BOOL Convert256To24 (char * fin, char * fout)
{
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
int Width, Height;
RGBQUAD Palette [256];
BYTE * inBuf;
RGBTRIPLE *outBuf;
HANDLE hIn, hOut;
DWORD RW;
DWORD OffBits;
int i, j;

HIn = CreateFile (fin, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hIn == INVALID_HANDLE_VALUE)
return FALSE;

HOut = CreateFile (fout, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (hOut == INVALID_HANDLE_VALUE)
{
CloseHandle (hIn);
return FALSE;
}

// Прочитаємо дані
ReadFile (hIn, & bfh, sizeof (bfh), & RW, NULL);
ReadFile (hIn, & bih, sizeof (bih), & RW, NULL);
ReadFile (hIn, Palette, 256 * sizeof (RGBQUAD), & RW, NULL);

// Встановимо покажчик початку растра
SetFilePointer (hIn, bfh.bfOffBits, NULL, FILE_BEGIN);
Width = bih.biWidth;
Height = bih.biHeight;
OffBits = bfh.bfOffBits;

// Виділимо пам'ять
inBuf = new BYTE [Width] ;
outBuf = new RGBTRIPLE [Width] ;

// Заповнимо заголовки
bfh.bfOffBits = sizeof(bfh) + sizeof(bih); // Не писатимемо палітру
bih.biBitCount = 24;
bfh.bfSize = bfh.bfOffBits + 4 * Width * Height + Height * (Width % 4); // Розмір файлу

// А решта не змінюється
// Запишемо заголовки
WriteFile (hOut, & bfh, sizeof (bfh), & RW, NULL);
WriteFile (hOut, & bih, sizeof (bih), & RW, NULL);

// Почнемо перетворювати
for (i = 0; i< Height; i++ )
{
ReadFile (hIn, inBuf, Width, & RW, NULL);
for (j = 0; j< Width; j++ )
{
outBuf[j].rgbtRed = Palette[inBuf[j]].rgbRed;
outBuf[j].rgbtGreen = Palette[inBuf[j]].rgbGreen;
outBuf[j].rgbtBlue = Palette[inBuf[j]].rgbBlue;
}
WriteFile (hOut, outBuf, sizeof (RGBTRIPLE) * Width, & RW, NULL );

// Пишемо сміття для вирівнювання
WriteFile (hOut, Palette, Width % 4, & RW, NULL);
SetFilePointer (hIn, (3 * Width) % 4, NULL, FILE_CURRENT);
}

delete inBuf;
delete outBuf;
CloseHandle (hIn);
CloseHandle (hOut);
return TRUE;
}

У функцію треба передавати імена вихідного та кінцевого файлу відповідно.

За наявності на комп'ютері встановленої антивірусної програмиможна сканувати всі файли на комп'ютері, а також кожен файл окремо. Можна сканувати будь-який файл, клацнувши правою кнопкою миші на файл і вибравши відповідну опцію для перевірки файлу на наявність вірусів.

Наприклад, на цьому малюнку виділено файл my-file.bmp, далі необхідно клацнути правою кнопкою миші по цьому файлу, і в меню файла вибрати опцію "сканувати за допомогою AVG". При виборі цього параметра відкриється AVG Antivirus, який перевірить цей файл на наявність вірусів.


Іноді помилка може виникнути в результаті неправильної установки програмного забезпеченнящо може бути пов'язане з проблемою, що виникла в процесі встановлення. Це може завадити вашій операційній системі зв'язати файл BMP з правильним прикладним програмним засобом, впливаючи на так звані "асоціації розширень файлів".

Іноді проста перевстановлення Adobe Illustrator CCможе вирішити вашу проблему, правильно зв'язавши BMP з Adobe Illustrator CC. В інших випадках проблеми з файловими асоціаціями можуть виникнути в результаті поганого програмування програмного забезпеченнярозробником, і вам може знадобитися зв'язатися з розробником для отримання додаткової допомоги.


Порада:Спробуйте оновити Adobe Illustrator CC до останньої версії, щоб переконатися, що встановлені останні виправлення та оновлення.


Це може здатися надто очевидним, але часто безпосередньо сам файл BMP може бути причиною проблеми. Якщо ви отримали файл через вкладення електронної пошти або завантажили його з веб-сайту, і процес завантаження був перерваний (наприклад, відключення живлення або з іншої причини), файл може зашкодити. Якщо можливо, спробуйте отримати нову копію BMP-файлу та спробуйте знову відкрити його.


Обережно:Пошкоджений файл може спричинити виникнення супутніх збитків попередньої або вже існуючої шкідливої ​​програми на вашому ПК, тому дуже важливо, щоб на вашому комп'ютері постійно працював оновлений антивірус.


Якщо ваш файл BMP пов'язаний з апаратним забезпеченням на вашому комп'ютері, щоб відкрити файл може знадобитися оновити драйвери пристроїв, пов'язаних із цим обладнанням.

Ця проблема зазвичай пов'язані з типами мультимедійних файлів, які залежать від успішного відкриття апаратного забезпечення всередині комп'ютера, наприклад, звукової картки або відеокарти. Наприклад, якщо ви намагаєтеся відкрити аудіофайл, але не можете його відкрити, вам може знадобитися оновити драйвери звукової карти.


Порада:Якщо при спробі відкрити файл BMP ви отримуєте повідомлення про помилку, пов'язану з.SYS file, проблема, ймовірно, може бути пов'язана з пошкодженими або застарілими драйверами пристроїв, які потрібно оновити. Цей процес можна полегшити за допомогою програмного забезпечення для оновлення драйверів, таких як DriverDoc .


Якщо кроки не вирішили проблему, і у вас все ще виникають проблеми з відкриттям файлів BMP, це може бути пов'язано з відсутністю доступних системних ресурсів. Для деяких версій файлів BMP може знадобитися значний обсяг ресурсів (наприклад, пам'ять/ОЗУ, обчислювальна потужність) для належного відкриття на вашому комп'ютері. Така проблема трапляється досить часто, якщо ви використовуєте досить старе комп'ютерне апаратне забезпечення та одночасно набагато нову операційну систему.

Така проблема може виникнути, коли комп'ютеру важко впоратися із завданням, оскільки операційна система (та інші служби, що працюють у фоновому режимі) можуть споживати надто багато ресурсів для відкриття файлу BMP. Спробуйте закрити всі програми на ПК, перш ніж відкривати Bitmap Image File. Звільнивши всі доступні ресурси на комп'ютері, ви забезпечите найкращі умови для спроби відкрити файл BMP.


Якщо ви виконали всі описані вище кроки, а ваш файл BMP, як і раніше, не відкривається, може знадобитися виконати оновлення обладнання. У більшості випадків, навіть при використанні старих версій обладнання, обчислювальна потужність може бути більш ніж достатньою для більшості додатків користувача (якщо ви не виконуєте багато ресурсомісткої роботи процесора, такий як 3D-рендеринг, фінансове/наукове моделювання або інтенсивна мультимедійна робота) . Таким чином, цілком імовірно, що вашому комп'ютеру не вистачає необхідного обсягу пам'яті(частіше званої «ОЗУ», чи оперативної пам'яттю) виконання завдання відкриття файла.




Top