Работа с изображениями средствами Borland C++ Builder

Работа с графикой и рисунками средствами Borland C++ Builder

В начало

Основные понятия

В двух следующих параграфах будут рассмотрены еще два рода объектов, которые имеют отношение к выводу изображений (условное разделение см. начало главы), а именно, графика и рисунок и классы и компоненты их инкапсулирующие.

  • Графика. Это растровое изображение некоторого файла или ресурса (битового образа, пиктограммы или метафайла). C++Builder определяет производные от базового класса TGraphic объектные классы TBitmap, Ticon и TMetafile, предназначенные для работы с графикой.
       Класс TBitmap, определен в Borland C++ Builder как Graphic::TBitmap, имеет свойства и методы, позволяющие создавать графические изображенеия, управлять их атрибутами, читать в память и сохранять как файлы DIB на диске. Graphic::TBitmap поддерживает как растровые графические изображения в виде массива пикселей, так и изображения в формате .bmp. Основное свойство класса - Canvas. Класс TGraphic предоставляет TBitmap минимальный стандартный интерфейс для работой с графикой.
       Классы TIcon и TMetafile также являются производными от базового класса TGraphic и имеют свойства и методы для работы с графикой, но в отличии от TBitmap не имеют свойства Canvas, что объясняется спецификой построения и использования изображений в формате *.ico и *.wmf (*.emf).

  • Рисунок представляет собой контейнер для графики, т.е. он может содержать любые классы графических объектов. Контейнерный класс TPicture может содержать битовый образ, пиктограмму, метафайл или некоторый другой графический тип, определенный пользователем, а приложение может стандартизовано обращаться ко всем объектам контейнера посредством объекта "рисунок". Класс TPicture инкапсулирован в класс TImage и визуальный компонент TImage, как их основной компонент и имеет возможность работы с иконоками, bmp-файлами и метафайлами. При некоторых дополнениях возможна работа с файлами других форматов (*.jpeg, *.jpg, *.gif).

Рассмотрение вопросов темы будем вести на примерах, в которых последовательно показывается использование основных свойств и методов классов. Работа с ресурсами выделена в отдельный раздел (см. Работа с ресурсами в Borland C++ Builder).

В начало

Классы TBitmap, TIcon и TMetafile

В данном параграфе рассматривается использование не инкапсулированных в другие классы и компоненты Borland C++ Builder классов TBitmap, TIcon и TMetafile.

В начало

Загрузка и сохранение графики

Первый пример показывает создание объектов соответствующих классов, загрузку в них файлов и сохранение файлов:

//Создаем объекты
Graphics::TBitmap*   gBitmap = new Graphics::TBitmap;
Graphics::TIcon*     gIcon   = new Graphics::TIcon;
Graphics::TMetafile* gMFile  = new Graphics::TMetafile;
//Загружаем в них файлы
gBitmap->LoadFromFile("1.bmp");
gIcon->LoadFromFile("1.ico");
//Свойство показывает, что файл .emf win32
gMFile->Enhanced=true; 
gMFile->LoadFromFile("1.emf");
//Сохранение изображений в файлы
gBitmap->SaveToFile("1.bmp");
gIcon->SaveToFile("2.ico");
gMFile->SaveToFile("2.emf");
//Утверждается, что Borland C++ Builder
//собироет мусор сам, но не помешает
delete gBitmap;
delete gIcon;
delete gMFile;

В начало

Загрузка и отрисовка графики

Следущий код использует класс TBitmap для загрузки изображения из файла и его отрисовки, а также для задания растрового изображения кисти. Из рисунка, показывающего результаты работы программы, видно, что вновь для кисти используется не весь битовый образ, а только первые его 8*8 пикселей.

//Создаем объект TBitmap
Graphics::TBitmap*  gBitmap = new Graphics::TBitmap;
//Загружаем в него изображение
gBitmap->LoadFromFile("1.bmp");
//Рисуем на канве загруженное изобоажение
Canvas->Draw(10,10,gBitmap);
//Берем загруженное изобоажение в качестве кисти
//из которого используются только 8*8 пикселей
Canvas->Brush->Bitmap = gBitmap;
//Рисуем элипс
Canvas->Ellipse(85,10,160,85);

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

graphics_3.jpg

Рис 1. Использование класса TBitmap

Полностью аналогичен код и для графики в форматах .ico и .emf:

