#1 TImage上でのマウスドラッグを処理して矩形領域を指定
の続きです。プロトタイプを動かしてみましょう。

ここで”Open”。

こうたどって前回の”frame0.jpg”を選択すると、

こうなるので、画像上でマウスをドラッグします。

左上で左クリックして、クリックしたまま右下までドラッグします。でボタンを離す。その状態が上図で、”AddRect”をクリックすると、

これでRect(矩形領域)が切り取れましたので、これで良ければ”Save”。

セーブされたファイルが上図です。プログラムを示しましょう。まずフォームは、

TImagex2,TButtonx3,TOpenDialogx1を上図のように配置。Unit1.hは、
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
#include <Vcl.Dialogs.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE で管理されるコンポーネント
TImage *Image1;
TButton *Open;
TOpenDialog *OpenDialog1;
TButton *AddRect;
TImage *Image2;
TButton *Save;
void __fastcall FormDestroy(TObject *Sender);
void __fastcall Image1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift,
int X, int Y);
void __fastcall Image1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y);
void __fastcall Image1MouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift,
int X, int Y);
void __fastcall FormPaint(TObject *Sender);
void __fastcall OpenClick(TObject *Sender);
void __fastcall AddRectClick(TObject *Sender);
void __fastcall SaveClick(TObject *Sender);
private: // ユーザー宣言
bool FDrawing; // ドラッグ中かどうかのフラグ
TPoint FStartPos; // マウスを押し下げた初期座標
TPoint FLastPos; // 直前のマウス座標(線を消す用)
TPoint FEndPos;
TBitmap *FBkBmp; // 背景画像を一時保存するビットマップ
public: // ユーザー宣言
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endifUnit1.cppは、
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <jpeg.hpp>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
int width;
int height;
int vheight;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
void LoadJpegFile(const AnsiString & Src,
Graphics::TBitmap * Bitmap)
{
TJPEGImage * Jpeg = new TJPEGImage();
Jpeg->Performance = jpBestQuality;
Jpeg->PixelFormat = jf24Bit;
Jpeg->Grayscale = false;
Jpeg->LoadFromFile(Src);
Bitmap->HandleType = bmDIB;
Bitmap->PixelFormat = pf32bit;
Bitmap->Width = Jpeg->Width;
width = Jpeg->Width;
Bitmap->Height = Jpeg->Height;
height = Jpeg->Height;
Bitmap->Canvas->Draw(0,0,Jpeg);
vheight = 640* height / width ;
delete Jpeg;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
delete FBkBmp;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Image1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift,
int X, int Y)
{
if (Button == mbLeft) // 左クリックのみ対象
{
FDrawing = true;
FStartPos = Point(X, Y);
FLastPos = Point(X, Y);
// 現在の Image1 の状態(背景)を FBkBmp にコピーして保存
FBkBmp->Assign(Image1->Picture->Bitmap);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Image1MouseMove(TObject *Sender, TShiftState Shift, int X,
int Y)
{
if (FDrawing)
{
// 毎回バックアップから背景を書き戻す(古いドラッグ枠を消すため)
Image1->Picture->Bitmap->Assign(FBkBmp);
// 描画設定
Image1->Canvas->Pen->Color = clRed;
Image1->Canvas->Pen->Width = 1;
Image1->Canvas->Brush->Style = bsClear; // 中は透明
// 開始位置から現在のカーソル位置まで四角形を描画
Image1->Canvas->Rectangle(FStartPos.x, FStartPos.y, X, Y);
// 画面更新
FEndPos.x = X;
FEndPos.y = Y;
Image1->Refresh();
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Image1MouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift,
int X, int Y)
{
if (Button == mbLeft && FDrawing)
{
FDrawing = false; // ドラッグ終了
// 最後に確定した図形を描画
Image1->Canvas->Pen->Color = clRed;
Image1->Canvas->Pen->Width = 1;
Image1->Canvas->Brush->Style = bsClear;
Image1->Canvas->Rectangle(FStartPos.x, FStartPos.y, X, Y);
Image1->Refresh();
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
//Graphics::TBitmap * Bitmap = new Graphics::TBitmap();
//LoadJpegFile("IMG_0201.JPG",Bitmap);
//Image1->Canvas->Draw(0,0,Bitmap);
//delete Bitmap;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OpenClick(TObject *Sender)
{
if( OpenDialog1->Execute()){
FDrawing = false;
FBkBmp = new TBitmap();
LoadJpegFile(OpenDialog1->FileName,FBkBmp);
//Image1->Canvas->Draw(0,0,FBkBmp);
TRect dest = {0,0,640,vheight};
Image1->Height = vheight;
Image1->Width = 640;
//Image1->Canvas->Draw(dest,FBkBmp);
Image1->Canvas->StretchDraw(dest,FBkBmp);
//Canvas->StretchDraw()
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::AddRectClick(TObject *Sender)
{
TRect area = { FStartPos.X+1,FStartPos.Y+1,FEndPos.X-1,FEndPos.Y-1};
int width2 = area.Width();
int height2 = area.Height();
Image2->Width = width2;
Image2->Height = height2;
TRect dst = {0,0,Image2->Width,Image2->Height};
Image2->Canvas->CopyRect(dst, Image1->Canvas, area);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SaveClick(TObject *Sender)
{
Image2->Picture->SaveToFile("output.png");
}
//---------------------------------------------------------------------------ポイントは、TImage上のイベント処理とjpgを直接Loadしないで、一旦TBitmapで受けてから描画することです。そうしないとTBitmapとImage1->Canvasが結びつかず、実行時エラーになります。そこは、
void LoadJpegFile(const AnsiString & Src,
Graphics::TBitmap * Bitmap)
{
TJPEGImage * Jpeg = new TJPEGImage();
Jpeg->Performance = jpBestQuality;
Jpeg->PixelFormat = jf24Bit;
Jpeg->Grayscale = false;
Jpeg->LoadFromFile(Src);
Bitmap->HandleType = bmDIB;
Bitmap->PixelFormat = pf32bit;
Bitmap->Width = Jpeg->Width;
width = Jpeg->Width;
Bitmap->Height = Jpeg->Height;
height = Jpeg->Height;
Bitmap->Canvas->Draw(0,0,Jpeg);
vheight = 640* height / width ;
delete Jpeg;
}
ですが、まわりくどいですね。このBitmapを
void __fastcall TForm1::OpenClick(TObject *Sender)
{
if( OpenDialog1->Execute()){
FDrawing = false;
FBkBmp = new TBitmap();
LoadJpegFile(OpenDialog1->FileName,FBkBmp);
//Image1->Canvas->Draw(0,0,FBkBmp);
TRect dest = {0,0,640,vheight};
Image1->Height = vheight;
Image1->Width = 640;
//Image1->Canvas->Draw(dest,FBkBmp);
Image1->Canvas->StretchDraw(dest,FBkBmp);
//Canvas->StretchDraw()
}
}表示します。TImage上のmouse_down,mouse_move,mouse_upを処理して矩形を描いています。



コメント