Жарков В.А. - Visual C++ 2005, DirectX 9.0c и Microsoft Agent в компьютерной графике, мультимедиа и играх (Листинги книги) - 2005
.pdfЧасть IX. Методология создания, конвертирования и мультипликации изображений на форме
Глава 56. Методика задания, конвертирования и замены изображений
Листинг 56.1. Метод с нашим кодом для вывода фонового изображения.
private: System::Void Form1_Load( System::Object^ sender, System::EventArgs^ e)
{
this->BackgroundImage = Image::FromFile("D:\\MyDocs\\Fig1.jpg");
}
Листинг 56.2. Обработчик щелчка кнопки для вывода фонового изображения.
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
this->BackgroundImage = Image::FromFile("D:\\MyDocs\\Fig5.jpg");
}
Теперь после старта проекта и щелчка кнопки предыдущее фоновое изображение Fig1.jpg (листинг 56.1) заменится новым изображением Fig5.jpg (листинг 56.2), показанным на рис. 56.7. Аналогично можно записать наш код в любой другой метод, например, в обработчик щелчка по любому элементу управления или по форме: в панели Properties (для Form) на вкладке Events дважды щелкаем по имени события Click. Появляется шаблон, который после записи нашего кода принимает такой вид:
private: System::Void Form1_Click( System::Object^ sender, System::EventArgs^ e)
{
this->BackgroundImage = Image::FromFile("D:\\MyDocs\\Bitmap1.jpg");
}
Глава 56. Методика задания, конвертирования и замены изображений |
271 |
Листинг 56.3. Конвертирование, сохранение и вывод изображения.
private: System::Void Form1_Load( System::Object^ sender, System::EventArgs^ e)
{
//Загружаем Fig2_1.jpg в объект myImage класса Image: Image^ myImage =
Image::FromFile("D:\\MyDocs\\Fig2_1.jpg"); //Конвертируем Fig2_1.jpg в (.gif) и сохраняем Save: myImage->Save("D:\\MyDocs\\Fig2_1.gif",
System::Drawing::Imaging::ImageFormat::Gif); //Выводим изображение как фоновое для формы: this->BackgroundImage =
Image::FromFile("D:\\MyDocs\\Fig2_1.gif");
}
Аналогично для конвертирования изображения Fig2_1.gif из формата (.gif), например, в формат (.png) используется код:
Image^ myImage =
Image::FromFile("D:\\MyDocs\\Fig2_1.gif");
myImage->Save("D:\\MyDocs\\Fig2_1.png", System::Drawing::Imaging::ImageFormat::Png);
Аналогично конвертируются изображения из одного формата в другой из перечня поддерживаемых форматов на рис. 56.8.
Теперь в файл Form1.h необходимо написать нашу часть кода. Сначала вверху файла Form1.h подключаем необходимое нам пространство имен:
using namespace stdcli::language; //Для создания массивов.
В любом месте внутри класса Form1 (например, ниже свернутого блока кода) объявляем массив изображений класса Image и глобальные переменные:
//Массив из 8 изображений (индекс 0 не используем): static array<Image^>^ myArrayImages =
gcnew array<Image^>(9);
//Объявляем и инициализируем целочисленные переменные: int static j = 0; int static k = 1;
Листинг 56.4. Метод Form1_Load для загрузки изображений.
private: System::Void Form1_Load( System::Object^ sender, System::EventArgs^ e)
{
//Из графических файлов 8 рисунков формата (.jpg) //заполняем массив myArrayImages: myArrayImages[1] =
272 Жарков В.А. Компьютерная графика, мультимедиа и игры на Visual C++ 2005
Image::FromFile("D:\\MyDocs\\Fig1.jpg"); myArrayImages[2] =
Image::FromFile("D:\\MyDocs\\Fig2.jpg"); myArrayImages[3] =
Image::FromFile("D:\\MyDocs\\Fig3.jpg"); myArrayImages[4] =
Image::FromFile("D:\\MyDocs\\Fig4.jpg"); myArrayImages[5] =
Image::FromFile("D:\\MyDocs\\Fig5.jpg"); myArrayImages[6] =
Image::FromFile("D:\\MyDocs\\Fig6.jpg"); myArrayImages[7] =
Image::FromFile("D:\\MyDocs\\Fig7.jpg"); myArrayImages[8] =
Image::FromFile("D:\\MyDocs\\Fig8.jpg");
}
Аналогично в приложение загружаются другие массивы, если мы хотим использовать чередование серии одних изображений сериями других. Чтобы подключить к работе таймер, дважды щелкаем значок для компонента Timer (ниже формы в режиме проектирования). Появляется файл Form1.h с шаблоном, который после записи нашего кода принимает следующий вид.
Листинг 56.5. Метод для компонента Timer1.
private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e)
{
//Выводим изображение в качестве фонового PictureBox: pictureBox1->BackgroundImage = myArrayImages[j]; //Организовываем цикл для восьми рисунков:
j = j + k; if (j == 8)
{
//От последнего рисунка переходим к первому: k = -8;
}
else if (j == 0)
{
//Задаем первый рисунок для начала цикла: k = 1;
}
}
Глава 57. Методика разработки мультипликации
Листинг 57.1. Массив и глобальные переменные.
//Массив из 6 изображений (индекс 0 используем): static array<Image^>^ myArrayImages =
gcnew array<Image^>(6);
//Объявляем и инициализируем целочисленные переменные: int static j = 0; int static k = 1;
Дважды щелкаем по Form1 в режиме проектирования (или Properties, Events, Load) и в шаблон записываем такой наш код.
Листинг 57.2. Метод Form1_Load для загрузки рисунков.
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e)
{
//Из графических файлов рисунков формата (.bmp) //заполняем массив myArrayImages[6]: myArrayImages[0] =
Image::FromFile("D:\\MyDocs\\" "DeepDrawing_step0.bmp");
myArrayImages[1] = Image::FromFile("D:\\MyDocs\\"
"DeepDrawing_step1.bmp"); myArrayImages[2] =
Image::FromFile("D:\\MyDocs\\" "DeepDrawing_step2.bmp");
myArrayImages[3] = Image::FromFile("D:\\MyDocs\\"
"DeepDrawing_step3.bmp"); myArrayImages[4] =
Image::FromFile("D:\\MyDocs\\" "DeepDrawing_step4.bmp");
myArrayImages[5] = Image::FromFile("D:\\MyDocs\\"
"DeepDrawing_step5.bmp");
}
Напомним, что метод Form1_Load выполняется одновременно с появлением (загрузкой – Load) Form1 на экране монитора. При этом рисунки мультипликации из любой папки загружаются в массив рисунков myArrayImages[N] с любым (заданным нами) количеством элементов N. Отметим, что в этом листинге полный путь распо-
274 Жарков В.А. Компьютерная графика, мультимедиа и игры на Visual C++ 2005
ложения файла каждого рисунка формата (.bmp), начиная от локального диска D, записан на двух строках по правилу переноса на C++.
Аналогично в приложение загружаются другие рисунки в другие массивы рисунков, если мы хотим чередовать мультипликацию из серии одних рисунков сериями других рисунков.
Чтобы подключить к работе таймер, дважды щелкаем значок для компонента Timer (ниже формы в режиме проектирования). Появляется файл Form1.h с шаблоном, который после записи нашего кода принимает следующий вид.
Листинг 57.3. Метод для мультипликации изображений.
private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e)
{
//Создаем объект myGraphics класса Graphics: Graphics^ myGraphics = CreateGraphics();
//Вызываем метод DrawImage, используя перегрузку № 8: myGraphics->DrawImage(myArrayImages[j], -10, -10,
myArrayImages[j]->Width, myArrayImages[j]->Height);
//Высвобождаем ресурсы, выделенные объекту myGraphics: myGraphics->Dispose();
//Организовываем цикл для всех рисунков: j = j + k;
if (j == 5)
{
//От последнего рисунка переходим к первому: k = -5;
}
else if (j == 0)
{
//Задаем первый рисунок для начала цикла: k = 1;
}
}
Листинг 57.4. Метод для элемента управления TrackBar.
private:
System::Void trackBar1_Scroll(System::Object^ sender, System::EventArgs^ e)
{
//Включаем таймер Timer (задаем Enabled равным true): timer1->Enabled = true;
//Устанавливаем свойство Interval таймера Timer
Глава 57. Методика разработки мультипликации |
275 |
//в зависимости от перемещения ползунка Value: timer1->Interval = trackBar1->Value;
}
Согласно разработанной выше методике, чтобы иметь возможность приостановить (и запустить вновь) процесс анимации на любом рисунке при помощи кнопки Stop Animation, дважды щелкаем эту кнопку в режиме проектирования (рис. 57.8). Появляется файл Form1.h с шаблоном, который после записи нашего кода имеет такой вид.
Листинг 57.5. Обработчик щелчка по кнопке Stop Animation.
//Объявляем булеву переменную OffOn
//и задаем ей значение, например, false: bool static OffOn = false;
private:
System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
//Задаем чередование остановки //и возобновления анимации
//после каждого щелчка кнопки Button: if (OffOn == false)
{
//Приостанавливаем анимацию: timer1->Enabled = false;
//Изменяем значение OffOn на противоположное: OffOn = true;
}
else
{
//Возобновляем анимацию: timer1->Enabled = true;
//Изменяем значение OffOn на противоположное: OffOn = false;
}
}
Листинг 57.6. Метод для компонента PrintDocument.
private: System::Void printDocument1_PrintPage( System::Object^ sender, System::Drawing::Printing::PrintPageEventArgs^ e)
{
//Чтобы печатать тот j-й рисунок, который видим: j = j - 1;
276 Жарков В.А. Компьютерная графика, мультимедиа и игры на Visual C++ 2005
//Выводим j-й рисунок, который видим на экране,
//при помощи метода DrawImage, используя перегрузку № 8: e->Graphics->DrawImage(myArrayImages[j], -10, -10, myArrayImages[j]->Width,
myArrayImages[j]->Height);
}
Теперь дважды щелкаем кнопку Print (рис. 57.8). Открывается файл Form1.h с шаблоном, в который записываем код для этого шаблона из приведенного выше параграфа “Методика печати изображения на принтере”; для цельности изложения приведем этот код еще раз в данной части книги.
Листинг 57.7. Код для печати изображения.
private:
System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
//Передаем объекту printDialog1 информацию об объекте
//printDocument1 при помощи свойства Document: printDialog1->Document = printDocument1;
//Выводим стандартную панель Print при помощи метода //ShowDialog() для задания параметров печати
//и печатаем документ при помощи метода Print(): printDialog1->ShowDialog(); printDocument1->Print();
}
Глава 58. Разработка мультипликации при помощи списка рисунков
Листинг 58.1. Метод для компонента Timer.
//Объявляем глобальную переменную currentImage //для номера текущего рисунка и приравниваем нулю: int static currentImage = 0;
private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e)
{
//Последовательно выводим рисунки: if(imageList1->Images->Empty != true)
{
//Центрируем рисунок внутри рамки PictureBox1: pictureBox1->SizeMode =
PictureBoxSizeMode::CenterImage; //Выводим рисунок с номером 'currentImage' : pictureBox1->Image =
imageList1->Images[currentImage]; //Организовываем цикл по индексу 'currentImage' : currentImage = currentImage + 1;
if (currentImage == imageList1->Images->Count) currentImage = 0;
}
}
Листинг 58.2. Метод для компонента PrintDocument.
private: System::Void printDocument1_PrintPage( System::Object^ sender, System::Drawing::Printing::PrintPageEventArgs^ e)
{
//Выводим рисунок, который видим на экране
//в рамке PictureBox, при помощи метода DrawImage: e->Graphics->DrawImage(pictureBox1->Image, 0, 0);
}
Глава 59. Методика управления цветом изображения
Листинг 59.1. Метод для вывода двух прямоугольников, заполненных цветом.
private:
System::Void pictureBox1_Paint(System::Object^ sender, System::Windows::Forms::PaintEventArgs^ e)
{
//Создаем изображение первого прямоугольника, //заполненного серым цветом:
Bitmap^ myBitmap = gcnew Bitmap(150, 150, PixelFormat::Format32bppArgb);
Graphics^ g = Graphics::FromImage(myBitmap); g->FillRectangle(gcnew SolidBrush(Color::FromArgb(255,
128, 128, 128)), 0, 0, 150, 150); myBitmap->Save("Rectangle1.jpg"); //Открываем файл изображения и //рисуем это первое изображение на экране:
Image^ myImage = Image::FromFile("Rectangle1.jpg"); e->Graphics->DrawImage(myImage, 20, 20);
//Создаем и инициализируем
//матрицу цвета myColorMatrix класса ColorMatrix: ColorMatrix^ myColorMatrix = gcnew ColorMatrix(); myColorMatrix->Matrix00 = 1.7F; // Red
myColorMatrix->Matrix11 = 1; |
// Green |
myColorMatrix->Matrix22 = 1; |
// Blue |
myColorMatrix->Matrix33 = 1; |
// alpha |
myColorMatrix->Matrix44 = 1; |
// w |
//Создаем объект myImageAttributes //класса ImageAttributes: ImageAttributes^ myImageAttributes =
gcnew ImageAttributes(); //Устанавливаем матрицу цвета myColorMatrix //в качестве текущей цветовой модели:
myImageAttributes->SetColorMatrix(myColorMatrix); //Создаем второй прямоугольник:
Rectangle myRectangle2(200, 20, 200, 200); //Рисуем на экране второй прямоугольник,
//заполненный при помощи матрицы цвета myColorMatrix: e->Graphics->DrawImage(myImage, myRectangle2, 0, 0,
200, 200, GraphicsUnit::Pixel, myImageAttributes);
}
Глава 59. Методика управления цветом изображения |
279 |
Листинг 59.2. Объявление и инициализация исходных данных.
//Объявляем и инициализируем исходные данные: static float Alpha = 0.1F;
float static Step_of_Color = 0.2F;
static ColorMatrix^ myColorMatrix = gcnew ColorMatrix(); static ImageAttributes^ myImageAttributes =
gcnew ImageAttributes(); static Rectangle myRectangle; //Объявляем матрицу myArray:
static array<float,2>^ myArray = gcnew array<float,2>(5,5); //Присваиваем двум объектам myImage1 и myImage2 //изображения двух обложек книг при помощи метода FromFile //и пути расположения файлов с этими изображениями:
static Image^ myImage1 = Image:: FromFile("D:/MyDocs/Fig1.jpg"); static Image^ myImage2 = Image:: FromFile("D:/MyDocs/Fig2.jpg");
//Создаем объект myRandom класса Random //для генерирования случайных чисел: static Random^ myRandom = gcnew Random();
Напомним, что в этом листинге 59.2 два имеющихся у нас рисунка из любой папки загружаются в объекты myImage1, myImage1 класса System.Drawing.Image.
Записан полный путь расположения файла каждого рисунка формата (.jpg), начиная от локального диска D. Аналогично в приложение загружаются другие рисунки, если мы хотим чередовать мультипликацию цветов различных рисунков.
Дважды щелкаем по форме Form1 в режиме проектирования и в появившийся шаблон записываем наш код, после чего метод принимает такой вид.
Листинг 59.3. Метод Form1_Load для Form1.
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e)
{
//Инициализируем матрицу myArray. //Сначала все элементы матрицы //с индексами "i" и "j" обнуляем: for(int i=0; i<5; ++i)
for(int j=0; j<5; ++j) myArray[i,j] = 0;
//Затем присваиваем значения диагональным элементам: myArray[0,0] = 1;
myArray[1,1] = 1; myArray[2,2] = 1;