Graphics::TIcon*     gIcon  = new Graphics::TIcon;
Graphics::TMetafile* gMFile = new Graphics::TMetafile;
gIcon->LoadFromFile("1.ico");
gMFile->Enhanced=true;
gMFile->LoadFromFile("1.emf");
Canvas->Draw(10,10,gIcon);
Canvas->Draw(50,50,gMFile);
delete gIcon;
delete gMFile;

Для отрисовки графики можно использовать функцию StretchDraw(), которая, в отличие от функция Draw() не только рисует, но и масштабирует изображение. Однако, иконки не масштабируются - им только выделяется указанный в функции кусок канвы

TRect tRect(10,10,50,50);
Canvas->StretchDraw(tRect,gBitmap);
TRect tRect1(100,100,150,150);
Canvas->StretchDraw(tRect1,gIcon);
TRect tRect2(250,250,350,350);
Canvas->StretchDraw(tRect2,gMFile);

Метод CopyRect() также предназначен для отрисовки графики и переносит указанную область изображения или его часть в канве источника изображения в указанную область изображения данного объекта TCanvas. Копирование производится в режиме, установленном свойством CopyMode канвы, разноообразие которых можно посмотреть в Help Borland C++ Builder.

//Создаем объект TBitmap
Graphics::TBitmap*  gBitmap = new Graphics::TBitmap;
//Загружаем в него изображение
gBitmap->LoadFromFile("1.bmp");
//Определяем размеры областей копирования
TRect tRectFrom(0,0,25,25);
TRect tRectTo(10,10,35,35);
//CopyMode cmSrcCopy - прямое копирование
Canvas->CopyMode=cmSrcCopy;
//Копируем часть изображения
Canvas->CopyRect(tRectTo,gBitmap->Canvas,tRectFrom);

В начало

Модификация графики

Следущий пример показывает как можно создать объект TBitmap, выполнить на нем рисунок и перенести на канву приложения. К сожалению это нельзя сделать не для иконок, не для метафайлов, у которых нет сваойства Canvas.

Graphics::TBitmap*  gBitmap = new Graphics::TBitmap;
gBitmap->Width  = 150;
gBitmap->Height = 150;
gBitmap->Canvas->Ellipse(0,0,150,150);
Canvas->Draw(10,10,gBitmap);
delete  gBitmap;

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

//Создаем объект TBitmap
Graphics::TBitmap*  gBitmap = new Graphics::TBitmap;
//Загружаем в него изображение
gBitmap->LoadFromFile("1.bmp");
//Задаем параметры кисти
gBitmap->Canvas->Brush->Color=clYellow;
//Рисуем на изображении файла круг
gBitmap->Canvas->Ellipse(0,0,gBitmap->Width,gBitmap->Height);
//Рисуем на канве загруженное изобоажение
Canvas->Draw(10,10,gBitmap);
delete  gBitmap;

В начало

Установка прозрачности

Bitmap может иметь один цвет, как прозрачный, тоесть цвет, который при выводе заменяется на цвет фона канвы отображения, не зависимо от смены ее цвета. Сделать это можно двумя способами. При первом способе определяется как "прозрачный" цвет левого верхнего пиксела Bitmap. При втором способе определяется прозрачным какой либо конкретный цвет. Установка того или иного способа определения прозрачных пикселов задается свойством TransparentMode (возможные значения для него - tmAuto и tmFixed соответственно). И в том, и в другом случае надо установить свойство Transparent для Bitmap в true.

//Создаем объект TBitmap
Graphics::TBitmap*  gBitmap = new Graphics::TBitmap;
//Установка свойства прозрачности
gBitmap->Transparent=true;
//Установка цвета левого верхнего
//пиксела в качестве прозрачного
gBitmap->TransparentMode=tmAuto;
gBitmap->LoadFromFile("1.bmp");
//Рисуем на канве загруженное изобоажение
Canvas->Draw(10,10,gBitmap);
//Установка конкретного цвета в качестве прозрачного
gBitmap->TransparentMode=tmFixed;
gBitmap->TransparentColor=clBlue;
Canvas->Draw(100,10,gBitmap);
delete  gBitmap;

В начало

Захват изображений с экрана монитора

В примере, описанном ниже, показано использование классов TCanvas и TBitmap для получения изображения с экрана монитора и сохранения его в файле. функция vPurloin() в зависимости от параметра, переданного ей, получает снимок экрана, окна приложения или клиентской части окна приложения (окна без заголовка) и сохраняет их в файл на диске. В принципе, этот пример использует и функции GDI для получение контекстов устройств и, в частности, экрана монитора, но основа, всеже, использование класса TBitmap.

