2011-01-09 7 views
2

ダウンロードソースコードをここに:http://www.eyeClaxton.com/download/delphi/ColorSwap.zipロードされたビットマップから赤、緑、青や灰色にプログラムのスワップ色、ピクセルのピクセルによって

はい、私は「主に緑の」何かに「ほとんど青」何かを変換したいです。

私は元のビットマップ(薄い青色)を取り、色(Pixel by Pixel)を赤、緑、青、灰色等価関係に変更したいと考えています。私が何を意味するのかを知るために、私はソースコードとスクリーンショットを含んでいます。どんな助けでも大歓迎です。さらに詳しい情報が必要な場合は、お気軽にお問い合わせください。

以下のコードを見ることができれば、私は助けを求めている3つの機能を持っています。 "RGBToRed、RGBToGreen、RGBToRed"という関数は、私は正しい数式を考え出すことができません。

alt text

unit MainUnit; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, ExtCtrls, StdCtrls; 

type 
    TMainFrm = class(TForm) 
    Panel1: TPanel; 
    Label1: TLabel; 
    Panel2: TPanel; 
    Label2: TLabel; 
    Button1: TButton; 
    BeforeImage1: TImage; 
    AfterImage1: TImage; 
    RadioGroup1: TRadioGroup; 
    procedure FormCreate(Sender: TObject); 
    procedure Button1Click(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    MainFrm: TMainFrm; 

implementation 

{$R *.DFM} 
function RGBToGray(RGBColor: TColor): TColor; 
var 
    Gray: Byte; 
begin 
    Gray := Round(
    (0.90 * GetRValue(RGBColor)) + 
    (0.88 * GetGValue(RGBColor)) + 
    (0.33 * GetBValue(RGBColor))); 

    Result := RGB(Gray, Gray, Gray); 
end; 

function RGBToRed(RGBColor: TColor): TColor; 
var 
    Red: Byte; 
begin 
    // Not sure of the algorithm for this color 
    Result := RGB(Red, Red, Red); 
end; 

function RGBToGreen(RGBColor: TColor): TColor; 
var 
    Green: Byte; 
begin 
    // Not sure of the algorithm for this color 
    Result := RGB(Green, Green, Green); 
end; 

function RGBToBlue(RGBColor: TColor): TColor; 
var 
    Blue: Byte; 
begin 
    // Not sure of the algorithm for this color 
    Result := RGB(Blue, Blue, Blue); 
end; 

procedure TMainFrm.FormCreate(Sender: TObject); 
begin 
    BeforeImage1.Picture.LoadFromFile('Images\RightCenter.bmp'); 
end; 

procedure TMainFrm.Button1Click(Sender: TObject); 
var 
    Bitmap: TBitmap; 
    I, X: Integer; 
    Color: Integer; 
begin 
    Bitmap := TBitmap.Create; 
    try 
    Bitmap.LoadFromFile('Images\RightCenter.bmp'); 

    for X := 0 to Bitmap.Height do 
    begin 
     for I := 0 to Bitmap.Width do 
     begin 
     Color := ColorToRGB(Bitmap.Canvas.Pixels[I, X]); 

     case Color of 
      $00000000: ; // Skip any Color Here! 
     else 
      case RadioGroup1.ItemIndex of 
      0: Bitmap.Canvas.Pixels[I, X] := RGBToBlue(Color); 
      1: Bitmap.Canvas.Pixels[I, X] := RGBToRed(Color); 
      2: Bitmap.Canvas.Pixels[I, X] := RGBToGreen(Color); 
      3: Bitmap.Canvas.Pixels[I, X] := RGBToGray(Color); 
      end; 
     end; 
     end; 
    end; 
    AfterImage1.Picture.Graphic := Bitmap; 
    finally 
    Bitmap.Free; 
    end; 
end; 

end. 

さて、私はそれが明確になっていないことをお詫び申し上げます。私は、ビットマップ(青の色)を取って、別の色で青のピクセルを交換しようとしています。以下のショットのように。

alt text

alt text

+0

わかりません。あなたが提供したコードは、どのようにしてあなたが必要としていることをしていないのですか? –

+0

[OK]を、私はあなたがスクリーンショットとコードを提供している顔が好きですが、私はあなたから私たちのものを得ることはありません。何が問題なのですか、あるいはあなたが望むようにどの部分がうまくいかないのですか? –

+0

上記のコードを見ることができたら、私は助けを求めている3つの機能を持っています。 "RGBToRed、RGBToGreen、RGBToRed"という関数は、私は正しい数式を考え出すことができません。 – eyeClaxton

答えて

13

私はあなたが達成しようとしているものは考えています。まず、質問はequivalence relationsと何が関係していますか?

は第二に、コード

function RGBToRed(RGBColor: TColor): TColor; 
var 
    Red: Byte; 
begin 
    // Not sure of the algorithm for this color 
    Result := RGB(Red, Red, Red); 
end; 

は無意味です。戻り値は未定義です。 RGB関数は、0〜255の範囲で赤、緑、青の強度を取り、これらの成分を持つTColorを返します。例えば、RGB(255, 0, 0)は、純粋な赤色、すなわち、255個の赤色、0個の緑色、および0個の青色である。ただし、上記のコードでは、Redは初期化されていないため、Resultはどのような灰色でもかまいません(Red)。 [あなたが知っているように、同じ量の赤、緑、青を混ぜると、灰色になります。]たとえば、Redはアプリケーションを実行したときに45回発生する可能性があります。グレーの色はRGB(45, 45, 45)になります。次回は163かもしれません。

おそらくTColorを受け取り、それの赤い成分を返す関数が必要なのでしょうか?その後、GetRValueが行います。もちろん、GetGValueGetBValueもあります。

または、Photoshopを使用してカラー画像からグレースケール画像を作成するときと同じように、指定したTColorから灰色を作成することができます。 ColorTColorであればその後、適切なグレー値は、これを行う他の方法があります

grey := (GetRValue(Color) + GetGValue(Color) + GetBValue(Color)) div 3; 

である(微妙に異なるグレースケール画像が得られはするが、これは最も簡単です(最速))。 (たとえば、あなたは、HSVまたはHSLにRGBから色を変換して、ゼロに等しい鮮やかさを設定することができます。)

更新

私は私はあなたが何をしたいのか見ると思います。赤、緑、青のチャンネルを抽出したい場合があります。つまり、赤の場合、各ピクセルRGB(R, G, B)RGB(R, 0, 0)に変換する必要があります。これはあなたが何をしたいのかである場合は、

function RGBToRed(RGBColor: TColor): TColor; 
begin 
    Result := RGB(GetRValue(RGBColor), 0, 0); 
end; 

を行う必要があり、同様に他のコンポーネントのために、それは多分

function RGBToGreen(RGBColor: TColor): TColor; 
begin 
    Result := RGB(0, GetGValue(RGBColor), 0); 
end; 

function RGBToBlue(RGBColor: TColor): TColor; 
begin 
    Result := RGB(0, 0, GetBValue(RGBColor)); 
end; 

か、あります

画像をグレースケールにしてから、 "カラー"それは赤(または緑、または青)です。それから重い機械が必要です。理論的には、赤の場合はHSV(h, s, v)HSV(0, s, v)、緑の場合はHSV(120, s, v)、青の場合はHSV(240, s, v)の各ピクセルを置き換えます。

function RGBToHSV(const Color: TRGB): THSV; 
var 
    cmax, cmin, cdiff: real; 
begin 
    cmax := MaxComponent(Color); 
    cmin := MinComponent(Color); 
    cdiff := cmax - cmin; 

    with Color, result do 
    begin 

    // Hue 
    if cmax = cmin then 
     hsvHue := 0 
    else if cmax = rgbRed then 
     hsvHue := (60 * (rgbGreen - rgbBlue)/cdiff) 
    else if cmax = rgbGreen then 
     hsvHue := (60 * (rgbBlue - rgbRed)/cdiff) + 120 
    else 
     hsvHue := (60 * (rgbRed - rgbGreen)/cdiff) + 240; 

    hsvHue := Fix360(hsvHue); 

    // Saturation 
    if cmax = 0 then 
     hsvSaturation := 0 
    else 
     hsvSaturation := 1 - cmin/cmax; 

    // Value 
    hsvValue := cmax; 

    end; 

end; 

function HSVToRGB(const Color: THSV): TRGB; 
var 
    hi: integer; 
    f, q, p, t: real; 
begin 

    with Color do 
    begin 

    hi := floor(hsvHue/60) mod 6; 
    f := hsvHue/60 - floor(hsvHue/60); 
    p := hsvValue * (1 - hsvSaturation); 
    q := hsvValue * (1 - f * hsvSaturation); 
    t := hsvValue * (1 - (1 - f) * hsvSaturation); 

    case hi of 
     0: result := RGB(hsvValue, t, p); 
     1: result := RGB(q, hsvValue, p); 
     2: result := RGB(p, hsvValue, t); 
     3: result := RGB(p, q, hsvValue); 
     4: result := RGB(t, p, hsvValue); 
     5: result := RGB(hsvValue, p, q); 
    end; 

    end; 

end; 

どこ

type 
    TRGB = record 
    rgbRed,   // red intensity between 0 and 1 
    rgbGreen,   // green intensity between 0 and 1 
    rgbBlue: double; // blue intensity between 0 and 1 
    end; 

    THSV = record 
    hsvHue,   // hue angle between 0 and 360 
    hsvSaturation,  // saturation between 0 (grey) and 1 (full colour) 
    hsvValue: double; // value between 0 (dark) and 1 ("normal") 
    end; 
:または、多分あなたはまた、私はRGBとHSVの間で変換するには、次のrutinesを使用1.

に飽和sを設定したいです

最終結果は、緑色の場合、

のようになります最初のケース(120に固定された色相)において

Hue fixed to 120 http://english.rejbrand.se/algosim/manual/pmproc/fixHue120.jpg

後者の場合に

Hue fixed to 120 and saturation fixed to 1 http://english.rejbrand.se/algosim/manual/pmproc/monochromatic120.jpg

(色相が120に固定され、飽和度が1に固定されました)。

あるいは、おそらく

あなたの質問にも編集して、非常にvaugeです。あなたは何か「ほとんど青い」を「ほとんど緑色」に変換したいと思っています。しかし、それを行うには何千もの方法があります!非常に単純な方法は、当然のことながら、ちょうどあなたが

R and G channels swapped http://english.rejbrand.se/algosim/manual/pmproc/swapRG.jpg

のようなものを取得するには、明示的、

function SwapBlueGreen(Color: TColor): TColor; 
begin 
    result := RGB(GetRValue(Color), GetBValue(Color), GetGValue(Color)); 
end; 

RGB(r, b, g)RGB(r, g, b)を交換、または、つまり、青と緑のチャンネルを交換することです

赤と緑のチャンネルが入れ替わっています。赤いスティックが緑色になり、緑色の草が赤色になります。白は白のままです。

最後に

はピックスマップ操作の世界へようこそ!簡単で楽しいことがたくさんあります。いくつかの私の例:http://english.rejbrand.se/algosim/manual/pmproc/pmproc.html

+0

はい、「ほとんど青色」を「ほとんど緑色」に変換したいと思います。 – eyeClaxton

+1

+1、素敵な答え! –

+0

+1華麗な総合的な答え!おそらく私はそのようなコードの背後にある論理を理解することができます: –

2

"ピクセル"プロパティで色情報にアクセスするのは本当に遅いです。 「Scanline」プロパティを使用して、約2レベルの高速コードを取得することを検討する必要があります。 http://blogs.embarcadero.com/pawelglowacki/2010/04/15/39051にはコードサンプルが含まれています。

成功!

+0

古いニュースは、efg2.comを参照してください –