Нужно програмно создать BMP файл, если можно обьясните как для чайника
Есть много описаний структуры bmp файла, я их пересмотрел (даже из msdn находил инфу), но все равно не могу понять как мне с этим работать. Даже не представляю с какой стороны походить. Может кто поможет разобраться, сделать примерно следующее: например есть две точки, координаты и цвет: (10, 10, белый); (20, 30, серый). Как можно програмно создать bmp с этими точками?
Или может исходник есть где используется что-то подобное? Вышлите пожалуйста на мыло [email]andreww@svitonline.com[/email] буду очень-очень благодарен.
Здравствуйте! У меня такой вопрос. Есть файл в виде координат точек, и их цвет (цвет каждой точки, если это важно - то он будет задаваться градациями серого [черно-белая картинка]). Из этих точек нужно слепить BMP файл. (Просто раньше эти точки выводились на экран в DOS режиме, а теперь нужно их запихивать в BMP, потому что прога которая с ними будет работать понимает BMP формат).
Есть много описаний структуры bmp файла, я их пересмотрел (даже из msdn находил инфу), но все равно не могу понять как мне с этим работать. Даже не представляю с какой стороны походить. Может кто поможет разобраться, сделать примерно следующее: например есть две точки, координаты и цвет: (10, 10, белый); (20, 30, серый). Как можно програмно создать bmp с этими точками?
Или может исходник есть где используется что-то подобное? Вышлите пожалуйста на мыло [email]andreww@svitonline.com[/email] буду очень-очень благодарен.
Если кратко, то у BMP-файла есть заголовок, который идет в начале (там много нужной и бесполезной инфромации, в основном, конечно, нужной :)
Вся проблема в том (в твоем случае), что формат 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" и удивляться, сколько информации будет найдено :) Ну, или зайти в обычный книжный магазин, поискать что-нибудь с примерами. Я помочь исходником не могу, потому что готового ничего нет, а писАть лениво, время нужно. Но я уверяю, ничего сложного нет
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
}
}
Есть много описаний структуры bmp файла, я их пересмотрел (даже из msdn находил инфу), но все равно не могу понять как мне с этим работать. Даже не представляю с какой стороны походить. Может кто поможет разобраться, сделать примерно следующее: например есть две точки, координаты и цвет: (10, 10, белый); (20, 30, серый). Как можно програмно создать bmp с этими точками?
Или может исходник есть где используется что-то подобное? Вышлите пожалуйста на мыло [email]andreww@svitonline.com[/email] буду очень-очень благодарен.
Все очень просто:
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
Очень прикольно то что действительно не RGB, а BGR - для задания цвета я открыл свою книгу по ХТМЛ, нашел красный, и задал как ff0000 - получился синий :-) поменял на 0000ff - красный :-))).
Можно еще пару вопросов, чтоб уже так сказать на этом сделать логическое завершение?
1) Что собой представляет ScanLine[30]? Это 30-я позиция массива ScanLine? И это мы в ScanLine[Y] подставляем координату Y, а в *(scan+X*3)=0x80 - координату X?
Что происходит вот здесь : scan=(BYTE*)bmp->ScanLine[30]? bmp - это динамический массив который мы создали, потом преобразовали его к типу BYTE, да? А вот это что: (BYTE*)bmp->ScanLine[30]?
Graphics - это класс в котором все описано, а мы только пользуемся его членами/методами?
(Заметно, наверно какой я ламер в С++, просто приходится перелазить с Си на С++, а то есть угроза отстать от прогресса :-))
2) Как можно сделать чтоб фон рисунка был черным а не белым? Зарисовать все черными точками, а потом поверху рисовать своими серо-белыми? Или можно как то сразу с черным фоном создать?
В рез-те у меня должна получиться бело-серая картинка на черном фоне.
Если будете выбирать на какой вопрос отвечать то лучше на второй, плз. Хотя теор-часть (первый вопрос) меня тоже очень интересует.
1) Что собой представляет ScanLine[30]? Это 30-я позиция массива ScanLine? И это мы в ScanLine[Y] подставляем координату Y, а в *(scan+X*3)=0x80 - координату X?
Что происходит вот здесь : scan=(BYTE*)bmp->ScanLine[30]? bmp - это динамический массив который мы создали, потом преобразовали его к типу BYTE, да? А вот это что: (BYTE*)bmp->ScanLine[30]?
ScanLine[30]-30-я строка битмапа, ScanLine[10] - 10-я и т.п.
Тот пример (но с комментариями):
// указатель на начало 10-й строки битмапа суем в
scan
BYTE *scan=(BYTE*)bmp->ScanLine[10];
/* это все обычная работа с указателями. С++ здесь ни при чем :) Пример написан с расчетом на то, что цвет точки задается 3-х байтовым значением. 10 в данном случае - это 10-я точка в строке - мы же сейчас рассматриваем точку с координатами (10,10). */
*(scan+10*3)=0xFF; - код B
*(scan+10*3+1)=0xFF; - код G
*(scan+10*3+2)=0xFF; - код R
короче, в результате выполнения этого куска точка с координатами (10,10) будет белий-белий
(Заметно, наверно какой я ламер в С++, просто приходится перелазить с Си на С++, а то есть угроза отстать от прогресса :-))
Ну, вроде того :) А ты что думал? Волшебное слово такое? :)
В рез-те у меня должна получиться бело-серая картинка на черном фоне.
Точками зарисовывать вообще-то долго. Лучше сделать заливку прямоугольной области (называться будет как-нибудь навроде FillRect, точно сказать не могу, так как билдером не пользуюсь). Или создать битмап черного цвету изначально
Graphics - это класс в котором все описано, а мы только пользуемся его членами/методами?
Graphics - это namespace которому принадлежит класс TBitmap.
2) Как можно сделать чтоб фон рисунка был черным а не белым? Зарисовать все черными точками, а потом поверху рисовать своими серо-белыми? Или можно как то сразу с черным фоном создать?
В рез-те у меня должна получиться бело-серая картинка на черном фоне.
У класса TBitmap есть своя канва - так что ты свободно можешь использовать ВСЕ методы класса TCanvas для рисования в битмапе. Например - чтобы сделать битмапу с черным фоном:
Graphics::TBitmap *bmp=new Graphics::TBitmap();
bmp->PixelFormat=pf24bit;
bmp->Width=100;
bmp->Height=100;
bmp->Canvas->Brush->Color=clBlack;
bmp->Canvas->FillRect(Rect(0,0,bmp->Width,bmp->Height));
bmp->SaveToFile("c:\\test.bmp");
delete bmp;
ну или по другому:
for (int i=0;i<bmp->Height;i++) memset(bmp->ScanLine,0,bmp->Width*3);
Вобщем вот так.
PS Кстати с праздником!
А можно ли посмотреть как-нибудь описание класса TBitmap в Билдере? Мне очень хочется сделать исходник не зависимый от среды разработки. Чтоб на чем угодно можно было скомпилить. В хидере <graphics.hpp>, который используется для работы с битмапом я нашел только обьявление разных там функций. А определений явно не нашел. Или определения в явном виде не доступны?
PS Кстати с праздником!
Гы!
Для этих вещей треба Билдер ставить с опцией установки исходников VCL :) Тогда в папке билдера будет директорка Source в которой находишь паку VCL и ищещь в ней graphics.pas :) Токмо исходники на паскале :) А вообще советую тебе поискать сорцы для работы с битмапами в инете. Проще будет - сразу говорю. Сам формат не сложный - заголовок + RAW data. Ну есть там несколько заморочек - палитры например (кое где они идут в стандартном виде RGB - а кое где появляется еще и альфа-канал). Ну еще идиотский прикол что растр у битмапа перевернутый - идиотизм полнейший - тоесть скан-линии растра идут не снизу вверх, а сверху вниз. Ну и в некоторых случаях битмапы могут быть еще пожаты - но там стандартный RLE (кажется точно такой-же как и у PCX). Да, и еще тупорылые мелкомягкие сделали такое дебильное выравнивание (особенно чувствительно для 24 битных изображений), что вообще непонятно на какие границы они пытаются выровнять каждый скан - ну это уж вопрос к мыкрософту. Вобщем вот так.
Да, у меня Билдер с исходниками установлен. Вот только не ожидал увидеть расширение PAS. Это они что сначала Дельфи пишут, а потом на нем Билдер делают? Вот почему релиз Билдера всегда с опозанием относително Дельфи
Да, это политика Борланд. И еще одно соображение, почему надо писать на Дельфи, а не на Билдере ;)
Да, это политика Борланд. И еще одно соображение, почему надо писать на Дельфи, а не на Билдере ;)
Не, надо переходить на альтернативные IDE, например CodeWarrior (вот только достать его - проблема), эта среда существует для всех ОСей (Win, MacOS, и скорее всего Linux), Языки: C++, Java;
Вот только взять и резко перепрыгнуть это конечно проблема. Я вот даже на VC не спешу перелазить.
Вот только взять и резко перепрыгнуть это конечно проблема. Я вот даже на VC не спешу перелазить.
Я к тому, что писать с использованием VCL надо на Дельфи. А без него - пожалуйста, выбирай что хочешь.
Я к тому, что писать с использованием VCL надо на Дельфи. А без него - пожалуйста, выбирай что хочешь.
Необязательно писать на дельфи. Builder весьма неплохо справляется с паскальным кодом :). Более того - при разработке прог на Билдере можно включать в проект паскалевские файлы - а в Дельфи сишный код включить не получится :). Да и C как язык помощнее Паскаля будет, хотя не скрою, в свое время писал исключительно на Паскале :)
Необязательно писать на дельфи. Builder весьма неплохо справляется с паскальным кодом :). Более того - при разработке прог на Билдере можно включать в проект паскалевские файлы - а в Дельфи сишный код включить не получится :).
Так в том-то и фишка, что для VCL Си не нужен, достаточно одного Дельфи. Поскольку весь VCL написан на Паскале, Си тут оказывается лишним, не побоюсь этого выражения. ;)
Да и C как язык помощнее Паскаля будет, хотя не скрою, в свое время писал исключительно на Паскале :)
А с этим никто не спорит. Все дело в перце.