鮮やかさのアップダウン

 鮮やかさのアップダウンを行うプログラムです。
RGBtoHSV、 あるいは、RGBtoYSH 変換、逆変換を利用して、彩度を変更する方法もありますが、此処では単に鮮やかさ度だけを変更するプログラムを取り上げました。
RGBtoHSV、RGBtoYSH 変換、逆変換を利用した場合、彩度を大きくしても、RGBの最大値が、明度で制限されるため、鮮やかさがあまり上がらない場合があります。
此処での方法の場合、制限がない為、鮮やかさをかなり変化させることが出来ます。

計算は、意外と単純で、

鮮やかさ計算
 各列と各行の鮮やかさ係数の合計が 1 になるように、計算します。

鮮やかさ係数は、 1 で変化なし、 1 より大きくすれば、鮮やかさが上がり、1 より小さくすれば下がります。
鮮やかさ係数を 0.333 (1/3) に設定すると、RGB 三色平均のグレー画像となり、それより小さくすると、補色になります。

画像サンプル

 RGBtoHSV、RGBtoYSHの 変換、逆変換を使用した場合は、彩度係数をゼロにするとグレーになり、マイナスの値にすると補色になります。

サンプルプログラム

// Saturation
// 鮮やかさの変更
unit Saturation_Main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.ExtDlgs, system.Types,
  system.Math, system.UITypes;

