ScanLineで色(RGB)を取得してその色を加工塗布

解決


一休  2011-05-05 22:32:04  No: 40499

(D6パーソナル)
先日画像回転の高速化でScanLineを教えていただき高速化に成功しました。
どうせなら回転時にピクセル毎の色を加工して一度で色の加工処理をして一層の高速化をしたいと思います。現在のソースの要点は下記のようにしていますが  pDests[iy][ix] := pSources[my][mx];  のところで色を取得して、例えば(一定以上の明るさであれば星と判定みたいに選別するとして)
  if R+G+B>50 then begin
      R1:=255; G1:=255; B1:=255;  //適当なRGBを指定したい
  end;
このR1,G1,B1を回転後のピクセルに塗る、という処理をしたいのですがScanLineは初めてでやりかたがわかりません。よろしくお願いします。

var
  Dest: TBitmap; 
  pSources, pDests: array of PRGBArray;
  soWidth, soHeight, deWidth, deHeight: Integer;
  (その他は省略)
Begin

(幅、高、中心座標などの計算と設定)

  //** 回転後画像の設定
  Dest := TBitmap.Create;

  deWidth := sowidth; 
    deHeight := soheight; 

  try

    Dest.PixelFormat := pf24bit;

    dest.Width:=sowidth;
    dest.Height:=soheight;

    with Dest.Canvas do  //白く塗る
    begin
      Brush.Color := clWhite;
      FillRect(Rect(0, 0, soWidth, soHeight));
    end;

    //** ScanLineキャッシュの作成
    //== 元画像
    SetLength(pSources, soHeight);
    for I := 0 to soHeight - 1 do pSources[I] := Source.ScanLine[I];

    //== 回転後の画像
    SetLength(pDests, deHeight);
    for I := 0 to deHeight - 1 do pDests[I] := Dest.ScanLine[I];

    //## 画像の回転 
    for iy := 0 to soHeight - 1 do begin
      dy:=iy-cy;    //cy=高さ/2

      for ix := 0 to soWidth - 1 do begin
        dx:=ix-cx;  //cx=幅/2
                mx := Trunc(CosRad * dx - SinRad * dy + 0.5+cx); 
                my := Trunc(SinRad * dx + CosRad * dy + 0.5+cy);  
 
        if (mx<sowidth) and (mx>0) and (my<soheight) and (my>0) then begin
        
                pDests[iy][ix] := pSources[my][mx];

        end;

      end; //ix
    end;   //iy

  finally
    Source.Free;
  end;


KHE00221  2011-05-06 04:30:54  No: 40500

これでわかるかな?

  TRGB = packed record 
    Blue     : Byte;
    Green    : Byte;
    Red      : Byte;
  end;

  TRGBArray    = array[0..0] of TRGB;
  PRGBArray    = ^TRGBarray;

var
   SrcRow : pRGBArray;

   for Y:=0 to H-1 do
   begin
     SrcRow := Bmp.ScanLine[Y];
     for X:=0 to W-1 do
     begin
       R := SrcRow[X].Red;
       G := SrcRow[X].Green;
       B := SrcRow[X].Blue;
     end;
   end;


一休  2011-05-06 20:58:52  No: 40501

KHE00221様、解決しました。  ありがとうございます。
いただいたサンプルは1行だけのScanLineでしたのでまず1行づつ変色のテストをして成功しました。最終的には画像の回転がありますので違う行のデータを操作
する必要がありますので各行のデータを(技術的にはよくわからない状況ですが)試しに配列にしてみましたらうまくいきました。下記のテスト例はカラーをモノクロにして上下反転してみました。これができれば思ったことが実現できるはずですのでこれから実装したいと思います。いろいろ工夫してこの技を身につけたいと思います。ありがとうございました。

/////
bmp1.PixelFormat := pf24bit;
bmp2.PixelFormat := pf24bit;

setlength(abmprow1 ,h1);
setlength(abmprow2 ,h1);

 for jy := 0 to h1-1 do aBMProw1[jy]:=bmp1.ScanLine[jy];
 for jy := 0 to h1-1 do aBMProw2[jy]:=bmp2.ScanLine[jy];

 for jy := 0 to h1-1 do  //縦方向の繰り返し
  begin

   ky:=h1-jy-1;  //上下反転のy座標

   for ix := 0 to w1-1 do //横方向の繰り返し
    begin

       Rb := abmpRow1[jy][iX].R;
       Gb := abmpRow1[jy][iX].G;
       Bb := abmpRow1[jy][iX].B;

     brt:=trunc(rb*0.3+gb*0.59+bb*0.11);
     aBMProw2[ky][ix].R := brt;
     aBMProw2[ky][ix].G := brt;
     aBMProw2[ky][ix].B := brt;
    end;
  end;

//最後にFORM1へコピー
 form1.Canvas.Draw(0,50,bmp2);
 bmp1.Free;
 bmp2.Free;


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加