{$R-}で範囲チェックさせない!
Delphiで、画像をグレースケール変換するプログラムを作成。実行すると、
プログラムのコードは、次の通り。
Image1に表示した画像をグレースケールに変換してImage2に表示するというモノ。
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, Jpeg,
Vcl.ComCtrls;
type
TForm1 = class(TForm)
Image1: TImage;
Image2: TImage;
Button1: TButton;
StatusBar1: TStatusBar;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function CreateGrayScalePalette(Tone:Byte): HPALETTE;
var
Palette: ^TLogPalette;
i: Integer;
begin
GetMem(Palette, SizeOf(TLogPalette) + SizeOf(TPaletteEntry) * Tone );
Palette^.palNumEntries:=Tone+1;
Palette^.palVersion:=$0300;
for i := 0 to Tone - 1 do begin
Palette^.palPalEntry[i].peRed:= Tone - i;
Palette^.palPalEntry[i].peGreen:= Tone - i;
Palette^.palPalEntry[i].peBlue:= Tone - i;
Palette^.palPalEntry[i].peFlags:= 0;
end;
Result:=CreatePalette(Palette^);
FreeMem(Palette);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
X, Y: Integer;
Bmp: TBitmap;
P: PByte;
begin
Bmp := TBitmap.Create;
try
Bmp.Assign(Image1.Picture.Bitmap);
Bmp.PixelFormat := pf8bit;
Bmp.Palette := CreateGrayScalePalette(255);
Image2.Picture.Bitmap := Bmp;
finally
Bmp.Free;
end;
Image2.Width:=Image2.Picture.Bitmap.Width;
Image2.Height:=Image2.Picture.Bitmap.Height;
Image2.Visible:=True;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
jpg: TJPEGImage;
begin
StatusBar1.SimplePanel:=true;
// TJPEGImageオブジェクトをインスタンス化
jpg := TJPEGImage.Create;
try
// Jpegファイル読み込み
jpg.LoadFromFile('Image.jpg');
// Image1に割り当てる
Image1.Picture.Bitmap.Assign(jpg);
Image1.Width:=Image1.Picture.Bitmap.Width;
Image1.Height:=Image1.Picture.Bitmap.Height;
//StatusBar1.SimpleText:=IntToStr(Image1.Width)+'/'+IntToStr(Image1.Height);
finally
// TJPEGImageオブジェクトを破棄
jpg.Free;
end;
end;
end.
グレースケール変換実行のボタン(Button1)をクリックすると・・・
このButton1Click手続き内で呼び出しているCreateGrayScalePalette関数でエラーが発生。
ブレークして確認すると、エラーになるのはココ。
でも、なんでエラーになるのか、わからない・・・
Google先生に訊くと、次のような情報を発見。
https://qiita.com/pik/items/25276e49fb131425db07
早速、範囲チェックさせないコンパイラ指令 {$R-} を追加。
ナニがどうして、そうなるのか?
原因も、理由も、皆目わからないけれど・・・
範囲チェックエラーは出なくなりました!
範囲チェックを実行しないというコンパイラ指令 {$R-} は知りませんでした。
同じ理由で困ってる方もいるかもしれないと思い、記録だけUpしました。
なお、画像のグレースケール化にあたっては、次のWebサイト様にあった情報を使わせていただきました。24bitのフルカラー画像を256階調のモノクロ画像に変換(グレースケール変換)する処理を行う際に役立つ情報が、そのアルゴリズムも含めて、多数紹介されています。
http://rakasaka.fc2web.com/delphi/grayscale.html
また、上のWebサイト様で紹介されている配列要素を動的に確保する必要のない、Delphiが独自に定義しているTMaxLogPalette構造体を使用したCreateGrayScalePalette関数を利用した場合は、範囲チェックエラーは発生しませんでした。
お願いとお断り
このサイトの内容を利用される場合は、自己責任でお願いします。ここに記載した内容を利用した結果、利用者および第三者に損害が発生したとしても、このサイトの管理者は一切責任を負えません。予め、ご了承ください。