Как создать bmp файл c

Обновлено: 06.07.2024

Я хотел бы создать файл BMP из значений RGB, которые я уже сохранил.

Я программирую на OS X, поэтому я не могу использовать предопределенные заголовки BMP.

Я попытался сделать ниже, но предварительный просмотр говорит, что файл поврежден.

Я не уверен, что правильно понимаю структуру. Я пытался прочитать об этом, но я должен что-то упустить.

Вот шестнадцатеричный вывод файла

42 4D 00 02 38 00 00 00 00 00 00 00 36 00 00 00 28 00 00 00 80 02 00 00 E0 01 00
00 01 00 18 00 00 00 00 00 00 00 00 00 C4 0E 00 00 C4 0E 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00

Решение

Вопрос хороший, потому что он освещает некоторые подводные камни. Вот все проблемы в вашем коде. Исправив их, все работает как положено:

Ваше поле bfSize не включает размер растрового изображения

Общее: BITMAPFILEHEADER становится большим, поскольку начинается с 2-байтового значения, за которым следует 4-байтовое значение. Правила заполнения говорят, что в этой структуре первое поле будет 4 байта вместо 2. Решение: напишите магическое число отдельно, исключив его из BITMAPFILEHEADER :

Эта модификация также подразумевает, что BITMAPFILEHEADER::bfSize является 2+sizeof(BITMAPFILEHADER) + sizeof(BITMAPINFOHEADER)+ biWidth*biHeight*3

Вы также прошли sizeof(bfh) для стенда bfh а также bih итак, полный BITMAPINFOHEADER никогда не написано

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

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

Растровые файлы хранятся строка-мудрый, так что вы должны зацикливаться Икс-координаты в самом внутреннем цикле

Вы также должны написать неправильные значения пикселей. Ты должен написать unsigned char вместо того, чтобы плавать. Вы пишете правильный размер (1 байт), но это не будет правильным значением:

Кроме того, растровые изображения являются BGR (A), а не RGB (A).

Если у вас хорошая ширина, рабочий пример

Это выход

Другие решения

Код user877329 работал для меня. (Просто некоторые незначительные изменения, потому что я использую C)
Примечание: просто обратите внимание на «размер» переменных, поскольку они могут различаться в зависимости от платформы, которую вы компилируете.

Вся проблема в том (в твоем случае), что формат BMP не может сохранять что-то по точкам, в нем хранится некая прямоугольная область. Т.е. например, если у тебя черный экран, и есть две точки (10, 10, белый); (20, 30, серый), то тебе нужно сохранять область экрана (10,10,30,30) - это по-минимуму. По-другому не выйдет. В файле будет все забито нулями (черный цвет) кроме твоих 2-х точек. Поэтому BMP такие здоровые

Если кратко, то у BMP-файла есть заголовок, который идет в начале (там много нужной и бесполезной инфромации, в основном, конечно, нужной :)

Вся проблема в том (в твоем случае), что формат BMP не может сохранять что-то по точкам, в нем хранится некая прямоугольная область. Т.е. например, если у тебя черный экран, и есть две точки (10, 10, белый); (20, 30, серый), то тебе нужно сохранять область экрана (10,10,30,30) - это по-минимуму. По-другому не выйдет. В файле будет все забито нулями (черный цвет) кроме твоих 2-х точек. Поэтому BMP такие здоровые

Ну, у меня на самом деле не 2 точки, а немеряно точек (дифракционная картина, если интересно); а выбор именно бмп основан на том что программа куда это передается работает с бмп.
Почитать ничего нету по этому поводу (в смысле как записать), а? А то сильно надо. Очень сильно :-)

Ну, у меня на самом деле не 2 точки, а немеряно точек (дифракционная картина, если интересно); а выбор именно бмп основан на том что программа куда это передается работает с бмп.
Почитать ничего нету по этому поводу (в смысле как записать), а? А то сильно надо. Очень сильно :-)

Да хоть интерференционная :) BMP хорош только тем, что открывается проще других форматов, так как содержит битовую карту (bitmap), никаких сжатий и т.п. как например у JPG.

А не пробовал здесь поискать? На codenet куча исходников и книжек. Можно в поиске по сайту написать "bmp" и удивляться, сколько информации будет найдено :) Ну, или зайти в обычный книжный магазин, поискать что-нибудь с примерами. Я помочь исходником не могу, потому что готового ничего нет, а писАть лениво, время нужно. Но я уверяю, ничего сложного нет

