2

私は次のことを達成しようとしています:

50個の他のpngファイルを含む大きなpng(透明な背景16000 x 70px)を想定します...そのpngをロードして、そこから個々のpngを抽出する必要があります(たとえば、座標で言うことができる関数のようなものを用意するのが最善です(左、上、高さ、幅) どの png を抽出しますか? 抽出した png を timage に表示する必要があります...

もちろん、Gif 画像を使用してアニメーションを再作成することもできますが、何らかの理由で png が必要です...

イメージリストにロードするというアイデアがありましたが、50 個の png のすべてが (320x70px) の寸法を持っているため、失敗しました timagelist は 256px 幅しかサポートしていません...

私の次のアイデアは、次のようなことができるかもしれないということでした:

Png を TBitmapArray にロードします。まあ、抽出は非常にうまく機能しますが、すべてがアルファチャンネルを失っているという副作用があり、何も透明ではなく、代わりに太い黒い境界線が表示されます:-(

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;

誰かが透明性を失うことなくこれを行う方法を知っているかもしれません...どんな助けも大歓迎ですが、おそらくサードパーティのコンポーネントがなくてもいいでしょう...少なくともGr32も大丈夫でしょう

よろしくお願いし
ます。

4

2 に答える 2

1

サイズ制限についてはわかりませんが、PngComponents の TPngCollection を試しましたか( D2009+ を使用していることを願っています)。TPngImageList とは対照的に、TPngCollection の各エントリは異なるサイズにすることができます。ここでは必要ないかもしれませんが、サイズの壁を破る可能性があります。

まあ、サードパーティなしではそうではありません...

于 2010-07-08T13:47:51.657 に答える
0

基本的に、独自のイメージリストを作成しています。おそらく、既存の ImageList コードを見つけて変更することができます。Delphi のソースがあれば、難しくはないはずです。おそらく、いくつかの定数を拡張して、より大きな画像を使用できるようにするだけです。DevExpress の TcxImageList を使用すると、サイズをカスタマイズできるようです。500x500 を試してみたところ、うまくいきました (テストはしていませんが、うまくいくと思います)。TMS には ImageList もありますが、その機能については不明です (現在、ここにはありません)。

于 2010-07-08T13:51:22.407 に答える