【问题标题】:Using an ImageMap extracting Images (PNG) and display on TImage使用 ImageMap 提取图像 (PNG) 并在 TImage 上显示
【发布时间】:2011-03-13 07:53:54
【问题描述】:

我正在努力实现以下目标:

假设一个包含 50 个不同的其他 png 文件的大 png(透明背景 16000 x 70 像素)... 我需要加载该png并从中提取单个png(最好是例如具有一种我可以通过坐标(左,上,高,宽)说我想提取的png的功能......提取的png 应该显示在 timage 中然后...

当然我可以使用 Gif 图像并重新创建动画,但出于某种原因我需要 png...

一个想法是将其加载到图像列表中,但失败了,因为所有 50 个 png 的尺寸均为 (320x70px) timagelist 仅支持 256px 宽度...

我的下一个想法是也许我可以这样做:

将 Png 加载到 TBitmapArray 中。好吧,提取效果很好,但副作用是所有都失去了 alphachannel,没有什么是透明的,而是我得到了一个黑色的粗边框:-(

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;

也许有人知道如何在不失去透明度的情况下做到这一点...... 任何帮助都非常感谢,但如果没有 3rd 方组件可能会很好......至少 Gr32 也可以

最诚挚的问候,
秒!

【问题讨论】:

  • 这里的最终目标到底是什么?您是否正在尝试创建动画?需要嵌入到exe中的图形文件吗?
  • 从具有透明度的大 png 中提取单个 png 保持不变!不谈论在可执行文件中嵌入某事没问题...我正在从光盘加载图像文件问候s!

标签: delphi animation png timage


【解决方案1】:

我不确定是否有任何大小限制,但您是否尝试过来自PngComponents 的 TPngCollection(我希望您使用的是 D2009+)。与 TPngImageList 相比,TPngCollection 中的每个条目可以具有不同的大小。虽然你在这里可能不需要它,但它可能会打破尺寸障碍。

嗯,不是真的没有第 3 方...

【讨论】:

  • 是的,我在 Delphi 2010 ... 问题是,PngImagelist 有相同的限制。对于您对 Pngcollection 的想法,这是行不通的,因为它不会以指定的坐标切割整个 16000 像素宽的大 png,而是将其作为一个部分加载,这对我没有帮助......好吧,它还会更多工作,因为我需要自己剪切所有 50 个 png,并将它们全部保存到单独的文件中,然后将它们加载到 PngCollection 组件中......最诚挚的问候,s!
【解决方案2】:

您实际上是在构建自己的图像列表。也许您可以找到现有的 ImageList 代码并对其进行修改。如果你有 Delphi 源码,应该不难。可能只是扩展一些常量以使其使用更大的图像。我看到 DevExpress 的 TcxImageList 允许您自定义大小。我刚刚尝试了 500x500,它让我(虽然没有测试它,但我希望它可以工作)。 TMS 还有一个 ImageList,不确定功能(现在这里没有)。

【讨论】:

  • 嗯,这可能可行,也许我还没有检查过,但我真的更喜欢从提取函数内部进行的方法,或者只是透明的东西:-)...跨度>
  • 顺便说一句。我很快就测试了 TcxImageList 它真正的无限制尺寸,但即使定义了正确的宽度/高度,图像也不会保持完整。 TcxImageList 里面很有趣,一切看起来都很好......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-28
  • 2022-07-28
  • 1970-01-01
  • 2017-11-29
  • 2014-04-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多