БлогNot. Visual C++: преобразуем рисунок в PictureBox

Visual C++: преобразуем рисунок в PictureBox

Стандартная компонента PictureBox - удобная "рамка" для рисунка, куда его очень легко загрузить:

openFileDialog1->ShowDialog();
if (openFileDialog1->FileName != nullptr) 
 this->pictureBox1->ImageLocation = this->openFileDialog1->FileName;

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

В дальнейшем обращаться к рисунку можно через свойство Image, а свойство SizeMode управляет режимом вывода рисунка, покрывая почти все типовые потребности:

  • значение Normal - вывод рисунка по левому верхнему углу контейнера с обрезанием;
  • значение StretchImage - вписать изображение в компонент;
  • значение AutoSize - компонент примет размеры изображения;
  • значение CenterImage - центрировать, не меняя размеры (это может обрезать рисунок);
  • значение Zoom - пропорционально масштабировать по размерам компонента (пространство имен PictureBoxSizeMode).

Не хватает, разве что, возможности стандартной прокрутки загруженного изображения, но и это легко решается: достаточно разместить PictureBox на элементе Panel с установленным свойством AutoScroll = true и при этом для PictureBox указать SizeMode = AutoSize. После этого можно загрузить рисунок кодом вида

Image ^ Img = gcnew Bitmap(openFileDialog1->FileName);
pictureBox1->Image = Img;

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

Однако, у новичков часто вызывают затруднения преобразования над рисунком, загруженным в pictureBox, между тем, они также несложны, выполним примеры для основных из них.

1. Поворот и отражение изображений
Bitmap^ bitmap1 = gcnew Bitmap (pictureBox1->Image);
if ( bitmap1 != nullptr )  {
 bitmap1->RotateFlip( RotateFlipType::Rotate180FlipY );
 pictureBox1->Image = bitmap1;
}

В этом коде выведенный в настроенный как выше PictureBox рисунок отражается относительно оси 0Y и выводится обратно в компонент. Почитав о RotateFlip, легко добиться других поворотов и отражений.

2. Масштабирование изображения или его части.

Код ниже показывает, как можно программно уменьшить загруженное в компоненту PictureBox изображение в 2 раза и показать в том же pictureBox1, что получилось:

Bitmap^ bitmap1 = gcnew Bitmap (pictureBox1->Image); //взяли рисунок из компоненты
Graphics ^ Gr1 = Graphics::FromImage(bitmap1); //получили поверхность рисования из исходного рисунка
Bitmap^ bitmap2 = gcnew Bitmap (bitmap1->Width/2, bitmap1->Height/2, Gr1); 
 //сделали вдвое меньший рисунок с тем же разрешением
Graphics ^ Gr2 = Graphics::FromImage(bitmap2); //получили поверхность рисования из меньшего рисунка
Rectangle compressionRectangle = Rectangle(0, 0, bitmap1->Width/2, bitmap1->Height/2); 
 //определили масштабирующий прямоугольник
Gr2->DrawImage(bitmap1, compressionRectangle); 
 //отрисовали на поверхности второго рисунка первый со сжатием
Pen ^ MyPen = gcnew Pen(Color::Red); //на измененном рисунке можно что-то подрисовать
Gr2->DrawRectangle(MyPen, 0, 0, bitmap2->Width-1, bitmap2->Height-1); 
 //например, сделать красную рамку :)
pictureBox1->Image = bitmap2; //назначили второй рисунок компоненте
pictureBox1->Size = bitmap2->Size; //поставили размер компоненты по размерам нового рисунка
this->ClientSize = pictureBox1->Size; //...и такой же размер клиентской части формы

Изменённый рисунок можно сохранить стандартными средствами:

Bitmap ^bitmap1 = gcnew Bitmap(pictureBox1->Image);
 try {
  bitmap1->Save ("my.jpg"); 
 } 
 catch (Exception^ e) {
  MessageBox::Show(e->Message + "\nНе удалось сохранить файл", "Ошибка",MessageBoxButtons::OK, MessageBoxIcon::Exclamation);
  return;
 }

Если изменённый файл "не хочет переписываться" - применяйте решение из этой заметки.

3. Изменение цвета на изображении

На форму добавлен стандартный colorDialog и выбранный в нём цвет ставится как прозрачный.

Bitmap^ bitmap1 = gcnew Bitmap (pictureBox1->Image);
if ( colorDialog1->ShowDialog() == ::System::Windows::Forms::