前回に引き続き、ScanLineを使った画像処理です。
今回は、応用として白黒のグレースケールに変換します。
グレースケールに変換するには
Gray = ( B * 0.114478 + G * 0.586611 + R * 0.298912 )
という変換式があります。
R=G=B=Grayというように同じ値を設定してやればグレースケールになるのです。
↑フルカラーネコがグレースケールネコに....
という訳で、前回と同様にフォームにTImageを貼り付けて、実行用に読込ボタンと変換ボタンを作ります。
<Unit1.h>
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE 管理のコンポーネント
TImage *Image1;
TButton *LoadBtn;
TButton *ConvertBtn;
void __fastcall LoadBtnClick(TObject *Sender);
void __fastcall ConvertBtnClick(TObject *Sender);
private: // ユーザー宣言
public: // ユーザー宣言
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
<Unit1.cpp>
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::LoadBtnClick(TObject *Sender)
{
// ビットマップを読み込んで表示
Image1->Picture->LoadFromFile("neko.bmp");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ConvertBtnClick(TObject *Sender)
{
// Image1に画像を読み込んでなければ終了
if( Image1->Picture->Bitmap == NULL ) return;
// TBitmapオブジェクトを作成
Graphics::TBitmap *BM = new Graphics::TBitmap;
// ビットマップをTImageから読み込み
BM->Assign(Image1->Picture);
// 画像を1pixelずつ走査していきます
for( int y=0; y<BM->Height; y++ ){
// ScanLineで1行分まとめて取得
Byte *Line = (Byte*)BM->ScanLine[y];
int i=0;
for( int x=0; x<BM->Width; x++ ){
Byte b = Line[i]; // B
Byte g = Line[i+1]; // G
Byte r = Line[i+2]; // R
// グレースケールの変換式
Byte gray = b*0.11 + g*0.59 + r*0.30;
Line[i] = gray; // それぞれに同じ値を設定
Line[i+1] = gray;
Line[i+2] = gray;
i+=3;
}
}
Image1->Picture->Assign(BM); // Image1にコピー
delete BM; // オブジェクト解放
}
//---------------------------------------------------------------------------
ちなみに、この変換式を使わなくても
R,G,Bそれぞれに同じ値を入れてやれば、とりあえずは白黒になりますので。
ちょっと明るくしたい時や暗くしたい時など、少し値を変えてやれば良いのです。