Этот пример иллюстрирует возможность создания формата (полностью демонстрационного) для хранения изображений. В общем-то являясь уступающим аналогом DIB (по нашему - BMP), тем не менее я думаю это хороший пример.
Некоторая оговорка. Я не говорю, что TFileStream вообще и в данном случае - наилучший вариант поточного io класса. Например, можно было использовать fstream [basic_fstream]. Но все-таки это раздел, посвященный VCL и всему, что с ним связано. Поскольку программист на C++ Builder часто использует компонентные классы VCL, то ему приходится обращаться к сооствествующим поточным классам (потомкам TStream).
Алгоритм просто перписывает информацию в файл с указанием ширины и высоты изображения. Вообще-то это неэффективное использование массива Pixels и свойства ScanLine. В реальной программе для этого бы использовались функции WinAPI для прямой работы с матрицей, типа GetDIBits и SetDIBits. Но при использовании этих функций пример бы потерял выразительность.
Я использовал некоторые возможности программы ScrollView для просмотра изображений. Вот форма приложения:
Для более удобного отображения здесь использован компонент TPageControl с палитры Win32. Для создания новых страниц (это компонент, работающий по принципу ноутбука или блокнота) используются команды контескстного меню <New page>, <Next Page>. Рассмотрю его подробнее позже. В каждую из страниц помещен компонент TScrollBox и TImage. У первого Align = alClient, у второго обычный. Кнопки на нижней панели отвечают за загрузку, конвертирование и преобразование изображения. Для оного используется временный файл "test.xgr" в текущем каталоге (надеюсь, такое расширение еще никто не задействовал :)). Еще на форму кинут один компонент TOpenPictureDialog.
Для оперделения скорости процесса конвертирования еще использован компонент TProgressBar со страницы Win32. Еще раз предупреждаю, что процесс обращения к отдельным пикселям очень неэффективен. Поэтому не рекомендую открывать в программе большие изображения, типа 1024x768 скриншотов. У меня (P850E) один такой скриншот открывался секунд 30. В смысле сохранялся. Открывается быстрее, но все равно не надо.
Так вот. TProgressBar - это индикатор. Обычно его используют в процессах, продолжающихся длительное время. Вкратце. Свойства Min и Max определяют минимальную и максимальную позиции индикатора. Свойство Position текущую позицию индикатора. Свойство Step сдвиг в позиции пл вызову метода StepIt.
Вот код:
//Эту функцию мне пришлось использовать из-за // несовместимости формата DIB пикселей // с выдаваемыми свойством Pixels //Она переставляет R и B части цвета и удаляет высший байт.. long ConvertCol(long col) { col&=0x00FFFFFF; long bcol=col; bcol&=0x0000FF; bcol*=0x10000; long rcol=col; rcol&=0xFF0000; rcol/=0x10000; long gcol=col; gcol&=0x00FF00; TColor result=(TColor)(rcol|gcol|bcol); return result; }; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::SaveClick(TObject *Sender) { TFileStream* fs=new TFileStream("test.xgr",fmCreate); TVclBmp* bmp=new TVclBmp; TColor *row; TColor ptr; int iptr; int ns=sizeof(TColor); bmp->Width=Image1->Picture->Bitmap->Width; bmp->Height=Image1->Picture->Bitmap->Height; TRect rect(0,0,Image1->Width,Image1->Height); bmp->Canvas->CopyRect(rect,Image1->Picture->Bitmap->Canvas,rect); iptr=bmp->Width; fs->Write(&iptr,ns); iptr=bmp->Height; fs->Write(&iptr,ns); Bar->Position=0; Bar->Max=bmp->Height; for(int i=0;iHeight;i++) { Bar->StepIt(); row=(TColor*)bmp->ScanLine[i]; fs->WriteBuffer(row,ns*bmp->Width); }; delete fs; delete bmp; ScrollBox1Resize(0); } //--------------------------------------------------------------------------- void __fastcall TForm1::LoadClick(TObject *Sender) { TFileStream* fs=new TFileStream("test.xgr",fmOpenRead); TVclBmp* bmp=new TVclBmp; TColor ptr; int ns=sizeof(TColor); bmp->PixelFormat=pf32bit; fs->Read(&ptr,ns); bmp->Width=ptr; fs->Read(&ptr,ns); bmp->Height=ptr; Bar->Position=0; Bar->Max=bmp->Height; for(int i=0;i Height;i++) { Bar->StepIt(); for(int j=0;j Width;j++) { fs->Read(&ptr,ns); bmp->Canvas->Pixels[j][i]=ConvertCol(ptr); }; }; Image2->Picture->Bitmap->Width=bmp->Width; Image2->Picture->Bitmap->Height=bmp->Height; Image2->Canvas->Draw(0,0,bmp); delete fs; delete bmp; ScrollBox2Resize(0); } //--------------------------------------------------------------------------- void __fastcall TForm1::LoadFileClick(TObject *Sender) { if(!Open1->Execute())return; Image1->Picture->LoadFromFile(Open1->FileName); } //--------------------------------------------------------------------------- void __fastcall TForm1::ScrollBox1Resize(TObject *Sender) { if(Image1->Width ClientRect.Width()) Image1->Left=(ScrollBox1->ClientRect.Width()-Image1->Width)/2; else Image1->Left=0; if(Image1->Height ClientRect.Height()) Image1->Top=(ScrollBox1->ClientRect.Height()-Image1->Height)/2; else Image1->Top=0; } //--------------------------------------------------------------------------- void __fastcall TForm1::ScrollBox2Resize(TObject *Sender) { if(Image2->Width ClientRect.Width()) Image2->Left=(ScrollBox1->ClientRect.Width()-Image2->Width)/2; else Image2->Left=0; if(Image2->Height ClientRect.Height()) Image2->Top=(ScrollBox1->ClientRect.Height()-Image2->Height)/2; else Image2->Top=0; } //---------------------------------------------------------------------------
Вот так вот.