Вот, кстати, в хелпе по билдеру нашел (вообще, посмотри каталог Examples, там этого добра навалом):

The picture object can load and save graphics in several formats, and you can create and register your own graphic-file formats so that picture objects can load and store them as well.
To save the contents of an image control in a file, call the SaveToFile method of the image control’s Picture object.
The SaveToFile method requires the name of a file in which to save. If the picture is newly created, it might not have a file name, or a user might want to save an existing picture in a different file. In either case, the application needs to get a file name from the user before saving, as shown in the next section.

The following pair of event handlers, attached to the File|Save and File|Save As menu items, respectively, handle the resaving of named files, saving of unnamed files, and saving existing files under new names.

void __fastcallTForm1::Save1Click(TObject *Sender)

if (!CurrentFile.IsEmpty())
Image->Picture->SaveToFile(CurrentFile); // save if already named
else SaveAs1Click(Sender); // otherwise get a name
>

void __fastcallTForm1::SaveAs1Click(TObject *Sender)

if (SaveDialog1->Execute()) // get a file name
CurrentFile = SaveDialog1->FileName; // save user-specified name
Save1Click(Sender); // then save normally
>
>

Все очень просто:

void __fastcall bmp_store(void)
Graphics::TBitmap *bmp=new Graphics::TBitmap();
bmp->PixelFormat=pf24bit;
/*
pf1bit - монохромные битмапы
pf4bit - палетризованные 16 цветные
pf8bit - палетризованные 256 цветные
pf15bit - 5:5:5 (держит только Windows9x)
pf16bit - 5:6:5
pf24bit - RGB
pf32bit - RGBA
*/
bmp->Width=100;
bmp->Height=100;
/*
для доступа к данным битмапа есть два способа:
1. Через канву.
*/
bmp->Canvas->Pixels[10][10]=clWhite;
bmp->Canvas->Pixels[20][30]=clGray;
bmp->Canvas->Pen->Color=clRed;
bmp->Canvas->Pen->MoveTo(0,0);
bmp->Canvas->Pen->LineTo(100,100);
/*
Способ второй - непосредственно через сканы:
Только в этом случае важно помнить следующее - количество бит отводимых под каждый пиксел в этом случае зависит непосредственно от пиксельного формата заданного для изображения.
pf1bit - 1 байт на 8 точек по горизонтали.
pf4bit - 1 байт на 2 точки
pf8bit - байт на точку
pf15bit и pf16bit - 2 байта на точку
pf24bit - 3 байта на точку
pf32bit - 4 байта на точку.

Ну еще и помнить следующее - у майкросовта все никак у людей - цветовая ориентация не RGB а BGR :) Все их на голубизну тянет.

Пример:
*/
BYTE *scan=(BYTE*)bmp->ScanLine[10];
// (10,10,белый цвет)
*(scan+10*3)=0xFF;
*(scan+10*3+1)=0xFF;
*(scan+10*3+2)=0xFF;
// (20,30,серый цвет)
scan=(BYTE*)bmp->ScanLine[30];
*(scan+20*3)=0x80;
*(scan+20*3+1)=0x80;
*(scan+20*3+2)=0x80;
// ну вобщем все в таком духе.
// А теперь сохраним полученный результат:
bmp->SaveToFile("c:\test.bmp");
// Готово собственно.
delete bmp;
>

Да, отмечу - форматы pf15bit,pf16bit,pf32bit - понимаются не всеми прогами - фотошоп например стал их поддерживать только в 7 версии.
Вобщем смотри хелп по TBitmap

Я пытаюсь создать файл.bmp (заполненный одним цветом для целей тестирования).

Вот код, который я использую:

Я что-то неправильно понял и что я здесь делаю неправильно?

Также не уверен, что важно, но я использую Ubuntu 14.04 для компиляции этого.

Нашел еще один вопрос:

Но все еще не видно изображения.

спросил(а) 2014-11-30T19:46:00+03:00 6 лет, 11 месяцев назад

Я считаю, что ваши размеры полей неверны, попробуйте это

ответил(а) 2014-11-30T21:13:00+03:00 6 лет, 11 месяцев назад

Прежде всего, вы устанавливаете:

bfSize Определяет размер файла в байтах.

