Как вывести bmp файл с
Перейти к содержимому

Как вывести bmp файл с

  • автор:

Как вывести bmp файл с

BMP (BitMaP) — основной метод хранения несжатых графических файлов. Фотография с 6-ти мегапискельного фотоаппарата в этом формате будет иметь размер 18М байт.

В начале 2000-х годов Microsoft пыталась сделать BMP-файлы основным видом графических файлов. В связи с этим была добавлена возможность хранения в этих файлах графических файлов других графических форматов (включая png, jpeg и др.). Но сейчас от этой идеи отказались и BMP-файлы используются лишь для хранения несжатых изображений.

Помимо базового варианта (3 байта на точку, BMP-24) может быть «серый» файл (1 байт на точку) и некоторые другие. Далее мы будем рассматриать только файлы формата BMP-24.

Строчки в bmp-файле хранятся в обратном порядке, то есть в начале идет самая нижняя строка изображения. Внутри строки байты имеют порядок BGR BGR . Кроме того, длина каждой строки выровнена до кратного четырех. То есть для изображения шириной 3 точки длина строки равна 12 байт (3 точки по 3 байта, всего 9 байт, затем увеличиваем длину строки до кратного 4).

В начале bmp-файла идет заголовок следующей структуры:

typedef unsigned __int16 WORD; typedef struct < WORD bfType; // 0x4d42 | 0x4349 | 0x5450 int bfSize; // размер файла int bfReserved; // 0 int bfOffBits; // смещение до поля данных, // обычно 54 = 16 + biSize int biSize; // размер струкуры в байтах: // 40(BITMAPINFOHEADER) или 108(BITMAPV4HEADER) // или 124(BITMAPV5HEADER) int biWidth; // ширина в точках int biHeight; // высота в точках WORD biPlanes; // всегда должно быть 1 WORD biBitCount; // 0 | 1 | 4 | 8 | 16 | 24 | 32 int biCompression; // BI_RGB | BI_RLE8 | BI_RLE4 | // BI_BITFIELDS | BI_JPEG | BI_PNG // реально используется лишь BI_RGB int biSizeImage; // Количество байт в поле данных // Обычно устанавливается в 0 int biXPelsPerMeter;// горизонтальное разрешение, точек на дюйм int biYPelsPerMeter;// вертикальное разрешение, точек на дюйм int biClrUsed; // Количество используемых цветов // (если есть таблица цветов) int biClrImportant; // Количество существенных цветов. // Можно считать, просто 0 >BMPheader;

Отметим, что в этом примере кода тип int предполагается 32-битовым. Если в вашем случае это не так, то вместо int надо использовать тип 4-х байтового целого числа. Аналогично, __int16 означает 16-битовое целое число. Если ваш компилятор такого идентификатора не знает, то его надо заменить на соответствующий.

Чтение файла формата BMP-24 можно осуществить следующей функцией. В переменных mx,my возвращаются размеры файла. Для графических данных функция выделяет память (new int[mx*my]). Именно этот указатель и возвращатся в качестве результата. Он указывает на одномерный массив целых чисел, в котором лежат последовательно цветовые значения всех пикселей изображения. В каждое целое 4-х байтовое число упаковано по 3 байта RGB в формате R + 256*G + 65536*B. В случае какой-либо ошибки память не выделяется, возвращается NULL.