Код функции:

void __fastcall
TForm1::vPurloin(int viI)
{
 //Создаем канву, которую будем использовать
 //для контекста рабочего стола
 TCanvas* tCanvas = new TCanvas;
 //Объект TBitmap также имеет канву
 Graphics::TBitmap*  gBitmap = new Graphics::TBitmap;
 //Размеры областей откуда и куда
 TRect tRectFrom;
 TRect tRectTo;
 //Исходные точки
 tRectFrom.Left=0;
 tRectFrom.Top=0;
 tRectTo.Left=0;
 tRectTo.Top=0;
 switch(viI)
 {
  case  0:
   //Делаем снимок всего рабочего
   //стола Для этого:
   // Получаем его Handle
   tCanvas->Handle = CreateDC("DISPLAY",NULL,NULL,NULL);
   //Устанавливаем размеры TBitmap
   //cоответствующие размеру экрана
   gBitmap->Width = Screen->Width;
   gBitmap->Height = Screen->Height;
   //Соответственно размеры для
   //функции копирования
   tRectFrom.Right=Screen->Width;
   tRectFrom.Bottom=Screen->Height;
   tRectTo.Right=Screen->Width;
   tRectTo.Bottom=Screen->Height;
  break;
  case 1:
   //Делаем снимок только окна приложения
   tCanvas->Handle = GetDC(0);
   //Устанавливаем размеры TBitmap
   //cоответствующие размеру окна
   gBitmap->Width = Width;
   gBitmap->Height = Height;
   //Соответственно размеры для
   //функции копирования
   //BoundsRect - Идентифицирует размер
   //окна приложения на экране
   tRectFrom=BoundsRect;
   Caption=tRectFrom.Left;
   tRectTo.Right=Width;
   tRectTo.Bottom=Height;
  break;
  case 2:
   //Всего окна приложения без заголовка
   //(клиентской области окна
   tCanvas->Handle = GetDC(Handle);
   //Устанавливаем размеры TBitmap cоответствующие
   //размеру клиенской области окна
   gBitmap->Width = ClientWidth;
   gBitmap->Height = ClientHeight;
   //Соответственно размеры для
   //функции копирования
   tRectFrom.Right=ClientWidth;
   tRectFrom.Bottom=ClientHeight;
   tRectTo.Right=ClientWidth;
   tRectTo.Bottom=ClientHeight;
  break;
 }
 //Копируем озображение в TBitmap с одной канвы в другую
 gBitmap->Canvas->CopyRect(tRectTo,tCanvas,tRectFrom);
 //Сохраняем в формате DIB
 gBitmap->SaveToFile("1.bmp");
 //Освобождаем ресурсы, хотя это выполняет само приложение
 delete gBitmap;
 delete tCanvas;
}

В начало

Использование буфера обмена для работы с графикой

Использование метода Assign позволяет проводить обмен данными между совершенно разнородными компонентами, например, компонентом буфера обмена TClipboard и графическим объектом TBitmap. Отметим, что следущий пример может быть повторен для метафайлов и не подходит для иконок, так как буфер обмена не поддерживает формат .ico. О том, как все же можно поместить в буфер обмена иконку (см. Работа с ресурсами в Borland C++ Builder).

Записать изображение в буфер можно оператором:

Clipboard()->Assign(gBitmap);

Прочитать изображение из буфера изображение оператором:

gBitmap->Assign(Clipboard());

Следующий пример деманстрирует возможности этих операторов:

.......
//Обязательно включить эту директиву
#include <Clipbrd.hpp>
......
void __fastcall 
TForm1::Button1Click(TObject *Sender)
{
 //Создаем объект TBitmap
 Graphics::TBitmap*  gBitmap = new Graphics::TBitmap;
 //Загружаем изображение
 gBitmap->LoadFromFile("1.bmp");
 //Копируем в буфер обмена
 Clipboard()->Assign(gBitmap);
 delete  gBitmap;
}
void __fastcall
TForm1::Button2Click(TObject *Sender)
{
 //Создаем объект TBitmap
 Graphics::TBitmap*  gBitmap = new Graphics::TBitmap;
 //Загружаем в него изображение из буфера обмена
 gBitmap->Assign(Clipboard());
 //Рисуем на канве загруженное изобоажение
 Canvas->Draw(10,10,gBitmap);
 delete  gBitmap;
}

