2013-08-02 1 views
1
나는 다음과 같은 요구 사항을 캔버스에 (A TPicture에서)는 PNG를 그릴 필요

:GDI를 사용하지 않고 캔버스에 TPicture을 형식의 PNG 파일을 그립니다 +

그것은 매우 (빠른 PC를 대상으로하기 때문에 할 필요가
  1. 느린 CPU를 실행).
  2. 2G 모바일 연결에서 대상 PC 자동 업데이트로 인해 EXE 크기를 늘릴 추가 라이브러리가 필요하지 않습니다.

아래의 코드는 일을하지만, GDI + 및 사용

  1. BitBlt를 사용하여 간단한 불투명 비트 맵을 그리기보다 훨씬 느립니다. 빠른 프로세서에서 그리기 시간은 1ms에서 16ms로 증가합니다. 느린 CPU에서는 100ms에서 900ms로 증가합니다.
  2. exe ​​크기를 약 0.5MB 증가시킵니다.

다음은 GDI + 코드입니다. 내가 GDI는 델파이의 PNG 지원 내장을 사용하여 + 제거하는 관리 다윗의 제안을 사용

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, 
    ComCtrls, ExtCtrls, 

    GDIPObj, GDIPAPI; 
... 

procedure DrawPictureToBitmap(Bitmap: TBitmap; X, Y: Integer; Picture: TPicture); 

    function PictureToGPBitmap(Picture: TPicture): TGPBitmap; 
    var 
    MemStream: TMemoryStream; 
    begin 
    MemStream := TMemoryStream.Create; 
    try 
     Picture.Graphic.SaveToStream(MemStream); 

     MemStream.Position := 0; 

     Result := TGPBitmap.Create(TStreamAdapter.Create(MemStream)); 
    finally 
     FreeAndNil(MemStream); 
    end; 
    end; 

var 
    GDICanvas: TGPGraphics; 
    GPImage: TGPImage; 
begin 
    GDICanvas := TGPGraphics.Create(Bitmap.Canvas.Handle); 
    try 
    GPImage := PictureToGPBitmap(Picture); 
    try 
     GDICanvas.DrawImage(GPImage, X, Y); 

     // Did the draw succeed? 
     if GDICanvas.GetLastStatus <> Ok then 
     begin 
     // No, try a BitBlt! 
     BitBlt(Bitmap.Canvas.Handle, X, Y, Bitmap.Height, Bitmap.Width, Picture.Bitmap.Canvas.Handle, 0, 0, SRCCOPY); 
     end; 
    finally 
     FreeAndNil(GPImage); 
    end; 
    finally 
    FreeAndNil(GDICanvas); 
    end; 
end; 

업데이트 1

: 경우 표준 비트 블리트으로 폴백하도록 설계되었습니다.

procedure DrawPictureToBitmap(Bitmap: TBitmap; X, Y: Integer; Picture: TPicture); 
var 
    PNG: TPngImage; 
    MemStream: TMemoryStream; 
begin 
    PNG := TPngImage.Create; 
    try 
    MemStream := TMemoryStream.Create; 
    try 
     Picture.Graphic.SaveToStream(MemStream); 

     MemStream.Position := 0; 

     PNG.LoadFromStream(MemStream); 
    finally 
     FreeAndNil(MemStream); 
    end; 

    PNG.Draw(Bitmap.Canvas, Rect(X, Y, X + Picture.Width, Y + Picture.Height)); 
    finally 
    FreeAndNil(PNG); 
    end; 
end; 

불행히도 그리기 시간은 GDI + 메서드와 완전히 동일합니다. 이것이 최적화 될 수있는 방법이 있습니까?

+0

@DavidHeffernan - 좋은 아이디어. 이렇게하면 GDI + 종속성이 제거되지만 그리기 시간은 향상되지 않습니다. 위의 업데이트를 참조하십시오. – norgepaul

+2

왜 DestinationCanvas.Draw (X, Y, Image1.Picture.Graphic)가 아닌가? – bummi

답변

2

필자는 불필요하게 메모리 내 그래픽을 PNG로 압축 한 다음 압축을 해제 한 것으로 보입니다. 그래픽을 직접 그릴 수 있습니다.

단순히 비트 맵 캔버스 Picture.Graphic 전달에 Draw 전화 :

procedure DrawPictureToBitmap(Bitmap: TBitmap; X, Y: Integer; Picture: TPicture); 
begin 
    Bitmap.Canvas.Draw(X, Y, Picture.Graphic); 
end; 

하는 당신은 아마 DrawPictureToBitmap 무의미 결정할 것 포인트, 제거, 직접 Bitmap.Canvas.Draw()를 호출합니다.

질문의 코드에 따라 그림이 PNG 이미지를 포함하는 것에 국한되지 않는 이점이 있습니다.

+0

위의 두 가지 문제가 모두 수정되었습니다. – norgepaul

관련 문제