int *loadBMP( const char *fname, int &mx, int &my ) < mx = my = -1; FILE *f = fopen( fname, "rb" ); if( !f ) return NULL; BMPheader bh; // File header sizeof(BMPheader) = 56 size_t res; // читаем заголовок res = fread( &bh, 1, sizeof(BMPheader), f ); if( res != sizeof(BMPheader) ) < fclose(f); return NULL; >// проверяем сигнатуру if( bh.bfType!=0x4d42 && bh.bfType!=0x4349 && bh.bfType!=0x5450 ) < fclose(f); return NULL; >// проверка размера файла fseek( f, 0, SEEK_END); int filesize = ftell(f); // восстановим указатель в файле: fseek( f, sizeof(BMPheader), SEEK_SET); // проверим условия if( bh.bfSize != filesize || bh.bfReserved != 0 || bh.biPlanes != 1 || (bh.biSize!=40 && bh.biSize!=108 && bh.biSize!=124)|| bh.bfOffBits != 14+bh.biSize || bh.biWidth 10000 || bh.biHeight10000 || bh.biBitCount != 24 || // пока рассматриваем только полноцветные изображения bh.biCompression != 0 // пока рассматриваем только несжатие изображения ) < fclose(f); return NULL; >// Заголовок прочитан и проверен, тип - верный (BGR-24), размеры (mx,my) найдены int mx = bh.biWidth; int my = bh.biHeight; int mx3 = (3*mx+3) & (-4); // Compute row width in file, including padding to 4-byte boundary unsigned char *tmp_buf = new unsigned char[mx3*my]; // читаем данные res = fread( tmp_buf, 1, mx3*my, f); if( (int)res != mx3*my ) < delete []tmp_buf; fclose(f); return NULL; >// данные прочитаны fclose(f); // выделим память для результата v = new int[mx*my]; // Перенос данных (не забудем про BGR->RGB) unsigned char *ptr = (unsigned char *) v; for(int y = my-1; y >= 0; y--) < unsigned char *pRow = tmp_buf + mx3*y; for(int x=0; x< mx; x++) < *ptr++ = *(pRow + 2); *ptr++ = *(pRow + 1); *ptr++ = *pRow; pRow+=3; ptr ++; >> delete []tmp_buf; return v; // OK >

ВНИМАНИЕ!. Освобождать память должна будет программа, вызвавшая данную функцию, например:

. int mx, my; // для размеров изображения int *v = loadBMP("picture.bmp", mx, my); // выделяем память и читаем туда файл . delete [] v; // освобождаем память

Для записи в BMP-файл можно использовать фунцию

int saveBMP( const char *fname, int *v, int mx, my ) // В каждом элементе упаковано все три RGB-байта < BMPheader bh; // Заголовок файла, sizeof(BMPheader) = 56 memset( &bh, 0, sizeof(bh) ); bh.bfType =0x4d42; // 'BM' // Найдем длину строки в файле, включая округление вверх до кратного 4: int mx3 = (3*mx+3) & (-4); int filesize = 54 + my*mx3; bh.bfSize = filesize; bh.bfReserved = 0; bh.biPlanes = 1; bh.biSize = 40; bh.bfOffBits = 14 + bh.biSize; bh.biWidth = mx; bh.biHeight = my; bh.biBitCount = 24; bh.biCompression= 0; FILE *f = fopen( fname, "wb" ); if( !f ) return -1; size_t res; // пишем заголовок res = fwrite( &bh, 1, sizeof(BMPheader), f ); if( res != sizeof(BMPheader) ) < fclose(f); return -1; >// приготовим временный буфер unsigned char *tmp_buf = new unsigned char[mx3*my]; // Перенос данных (не забудем про RGB->BGR) unsigned char *ptr = (unsigned char *) v; for(int y = my-1; y >= 0; y--) < unsigned char *pRow = tmp_buf + mx3*y; for(int x=0; x< mx; x++) < *(pRow + 2) = *ptr++; *(pRow + 1) = *ptr++; *pRow = *ptr++; pRow+=3; ptr++; >> // сбросим в файл fwrite( tmp_buf, 1, mx3*my, f ); fclose(f); delete []tmp_buf; return 0; // OK >

Создать программно bmp файл

Смотрел решение данной проблемы на msdn и тут : C++ How to create a bitmap file Создает файл с расширением .bmp но при этом в описании ничего нету, файл пишет что поврежден. заголовок читал, смотрел, вроде то. пытался скопировать из bmp в bmp, если полностью скопировать bmpFileHeader и bmpInfoHeader то работает. Также пробовал делать еще некоторые манипуляции, перевернуть отразить. Похоже что я что то не так делаю с заголовками