Другой, но мало привлекательный метод работы с буфером обмена - SaveToClipboardFormat(). Он создает копию изображения в формате Clipboard - формат, указатель на данные и палитру, возвращаются как параметры функции. Стандартно зарегистрированные форматы: CF_BITMAP для битовых карт и CF_METAFILEPICT для метафайлов. Формат для нового типа графического объекта предварительно должен быть зарегистрирован методом RegisterClipboardFormat().

После применения метода SaveToClipboardFormat() надо передать объекту Clipboard полученные значения параметров.

Пример использования метода SaveToClipboardFormat():

.......
//Обязательно включить эту директиву
#include <Clipbrd.hpp>
......
//В любом обработчике пишем код:
//Определяем параметры функции SaveToClipboardFormat()
THandle   tDataHandle;
HPALETTE  hPalette;
Word      wFormat;
//Создаем два объекта TBitmap, чтобы доказать
//себе, что изображение получено именно из буфера
//хотя можно было воспользоваться методом Clear()
Graphics::TBitmap *gBitmap    = new Graphics::TBitmap();
Graphics::TBitmap *gBitmapNew = new Graphics::TBitmap();
//Загружаем изображение
gBitmap->LoadFromFile("1.bmp");
//Направляем в буфер и получаем параметры изображения
gBitmap->SaveToClipboardFormat(wFormat,
                                 tDataHandle,hPalette);
//Регистрируем формат в буфере обмена
Clipboard()->SetAsHandle(wFormat,tDataHandle);
//Если формат в буфере, соответствует исходному
if(Clipboard()->HasFormat(wFormat))
{
 //Загружаем изображение из буфера
 gBitmapNew->LoadFromClipboardFormat(wFormat,
                                     tDataHandle,hPalette);
 //Проводим отрисовку
 Canvas->Draw(5,5,gBitmapNew);
}else
{
  //Сообщение об ошибке
}
delete gBitmap;
delete gBitmapNew;

В начало

Экономия ресурсов

В этом примере показано освобождение ресурсов изображения на различных уровнях (методы Dormant(), FreeImage(), ReleaseHandle()), кроме того в примере показано как преобразовать изображение в монохромное (свойство Monochrome):

//Создаем объект TBitmap
Graphics::TBitmap*  gBitmap = new Graphics::TBitmap;
//Загружаем изображение в TBitmap
gBitmap->LoadFromFile("1.bmp");
//Освобождение ресурсов GDI занятых TBitmap
gBitmap->Dormant();
//Освобождение памяти, но изображение не удаляется
//пока на него есть ссылка (Handle), хотя его память
//и может быть занята другими объектами приложения
gBitmap->FreeImage();
//Рисуем изображение из TBitmap
Canvas->Draw(10,10,gBitmap);
//Устанавливается монохромный режим для TBitmap
gBitmap->Monochrome = true;
//Можно нарисовать монохромный вариант
Canvas->Draw(150,10,gBitmap);
//Убрать ссылку на изображение - изображение теряется
gBitmap->ReleaseHandle();
//Больше изображение не отображается
Canvas->Draw(300,10,gBitmap);
delete  gBitmap;

Аналогично можно использовать для освобождения ресурсов для графики в формате .ico и .emf.

В начало

Другие методы и свойства TBitmap, TIcon, TMetafile