type
  TForm1 = class(TForm)
    FileOpen: TButton;
    OpenPictureDialog1: TOpenPictureDialog;
    ScrollBox1: TScrollBox;
    Image2: TImage;
    ScrollBox2: TScrollBox;
    Image1: TImage;
    SaturationBtn: TButton;
    LabeledEdit1: TLabeledEdit;
    SavePictureDialog1: TSavePictureDialog;
    FileeSaveBtn: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FileOpenClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure SaturationBtnClick(Sender: TObject);
    procedure FileeSaveBtnClick(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type
  TPrgbarry = array[0..0] of Trgbtriple;      // 24ビットカラーレコード 32ビット用はTRGBQuadArray
  Prgbarray = ^TPrgbarry;                     // ポインター
                                              // 配列のポインターが必要なだけなので、長さは1 [0..0]で問題ありません。
const
// ファイル拡張子設定
  OpenFileFilter =
    '画像ファイル|*.png;*.jpg;*.gif;*.bmp;*.tif;*.ico;*.wdp'+
    '|*.png|*.png' +
    '|*.jpg|*.jpg' +
    '|*.gif|*.gif' +
    '|*.bmp|*.bmp' +
    '|*.tif|*.tif' +
    '|*.ico|*.ico' +
    '|*.wdp|*.wdp';

  SaveFileFilter =
    '画像ファイル|*.png;*.jpg;*.gif;*.bmp;*.tif;*.wdp' +
    '|*.png|*.png' +
    '|*.jpg|*.jpg' +
    '|*.gif|*.gif' +
    '|*.bmp|*.bmp' +
    '|*.tif|*.tif' +
    '|*.wdp|*.wdp';

// 必要変数の宣言
var
  InBitmap        : TBitmap;                  // ビットマップ
  OutBitmap       : TBitmap;
  GHeight, GWidth : integer;                  // ソース画像サイズ

//***************************************************************************
// 鮮やかさの調整
// R = Rin * sat + Gin * (1 - sat) / 2 + Bin * (1 - sat) / 2     係数合計 1
// G = Rin * (1 - sat) / 2 + Gin * sat + Bin * (1 - sat) / 2     係数合計 1
// B = Rin * (1 - sat) / 2 + Gin * (1 - sat) / 2 + Bin * sat     係数合計 1
//     係数合計 1           係数合計 1          係数合計 1
// 行及び列の調整係数の合計が1になるように設定します
//***************************************************************************
procedure TForm1.SaturationBtnClick(Sender: TObject);
var
  X, Y          : Integer;
  Pin, Pout     : Prgbarray;
  Rin, Gin, Bin : Smallint;
  R, G, B       : Smallint;
  sat, mst      : Double;             // 華やかさ調整係数
begin
  Val(LabeledEdit1.Text, sat, X);     // 鮮やかさ係数
  if X <> 0 then begin
    Application.MessageBox('入力値は数値ではありません','鮮やかさ係数',0);
    exit;
  end;
  mst := (1 - sat) / 2;                  // 補正係数計算
  for Y := 0 to GHeight - 1 do begin
    Pin  := InBitmap.ScanLine[Y];
    Pout := OutBitmap.ScanLine[Y];
    for X := 0 to GWidth - 1 do begin
      Bin := pin[X].rgbtBlue;
      Gin := pin[X].rgbtGreen;
      Rin := pin[X].rgbtRed;
      B := Round(Bin * sat + Gin * mst + Rin * mst);
      G := Round(Bin * mst + Gin * sat + Rin * mst);
      R := Round(Bin * mst + Gin * mst + Rin * sat);
      if R < 0 then R := 0;
      if G < 0 then G := 0;
      if B < 0 then B := 0;
      if R > 255 then R := 255;
      if G > 255 then G := 255;
      if B > 255 then B := 255;
      Pout[X].rgbtBlue  := B;
      Pout[X].rgbtGreen := G;
      Pout[X].rgbtRed   := R;
    end;
  end;
  image2.Picture.Bitmap := OutBitmap;                    // 画像表示
  FileeSaveBtn.Enabled  := True;
end;

//************************************************************
// ファイルのオープン WIC がファイルの種類が多いので使用
//************************************************************
procedure TForm1.FileOpenClick(Sender: TObject);
var
  WIC         : TWICImage;
  InFilename  : String;
begin
  OpenPictureDialog1.Filter := OpenFileFilter;                // ファイルオープンフィルターの設定
  if OpenPictureDialog1.Execute then                          // ファイルが指定されたら
    begin
      WIC := TWICImage.Create;                                // TWICImageの生成
      try
        InFilename := OpenPictureDialog1.FileName;            // ファイル名の取得
        WIC.LoadFromFile(InFilename);                         // 画像の読み込み
        GHeight := WIC.Height;                                // 画像高さ取得
        GWidth  := WIC.Width;                                 // 画像幅取得
        InBitmap.Width    := GWidth;
        InBitmap.Height   := GHeight;
        InBitmap.Canvas.Draw(0, 0, WIC);                      // DrawでInBitmapに入力画像設定フォーマット24ビットに変換されます
        OutBitmap.Width   := GWidth;                          // 出力画像幅
        OutBitmap.Height  := GHeight;                         // 出力画像高さ
        image1.Picture.Bitmap := InBitmap;                    // 画像表示
      finally
        WIC.Free;                                             // TWICImage 解放
      end;
    end
    else Exit;
  SaturationBtn.Enabled := True;
end;

//*************************************************************************
// TWICImage を使用してファイル保存
// XE3, XE4 では、メモリーリークが発生します
//*************************************************************************
procedure TForm1.FileeSaveBtnClick(Sender: TObject);
var
  WIC     : TWicImage;
  WICF    : TWicImageFormat;

  Fname   : String;
  ExeStr  : String;
  FnameTop: String;
  Findex  : integer;

  function WFormatSet: Boolean;
  begin
    Result := false;
    ExeStr := LowerCase(ExeStr);
    if ExeStr = '.jpg'  then  begin WICF := Wifjpeg; Result := True; end;
    if ExeStr = '.jpeg' then  begin WICF := Wifjpeg; Result := True; end;
    if ExeStr = '.tif'  then  begin WICF := Wiftiff; Result := True; end;
    if ExeStr = '.tiff' then  begin WICF := Wiftiff; Result := True; end;
    if ExeStr = '.png'  then  begin WICF := Wifpng;  Result := True; end;
    if ExeStr = '.gif'  then  begin WICF := Wifgif;  Result := True; end;
    if ExeStr = '.bmp'  then  begin WICF := Wifbmp;  Result := True; end;
    if ExeStr = '.wdp'  then  begin WICF := WifWMPhoto; Result := True; end;
    if ExeStr = '.hdp'  then  begin WICF := WifWMPhoto; Result := True; end;
  end;

begin
  SavePictureDialog1.Filter := SaveFileFilter;                             // ファイルセーブフィルターの設定
  if not SavePictureDialog1.Execute then exit;                             // ファイル名が設定されていなかったらここまで
  ExeStr := ExtractFileExt(SavePictureDialog1.FileName);
  if ExeStr = '' then begin
    Findex := SavePictureDialog1.FilterIndex;                              // FilterIndexによる拡張子の設定
    case Findex of
      1, 3 : Fname := ChangeFileExt(SavePictureDialog1.FileName,'.jpg');   // 拡張子の設定
         2 : Fname := ChangeFileExt(SavePictureDialog1.FileName,'.png');
         4 : Fname := ChangeFileExt(SavePictureDialog1.FileName,'.gif');
         5 : Fname := ChangeFileExt(SavePictureDialog1.FileName,'.bmp');
         6 : Fname := ChangeFileExt(SavePictureDialog1.FileName,'.tif');
         7 : Fname := ChangeFileExt(SavePictureDialog1.FileName,'.wdp');
    end;
  end
  else
    Fname := SavePictureDialog1.FileName;                                  // 拡張子があったら
  ExeStr := ExtractFileExt(Fname);
  if not WFormatSet then begin
    application.MessageBox('ファイルの拡張子が間違っています。','注意', 0);
    exit;
  end;
  FnameTop := ExtractFileName(Fname);
  if Length(FnameTop) = Length(ExeStr) then begin
    application.MessageBox('ファイル名がありません。','注意', 0);
    exit;
  end;

  if FileExists(Fname) then
    if MessageDlg('既に同じ名前のファイルがあります上書きしますか ' + ExtractFileName(Fname) + '?',
                                                      mtConfirmation, [mbYes, mbNo], 0, mbNo) = IDNo then exit;

  WIC := TWicImage.Create;
  try
    WIC.Assign(OutBitmap);
    WIC.ImageFormat := WICF;
    WIC.SaveTofile(Fname);                 // XE3,XE4 ではメモリーリークが発生します。
  finally                                  // アンシャープマスキングを参照して下さい。
    WIC.Free;
  end;
end;

//*********************
// 初期設定
//*********************
procedure TForm1.FormCreate(Sender: TObject);
begin
  Top := (Screen.Height - Height) div 2;                      // 表示位置設定
  Left := (Screen.Width - Width) div 2;
  InBitmap      := TBitmap.Create;                            // 入力画像用
  OutBitmap     := TBitmap.Create;                            // 出力画像用
  InBitmap.PixelFormat    := pf24bit;                         // 24ビットカラーに設定
  OutBitmap.PixelFormat   := pf24bit;                         // 24ビットカラーに設定
  SaturationBtn.Enabled := False;
  FileeSaveBtn.Enabled  := False;
end;

//**********************
// ビットマップの解法
//**********************
procedure TForm1.FormDestroy(Sender: TObject);
begin
  InBitmap.Free;
  OutBitmap.Free;
end;

end.

    download Saturation.zip

画像処理一覧へ戻る

      最初に戻る