BITMAPFILEHEADER bmpFileHeader = < 0 >; BITMAPINFOHEADER bmpInfoHeader = < 0 >; RGBQUAD RGBcolor; for (size_t i = 0; i < height*width; ++i) image[i].reserved = 0; bmpFileHeader.bfType = 0x4d42; bmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER); bmpInfoHeader.biWidth = width; bmpInfoHeader.biHeight = height; bmpInfoHeader.biSizeImage = (DWORD)(bmpInfoHeader.biWidth * bmpInfoHeader.biHeight); bmpInfoHeader.biPlanes = 1; bmpInfoHeader.biBitCount = 8; bmpInfoHeader.biCompression = BI_RGB; bmpInfoHeader.biXPelsPerMeter = bmpInfoHeader.biYPelsPerMeter = 2000; bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER)+bmpInfoHeader.biSize + bmpInfoHeader.biSizeImage; bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + bmpInfoHeader.biSize + sizeof(RGBQUAD); for (size_t i = 0; i < height * width; ++i)< fwrite(&image[i], sizeof(RGBQUAD), 1, output); >typedef struct RGB< BYTE rgbtBlue; BYTE rgbtGreen; BYTE rgbtRed; BYTE reserved; >; 

Отслеживать
Peter Lavreniuk
задан 24 апр 2016 в 7:26
Peter Lavreniuk Peter Lavreniuk
2,941 7 7 золотых знаков 28 28 серебряных знаков 57 57 бронзовых знаков
Сравнить с рабочим BMP пробовали?
24 апр 2016 в 7:48

@ВладимирМартьянов пробовал. изменил biBitCount на 16 и что то пишет, но цвета искажает сильно и пишет один цвет в 3 пикселя .

24 апр 2016 в 8:06

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

bmpFileHeader.bfSize — поле заполнено неверно, должно быть: bmpFileHeader.bfSize = sizeof(BITMAPINFOHEADER);

bmpFileHeader.bfOffBits — здесь вы оставляете место под 256 записей палитры — непонятно зачем, потому что очевидно палитра вам тут не нужна и вы её точто не заполняете, а сразу пишете пиксели.

Также обратите внимание, что изображение в bmp — перевёрнутое, т.е. нижняя строка пикселов идёт первой, затем та что над ней итд.

Вообще, нужно внимательно читать описание каждого поля. По вашему коду видно, что многое вы упустили. Вот описание структуры на русском: http://www.vsokovikov.narod.ru/New_MSDN_API/Bitmaps/str_bitmapinfoheader.htm

В качестве примера работающего кода могу дать свой: https://github.com/nzeemin/ukncbtl/blob/master/util/BitmapFile.cpp — функция BmpFile_SaveScreenshot() в самом начале файла.

Проверьте поле biBitCount — сейчас у вас оно показывает что цвет 8-битный, а заливаете вы 32-битные пиксели.

Как вывести bmp файл с

Здравствуйте, уважаемые форумчане. Есть такая проблемка. Программирую на C. Создал в Visual studio 2008 bmp-шку и поместил ее в проект. Но вот незадача . ((( Как ее вывести в консоль(именно в консоль). В инете не могу найти добротного ответа. Прошу помочь с решением данной проблемы. Заранее благодарен. ))))

stas135642
Посмотреть профиль
Найти ещё сообщения от stas135642

Регистрация: 25.10.2011
Сообщений: 3,178

Что значит — «вывести bmp в консоль»? Вывести все печатные символы из файла? Вывести шестнадцатеричные коды всех символов в файле? Что?

Abstraction
Посмотреть профиль
Найти ещё сообщения от Abstraction

Пользователь
Регистрация: 31.10.2010
Сообщений: 39
Попиксельный вывод изображения на экран

stas135642
Посмотреть профиль
Найти ещё сообщения от stas135642

Регистрация: 28.01.2009
Сообщений: 21,000

консоль не предназначена для вывода графики.
а так у вас цель, через АПИ удобное или самому банально через файлы?

Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.

Пепел Феникса
Посмотреть профиль
Найти ещё сообщения от Пепел Феникса

КАК вывести в окно картинку?