Из интересных свойств отметим:

  • gBitmap->Handle, gBitmap->Palette - дескрипторы битовой карты и ее палитры.

  • HandleAllocated() - проверяет наличие дескриптора компонента у данного элемента. Если дескриптор имеется, то возвращается true. В отличии от проверки свойства Handle, этот метод не приводит к созданию дескриптора при его отсутствии.

  • ReleaseHandle() и ReleasePalette() - возвращают (обнуляет) дескриптор изображения и палитры соответственно. Следует отметить, что один объект может иметь несколько дескрипторов. При любом внешнем обращении к дескриптору битовой карты и попытке рисовать на ее канве объект получает собственную копию содержимого дескриптора (тоесть совместного использования дескрипторов нет).

  • ReleaseMaskHandle() - освобождает дескриптор маски точечного рисунка. Действие аналогично ReleasePalette.

  • Mask() - конвертирует текущее растровое изображение в одноцветную маску, заменяя TransparentColor белым цветом, остальные черным. Используется когда надо превратить битовую карту в маску для других битовых карт. Для преобразования могут использоваться свойства MaskHandle, и метод ReleaseMaskHandle().

  • Свойство HandleType - может принимать значения bmDIB или bmDDB и позволяет проверить тип изображение (DDB или DIB).

  • Свойство PixelFormat - позволяет определить и изменить формат изображения. Возможные значения - pfDevice, pf1bit, pf4bit, pf8bit, pf15bit, pf16bit, pf24bit, pf32bit, pfCustom. Режим pfDevice соответствует битовой карте DDB. Глубина цвета в 1, 4 и 8 бит на пиксел предусматривает наличие у изображения палитры. Другие режимы хранят значения яркостей точек в каждом из трех основных цветов - красном (R), зеленом (G) и синем (В). Разрядность 15 бит соответствует распределению бит 5-5-5 (RGB555), 16 бит - RGB 565, 24 бит - RGB888. Режим 32 бит похож на 24-битный, но в нем дополнительно добавлен четвертый канал (альфа-канал), содержащий дополнительную информацию о прозрачности каждой точки. Режим pfCustom предназначен для реализации программистом собственных графических конструкций (использовать его целесообразно только в собственных потомках TBitmap).

    Простейший пример предбразования:

     Graphics::TBitmap *gBitmap = new Graphics::TBitmap();
     gBitmap->LoadFromFile("1.bmp");
     //Преобразуем из того, что имели в формат TrueColor
     gBitmap->PixelFormat=pf24bit;
     Canvas->Draw(10,10,gBitmap);
    
  • IgnorePalette - требование игнолировать палитру при значении true, увеличивает скорость работы с изображением, но ведет к потери качества для изображений особенно 16 и 256 цветов.

  • ScanLine[] - обеспечивает индексированный доступ к строкам пикселов растрового изображения. Метод используется только с форматами растрового изображения DIB.

    Byte *ptr,
    //Если "y" - нометр строки, то получить
    //указатель на строку байт линии
    ptr = (Byte *)gBitmap->ScanLine[y];
    

    Внутри строки данные упорядочены в соответствии с форматом (pixelFormat). Для формата pf1bit каждый бит в строке соответствует одному пикселу, для форматов до pf24bit пикселу соответствуют два байта, pf24bit - три байта (по байту на канал), pf32bit - четыре байта.

    Более подробно об использовании метода ScanLine[] в параграфе посвященном повороту изображений далее в этом разделе.

В начало

Класс TImage и работа с изображениями

Визуальный компонент TImage создает на форме контейнер графического изображения (битового образа, пиктограммы или метафайла).

Большинство свойств компонента TImage такиеже как и у многих других компонент (положение изобрыжения на форме, его размеры, помощь, отображение подсказок и т.п.). Среди "не стандартных" свойств, отметим:

  • Picture. Контейнер графики. Окно загрузки файлов изображений открывается кнопкой в графе свойства Picture компонента TImage. Кроме того это свойство имеет методы LoadFromFile(), SaveToFile().

  • AutoSize. Чтобы контейнер изменил свои размеры так, чтобы вместить изображение целиком, устанавливается значение true свойства AutoSize.

  • Stretch. Чтобы исходное изображение растянулось на весь контейнер, задается значение true свойства Stretch.

  • Center - если AutoSize=false, то изображение помещается в центре компонента.

  • IncrementalDisplay - если true, то при загрузке больших файлов они будут показываться по частям по мере загрузки.

  • Transparent - считает цвет одного из угловых пикселей цветом прозрачности (левый нижний).

Отметим, что класс TImage может создаваться и как невизуальный компонент и использовать теже свойства и методы, что и визуальный компонент. и оба они могут использовать канву:

//Визуальный компонент
Image1->Canvas...
//Класс
TImage *tImage;
tImage=new TImage(this);
tImage->Canvas

Рассмотрение вопросов параграфа темы будем вести на примерах, в которых последовательно показывается использование основных свойств и методов компонента и класса TImage. Работа с ресурсами выделена в отдельный раздел (см. Работа с ресурсами в Borland C++ Builder) и здесь опущена.

Кроме того, так как эти классы инкапсулируют в свойстве TPicture классы TBitmap, TIcon и TMetafile, то все, что относится непосредственно к работе с этими классами, более подробно можно посмотреть в предыдущем параграфе. Здесь же основное внимание уделено технологии работе с классами.

В начало

Загрузка и сохранение графики

Методы LoadFromFile() и SaveToFile() объектного свойства Picture служат для динамической загрузки и сохранения файлов изображений с помощью инструкций типа, которые могут быть использованы двояко:

