2010-07-08 80 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