Картинки. Когда-то я перерыл горы литературы, чтобы изучить форматы файлов BMP и JPG для добавления картинок в свои программы. Поскольку программирование для Windows в достаточной степени унифицированно, операционная система берёт на себя чтение формата файла, и нам практически ничего не придётся делать вручную!
Это самая благодарная работа, потому что она видна сразу. Начиная от маленького окошечка «О программе», где вы можете скромно разместить свою фотографию и заканчивая 2-х мерными играми, где всё: фон, герой, призы, враги будут отдельными картинками. Умело включив в свою игру красивые рисунки, вы избежите необходимости ломать голову над разработкой дружественного и интерфейса!

Окно

Так называемые «скины» (scins) — это картинки, натянутые на окно. Многие программы позволяют менять эти скины, например известный медаплеер WinAmp. Сама Windows позволяет натягивать изображения на кнопки, что бесконечно их преображает. Кроме кнопок, изображения выводятся почти куда угодно: в меню, в прокручиваемых и выпадающих списках, в панели управления, в контекстных меню.

Наломав руки с выводом картинок PCX и BMP в MS-DOS, я думал, что в Windows их выводить ещё сложнее. Каково же было моё удивление, когда я узнал, что загружать картинки ничуть не сложнее, чем курсоры и иконки!

Итак, вы уже знаете, как включать файлы в проект. Знаете и про файлы ресурсов. Новый проект создавать не обязательно. Скопируйте файл с расширением BMP в папку с вашим проектом. Добавьте этот файл в проект через команды меню Project->Add Resource (Project->Add To Project->New) или нажмите Ctrl+R. В стандартном окне выбора ресурсов выберите Bitmap. Однако наш компилятор считает, что bitmap — это маленькая картинка вроде иконки. Если вы нажмёте New, он предложит вам её нарисовать самому, размером 16Х16. Вы гордо откажетесь и выберите Import. Указав файл картинки в окне «Открыть..», вы тем самым добавите его в проект. По умолчанию, ему присвоится имя IDB_MYIMAGE. Вы можете его изменить на BMImage, например.

Файл ресурсов у вас теперь будет такой:

//First1.rc
#include «windows.h»

IDI_MYICON ICON «serdechko.ico»
IDC_MYCURSOR «dagger.cur»
IDB_MYIMAGE BITMAP «1.bmp»

В проекте уже присутствует файл 1.bmp, который мы назвали BMImage, Теперь призовём всю мощь API функций и выведем на экран эту картинку.

Шаг 1.Объявим имя картинки:

char szProgName[]=»Имя программы»; //имя программы
char szIconName[]=»IDI_MYICON»; //иия иконки
char szCursorName[]=»IDC_MYCURSOR» //имя курсора
char szImageName[]=»BMImage»; //а эту строчку мы добавили

Шаг 2. Связывание идентификатора картинки с ресурсом

int WINAPI WinMain( . )
HWND hWnd;
MSG lpMsg;
WNDCLASS w;

HBITMAP hBitmap=LoadBitmap(hInstance, szImageName); //Связываем идентификатор картинки с ресурсом

Шаг 3.Объявление контекста изображения

LRESULT CALLBACK WndProc(. )

HDC hdc, hmdc; //объявляем ещё один контекст изображения hmdc
PAINTSTRUCT ps;

Шаг 4. Объявляем экзмепляр структуры BITAMP

BITMAP bm;

Шаг 5. Вывод на экран

case WM_PAINT:
hdc=BeginPaint(hWnd, &ps);

//здесь начинаются строки, связанные с рисованием картинки
hmdc=CreateCompatibleDC(hdc); //Создаёт совместимый с оконным контекст памяти
SelectObject(hmdc, hBitmap); //Выбирает объект картинку
GetObject(hBitmap, sizeof(bm), (LPSTR) &bm); //получаем высоту и ширину картинки
BitBlt(hdc, 10,10, bm.Width, bm.bmHeight, hmdc, 0,0, SRCCOPY); //Помещает картинку на экран в точку 10, 10
//из памяти (hmdc)

DeleteDC(hmdc); //удаляем из памяти контекст
//Конец рисования картинки