Image1->Picture->LoadFromFile("1.bmp");
Image1->Picture->SaveToFile("2.bmp");
.....
Image1->Picture->LoadFromFile("1.ico");
Image1->Picture->SaveToFile("2.ico");
.....
//Свойство Enhanced показывает, что файл .emf win32
Image1->Picture->Metafile->Enhanced=true;
Image1->Picture->LoadFromFile("1.emf");
Image1->Picture->SaveToFile("2.emf");
.....
Image1->Picture->Bitmap->LoadFromFile("1.bmp");
Image1->Picture->Bitmap->SaveToFile("2.bmp");
.....
Image1->Picture->Icon->LoadFromFile("1.ico");
Image1->Picture->Icon->SaveToFile("2.ico");
.....
//Свойство показывает, что файл .emf win32
Image1->Picture->Metafile->Enhanced=true;
Image1->Picture->Metafile->LoadFromFile("1.emf");
Image1->Picture->Metafile->SaveToFile("2.emf");
.....
//Аналогично для класса
TImage *tImage;
tImage=new TImage(this);
tImage->Picture->LoadFromFile("1.bmp");
tImage->Picture->SaveToFile("2.bmp");
.......
delete tImage;

В начало

Загрузка и отрисовка графики

Отрисовка графики при использовании визуального компонента предельно проста - изображение отображается сразу при загрузке в компонент. При этом можно управлять многими параметрами изображений, например:

Image1->Left=50;
Image1->Top=50;
Image1->Width=200;
Image1->Height=200;
//Устанавливаем прозрачность, по умолчанию tmAuto
Image1->Transparent=true;
Image1->Picture->LoadFromFile("1.bmp"); 

Для отображения графики, загруженной в созданный класс TImage, можно как и ранее воспользоваться функциями Draw() и StretchDraw():

TImage *tImage;
tImage=new TImage(this);
tImage->Picture->LoadFromFile("1.bmp");
tImage->Transparent=true;
Canvas->Draw(100,0,tImage->Picture->Bitmap);
	delete tImage;

Отметим, что масштабирования Bitmap в классе не предусмотрено и это возможно только при отрисовки, например функцией StretchDraw():

TRect tRect(0,0,500,250);
Canvas->StretchDraw(tRect,tImage->Picture->Bitmap);

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

TImage *tImage;
tImage=new TImage(this);
tImage->Picture->Metafile->Enhanced=true;
tImage->Picture->Metafile->LoadFromFile("1.emf");
tImage->Center=true;
tImage->Picture->Metafile->Width=250;
tImage->Picture->Metafile->Height=250;
tImage->Stretch=true;
Canvas->Draw(100,0,tImage->Picture->Metafile);
delete tImage;

Отметим, что класс поддерживает масштабирование для метафайлов.

И для визуальных компонентов:

Image1->Left=0;
Image1->Top=0;
Image1->Width=250;
Image1->Height=250;
Image1->Center=true;
Image1->Stretch=true;
Image1->Picture->Metafile->Enhanced=true;
Image1->Picture->Metafile->LoadFromFile("1.emf");

Обратим внимание на некоторое различие на задание размеров отображаемого рисунка. Такая конструкция не сработает для TImage:

Image1->Picture->Metafile->Width=250;
Image1->Picture->Metafile->Height=250;

И, как и в случае с объектным классом TIcon, не сработает никакой из способов задания размеров для иконки, в том числе и для визуального компонента. Иконка не изменит своих размеров в следующем коде:

//Это работает
Image1->Left=0;
Image1->Top=0;
//Эти операторы - нет
Image1->Width=250;
Image1->Height=250;
Image1->Center=true;
Image1->Stretch=true;
//Отображаем иконку
Image1->Picture->Icon->LoadFromFile("1.ico");

Аналогично и для класса TImage:

 
TImage *tImage;
tImage=new TImage(this);
//Четыре опера не работают
tImage->Picture->Icon->Width=250;
tImage->Picture->Icon->Height=250;
tImage->Center=true;
tImage->Stretch=true;
//Загружаем иконку
tImage->Picture->Icon->LoadFromFile("1.ico");
//Отображаем иконку
Canvas->Draw(0,0,tImage->Picture->Icon);
delete tImage;

Метод CopyRect() также предназначен для отрисовки изображений, переносит указанную область изображения или его часть в канве источника изображения в указанную область данного объекта TCanvas. Копирование производится в режиме, установленном свойством CopyMode канвы, разноообразие которых можно посмотреть в Help Borland C++ Builder.

