2010-07-08 47 views
2
圖像映射提取圖像(PNG),並顯示

我試圖實現以下目標:使用上的TImage

假設一個大PNG(背景透明16000 X 70像素),其中包含50個不同的其他PNG文件... 我需要加載該PNG,並從中提取個別PNG(最好是例如有一種函數,我可以說coords(左,頂部,高度,寬度),我想提取的PNG ...提取PNG應該顯示在timage然後...

當然,我可以使用GIF圖像,再次重新創建動畫,但我需要PNG出於某種原因...

的想法是將其加載到一個ImageList但失敗了,因爲所有的50個png格式的有(320x70px)的TImageList的尺寸僅支持256PX寬度...

我的下一個想法是,也許我可以這樣做:

將Png加載到TBitmapArray中。那麼,提取工作相當不錯,但與所有正在失去alpha通道沒有什麼副作用是透明的,而不是了,我得到一個胖黑色邊框:-(

type 
    TRectArray = array of TRect; 
    TBitmapArray = array of TBitmap; 


// Zwei Funktionen die Rechtecke aufbereiten: 
function FixRect(SrcRect: TRect): TRect; 
    procedure Switch(var a,b: integer); 
    var c: integer; 
    begin 
    c := a; a := b; b := c; 
    end; 
begin 
    if SrcRect.Left > SrcRect.Right then 
    Switch(SrcRect.Left,SrcRect.Right); 
    if SrcRect.Top > SrcRect.Bottom then 
    Switch(SrcRect.Top,SrcRect.Bottom); 
    result := SrcRect; 
end; 

function TrimRect(SrcRect: TRect; minx,miny,maxx,maxy: integer): TRect; 
begin 
    result := fixrect(srcrect); 
    if result.Left < minx then result.left := minx; 
    if result.top < miny then result.top := miny; 
    if result.right > maxx then result.right := maxx; 
    if result.bottom > maxy then result.bottom := maxy; 
end; 

// Stanzt die in SrcRect übergebenen rechtecke aus SrcPNG aus und lädt sie ins 
// DstBitmapArray 
procedure GetBitmaps(const SrcPNG: TPNGObject; const SrcRects: TRectArray; 
    var DstBitmapArray: TBitmapArray); 
var 
    i: integer; 
    Rct: TRect; 
    Bmp: TBitmap; 
begin 
    // Bitmap vom PNG Erzeugen 
    Bmp := TBitmap.Create; 
    Bmp.Assign(SrcPNG); 
    // Länge der auszugebenden Bilderliste festlegen (=Anzahl der Rechtecke) 
    setlength(DstBitmapArray,high(SrcRects)+1); 
    for i := 0 to high(SrcRects) do 
    begin 
    // Bitmap erzeugen 
    DstBitmapArray[i] := TBitmap.Create; 
    // Rechteck vorbereiten mit obigen Funktionen (ggf Zurechtschneiden, 
    // falls es über die Grenzen des PNGs hinausgeht) 
    Rct := TrimRect(SrcRects[i],0,0,SrcPng.Width,SrcPNG.Height); 
    // Größe des Bitmaps setzen 
    DstBitmapArray[i].SetSize(rct.Right-rct.left,rct.bottom-rct.top); 
    // rechteck ausstanzen und auf Bitmap kopieren 
    BitBlt(DstBitmapArray[i].Canvas.Handle,0,0,DstBitmapArray[i].width, 
     DstBitmapArray[i].Height,bmp.Canvas.handle,rct.left,rct.top,srccopy); 
    end; 
    Bmp.free; 
end; 

// Stanzt ebenfalls Bilder aus dem PNG aus, die rechtecke werden aber im 
// Parameter Positions testbasiert übergeben. jede Zeile definiert ein rechteck 
// Die Koordinaten des Rechtecks werden in der reihenfolge Left, Top, Right, Bottom 
// angegeben und durch Kommata separiert. Beispiel: 
// 0,0,100,50 
// 100,0,100,100 
// etc... 
procedure LoadBitmaps(const SrcPNG: TPNGObject; const Positions: TStrings; 
    var DstBitmapArray: TBitmapArray); 
var 
    i: integer; 
    l: integer; 
    rectarray: TRectArray; 
    tmp: tstringlist; 
begin 
    setlength(rectarray,positions.Count); 
    l := 0; 
    tmp := tstringlist.Create; 
    tmp.Delimiter := ','; 
    for i := 0 to positions.count - 1 do 
    begin 
    tmp.DelimitedText := Positions[i]; 
    if TryStrToInt(trim(tmp[0]),rectarray[l].Left) and 
     TryStrToInt(trim(tmp[1]),rectarray[l].Top) and 
     TryStrToInt(trim(tmp[2]),rectarray[l].Right) and 
     TryStrToInt(trim(tmp[3]),rectarray[l].Bottom) then 
     inc(l); 
    end; 
    setlength(rectarray,l); 
    GetBitmaps(srcpng,rectarray,dstbitmaparray); 
    tmp.free; 
end; 

//extract the second png from the large one 

procedure TForm1.btnExtractClick(Sender: TObject); 
var 
    src: TPNGImage; 
begin 
    src := TPNGImage.Create; 
    src.Assign(img.Picture.Graphic); 
    try 
    myPictures[0] := TBitmap.Create; 
    // ok transparency is lost here! 
    LoadBitmaps(src, ImageListAreas, myPictures); 
    imgExtract.Picture.Assign(myPictures[0]); 
    finally 
    FreeAndNil(src); 
    end; 
end; 

也許有人有一個想法,如何可以這樣做不失去tranparency ... 任何幫助深表感謝,但是這將是很好也許沒有第三方組件...至少GR32將是確定太

最親切的問候,
小號!

+0

這裏的最終目標究竟是什麼?你想創建一個動畫?你需要將圖形文件嵌入到exe文件中嗎? – GrandmasterB 2010-07-08 18:49:59

+0

從透明的png中提取單獨的png保持不變! 沒有talkig關於嵌入可執行多數民衆贊成在沒問題...我正在加載圖像文件從光盤 問候 s! – stOrM 2010-07-13 11:09:56

回答

1

我不是確定任何大小的限制,但是你是否嘗試過TPn gCollection從PngComponents(我希望你在D2009 +)。與TPngImageList相比,TPngCollection中的每個條目可以具有不同的大小。雖然這裏可能不需要它,但它可能會打破尺寸障礙。

嗯,不是真的沒有第三方...

+0

是的,我在德爾福2010 ... 問題是,PngImagelist有相同的限制。 對於你關於Pngcollection的想法,這將不起作用,因爲它不會在指定的座標系中切割整個16000像素寬的png,而是會將它作爲一個部分加載,這對我來說並不是很有幫助......它也會很多更多的工作,因爲我將需要我自己的所有50個PNG的,並將所有他們保存到單獨的文件,然後將它們加載到PngCollection組件... 仁慈的問候, s! – stOrM 2010-07-08 14:03:24

0

你基本上建立自己的圖像列表。也許你可以找到現有的ImageList代碼並修改它。如果你有Delphi源代碼,它不應該很難。可能只是擴大一些常量,讓它使用更大的圖像。我看到DevExpress的TcxImageList可以讓你自定義大小。我只是嘗試500x500,它讓我(雖然沒有測試,但我期望它的工作原理)。 TMS也有一個ImageList,不確定這些功能(現在沒有這個功能)。

+0

嗯,可能工作,也許我還沒有檢查過這一點,但我真的更喜歡一種方式,從內部提取功能或只是與透明度: - )... – stOrM 2010-07-08 14:00:33

+0

順便說一句。我已經測試了TcxImageList,它的真實尺寸沒有限制,但是即使定義了正確的寬度/高度,圖像也不會保持不變。 有趣的TcxImageList內一切看起來很好... – stOrM 2010-07-08 15:13:36