あんまり早くないと思うけど、今使ってる奴

procedure  SetBlendBMP(bmpRet:TBitmap;x1,y1,blend:Integer;bmp1,bmp2:TBitmap);
type TRGB = packed record r,g,b:Byte ; end;
type TaRGB=array[0..32767] of TRGB;
type TPaRGB= ^TaRGB;
type TADWORD =array [0..100] of cardinal;
type TPADWORD =^TADWORD;
var p1,p2,pe:TPaRGB;
var a1:TPADWORD absolute p1;
var a2:TPADWORD absolute p2;
var d3:TPADWORD absolute pe;
var y4,y4s,ymax,x,y,a,b:cardinal;
var c:TRGB;
function M32(a, Y: cardinal): cardinal; register;
asm
 MUL  Y
 SHRD  EAX,EDX,8
end;
begin
 a:=(blend*256) div 100;
 b:=256-a;
 ymax:=bmp1.Width;
 y4 :=(ymax*3) div 4;
 y4s := (y4*4) div 3;

 for y:=0 to bmp1.Height-1 do begin
  p1:=TPaRGB(bmp1 .ScanLine[y]);
  p2:=TPaRGB(bmp2 .ScanLine[y]);
  pe:=TPaRGB(bmpRet.ScanLine[y]);
  for x:=0 to y4-1 do
  begin
   d3^[x]:=
  ((M32(a1^[x]and $FF00FF00,a)
   +M32(a2^[x]and $FF00FF00,b) ) and $FF00FF00)
  or
  ((M32(a1^[x]and $00FF00FF,a)
   +M32(a2^[x]and $00FF00FF,b) ) and $00FF00FF) ;
  end;
  for x:=y4s to ymax-1 do
  begin
   c.r:=(p1^[x].r*a + p2^[x].r*b) div 256;
   c.g:=(p1^[x].g*a + p2^[x].g*b) div 256;
   c.b:=(p1^[x].b*a + p2^[x].b*b) div 256;
   pe^[x]:=c;
  end;
 end;
end;