Следующий код показывает возможность копирования части изображения:

 
//Загружаем  изображение
Image1->Picture->Bitmap->LoadFromFile("1.bmp");
//Определяем размеры областей копирования
TRect tRectFrom(0,0,25,25);
TRect tRectTo(10,10,35,35);
//CopyMode cmSrcCopy - прямое копирование
Canvas->CopyMode=cmSrcCopy;
//Копируем часть изображения
Canvas->CopyRect(tRectTo,Image1->Picture->Bitmap->Canvas,tRectFrom);

Этот метод позволяет и увеличить размер изображения иконки как показано в следующем примере:

//Загружаем  изображение иконки
Image1->Picture->Icon->LoadFromFile("1.ico");
//Рисуем ее на канве
Canvas->Draw(0,0,Image1->Picture->Icon);
//Определяем размеры областей копирования
TRect tRectFrom(0,0,32,32);
//Эта область в два раза больше
TRect tRectTo(50,50,114,114);
//CopyMode cmSrcCopy - прямое копирование
Canvas->CopyMode=cmSrcCopy;
//Копируем иконку в увеличенном виде
Canvas->CopyRect(tRectTo,Canvas,tRectFrom);

В начало

Модификация графики

Следущие примеры показывают возможность выполнить некоторый рисунок на уже загруженном изображении. К сожалению это нельзя сделать не для иконок, не для метафайлов, у которых нет сваойства Canvas.

Для визуального компонента:

Image1->AutoSize=true;
//Загружаем в него изображение
Image1->Picture->Bitmap->LoadFromFile("1.bmp");
//Задаем параметры кисти
Image1->Picture->Bitmap->Canvas->Brush->Color=clYellow;
//Рисуем на изображении круг
Image1->Picture->Bitmap->Canvas->Ellipse(0,0,
                  Image1->Picture->Bitmap->Width,
                   Image1->Picture->Bitmap->Height);

Аналогично для класса:

TImage *tImage;
tImage=new TImage(this);
tImage->Picture->Bitmap->LoadFromFile("1.bmp");
tImage->Picture->Bitmap->Canvas->Brush->Color=clYellow;
tImage->Picture->Bitmap->Canvas->Ellipse(0,0,
                  tImage->Picture->Bitmap->Width,
                  tImage->Picture->Bitmap->Height);
Canvas->Draw(0,0,tImage->Picture->Bitmap);
delete tImage;

В начало

Установка прозрачности

Все сказанное выше равным образом относится и для Timage, поэтому останавливаться на этом не будем. В примерах параграфа "Загрузка и отрисовка изображений" уже использовалось свойство Transparent для TImage. Отметим, что для иконок, если они созданы (например в Tools/Image Editor) как имеющие области прозрачности, установка свойства Transparent в false не поможет.

Пример установки прозрачности для класса TImage:

TImage *tImage;
tImage=new TImage(this);
tImage->Transparent=true;
//Установка цвета левого верхнего
//пиксела в качестве прозрачного
tImage->Picture->Bitmap->TransparentMode=tmAuto;
tImage->Picture->Bitmap->LoadFromFile("1.bmp");
Canvas->Draw(0,0,tImage->Picture->Bitmap);
//Или так
tImage->Picture->Bitmap->TransparentMode=tmFixed;
tImage->Picture->Bitmap->TransparentColor=clRed;
Canvas->Draw(100,0,tImage->Picture->Bitmap);
delete tImage;

Тоже для визуального компонента:

Image1->Transparent=true;
//Установка цвета левого верхнего
//пиксела в качестве прозрачного
Image1->Picture->Bitmap->TransparentMode=tmAuto;
Image1->Picture->Bitmap->LoadFromFile("1.bmp");
//Или сменить цвет прозрачности
Image1->Picture->Bitmap->TransparentMode=tmFixed;
Image1->Picture->Bitmap->TransparentColor=clRed;

В начало

Захват изображений с экрана монитора

Самый простой способ получить изображение экрана монитора это присвоить Handle канвы TImage Handle экрана или окна приложения:

Image1->Width=Screen->Width;
Image1->Height=Screen->Height;
Image1->Canvas->Handle=CreateDC("DISPLAY",NULL,NULL,NULL);
.........
Image1->Width=Width;
Image1->Height=Height;
Image1->Canvas->Handle=GetDC(Handle);

Недостаток этого способа в том, что снимки нельзя масштабировать. Поэтому при необходимости масштабирования можно применить подход описанный для TBitmap, что для TImage выглядит так:

//Создаем канву, которую будем использовать
//для контекста рабочего стола
TCanvas* tCanvas = new TCanvas;
//Размеры областей откуда и куда
TRect tRectFrom;
TRect tRectTo;
//Исходные точки
tRectFrom.Left=0;
tRectFrom.Top=0;
tRectTo.Left=0;
tRectTo.Top=0;
//Делаем снимок всего рабочего
//стола Для этого получаем его Handle
tCanvas->Handle = CreateDC("DISPLAY",NULL,NULL,NULL);
//Устанавливаем размеры TBitmap cоответствующие размеру экрана
Image1->Picture->Bitmap->Width = Screen->Width;
Image1->Picture->Bitmap->Height = Screen->Height;
//Соответственно размеры для функции копирования
tRectFrom.Right=Screen->Width;
tRectFrom.Bottom=Screen->Height;
tRectTo.Right=Screen->Width;
tRectTo.Bottom=Screen->Height;
//Копируем озображение в TBitmap с одной канвы в другую
Image1->Picture->Bitmap->Canvas->CopyRect(tRectTo,tCanvas,tRectFrom);
//Изображение экрана можно сохранить в памяти
Image1->Picture->SaveToFile("a.bmp");
//Масштабируем изображение
Image1->Stretch=true;
delete tCanvas;

Для того, чтобы получить снимок окна приложения в код внесем изменения:

//Клиентская область окна
tCanvas->Handle = GetDC(Handle);
//Устанавливаем размеры TBitmap cоответствующие
//размеру клиенской области окна
Image1->Picture->Bitmap->Width = ClientWidth;
Image1->Picture->Bitmap->Height = ClientHeight;
//Соответственно размеры для функции копирования
tRectFrom.Right=ClientWidth;
tRectFrom.Bottom=ClientHeight;
tRectTo.Right=ClientWidth;
tRectTo.Bottom=ClientHeight;

В начало

Использование буфера обмена для работы с графикой

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

Записать изображение в буфер и прочитать его можно операторами:

Image1->Picture->Bitmap->LoadFromFile("1.bmp");
Clipboard()->Assign(Image1->Picture->Bitmap);
Image1->Picture->Bitmap->Assign(Clipboard());

И пример, использования функции SaveToClipboardFormat(), описание которой приводилось ранее:

//Определяем параметры функции SaveToClipboardFormat()
THandle   tDataHandle;
HPALETTE  hPalette;
Word      wFormat;
//Загружаем изображение в класс TImage
TImage *tImage;
tImage=new TImage(this);
tImage->Picture->Bitmap->LoadFromFile("1.bmp");
//Направляем в буфер и получаем параметры изображения
tImage->Picture->Bitmap->SaveToClipboardFormat(wFormat,
                                               tDataHandle,hPalette);
//Регистрируем формат в буфере обмена
Clipboard()->SetAsHandle(wFormat,tDataHandle);
//Удаляем объект TImage
delete tImage;
//Если формат в буфере, соответствует исходному
if(Clipboard()->HasFormat(wFormat))
{
 //Загружаем изображение из буфера
 Image1->Picture->Bitmap->LoadFromClipboardFormat(wFormat,
                                    tDataHandle,hPalette);
 //Можно провести отрисовку
 Canvas->Draw(5,5,Image1->Picture->Bitmap);
}else
{
 //Сообщение об ошибке
}

В начало

Экономия ресурсов

Этот пример полностью аналогичен, примеру для класса TBitmap:

 
//Загружаем изображение
Image1->Picture->Bitmap->LoadFromFile("1.bmp");
//Освобождение ресурсов GDI
Image1->Picture->Bitmap->Dormant();
//Освобождение памяти, но изображение не удаляется
//пока на него есть ссылка (Handle), хотя его память
//и может быть занята другими объектами приложения
Image1->Picture->Bitmap->FreeImage();
//Рисуем изображение из TBitmap
Canvas->Draw(10,10,Image1->Picture->Bitmap);
//Устанавливается монохромный режим для TBitmap
Image1->Picture->Bitmap->Monochrome = true;
//Можно нарисовать монохромный вариант
Canvas->Draw(150,10,Image1->Picture->Bitmap);
//Убрать ссылку на изображение - изображение теряется
Image1->Picture->Bitmap->ReleaseHandle();
//Больше изображение не отображается
Canvas->Draw(300,10,Image1->Picture->Bitmap);

Аналогично можно использовать для освобождение ресурсов для графики в формате .ico и .emf.

В начало

В начало главы

В начало раздела

Домой



Сайт управляется системой uCoz