Итак, немного поподробней о том, что мы сделали:

Шаг 1. Перемення szImage[] будет содержать в себе строку с именем ресурса IDB_MYIMAGE.

Шаг 2. HBITMAP hBitmap=LoadBitmap(hInstance, szImageName);
Тип данных HBITMAP подобен HCURSOR и HICON тем, что переменного этого типа служит для связи программы с каким-то ресурсом. В данном случае, изображением.

Шаг 3. Для вывода на экран картинки, ей выделяется свой личный контекст, отличный от HDC. Тем не менее, он должен быть совместим с HDC, для этого на 5-м шаге мы применяем функцию CreateCompatibleDC(HDC), значение которой приравниваем контексту изображения. Теперь, выводя картинку в hmdc, всё равно, что мы выводим её в HDC.

Шаг 4. Все данные об изображении: размер, количество планов, высоту, ширину, количество бит, выделенных для описания пикселя, содержит структура BITMAP. Создавая её экземпляр BITMAP bm, мы заполняем эту структуру информацией о нашей многострадальной картинке из ресурса 1.bmp. После выполнения на пятом шаге GetObject(hBitmap, sizeof(bm), &bm), cтруктура BITMAP будет заполнена всем, что связано с hBitmap. Вторым аргументом функции GetObject, мы указываем размер структуры, получив её размер через sizeof(bm).

Шаг 5. Здесь мы создаём совместимый контекст функцией CreateCompatibleDC(), делаем активным объект hBitmap в контексте hmdc, заполняем структуру BITMAP с помощью GetObject(), выводим на экран картинку с помощью BitBlt().

Функция BitBlt широко применяется во всевозможных графических редакторах и программах. Её достоинство в том, что она копирует область из памяти куда угодно и с какими угодно размерами. Это удобно для игровых программ, когда надо постоянно выводить картинку с изображением игрока в разных местах.
Первый аргумент функции контекст куда мы выводим — HDC.Второй и третий — координаты левого верхнего угла картинки. Четвёртый — ширина и высота картинки, пятый — контекст из которого выводим — hmdc. Шестой и седьмой — с какого места контекста hmdc копируем — естественно с самого начала (0,0). Последний аргмуент — режим копирования. Их несколько:

Как видите, спецэффектов много, но они не богатые. Конечно они хороши для простых игр, но для больших «наворотов» используются возможности библиотеки DirectX, а точнее DirectDraw. Это очень обширная тема, и по ней одной можно написать отдельную книгу.

Небольшая оговорочка. Всё это очень хорошо, если у нас картинки хранятся в ресурсе и совершенно непригодно для открытия файла картинки с диска, например, через стандартное окно «Открыть». Для открытия любой картинки из файла нам необходимо так же, как и в DOS знать формат файла: PCX, JPG, TIFF или BMP. Дело облегчается тем, что давно уже написаны классы для работы с этими форматами, поэтому изобретать велосипед не нужно. Часто в книгах по Visual C++ эти классы приведены целиком.
Создав экземпляр такого класса, например:

CBitmаp *cbmp = new CBitmap;

вы сможете пользоваться всеми его методами для открытия, сохранения, получения информации о картинке и др.

cbmp->OpenBmp(«c:\MyPics\sexy.bmp»); //использованиe метода открытия картинки

cbmp->SaveToFile(«default.bmp»); //использованиe метода сохранения картинки

bmpInfo = cbmp.BmpInfo(); //информация о файле

И, пожалуй, это будет лучший выход из положения. Названия функций могут быть различны, но суть у них одна. И здесь процедурное программирование проигрывает перед объектно-ориентированным.

Задание:

1. Поменяв последний параметр BitBlt, добиться вывода картинки в негативном отображении.
2. Разместите в ресурсах три изображения 200Х400 точек, в которых будут нарисованы три карты (создать и нарисовать карты можно в редакторе Paint, в котором есть средство изменения размера картинки). Карты должны быть: 2 червей, 6 пик и 10 треф. Используя полученные знания, разместите карты в середине экрана. Над ними выведите надпись (функция TextOut): «Выберит любую карту».

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *