unit light;

interface

uses
  Windows, Graphics,types,ABitmaplight,sysUtils,math;

procedure EffectLightMode(var SrcBitmap :TBitmap;Value:Integer);
procedure EffectEnbos(var SrcBitmap :TBitmap);
procedure EffectMirror(var SrcBitmap :TBitmap);
procedure EffectFlip(var SrcBitmap :TBitmap);
procedure EffectSepia(var SrcBitmap :TBitmap;effect:Integer=0);
procedure EffectCustom(var SrcBitmap: TBitmap;masktype:Integer);
procedure EffectNOTMask(var srcBitmap: TBitmap);
procedure EffectShiftRGB(var SrcBitmap: TBitmap;mode:Integer);
procedure EffectMono(var SrcBitmap:TBitmap;value:smallInt);
procedure EffectThreadLine(var SrcBitmap:TBitmap;const effect:Integer=0);
procedure EffectKakusan(var srcBitmap: TBitmap);
procedure EffectNoize(var SrcBitmap:TBitmap;noise:smallInt;const mode:shortInt);
procedure EffectResize(Var srcBitmap:TBitmap;const width,height:Integer;smooth:boolean=false);
procedure EffectsTurn270(var SrcBitmap:TBitmap);
procedure EffectsTurn90(var SrcBitmap:TBitmap);
procedure EffectsMosaic(var SrcBitmap:TBitmap;Value:Integer);
procedure Set32bit(var Src,Dest :TBitmap);
procedure EffectClip(var SrcBitmap:TBitmap;Clip:TRect);
procedure FillBMP(bitmap:TBitmap;const pxlRGB:TColor;isPaint:boolean=true);
procedure EffectResizeNormal(ix2,iy2,iw2,ih2:Double;ox2,oy2:Double;ow2,oh2:Integer;InBMP,OutBMP:TBitmap);

type

TBitbltInf = record
 x,y,w,h,sx,sy:Integer;
end;

TPaintInf = record
 alpha:byte;
 srcX,srcY,srcW,srcH:Integer;
 isClip:boolean;
 destX,destY,destH,destW:Integer;
 mode:byte;
end;

TADCanvas= class(TObject)
private
 bmpBkg:TABitmap;
 bmpDest:TBitmap;
public
 procedure setBitmap(bmp:TBitmap);
 constructor create();
 destructor destroy();override;
 procedure StretchDrawEx(Bitmap:TBitmap;inf:TPaintInf);
 procedure DrawLogic(Bitmap:TBitmap;inf:TPaintInf);
 procedure DrawTranslucent (bitmap:TBitmap;inf:TPaintInf);
 function getBltInf(const inf:TPaintInf):TBitBltInf;
end;

type
 //32bitアクセス用ポインタ
 TRGBarray  = array[0..0] of TRGBQUAD; //None リテラル
 pRGBarray  = ^TRGBarray;

type
 //32bitアクセス用ダブルポインタ
 PPBits = ^TPBits;
 TPBits = array[0..0] of pRGBarray; //None リテラル



implementation

{function covertColor(color:Dword):TColor;
begin
 result:=((color and $ff000000)
         or   (color and $ff0000) shr 16)   //青
         or (color and $00ff00)           //緑
         or ((color and $0000ff) shl 16);//赤
end;  }


procedure Set32bit(var Src,Dest :Tbitmap);
begin
  Src.PixelFormat :=pf32bit;
  Dest.PixelFormat:=pf32bit;
  Dest.Width:=Src.Width;
  Dest.Height:=Src.Height;
end;

function SetOutXYWHSuper(var ix,iy,iw,ih:Double;var ox,oy:Double;var ow,oh:Integer;iWW,iHH,oWW,oHH:Integer):Boolean;
var iZW,iZH:Double;
begin

   iZW:=iw/ow;
   iZH:=ih/oh;


   Result:=False;

   //入力位置が変なモノも終了。
   if (ix<0) or (ix>iWW) then exit;
   if (iy<0) or (iy>iHH) then exit;

   //出力位置は適切か調べる。
   If oX>=oWW then exit;
   If oY>=oHH then exit;
   If oX+oW<=0 then exit;
   If oY+oH<=0 then exit;


   {表示エリアに入るサイズで、マイナスな場合}
   //マイナスの場合の変更処理
   If oX<0 then begin
      //入力サイズの変更
      iw:=iZW*(oW+oX);
      iX:=iX+Abs(oX)*iZW;

      oW:=Trunc(oW+oX);
      oX:=0;

   end;

   If oY<0 then begin
      //入力サイズの変更
      ih:=iZH*oh;
      iy:=iY+(Abs(oY)*iZH);

      oH:=Trunc(oH+oY);
      oY:=0;
   end;

   {表示エリアを越えているだけの場合}
   //範囲越えの時の変更処理。
   If oX+oW>oWW then begin
      //入力位置も変更しておく。
      iW:=iZW*(oWW-oX);

      //幅をX方向を引いて代入。
      oW:=Trunc(oWW-oX);
   end;

   If oY+oH>oHH then begin
      //入力位置も変更しておく。
      iH:=iZH*(oHH-oY);

      //幅をX方向を引いて代入。
      oH:=Trunc(oHH-oY);
   end;


   //編集結果のチェック。
   if ow<=0 then exit;
   if oh<=0 then exit;
   if (ix<0) or (ix>iww) then exit;
   if (iy<0) or (iy>ihh) then exit;
   if (ix+iw)>iWW then iw:=iWW-iX;
   if (iy+ih)>iHH then ih:=iHH-iY;

   //ShowMessage(Format('%d,%d %d,%d',[iw,ih,ow,oh]));

   //結果オッケー。
   Result:=True;

end;

procedure FillBMP(bitmap:TBitmap;const pxlRGB:TColor;isPaint:boolean=true);
var pBit:PByteArray;
    ew,y:Integer;
    col:TColor;
begin

 //出力先がないときも終了
 If not SelfCheck(bitmap) then exit;

 bitmap.PixelFormat:=pf32bit;

 col:=(  (pxlRGB and $ff000000)
         or(pxlRGB and $ff0000) shr 16)   //青
         or (pxlRGB and $00ff00)           //緑
         or ((pxlRGB and $0000ff) shl 16);//赤
 // windows.MessageBox(0,'',PChar(IntToHex(col,2)),MB_OK);

 ew:=(bitmap.Width);

   for y:=0 to bitmap.Height-1 do begin
     pBit:= bitmap.ScanLine[y];
     asm
       push esi; push edi; push ebx; // レジスタ退避
       mov esi,pBit;
       mov ebx,col;
       mov ecx,ew;
      @loop:
         mov [esi],ebx;
         add esi,4;
         dec ecx;
         jnz @loop;

       pop ebx; pop edi; pop esi;    // レジスタ復活
     end;
   end;
  if(isPaint)then
  bitblt(bitmap.Canvas.Handle,0,0,bitmap.Width,bitmap.Height,
         bitmap.Canvas.Handle,0,0,srcCopy);
end;



constructor TADCanvas.create();
begin
 inherited;
 bmpBkg:=TABitmap.create();
 bmpBkg.pixelformat:=pf32bit;
end;

destructor TADCanvas.destroy();
begin
 bmpBkg.Free();
 self.bmpDest:=nil;
 inherited;
end;

procedure TADCanvas.setBitmap(bmp:TBitmap);
begin
 self.bmpDest:=nil;
 self.bmpDest:=bmp;
end;

function TADCanvas.getBltInf(const inf:TPaintInf):TBitBltInf;
begin
 if not(inf.isClip)then
 begin
  result.x:=inf.srcX;
  result.y:=inf.srcY;
  result.w:=inf.srcW;
  result.h:=inf.srcH;
  result.sx:=0;
  result.sy:=0;
 end
 else
 begin
  if(inf.srcX>=inf.destX)then
    begin
     result.x:=inf.srcX;
     result.sx:=0;
    end
    else
    begin
     result.x:=inf.destX;
     result.sx:=inf.destX-inf.srcX;
    end;

    if(inf.srcY>=inf.destY)then
    begin
     result.y:=inf.srcY;
     result.sy:=0;
    end
    else
    begin
     result.y:=inf.destY;
     result.sy:=inf.destY-inf.srcY;
    end;

    if(inf.srcX+inf.srcW<=inf.destX+inf.destW)then
    begin
     result.w:=inf.srcW-result.sx;
    end
    else
     result.w:=inf.srcW-(inf.srcX+inf.srcW-inf.destX-inf.destW)-result.sx;

    if(inf.srcY+inf.srcH<=inf.destY+inf.destH)then
    begin
     result.h:=inf.srcH-result.sy;
    end
    else
     result.h:=inf.srcH-(inf.srcY+inf.srcH-inf.destY-inf.destH)-result.sy;
 end;
end;



procedure TADCanvas.StretchDrawEx(Bitmap:TBitmap;inf:TPaintInf);
var
 binf:TBitbltinf;
 b:TBitmap;
begin


  case inf.mode of
   0:
   if(inf.isClip)then
   begin
   { bmpBkg.Width:=inf.srcW;
    bmpBkg.Height:=inf.srcH;
    bitBlt(bmpBkg.Canvas.Handle,0,0,inf.srcW,inf.srcH,bmpDest.Canvas.Handle,inf.srcX,
     inf.srcY,srcCopy);

    if(bitmap.Transparent)then
    begin
     b:=TBitmap.Create;
  {   b.Width:=inf.srcW;
     b.Height:=inf.srcH;
     b.PixelFormat:=pf32bit;
     b.Transparent:=bitmap.Transparent;
     stretchblt(b.Canvas.Handle,0,0,inf.srcW,inf.srcH,
      bitmap.Canvas.Handle,0,0,bitmap.Width,bitmap.Height,srcCopy);
     b.TransparentColor:=b.Canvas.Pixels[0,0];
     b.Assign(bitmap);
     bmpBkg.Canvas.StretchDraw(Bounds(0,0,inf.srcW,inf.srcH),b);
     b.Free();            }
    bmpBkg.Width:=inf.srcW;
    bmpBkg.Height:=inf.srcH;
    bitBlt(bmpBkg.Canvas.Handle,0,0,inf.srcW,inf.srcH,bmpDest.Canvas.Handle,inf.srcX,
     inf.srcY,srcCopy);

    b:=TBitmap.Create;
    b.Width:=inf.srcW;
    b.Height:=inf.srcH;
    b.PixelFormat:=pf32bit;
    b.Transparent:=bitmap.Transparent;
    bitblt(b.Canvas.Handle,0,0,inf.srcW,inf.srcH,bitmap.Canvas.Handle,
     0,0,srcCopy);
    b.TransparentColor:=b.Canvas.Pixels[0,0];
    bmpBkg.Canvas.StretchDraw(Bounds(0,0,inf.srcW,inf.srcH),b);
    b.Free();

    binf:=self.getBltInf(inf);
    bitblt(bmpDest.Canvas.Handle,binf.x,binf.y,binf.w,binf.h,bmpBkg.Canvas.Handle,
     binf.sx,binf.sy,srccopy);
  {  end
    else
    Stretchblt
     (bmpBkg.Canvas.Handle,0,0,inf.srcW,inf.srcH,
      bitmap.Canvas.Handle,0,0,bitmap.Width,bitmap.Height,SrcCopy);

    binf:=self.getBltInf(inf);
    bitblt(bmpDest.Canvas.Handle,binf.x,binf.y,binf.w,binf.h,bmpBkg.Canvas.Handle,
     binf.sx,binf.sy,srccopy);  }

   end
   else
   begin
    if(bitmap.Transparent)then
    begin
     b:=TBitmap.Create;
     b.Assign(bitmap);
     bmpDest.Canvas.StretchDraw
     (Bounds(inf.srcX,inf.srcY,inf.srcW,inf.srcH),b);
     b.Free();
    end
    else
     Stretchblt
     (bmpDest.Canvas.Handle,inf.srcX,inf.srcY,inf.srcW,inf.srcH,
      bitmap.Canvas.Handle,0,0,bitmap.Width,bitmap.Height,SrcCopy);
   end;

   1,2:DrawLogic(Bitmap,inf);
   3:DrawTranslucent(bitmap,inf);
  end;

end;


procedure TADCanvas.DrawTranslucent(bitmap:TBitmap;inf:TPaintInf);
var
  w,h: Integer;
  subBitmap:TBitmap;
  color:TColor;
  binf:TBitbltinf;
begin

  // 背景を貼り付け範囲の大きさ分、切り取る

  h:=inf.srcH;
  w:=inf.srcW;

 // bitmap.PixelFormat:=pf32bit;
  bmpBkg.Width:=w;
  bmpBkg.Height:=h;
  bmpBkg.Canvas.CopyRect(bmpBkg.Canvas.ClipRect,bitmap.Canvas,bitmap.Canvas.ClipRect);

  subBitmap:=TBitmap.Create();
  subBitmap.PixelFormat:=pf32bit;
  subBitmap.Width:=w;
  subBitmap.Height:=h;
  stretchBlt(subBitmap.Canvas.Handle,0,0,w,h,
   bmpDest.Canvas.Handle,inf.srcX,inf.srcY,inf.srcW,inf.srcH,SrcCopy);

  if(bitmap.Transparent)then
  begin
   bmpBkg.GetRGBColor(0,0,color);
   bmpBkg.ColorKeyAlphaMMX(0,0,w,h,0,0,subbitmap,color,inf.alpha);
  end
  else
   bmpBkg.ColorAlphaMMX(0,0,w,h,0,0,subbitmap,inf.alpha);

  if(inf.isClip)then
  begin
   binf:=self.getBltInf(inf);
   bitblt(bmpDest.Canvas.Handle,binf.x,binf.y,binf.w,binf.h,subbitmap.Canvas.Handle,
    binf.sx,binf.sy,srccopy);
  end
  else
  begin
  BitBlt(bmpDest.Canvas.Handle,inf.srcX,inf.srcY,w,h,
    subbitmap.Canvas.Handle,0,0,SrcCopy);
  end;

//  
  subBitmap.Free();

end;

(*andもしくはorによる描画を行なう*)
procedure TADCanvas.DrawLogic(Bitmap:TBitmap;inf:TPaintInf);
var
 dwRop:Cardinal;
 binf:TBitbltinf;
 b:TBitmap;
begin

 b:=TBitmap.Create();
 b.PixelFormat:=pf32bit;

 case inf.mode of
 1:
 begin
  b.Canvas.Brush.Color:=$ffffff;
  bmpDest.Canvas.CopyMode:=cmSrcAnd;
  dwRop:=SRCAND;
 end;
 2:
 begin
  b.Canvas.Brush.Color:=0;
  bmpDest.Canvas.CopyMode:=cmSrcPaint;
  dwRop:=SRCPAINT;
 end;
 else exit;
 end;

 b.Width:=inf.srcW; 
 b.Height:=inf.srcH;

 b.Canvas.FillRect(b.Canvas.ClipRect);
 b.Canvas.StretchDraw(b.Canvas.ClipRect,bitmap);

  if(inf.isClip)then
  begin
   binf:=self.getBltInf(inf);
   bitblt(bmpDest.Canvas.Handle,binf.x,binf.y,binf.w,binf.h,b.Canvas.Handle,
    binf.sx,binf.sy,dwRop);
  end
  else
  begin
   bitBlt(bmpDest.Canvas.Handle,inf.srcX,inf.srcY,inf.srcW,inf.srcH,
    b.Canvas.Handle,0,0,dwRop);
  end;

 b.Free();

end;

(*モザイクエフェクトを行なう*)
procedure EffectsMosaic(var SrcBitmap:TBitmap;Value:Integer);
var x,y:Integer;
    pBit,pBit2:PDWORDArray;

    //高速化用
    bufX:PWORDArray;
begin

  if(value<1)then exit;

  GetMEM(bufX,(SrcBitmap.width+1)*2);

  for x:=0 to SrcBitmap.width-1 do begin
      bufX[x]:=((x) div Value)*Value;
  end;


  for y:=0 to SrcBitmap.height-1 do begin
      ///現在の入力画像の高さ位置
      pBit :=SrcBitmap.ScanLine[y];
      pBit2:=SrcBitmap.ScanLine[(y div Value)*Value];

      for x:=0 to SrcBitmap.width-1 do begin
          pBit[x]:=pBit2[bufX[x]];
      end;
  end;

  FreeMEM(bufX);

end;


procedure EffectsTurn90(var SrcBitmap:TBitmap);
var
 Row,Col              : Integer;
 SrcRow               : pRGBArray;
 DestBitmap : TBitmap;
 DestBits : PPBits;
begin

  if(srcBitmap.Width*srcBitmap.Height=0)then exit;

  DestBitmap  :=TBitmap.Create;
  DestBitmap.Width:= SrcBitmap.Height;
  DestBitmap.Height:=SrcBitmap.Width;
  DestBitmap.PixelFormat:=pf32bit;
  SrcBitmap.PixelFormat:=pf32bit;

  GetMem(DestBits, DestBitmap.Height * SizeOf(pRGBArray));
 try

  for Row:= 0 to DestBitmap.Height - 1 do
   DestBits[Row]:=DestBitmap.Scanline[Row];

  for Row:=0 to SrcBitmap.Height-1 do
  begin
      SrcRow:=SrcBitmap.ScanLine[Row];

        for Col:=0 to SrcBitmap.Width-1 do
        begin
             //右90度回転
          DestBits[Col][SrcBitmap.Height-1-Row]:=SrcRow[Col];
        end;
  end;

  FreeMem(DestBits); DestBits:=nil;
  SrcBitmap.Handle :=DestBitmap.ReleaseHandle;

  except
     if Assigned(DestBits) then FreeMem(DestBits);
     windows.MessageBox(0,'左ターンエラー','EffectTurn90',MB_OK);
  end;

  DestBitmap.Free;
end;


(*右回転*)
procedure EffectsTurn270(var SrcBitmap:TBitmap);
var
 Row,Col              : Integer;
 SrcRow               : pRGBArray;
 DestBitmap : TBitmap;
 DestBits : PPBits;
begin

  if(srcBitmap.Width*srcBitmap.Height=0)then exit;

  DestBitmap  :=TBitmap.Create;
  DestBitmap.Width:= SrcBitmap.Height;
  DestBitmap.Height:=SrcBitmap.Width;
  DestBitmap.PixelFormat:=pf32bit;
  SrcBitmap.PixelFormat:=pf32bit;
  
  GetMem(DestBits, DestBitmap.Height * SizeOf(pRGBArray));
 try

  for Row:= 0 to DestBitmap.Height - 1 do
    DestBits[Row]:=DestBitmap.Scanline[Row];

  for Row:=0 to SrcBitmap.Height-1 do
  begin
      SrcRow:=SrcBitmap.ScanLine[Row];

        for Col:=0 to SrcBitmap.Width-1 do
        begin
             //左90度回転(右270℃回転)
         DestBits[SrcBitmap.Width-1-COl][ROw]:=SrcRow[Col];
        end;
  end;

  FreeMem(DestBits);
  DestBits:=nil;
  SrcBitmap.Handle :=DestBitmap.ReleaseHandle;

  except
     if Assigned(DestBits) then FreeMem(DestBits);
     windows.MessageBox(0,'右ターンエラー','EffectMono',MB_OK);
  end;
  DestBitmap.Free;
end;

//掛け算割り算をループ内で一切使わないトンでも仕様。キャッシュ効きまくります
procedure EffectResizeNormal(ix2,iy2,iw2,ih2:Double;ox2,oy2:Double;ow2,oh2:Integer;InBMP,OutBMP:TBitmap);
var pBit,pBit2:PDWORDArray;
    y,x:Integer;//ループ用
    zx,zy:Integer;//入力もとの位置
    mzoomx,mzoomy:Integer;//ズーム倍率。

    //高速化用。
    i:Integer;//Xの代用。
    k:Integer;//ZXの一定移動幅の計算。
    //高速化用その２.
    l:Integer;//Yの位置の次への値の比率。
    //ix,
    iy:Integer;
    ix3,iy3,ox3,oy3,iw3,ih3:Double;
    ox,oy,ow,oh:Integer;
    ix8:Integer;
begin
  //最近傍法

  ix3:=ix2; iy3:=iy2; iw3:=iw2; ih3:=ih2;
  ox3:=ox2; oy3:=oy2; ow :=ow2; oh :=oh2;


  //逆数のズーム倍率を求める（ズーム先を基準にしているため)
  mzoomx:=Trunc(iw3*$FFFF / ow);//割るときは全部シフトで代用できるようにする。
  mzoomy:=Trunc(ih3*$FFFF / oh);

  //範囲内かどうかをチェックする。
  If not SetoutXYWHSuper(ix3,iy3,iw3,ih3,ox3,oy3,ow,oh,InBMP.Width,InBMP.Height,OutBMP.Width,OutBMP.Height) then exit;

  //Y位置のループ高速化用。
  l:=1;

  ix8:=Trunc(ix3*$FFFF);
  iy:=Trunc(iy3);
  ox:=Trunc(ox3);
  oy:=Trunc(oy3);

  for y:=oy to oy+oh-1 do begin
      pBit2:=OutBMP.ScanLine[y];

      ///現在の入力画像の高さ位置を計算
      zy:=iy+(l shr 16);

      pBit :=InBMP.ScanLine[zy];

      //xの代用用。
      i:=ox;
      k:=ix8;

      for x:=ox to ox+ow-1 do
      begin
       //入力位置を算出
       zx:=(k shr 16);

       //入力
       //出力
       pBit2[i]:=pBit[zx];
       inc(i);

       //次への位置をずらす。
       inc(k,mzoomx);

      end;
      //次への位置をずらす。
      l:=l+mzoomy;
  end;

end;
        {
(*透過色は可能か？*)
procedure EffectResizeKey(ix2,iy2,iw2,ih2:Double;
 ox2,oy2:Double;ow2,oh2:Integer;InBMP,OutBMP:TBitmap;color:TColor);
var pBit,pBit2:PDWORDArray;
    y,x:Integer;//ループ用
    zx,zy:Integer;//入力もとの位置
    mzoomx,mzoomy:Integer;//ズーム倍率。

    //高速化用。
    i:Integer;//Xの代用。
    k:Integer;//ZXの一定移動幅の計算。
    //高速化用その２.
    l:Integer;//Yの位置の次への値の比率。
    //ix,
    iy:Integer;
    ix3,iy3,ox3,oy3,iw3,ih3:Double;
    ox,oy,ow,oh:Integer;
    ix8:Integer;
begin
  //最近傍法
  ix3:=ix2; iy3:=iy2; iw3:=iw2; ih3:=ih2;
  ox3:=ox2; oy3:=oy2; ow :=ow2; oh :=oh2;
  InBmp.PixelFormat:=pf32bit;
  outBmp.PixelFormat:=pf32bit;

  //逆数のズーム倍率を求める（ズーム先を基準にしているため)
  mzoomx:=Trunc(iw3*$FFFF / ow);//割るときは全部シフトで代用できるようにする。
  mzoomy:=Trunc(ih3*$FFFF / oh);

  //範囲内かどうかをチェックする。
  If not SetoutXYWHSuper(ix3,iy3,iw3,ih3,ox3,oy3,ow,oh,InBMP.Width,InBMP.Height,OutBMP.Width,OutBMP.Height) then exit;

  //Y位置のループ高速化用。
  l:=1;

  ix8:=Trunc(ix3*$FFFF);
  iy:=Trunc(iy3);
  ox:=Trunc(ox3);
  oy:=Trunc(oy3);

  color:=color and $00ffffff;

  for y:=oy to oy+oh-1 do begin
      pBit2:=OutBMP.ScanLine[y];

      ///現在の入力画像の高さ位置を計算
      zy:=iy+(l shr 16);

      pBit :=InBMP.ScanLine[zy];

      asm
       push esi;
       push edi;
       push ebx;
       push ecx;
       // レジスタ退避  ecx
       mov esi,pbit;
       mov edi,pbit2;
       mov edx,color;
       add esi

       @loop_horz:
         mov eax,[esi];
         and eax,$00FFFFFF;
         cmp eax,ebx;
         je  @put_pixel_end;
         //コピー。

         mov [edi],eax;


         @put_pixel_end:
         add edi,4;
         add esi,4;
         dec ecx;
         jnz @loop_horz;

       pop ecx;
       pop ebx;
       pop edi;
       pop esi;    // レジスタ復活
      end;

      //xの代用用。
      i:=ox;
      k:=ix8;

      for x:=ox to ox+ow-1 do
      begin
       //入力位置を算出
       zx:=(k shr 16);

       //入力
       //出力
       if(pBit[zx]<>color)then
       pBit2[i]:=pBit[zx];
       inc(i);

       //次への位置をずらす。
       inc(k,mzoomx);

      end;
      //次への位置をずらす。
      l:=l+mzoomy;
  end;

end;
     }

(*線形補完法でサイズ変更*)
procedure EffectResizeSmooth(ix2,iy2,iw2,ih2:Double;ox2,oy2:Double;ow2,oh2:Integer;InBMP,OutBMP:TBitmap);
var pBit,pBitN,pBit2:PDWORDArray;
    //x
    y:Integer;//ループ用
    //zx,
    zy:Integer;//入力もとの位置
    mzoomx,mzoomy,zoomx,zoomy:DWORD;//ズーム倍率。

    //高速化用。
  //  i:Integer;//Xの代用。
  //  k:Integer;//ZXの一定移動幅の計算。
    //高速化用その２.
    l:DWORD;//Yの位置の次への値の比率。

    ix8:Integer;
    //端の考慮用
    tw,th:Integer;

    //高速化用・バイリニアの割合。
  //  l2,
    l3:DWORD;
    iy,iw,ih,ox,oy,ow,oh:Integer;// ix,
    ix3,iy3,ox3,oy3,iw3,ih3:Double;

    //MMX用
    ew,ew2:Integer;
    iMM4:DWORD;
//    ix8_2:Integer;
    ox4:Integer;  //  ,ix4

begin

  ix3:=ix2; iy3:=iy2; iw3:=iw2; ih3:=ih2;
  ox3:=ox2; oy3:=oy2; ow :=ow2; oh :=oh2;


  //逆数のズーム倍率を求める（ズーム先を基準にしているため)
  mzoomx:=Trunc(iw3*$FFFF / ow);//割るときは全部シフトで代用できるようにする。
  mzoomy:=Trunc(ih3*$FFFF / oh);

  //通常のズーム倍率を取得
  zoomx :=Trunc(ow*$FFFF / iw3);//割るときは全部シフトで代用できるようにする。
  zoomy :=Trunc(oh*$FFFF / ih3);

  //範囲内かどうかをチェックする。
  If not SetoutXYWHSuper(ix3,iy3,iw3,ih3,ox3,oy3,ow,oh,InBMP.Width,InBMP.Height,OutBMP.Width,OutBMP.Height) then exit;

  //Y位置のループ高速化用。
  l:=0;

  ix8:=Trunc(ix3*($FFFF));
  //ix8:=Trunc(ix3) shl 16;

//  ix:=Trunc(ix3);
  iy:=Trunc(iy3);
  ox:=Trunc(ox3);
  oy:=Trunc(oy3);
  iw:=Trunc(iw3);
  ih:=Trunc(ih3);

  //端を考慮。(端を抜いた理論的処理サイズを決定。)
  tw:=(iw-1)*zoomx shr 16;
  if InBMP.Height>iy+ih then begin
     th:=oh;
  end else begin
     th:=(ih-1)*zoomy div $FFFF;
  end;

  zy:=-1;

  //MMX用
  iMM4:=$00FF00FF;
  //幅。
  ew:=tw;
  ew2:=ow-tw;

  ox4:=ox shl 2;

  //ix8_2:=(iw-2) shl 8;

  for y:=oy to oy+th-1 do begin
      pBit2:=OutBMP.ScanLine[y];


      ///現在の入力画像の高さ位置を計算
      if zy<>iy+(l shr 16) then begin
         zy:=iy+(l shr 16);

         pBit :=InBMP.ScanLine[zy];
         pBitN:=InBMP.ScanLine[zy+1];
      end;
      //バイリニアの割合（Y方向）
      l3:=(l-((l shr 16) shl 16)) shr 8;//py


      asm
        push eax;push ebx;push ecx;push edx;push edi;push esi; // レジスタ退避

        //ピクセル位置
        mov edi,pBit;//Src
        mov esi,pBitN;//Src+1
        mov ebx,pBit2;//Dest

        //カウンター。
        mov eax,ew;

        //出力位置を調整。
        add ebx,ox4;


        //あまっているのは、ecx,edx
        mov ecx,ix8;//位置の絶対位置情報と値の保持

        //初期化
        pxor mm6,mm6;
        movd mm7,iMM4;//mm7には、$00FF00FFが入る。
        punpckldq mm7,mm7;//$00FF00FF 00FF00FFとコピーする。dword>qword

        //まずは、通常のループです。
        @LOOP1:
         //取得位置を指定。

            //元画像の位置を計算。
            mov edx,ecx;
            shr edx,16;

            //元画像のポインタを移動
            //元画像の入力(64ビット入力。)
            movq mm2,qword ptr[edi+edx*4];
            movq mm3,qword ptr[esi+edx*4];
            movq mm0,mm2;
            movq mm1,mm3;

            //元画像を整頓
            psrlq mm2,32;
            psrlq mm3,32;

            //QWORDに広げて計算できるようにする。
            punpcklbw mm0,mm6;// a
            punpcklbw mm1,mm6;// b
            punpcklbw mm2,mm6;// c
            punpcklbw mm3,mm6;// d

            //PXの計算。k-(zx shl 8);
            shl  edx,16;
            movd mm5,edx;
            movd mm4,ecx;
            psubd mm4,mm5;
            psrld mm4,8;

            //αを広げておく
            punpcklwd mm4,mm4;// $00aa > $00aa00aa
            punpckldq mm4,mm4;// $00aa00aa > $00aa00aa 00aa00aa
            movq  mm5,mm7;//反転用mm7
            psubw mm5,mm4;//反転完了。

	    //(px*py*(a+d-b-c) shr 8)+px*(b-a)+py*(c-a)) shr 8)+a;
            pmullw mm0, mm5; // a * px
            pmullw mm1, mm5; // c * px
            pmullw mm2, mm4; // b * (1 - px)
            pmullw mm3, mm4; // d * (1 - px)

            //PYの計算。といっても計算済み。
            movd mm4,l3; // a_dy
            punpcklwd mm4,mm4; //ワードからダブルワードへ
            punpckldq mm4,mm4; // 0x00bb00bb 00bb00bb
            movq mm5, mm7;//反転用mm7
            psubw mm5,mm4;//反転完了。

            //続き。
            paddusw mm0, mm2;  // (a * px + b * (1 - px))
            paddusw mm1, mm3;  // (c * px + d * (1 - px))
            psrlw mm0, 8;
            psrlw mm1, 8;
            pmullw mm0, mm5; // (a * px + b * (1 - px)) * py
            pmullw mm1, mm4; // (c * px + d * (1 - px)) * (1 - py)
            paddusw  mm0, mm1;  //
            psrlw    mm0, 8;
            packuswb mm0, mm6; // 0x00 00 00 00 B1' R0' G0' B0'

            //出力の準備
            movd dword ptr[ebx],mm0;
            add ebx,4;

            //Kを増やす。
            add ecx,mzoomx;

            dec eax;

            jne @LOOP1;

        //引き続き右端の特殊ループ、。

        //カウンター。
        mov eax,ew2;

        //あまっているのは、ecx,edx
        //mov ecx,ix8_2;//位置の絶対位置情報と値の保持

        //戻す
        sub ecx,mzoomx;


        @LOOP2:
         //取得位置を指定。

            //元画像の位置を計算。
            mov edx,ecx;
            shr edx,16;

            //元画像のポインタを移動
            //元画像の入力(64ビット入力。)
            movq mm0,qword ptr[edi+edx*4];
            movq mm1,qword ptr[esi+edx*4];
            movq mm2,mm0;
            movq mm3,mm1;

            //元画像を整頓
            psrlq mm2,32;
            psrlq mm3,32;

            //QWORDに広げて計算できるようにする。
            punpcklbw mm0,mm6;// a
            punpcklbw mm1,mm6;// c
            punpcklbw mm2,mm6;// b
            punpcklbw mm3,mm6;// d

            //PXの計算。k-(zx shl 8);
            shl  edx,16;
            movd mm4,ecx;
            movd mm5,edx;
            psubd mm4,mm5;
            psrld mm4,8;
            
            //αを広げておく
            punpcklwd mm4,mm4;// $00aa > $00aa00aa
            punpckldq mm4,mm4;// $00aa00aa > $00aa00aa 00aa00aa
            movq  mm5,mm7;//反転用mm7
            psubw mm5,mm4;//反転完了。

	    //(px*py*(a+d-b-c) shr 8)+px*(b-a)+py*(c-a)) shr 8)+a;
            pmullw mm0, mm5; // a * px
            pmullw mm1, mm5; // c * px
            pmullw mm2, mm4; // b * (1 - px)
            pmullw mm3, mm4; // d * (1 - px)

            //PYの計算。といっても計算済み。
            movd mm4,l3; // a_dy
            punpcklwd mm4,mm4; //ワードからダブルワードへ
            punpckldq mm4,mm4; // 0x00bb00bb 00bb00bb
            movq mm5, mm7;//反転用mm7
            psubw mm5,mm4;//反転完了。

            //続き。
            paddusw mm0, mm2;  // (a * px + b * (1 - px))
            paddusw mm1, mm3;  // (c * px + d * (1 - px))
            psrlw mm0, 8;
            psrlw mm1, 8;
            pmullw mm0, mm5; // (a * px + b * (1 - px)) * py
            pmullw mm1, mm4; // (c * px + d * (1 - px)) * (1 - py)
            paddusw  mm0, mm1;  //
            psrlw    mm0, 8;
            packuswb mm0, mm6; // 0x00 00 00 00 B1' R0' G0' B0'

            //出力の準備
            movd dword ptr[ebx],mm0;
            add ebx,4;
            
            //Kを増やす。
            add ecx,mzoomx;

            dec eax;

            jne @LOOP2;

        
        emms;
        pop esi;pop edi;pop edx;pop ecx;pop ebx;pop eax;    // レジスタ復活
      end;

      //次への位置をずらす。
      l:=l+mzoomy;
  end;


  if InBMP.Height>iy+ih then exit;

  zy:=iy+ih-1;
  l:=(ih-1)*($FFFF+1);


  for y:=oy+th to oy+oh-1 do begin
      pBit2:=OutBMP.ScanLine[y];


      ///現在の入力画像の高さ位置を計算
      //if zy<>iy+(l shr 8) then begin
      //   zy:=iy+(l shr 8);

         pBitN :=InBMP.ScanLine[zy-1];
         pBit:=InBMP.ScanLine[zy];
      //end;
      //バイリニアの割合（Y方向）
      l3:=(l-((l shr 16) shl 16))shr 8;//py


      asm
        push eax;push ebx;push ecx;push edx;push edi;push esi; // レジスタ退避

        //ピクセル位置
        mov edi,pBit;//Src
        mov esi,pBitN;//Src+1
        mov ebx,pBit2;//Dest

        //カウンター。
        mov eax,ew;

        //位置を調整。
        add ebx,ox4;


        //あまっているのは、ecx,edx
        mov ecx,ix8;//位置の絶対位置情報と値の保持

        //初期化
        pxor mm6,mm6;
        movd mm7,iMM4;//mm7には、$00FF00FFが入る。
        punpckldq mm7,mm7;//$00FF00FF 00FF00FFとコピーする。dword>qword

        //まずは、通常のループです。
        @LOOP1:
         //取得位置を指定。

            //元画像の位置を計算。
            mov edx,ecx;
            shr edx,16;

            //元画像のポインタを移動
            //元画像の入力(64ビット入力。)
            movq mm2,qword ptr[edi+edx*4];
            movq mm3,qword ptr[esi+edx*4];
            movq mm0,mm2;
            movq mm1,mm3;

            //元画像を整頓
            psrlq mm2,32;
            psrlq mm3,32;

            //QWORDに広げて計算できるようにする。
            punpcklbw mm0,mm6;// a
            punpcklbw mm1,mm6;// b
            punpcklbw mm2,mm6;// c
            punpcklbw mm3,mm6;// d

            //PXの計算。k-(zx shl 8);
            shl  edx,16;
            movd mm4,ecx;
            movd mm5,edx;
            psubd mm4,mm5;
            psrld mm4,8;

            //αを広げておく
            punpcklwd mm4,mm4;// $00aa > $00aa00aa
            punpckldq mm4,mm4;// $00aa00aa > $00aa00aa 00aa00aa
            movq  mm5,mm7;//反転用mm7
            psubw mm5,mm4;//反転完了。

	    //(px*py*(a+d-b-c) shr 8)+px*(b-a)+py*(c-a)) shr 8)+a;
            pmullw mm0, mm5; // a * px
            pmullw mm1, mm5; // c * px
            pmullw mm2, mm4; // b * (1 - px)
            pmullw mm3, mm4; // d * (1 - px)

            //PYの計算。といっても計算済み。
            movd mm4,l3; // a_dy
            punpcklwd mm4,mm4; //ワードからダブルワードへ
            punpckldq mm4,mm4; // 0x00bb00bb 00bb00bb
            movq mm5, mm7;//反転用mm7
            psubw mm5,mm4;//反転完了。

            //続き。
            paddusw mm0, mm2;  // (a * px + b * (1 - px))
            paddusw mm1, mm3;  // (c * px + d * (1 - px))
            psrlw mm0, 8;
            psrlw mm1, 8;
            pmullw mm0, mm5; // (a * px + b * (1 - px)) * py
            pmullw mm1, mm4; // (c * px + d * (1 - px)) * (1 - py)
            paddusw  mm0, mm1;  //
            psrlw    mm0, 8;
            packuswb mm0, mm6; // 0x00 00 00 00 B1' R0' G0' B0'

            //出力の準備
            movd dword ptr[ebx],mm0;
            add ebx,4;

            //Kを増やす。
            add ecx,mzoomx;

            dec eax;

            jne @LOOP1;

        //引き続き右端の特殊ループ、。

        //カウンター。
        mov eax,ew2;

        //あまっているのは、ecx,edx
        //mov ecx,ix8_2;//位置の絶対位置情報と値の保持

        //戻す
        sub ecx,mzoomx;

        @LOOP2:
         //取得位置を指定。

            //元画像の位置を計算。
            mov edx,ecx;
            shr edx,16;

            //元画像のポインタを移動
            //元画像の入力(64ビット入力。)
            movq mm0,qword ptr[edi+edx*4];
            movq mm1,qword ptr[esi+edx*4];
            movq mm2,mm0;
            movq mm3,mm1;

            //元画像を整頓
            psrlq mm2,32;
            psrlq mm3,32;

            //QWORDに広げて計算できるようにする。
            punpcklbw mm0,mm6;// a
            punpcklbw mm1,mm6;// c
            punpcklbw mm2,mm6;// b
            punpcklbw mm3,mm6;// d

            //PXの計算。k-(zx shl 8);
            shl  edx,16;
            movd mm4,ecx;
            movd mm5,edx;
            psubd mm4,mm5;
            psrld mm4,8;

            //αを広げておく
            punpcklwd mm4,mm4;// $00aa > $00aa00aa
            punpckldq mm4,mm4;// $00aa00aa > $00aa00aa 00aa00aa
            movq  mm5,mm7;//反転用mm7
            psubw mm5,mm4;//反転完了。

	    //(px*py*(a+d-b-c) shr 8)+px*(b-a)+py*(c-a)) shr 8)+a;
            pmullw mm0, mm5; // a * px
            pmullw mm1, mm5; // c * px
            pmullw mm2, mm4; // b * (1 - px)
            pmullw mm3, mm4; // d * (1 - px)

            //PYの計算。といっても計算済み。
            movd mm4,l3; // a_dy
            punpcklwd mm4,mm4; //ワードからダブルワードへ
            punpckldq mm4,mm4; // 0x00bb00bb 00bb00bb
            movq mm5, mm7;//反転用mm7
            psubw mm5,mm4;//反転完了。

            //続き。
            paddusw mm0, mm2;  // (a * px + b * (1 - px))
            paddusw mm1, mm3;  // (c * px + d * (1 - px))
            psrlw mm0, 8;
            psrlw mm1, 8;
            pmullw mm0, mm5; // (a * px + b * (1 - px)) * py
            pmullw mm1, mm4; // (c * px + d * (1 - px)) * (1 - py)
            paddusw  mm0, mm1;  //
            psrlw    mm0, 8;
            packuswb mm0, mm6; // 0x00 00 00 00 B1' R0' G0' B0'

            //出力の準備
            movd dword ptr[ebx],mm0;
            add ebx,4;

            //Kを増やす。
            add ecx,mzoomx;

            dec eax;

            jne @LOOP2;


        emms;
        pop esi;pop edi;pop edx;pop ecx;pop ebx;pop eax;    // レジスタ復活
      end;

      //次への位置をずらす。
      l:=l+mzoomy;
  end;

end;


(*ノイズを発生させる*)
procedure EffectNoize(var SrcBitmap:TBitmap;noise:smallInt;const mode:shortInt);
var
 Row,Col,val,value  : Integer;
 DestRow,SrcRow     : pRGBArray;
 DestBitmap: TBitmap;
begin


 if(srcBitmap.Width*srcBitmap.Height=0)or(noise=0)then exit;

 DestBitmap:=TBitmap.Create;
 set32bit(SrcBitmap,DestBitmap);
 value:=noise*2+1;
 Randomize();

try
  //バラバラノイズ
  if(mode=2)then
  begin
   for Row:=0 to DestBitmap.Height-1 do
   begin
    DestRow:=DestBitmap.ScanLine[Row];
    SrcRow:=SrcBitmap.ScanLine[Row];
    for Col:=0 to DestBitmap.Width-1 do
     begin
      DestRow[Col].rgbBlue  :=RoundByte(SrcRow[Col].rgbBlue+random(value)-noise);
      DestRow[Col].rgbGreen :=RoundByte(SrcRow[Col].rgbGreen+random(value)-noise);
      DestRow[Col].rgbRed   :=RoundByte(SrcRow[Col].rgbRed+random(value)-noise);
     end;
   end;
   SrcBitmap.Handle :=DestBitmap.ReleaseHandle;
  end
  //単一ノイズ
  else if(mode=1)then
  begin
   for Row:=0 to DestBitmap.Height-1 do
   begin
    DestRow:=DestBitmap.ScanLine[Row];
    SrcRow:=SrcBitmap.ScanLine[Row];
    for Col:=0 to DestBitmap.Width-1 do
     begin
      val:=random(value)-noise;
      DestRow[Col].rgbBlue  :=RoundByte(SrcRow[Col].rgbBlue+val);
      DestRow[Col].rgbGreen :=RoundByte(SrcRow[Col].rgbGreen+val);
      DestRow[Col].rgbRed   :=RoundByte(SrcRow[Col].rgbRed+val);
     end;
   end;
   SrcBitmap.Handle :=DestBitmap.ReleaseHandle;
  end;
except
  windows.MessageBox(0,'ノイズエラー','EffectMono',MB_OK);
end;

  DestBitmap.free;
end;

(*クリップ*)
procedure EffectClip(var SrcBitmap:TBitmap;Clip:TRect);
var
 h,w:Integer;
 //bitmap:TBitmap;
begin
 if(srcBitmap.Width*srcBitmap.Height=0)then exit;
 //bitmap:=TBitmap.Create();
// bitmap.PixelFormat:=pf32bit;

 w:=min(srcBitmap.Width,Clip.Right-Clip.Left);
 h:=min(SrcBitmap.Height,Clip.Bottom-Clip.Top);

// bitmap.Width:=w;
// bitmap.Height:=h;

 bitblt(srcBitmap.Canvas.Handle,0,0,w,h,
  srcBitmap.Canvas.Handle,clip.Left,clip.Top,srcCopy);

 //EffectResizeNormal(0,0,w,h,clip.Left,clip.Top,w,h,SrcBitmap,SrcBitmap);
 SrcBitmap.Width:=w;
 SrcBitmap.Height:=h;

 // SrcBitmap.Handle:=Bitmap.ReleaseHandle;

//  Bitmap.Free;
end;

(*サイズ変更*)
procedure EffectResize
 (Var srcBitmap:TBitmap;const width,height:Integer;smooth:boolean=false);
var
 DestBitmap: TBitmap;
begin

  if(width*height=0)then
  begin
   srcBitmap.Width:=width;
   srcBitmap.Height:=height;
   exit;
  end;

  srcBitmap.PixelFormat:=pf32bit;
  DestBitmap:=TBitmap.Create;
  DestBitmap.PixelFormat:=pf32bit;
  DestBitmap.Width:=width;
  DestBitmap.Height:=height;
  if(smooth)then
   EffectResizeSmooth(0,0,srcBitmap.Width,srcBitmap.Height,
    0,0,width,height,srcBitmap,DestBitmap)
  else
   EffectResizeNormal(0,0,srcBitmap.Width,srcBitmap.Height,
    0,0,width,height,srcBitmap,DestBitmap);
  SrcBitmap.Handle:=DestBitmap.ReleaseHandle;

  DestBitmap.Free;
end;

procedure EffectThreadLine(var SrcBitmap:TBitmap;const effect:Integer=0);
var
 transcolor:DWORD;
 SrcColor:pRGBArray;
 odd:byte;
 Row,Col,len:Integer;
 rgb:TRGBQUAD;
const
 VERTICAL=1;
 HORIZON=2;
 MESH=3;
begin

 if(srcBitmap.Width*srcBitmap.Height=0)then exit;

 SrcBitmap.PixelFormat:=pf32bit;
 SrcBitmap.Canvas.Pen.Color:=SrcBitmap.Canvas.Pixels[0,0];

 case effect of
 VERTICAL:
 begin
  len:=SrcBitmap.Height;
  for Col:=0 to SrcBitmap.Width div 2 -1 do
  begin
   SrcBitmap.Canvas.MoveTo(2*Col,0);
   SrcBitmap.Canvas.LineTo(2*Col,len);
  end;
 end;

 HORIZON:
 begin
  len:=SrcBitmap.Width;
  for Row:=0 to SrcBitmap.Height div 2 -1 do
  begin
   SrcBitmap.Canvas.MoveTo(0,2*Row);
   SrcBitmap.Canvas.LineTo(len,2*Row);
  end
 end;

 MESH:
 begin

  odd:=SrcBitmap.Width mod 2;//偶数か奇数か
  transcolor:=SrcBitmap.Canvas.Pixels[0,0];
  rgb.rgbBlue:=(transcolor and $00ff0000) shr 16;
  rgb.rgbRed:=transcolor and $000000ff;
  rgb.rgbGreen:=(transcolor and $0000ff00)shr 8;

  len:=SrcBitmap.Width div 2;

  for Row:=0 to (SrcBitmap.Height div 2)-1 do
  begin


  SrcColor:=SrcBitmap.ScanLine[Row*2];


   for Col:=0 to len -1 do
   begin
    SrcColor[col*2]:=rgb;
   end;


   if(len>=(Row+1))then
   begin
    SrcColor:=SrcBitmap.ScanLine[Row*2+1];
    for Col:=0 to len -1+odd do
    begin
     SrcColor[col*2+1]:=rgb;
    end;


   end;

  end;


 end;

 end;
 // SrcBitmap.SaveToFile('sub.bmp');
end;

//二階調
procedure EffectMono(var SrcBitmap:TBitmap;value:smallInt);
var
 Row,Col            : Integer;
 SrcRow,DestRow     : pRGBArray;
 DestBitmap: TBitmap;
begin

 if(srcBitmap.Width*srcBitmap.Height=0)then exit;

 DestBitmap:=TBitmap.Create;
 set32bit(SrcBitmap,DestBitmap);

try
  for Row:=0 to DestBitmap.Height-1 do
  begin
      SrcRow:=SrcBitmap.ScanLine[Row];
      DestRow:=DestBitmap.ScanLine[Row];
      for Col:=0 to DestBitmap.Width-1 do
      begin
       if  (SrcRow[Col].rgbBlue <=Value) and
           (SrcRow[Col].rgbred <=Value) and
           (SrcRow[Col].rgbGreen <=Value) then
       begin
         DestRow[Col].rgbBlue  :=0;
         DestRow[Col].rgbGreen :=0;
         DestRow[Col].rgbRed   :=0;
       end
       else
       begin
         DestRow[Col].rgbBlue  :=255;
         DestRow[Col].rgbGreen :=255;
         DestRow[Col].rgbRed   :=255;
       end;
      end;
  end;
  SrcBitmap.Handle :=DestBitmap.ReleaseHandle;
except
  windows.MessageBox(0,'画像処理エラー','EffectMono',MB_OK);
end;

  DestBitmap.free;
end;

//RGBチェンジ
procedure EffectShiftRGB(var SrcBitmap: TBitmap;mode:Integer);
var
  Row,Col         : Integer;
  SrcRow,DestRow  : pRGBArray;
  DestBitmap     : TBitmap;
const
 GBR=1;
 BRG=2;
 GR=3;
 BR=4;
 BG=5;
begin

  if(srcBitmap.Width*srcBitmap.Height=0)then exit;

  if(mode<1)or(mode>5)then exit;

  DestBitmap  :=TBitmap.Create;
  set32bit(SrcBitmap,DestBitmap);

  try
    for Row := 0 to SrcBitmap.Height - 1 do
    begin
      SrcRow  := SrcBitmap.Scanline[Row];
      DestRow := DestBitmap.Scanline[Row];

      for Col := 0 to SrcBitmap.Width - 1 do
      begin
       case mode of
        GBR:
        begin
         DestRow[Col].rgbRed   :=SrcRow[Col].rgbGreen;
         DestRow[Col].rgbGreen :=SrcRow[Col].rgbBlue;
         DestRow[Col].rgbBlue  :=SrcRow[Col].rgbRed;
        end;
        BRG:
        begin
         DestRow[Col].rgbRed   :=SrcRow[Col].rgbBlue;
         DestRow[Col].rgbGreen :=SrcRow[Col].rgbRed;
         DestRow[Col].rgbBlue  :=SrcRow[Col].rgbGreen;
        end;
        GR:
        begin
         DestRow[Col].rgbRed   :=SrcRow[Col].rgbGreen;
         DestRow[Col].rgbGreen :=SrcRow[Col].rgbRed;
         DestRow[Col].rgbBlue  :=SrcRow[Col].rgbBlue;
        end;
        BR:
        begin
         DestRow[Col].rgbRed   :=SrcRow[Col].rgbBlue;
         DestRow[Col].rgbBlue :=SrcRow[Col].rgbRed;
         DestRow[Col].rgbGreen   :=SrcRow[Col].rgbGreen;
        end;
        BG:
        begin
         DestRow[Col].rgbGreen   :=SrcRow[Col].rgbBlue;
         DestRow[Col].rgbBlue :=SrcRow[Col].rgbGreen;
         DestRow[Col].rgbRed :=SrcRow[Col].rgbRed;
        end;
       end;
     end;
    end;
     SrcBitmap.Handle :=DestBitmap.ReleaseHandle;
  except
   windows.MessageBox(0,'画像処理エラー','ShiftRGB',MB_OK);
  end;

  DestBitmap.Free;
end;


 //明るさ
procedure EffectLightMode(var SrcBitmap: TBitmap;Value:Integer);
var
  Row,Col         : Integer;
  SrcRow,DestRow  : pRGBArray;
  DestBitmap     : TBitmap;
begin

  if(srcBitmap.Width*srcBitmap.Height=0)then exit;

  DestBitmap  :=TBitmap.Create;
  set32bit(SrcBitmap,DestBitmap);

  try
    for Row := 0 to SrcBitmap.Height - 1 do
    begin
      SrcRow  := SrcBitmap.Scanline[Row];
      DestRow := DestBitmap.Scanline[Row];
      for Col := 0 to SrcBitmap.Width - 1 do
      begin
          //各RGBにValueを足す
          DestRow[Col].rgbRed   :=RoundByte(SrcRow[Col].rgbRed+Value);
          DestRow[Col].rgbGreen :=RoundByte(SrcRow[Col].rgbGreen+Value);
          DestRow[Col].rgbBlue  :=RoundByte(SrcRow[Col].rgbBlue+Value) ;
      end;
    end;
     SrcBitmap.Handle :=DestBitmap.ReleaseHandle;
  except
   windows.MessageBox(0,'画像処理エラー','lights',MB_OK);
  end;

  DestBitmap.Free;
end;


//セピア
procedure EffectSepia(var SrcBitmap :TBitmap;effect:Integer=0);
var
  Row,Col           : Integer;
  SrcRow,DestRow    : pRGBArray;
  RGBColor          : BYTE;
  DestBitmap: TBitmap;
const
  tune:array[1..15, 0..2] of smallInt=
  ((0,0,0),(30,0,-30),(255,0,30),(255,0,0),
  (0,255,0),(0,0,255),(191,191,0),(191,0,191),(0,191,191),
  (0,-255,-255),(-255,0,-255),(-255,-255,0),(0,0,-255),
  (0,-255,0),(-255,0,0));

begin

  if(srcBitmap.Width*srcBitmap.Height=0)then exit;

  if(SrcBitmap=nil)or(effect>Length(tune))or(effect<1)then exit;

  DestBitmap   :=TBitmap.Create;
  set32bit(SrcBitmap,DestBitmap);

try
  for Row:=0 to SrcBitmap.Height-1 do
  begin
    SrcRow:=SrcBitmap.ScanLine[Row];
    DestRow:=DestBitmap.ScanLine[Row];
    for Col:=0 to SrcBitmap.Width-1 do
    begin
      //NTSC系加重平均法を用いてグレースケール化
      RGBColor:=RoundByte(
                  (Round(SrcRow[Col].rgbRed   *0.289+
                         SrcRow[Col].rgbGreen *0.586+
                         SrcRow[Col].rgbBlue  *0.114 )));

      // 色のバランスを調整する
      DestRow[Col].rgbRed  :=RoundByte(RGBColor +tune[effect,0]);
      DestRow[Col].rgbGreen:=RoundByte(RGBColor +tune[effect,1]);
      DestRow[Col].rgbBlue :=RoundByte(RGBColor +tune[effect,2]);
    end;
  end;
  SrcBitmap.Handle:=DestBitmap.ReleaseHandle;
except
 windows.MessageBox(0,'画像処理エラー','colormap',MB_OK);
end;

  DestBitmap.Free();
end;


//左右反転
procedure EffectMirror(var SrcBitmap :TBitmap);
var
 Row,Col        : integer;
 SrcRow,DestRow : pRGBArray;
 DestBitmap     : TBitmap;
begin

 if(SrcBitmap=nil)or(srcBitmap.Width*srcBitmap.Height=0)then exit;
 DestBitmap  :=TBitmap.Create;

 set32bit(SrcBitmap,DestBitmap);

 Try
  for Row:=DestBitmap.Height-1 Downto 0 do
  begin
   SrcRow:=SrcBitmap.ScanLine[Row];
   DestRow:=DestBitmap.ScanLine[Row];

   for Col:=0 to DestBitmap.Width-1 do
   begin
    DestRow[Col]:=SrcRow[SrcBitmap.Width-Col-1];
   end;
  end;
 SrcBitmap.Handle:=DestBitmap.ReleaseHandle;
except
 windows.MessageBox(0,'画像処理エラー','mirror',MB_OK);
end;

 DestBitmap.Free;
end;

//上下反転
procedure EffectFlip(var SrcBitmap :TBitmap);
var
  Row,Col            : Integer;
  SrcRow,DestRow     : PDWORDArray;
  DestBitmap  : TBitmap;
begin

  if(SrcBitmap=nil)or(srcBitmap.Width*srcBitmap.Height=0)then exit;

  DestBitmap  :=TBitmap.Create;
  set32bit(SrcBitmap,DestBitmap);
  destBitmap.PixelFormat:=pf32bit;
  srcBitmap.PixelFormat:=pf32bit;
try
  for Row:=DestBitmap.Height-1 Downto 0 do
  begin
   SrcRow:=SrcBitmap.ScanLine[DestBitmap.Height-Row-1];
   DestRow:=DestBitmap.ScanLine[Row];

   for Col:=0 to DestBitmap.Width-1 do
   begin
    DestRow[Col]:=SrcRow[Col];
   end;
  end;

  //bitblt(SrcBitmap.Canvas.Handle,0,0,srcbitmap.Width,srcBitmap.Height,
 //   DestBitmap.Canvas.Handle,0,0,srcCopy);
 // srcBitmap.SaveToFile('j:\stest.bmp');
 // destBitmap.SaveToFile('j:\dtest.bmp');
  SrcBitmap.Handle := DestBitmap.ReleaseHandle;
except
  windows.MessageBox(0,'画像処理エラー','flip',MB_OK);
end;

// DestBitmap.Free;
end;

//エンボス
procedure EffectEnbos(var SrcBitmap :TBitmap);
var
  Row,Col         : Integer;
  _Height,_Width  : integer;
  DestBitmap   : TBitmap;
  SrcRow,SrcRow2,DestRow : pRGBArray;
  Origin,Origin_RightUp,HogeRGB,X   : integer;
begin

 DestBitmap  :=TBitmap.Create;
 set32bit(SrcBitmap,DestBitmap);
 _Height := SrcBitmap.height-1;
 _Width  := SrcBitmap.width-1;

try
  if(SrcBitmap=nil)or(srcBitmap.Width*srcBitmap.Height=0)then exit;

    For Row := 0 To _Height   do
    begin
        SrcRow :=SrcBitmap.ScanLine[Row];

        //範囲オーバーチェック
        if Row<>_Height  then
         SrcRow2:=SrcBitmap.ScanLine[Row+1]
        else
         SrcRow2:=SrcBitmap.ScanLine[Row];
         DestRow:=DestBitmap.ScanLine[Row];

        For Col := 0 To _Width do
        begin
            //簡易YIQ階調取得
            Origin:= (SrcRow[Col].rgbRed+SrcRow[Col].rgbGreen+SrcRow[Col].rgbBlue) div 3;

            //範囲オーバーチェック
            if Col = _Width Then
                X := Col
            else
                X := Col + 1;

            //簡易YIQ階調取得(起点の右上)
            Origin_RightUp:= (SrcRow2[X].rgbRed+SrcRow2[X].rgbGreen+SrcRow2[X].rgbBlue) div 3;

            //エンボス化
            HogeRGB := -Origin + Origin_RightUp + 128;
            If HogeRGB < 0 Then  HogeRGB := 0  ;

            DestRow[Col].rgbBlue := HogeRGB;
            DestRow[Col].rgbGreen:= HogeRGB;
            DestRow[Col].rgbRed  := HogeRGB;
      end;
    end;

 SrcBitmap.Handle := DestBitmap.ReleaseHandle;
except
 windows.MessageBox(0,'画像処理エラー','Enbos',MB_OK);
end;
 DestBitmap.free;
end;

//ネガポジ反転
procedure EffectNOTMask(var srcBitmap: TBitmap);
var
  Row,Col          : Integer;
  SrcRow,DestRow   : pRGBArray;
  _Height,_Width   : integer;
  DestBitmap : TBitmap;
begin

 DestBitmap  :=TBitmap.Create;
 set32bit(SrcBitmap,DestBitmap);
 _Height := SrcBitmap.height-1;
 _Width  := SrcBitmap.width-1;

try

 if(SrcBitmap=nil)or(srcBitmap.Width*srcBitmap.Height=0)then exit;

   For Row := 0 To _Height   do
   begin
       SrcRow:=SrcBitmap.ScanLine[Row];
       DestRow:=DestBitmap.ScanLine[Row];
       For Col := 0 To _Width do
       begin
        DestRow[Col].rgbBlue := not SrcRow[Col].rgbBlue ;
        DestRow[Col].rgbGreen:= not SrcRow[Col].rgbGreen;
        DestRow[Col].rgbRed  := not SrcRow[Col].rgbRed ;
       end;
    end;
  SrcBitmap.handle :=DestBitmap.ReleaseHandle;
except
 windows.MessageBox(0,'画像処理エラー','nega',MB_OK);
end;
  DestBitmap.Free;
end;

//拡散
procedure EffectKakusan(var srcBitmap: TBitmap);
var
  Row,Col,hoge,foo: Integer;
  SrcRow,DestRow   : pRGBArray;
  DestBitmap : TBitmap;
begin
   if(srcBitmap.Width*srcBitmap.Height=0)then exit;
 DestBitmap  :=TBitmap.Create;
 SrcBitmap.Pixelformat:=pf32bit;
 DestBitmap.Assign(Srcbitmap);

try
   For Row := 0 To SrcBitmap.height-1   do
   begin
       //起点を中心にしてその付近をランダムで求める
       foo:=abs(Row-(Random(4))+2);
       if foo>SrcBitmap.height-1 then foo:=SrcBitmap.height-1
       else if foo<0 then foo:=0;

       SrcRow:=SrcBitmap.ScanLine[foo];
       DestRow:=DestBitmap.ScanLine[Row];

        For Col := 0 To SrcBitmap.Width-1 do
        begin
           //起点を中心にしてその付近をランダムで求める
           hoge:=abs(Col-(Random(4))+2);
           if hoge>SrcBitmap.Width-1 then hoge:=SrcBitmap.Width-1
           else if hoge<0 then hoge:=0;

           DestRow[Col]:=SrcRow[hoge];

       end;
    end;
  SrcBitmap.Handle :=DestBitmap.ReleaseHandle;
except
 windows.MessageBox(0,'画像処理エラー','spread',MB_OK);
end;

  DestBitmap.Free;
end;


//多様な画像修飾
procedure EffectCustom(var SrcBitmap: TBitmap;masktype:Integer);
var
  Row,Col,yRow,xCol,r,g,b,X,y,EAX: Integer;
  DestRow          : pRGBArray;
  SourceBits       : PPBits;
  _Height,_Width   : integer;
  DestBitmap  : TBitmap;
  MaskBits : array[0..8] of Smallint;
  Divisor,Bias:byte;
begin

 if(SrcBitmap=nil)or(srcBitmap.Width*srcBitmap.Height=0)then exit;

 case masktype of
  1:
  begin //ぼかし
   Bias:=0;
   Divisor:=9;
   MaskBits[0]:= 1;   MaskBits[1]:= 1;   MaskBits[2]:= 1;
   MaskBits[3]:= 1;   MaskBits[4]:= 1;   MaskBits[5]:= 1;
   MaskBits[6]:= 1;   MaskBits[7]:= 1;   MaskBits[8]:= 1;
  end;
  2:
  begin //シャープ
   Bias:=0;
   Divisor:=16;
   MaskBits[0]:= -1;  MaskBits[1]:= -1;   MaskBits[2]:= -1;
   MaskBits[3]:= -1;  MaskBits[4]:= 24;   MaskBits[5]:= -1;
   MaskBits[6]:= -1;  MaskBits[7]:= -1;   MaskBits[8]:= -1;
  end;
  3:
  begin //サンパワー
   Bias:=0;
   Divisor:=16;
   MaskBits[0]:= 1;   MaskBits[1]:= 3;   MaskBits[2]:= 1;
   MaskBits[3]:= 3;   MaskBits[4]:= 5;   MaskBits[5]:= 3;
   MaskBits[6]:= 1;   MaskBits[7]:= 3;   MaskBits[8]:= 1;
  end;
  4:
  begin //カラーエンボス
   Divisor:=1; Bias:=0;
   MaskBits[0]:= -1;   MaskBits[1]:= -1;   MaskBits[2]:=-1;
   MaskBits[3]:= 0;    MaskBits[4]:= 1;    MaskBits[5]:= 0;
   MaskBits[6]:= 1;    MaskBits[7]:= 1;    MaskBits[8]:= 1;
  end;
  5:
  begin
   //ダークエンボス
   Divisor:=1; Bias:=128;
   MaskBits[0]:= -1;    MaskBits[1]:= -2;   MaskBits[2]:= -1;
   MaskBits[3]:=  0;    MaskBits[4]:=  0;   MaskBits[5]:=  0;
   MaskBits[6]:=  1;    MaskBits[7]:=  2;   MaskBits[8]:=  1;
  end;
  6:
  begin
   //エレクトリカル
   Divisor:=1; Bias:=0;
   MaskBits[0]:=  1;    MaskBits[1]:=  1;   MaskBits[2]:=  1;
   MaskBits[3]:=  1;    MaskBits[4]:=-15;   MaskBits[5]:=  1;
   MaskBits[6]:=  1;    MaskBits[7]:=  1;   MaskBits[8]:=  1;
  end;
  else
  begin
   exit;
  end;
 end;

 DestBitmap  :=TBitmap.Create;
 set32bit(SrcBitmap,DestBitmap);
 _Height := SrcBitmap.height-1;
 _Width  := SrcBitmap.width-1;

   GetMem(SourceBits, SrcBitmap.Height * SizeOf(pRGBArray));
try
   for Row:= 0 to SrcBitmap.Height - 1 do  SourceBits[Row]:=SrcBitmap.Scanline[Row];

   For Row := 0 To _Height   do
   begin

        DestRow:=DestBitmap.ScanLine[Row];

        For Col := 0 To _Width do
        begin
            //-------------
            // 0 - 1 - 2
            //-------------
            // 3 - 4 - 5
            //-------------
            // 6 - 7 - 8
            //-------------
            R:=0;G:=0;B:=0; EAX:=0;
            for y:= -1 to 1 do
            begin
              for x:= -1 to 1 do
              begin
                 //Y軸
                 if      Row+(y)> _Height then
                  yRow:=_Height
                 else if Row+(y)< 0       then
                  yRow:=0
                 else
                   yRow:=Row+(y);
                 //X軸
                 if      Col+(x)> _Width  then  xCol:=_Width
                 else if Col+(x)< 0       then  xCol:=0
                 else
                   xCol:=Col+(x);

                 B:=B+(SourceBits[yRow][xCol].rgbBlue*MaskBits[EAX]);
                 G:=G+(SourceBits[yRow][xCol].rgbGreen*MaskBits[EAX]);
                 R:=R+(SourceBits[yRow][xCol].rgbRed*MaskBits[EAX]);
                 inc(EAX);
              end;
            end;

         //  DestRow[col].rgbReserved:=SourceBits[yRow][xCol].rgbReserved;
           DestRow[Col].rgbRed   :=RoundByte((R div Divisor)+Bias);
           DestRow[Col].rgbGreen :=RoundByte((G div Divisor)+Bias);
           DestRow[Col].rgbBlue  :=RoundByte((B div Divisor)+Bias);

       end;
    end;

  FreeMem(SourceBits); SourceBits:=nil;
  SrcBitmap.handle :=DestBitmap.ReleaseHandle;

  except
     if Assigned(SourceBits) then FreeMem(SourceBits);
    windows.MessageBox(0,'画像処理エラー','EffectCustom',MB_OK); 
  end;

  DestBitmap.Free;
end;





end.