к недопустимому значению, ваш код привел к 1440112 тогда как размер файла на самом деле 1080112

Потому что sizeof(COLORREF_RGB) на самом деле 4 не 3.

Другая ошибка заключается в том, что размер ваших структур и типов:

* Я использую gcc на архитектуре x86_64

Ваши смещения просто не совпадают с смещениями в wikipedia, ссылка, которую вы используете, вероятно, была написана для 16-битного компилятора на 16-битной ОС (как указано чашкой в комментарии), поэтому предполагает, что int является типом 2B.

Использование значений из stdint.h работало для меня (руководство по stdint.h для Visual Studio здесь):

И последнее, но не менее важное: вы должны отключить выравнивание памяти, как было предложено Weather Vane.

ответил(а) 2014-11-30T22:07:00+03:00 6 лет, 11 месяцев назад

Вы пытаетесь отобразить структуру C в некоторый внешний двоичный формат. Существует ряд проблем с этим:

Размер

Язык C указывает только минимальные размеры этих типов. Их фактические размеры могут и зависят от разных компиляторов и операционных систем. Размеры и смещение членов в ваших структурах могут быть не такими, как вы ожидаете. Единственный размером, который вы можете рассчитывать на (практически на любой системе, что вы, вероятно, столкнуться в эти дни) является char является 8 битыми.

набивка

Для DWORD часто бывает вдвое больше UINT , и на самом деле ваша программа зависит от него. Обычно это означает, что компилятор будет вводить прокладку между bfType и bfSize чтобы дать последнему соответствующее выравнивание для своего типа. Формат .bmp не имеет такого дополнения.

порядок

Другая проблема заключается в том, что язык C не указывает на консистенцию типов. Элемент .bfType может храниться как [42][4D] (Big-Endian) или [4D][42] (Little-Endian) в памяти. Формат .bmp требует, чтобы значения сохранялись в порядке Little-Endian.

Решение

Единственный способ правильно записать двоичный формат, определяемый извне, - использовать массив unsigned char и записывать значения байта за раз. Лично я бы написал набор вспомогательных функций для определенных типов:

Я хотел бы создать файл BMP из значений RGB, которые я уже сохранил.

Я программирую на OS X, поэтому я не могу использовать предопределенные заголовки BMP.

Я попытался сделать ниже, но предварительный просмотр говорит, что файл поврежден.

Я не уверен, что правильно понимаю структуру. Я пытался прочитать об этом, но я должен что-то упустить.

Вот шестнадцатеричный вывод файла

42 4D 00 02 38 00 00 00 00 00 00 00 36 00 00 00 28 00 00 00 80 02 00 00 E0 01 00
00 01 00 18 00 00 00 00 00 00 00 00 00 C4 0E 00 00 C4 0E 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00

Решение

Вопрос хороший, потому что он освещает некоторые подводные камни. Вот все проблемы в вашем коде. Исправив их, все работает как положено:

Ваше поле bfSize не включает размер растрового изображения

Общее: BITMAPFILEHEADER становится большим, поскольку начинается с 2-байтового значения, за которым следует 4-байтовое значение. Правила заполнения говорят, что в этой структуре первое поле будет 4 байта вместо 2. Решение: напишите магическое число отдельно, исключив его из BITMAPFILEHEADER :

Эта модификация также подразумевает, что BITMAPFILEHEADER::bfSize является 2+sizeof(BITMAPFILEHADER) + sizeof(BITMAPINFOHEADER)+ biWidth*biHeight*3

Вы также прошли sizeof(bfh) для стенда bfh а также bih итак, полный BITMAPINFOHEADER никогда не написано

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

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

Растровые файлы хранятся строка-мудрый, так что вы должны зацикливаться Икс-координаты в самом внутреннем цикле

Вы также должны написать неправильные значения пикселей. Ты должен написать unsigned char вместо того, чтобы плавать. Вы пишете правильный размер (1 байт), но это не будет правильным значением:

Кроме того, растровые изображения являются BGR (A), а не RGB (A).

Если у вас хорошая ширина, рабочий пример

Это выход

Другие решения

Код user877329 работал для меня. (Просто некоторые незначительные изменения, потому что я использую C)
Примечание: просто обратите внимание на «размер» переменных, поскольку они могут различаться в зависимости от платформы, которую вы компилируете.

Читайте также: