2012-05-01 25 views
2

2つのPNGをマージするにはどうすればよいですか?私はPNGObject.Drawを使用できないことを知っています。なぜなら、alpha transperncy(私はわかりませんが、とにかく動作しません)をコピーしないので、カスタムプロシージャ/関数が必要です。私は空の手が付属して、私は、この手順を持っていなかった。他のPNGでPNG画像をペイント

procedure MergePNGLayer(Layer1,Layer2: TPNGObject; Const aLeft,aTop:Integer); 
var 
    x, y: Integer; 
    SL1, SL2, SLBlended : pRGBLine; 
    aSL1, aSL2, aSLBlended: PByteArray; 
    blendCoeff: single; 
    blendedPNG, Lay2buff: TPNGObject; 
begin 
    blendedPNG:=TPNGObject.Create; 
    blendedPNG.Assign(Layer1); 
    Lay2buff:=TPNGObject.Create; 
    Lay2buff.Assign(Layer2); 
    SetPNGCanvasSize(Layer2,Layer1.Width,Layer1.Height,aLeft,aTop); 
    for y := 0 to Layer1.Height-1 do 
    begin 
    SL1 := Layer1.Scanline[y]; 
    SL2 := Layer2.Scanline[y]; 
    aSL1 := Layer1.AlphaScanline[y]; 
    aSL2 := Layer2.AlphaScanline[y]; 
    SLBlended := blendedPNG.Scanline[y]; 
    aSLBlended := blendedPNG.AlphaScanline[y]; 
    for x := 0 to Layer1.Width-1 do 
    begin 
     blendCoeff:=aSL1[x] * 100/255/100; 
     aSLBlended[x] := round(aSL2[x] + (aSL1[x]-aSL2[x]) * blendCoeff); 
     SLBlended[x].rgbtRed := round(SL2[x].rgbtRed + (SL1[x].rgbtRed-SL2[x].rgbtRed) * blendCoeff); 
     SLBlended[x].rgbtGreen := round(SL2[x].rgbtGreen + (SL1[x].rgbtGreen-SL2[x].rgbtGreen) * blendCoeff); 
     SLBlended[x].rgbtBlue := round(SL2[x].rgbtBlue + (SL1[x].rgbtBlue-SL2[x].rgbtBlue) * blendCoeff); 
    end; 
    end; 
Layer1.Assign(blendedPNG); 
Layer2.Assign(Lay2buff); 
blendedPNG.Free; 
Lay2buff.Free; 
end; 

しかし、悲しいことに、それは、それは仕事が、右はしません方法を動作しません。空のイメージと読み込まれたイメージをマージすると正常に動作しますが、両方のイメージが空でなければ、イメージが失われます。

procedure TForm1.FormClick(Sender: TObject); 
var 
PNG1, PNG2, PNG3, Dest: TPNGObject; 
begin 
PNG1 := TPNGObject.Create; 
PNG2 := TPNGObject.Create; 
PNG3 := TPNGObject.Create; 

PNG1.LoadFromFile('Aero\TopLeft.png');//Width 10 
PNG2.LoadFromFile('Aero\Top.png');//Width 200 
PNG3.LoadFromFile('Aero\TopRight.png');//Width 10 

Dest := TPNGObject.CreateBlank(COLOR_RGBALPHA, 16, 220, 10); 
MergePNGLayer(Dest, PNG1, 0, 0); 
MergePNGLayer(Dest, PNG2, 10, 0); 
MergePNGLayer(Dest, PNG3, 210, 0); 
Dest.SaveToFile('C:\OUT.PNG'); 
end; 

募集結果:

enter image description here

実際の結果:あなたはこれらのimgaesの違いを見ることができれば

enter image description here

私はわかりませんが、あなたはこれらを開く必要がありますPNGエディタソフトウェアを使用すると、その違いがわかります。ですから、PNGをマージするには別の手順が必要です。私はちょうどPNGImageの最新バージョンを使用しています。

ありがとうございました!

+1

あなたは 'ビット深度= 16'と4色のチャンネルを持つあなたはに' CreateBlank'てもよろしいですか? – TLama

答えて

5

これがうまく動作するようです:

procedure DrawPngWithAlpha(Src, Dest: TPNGObject; const R: TRect); 
var 
    X, Y: Integer; 
    Alpha: PByte; 
begin 
    Src.Draw(Dest.Canvas, R); 

    // I have no idea why standard implementation of TPNGObject.Draw doesn't apply transparency. 
    for Y := R.Top to R.Bottom - 1 do 
    for X := R.Left to R.Right - 1 do 
    begin 
     Alpha := @Dest.AlphaScanline[Y]^[X]; 
     Alpha^ := Min(255, Alpha^ + Src.AlphaScanline[Y - R.Top]^[X - R.Left]); 
    end; 
end; 
+1

'Draw'を呼び出す前に' TPngObject.TransparencyMode'とは何ですか?それは 'ptmBit = 1'以外のものですか?とにかく単純な*可能な回避策のために+1してください;-) – TLama

+0

@TLama前に 'TransparencyMode'を使わなかった、全ての画像は_fresh_です –