www.pudn.com > MapEditor.zip > WIL.pas


unit WIL; 
 
interface 
 
uses 
  Windows, Classes, Graphics, SysUtils, DXDraws, DXClass, Dialogs, 
  DirectX, DIB, wmUtil, HUtil32; 
 
var 
  g_boUseDIBSurface  :Boolean = FALSE; 
  g_boWilNoCache     :Boolean = FALSE; 
  g_n4CBCEC          :Integer = 20020;//4CBCEC 
  g_n4CBCF0          :Integer = 20021;//4CBCF0 
type 
  TLibType = (ltLoadBmp, ltLoadMemory, ltLoadMunual, ltUseCache); 
 
 
  TBmpImage = record 
    Bmp           :TBitmap; 
    dwLatestTime  :LongWord; 
  end; 
  pTBmpImage = ^TBmpImage; 
 
   TBmpImageArr  = array[0..MaxListSize div 4] of TBmpImage; 
   TDxImageArr   = array[0..MaxListSize div 4] of TDxImage; 
   PTBmpImageArr = ^TBmpImageArr; 
   PTDxImageArr  = ^TDxImageArr; 
 
   TWMImages = class (TComponent) 
   private 
      FFileName: String;              //0x24 
      FImageCount: integer;           //0x28 
      FLibType: TLibType;             //0x2C 
      FDxDraw: TDxDraw;               //0x30 
      FDDraw: TDirectDraw;            //0x34 
      FMaxMemorySize: integer;        //0x38 
      btVersion:Byte;                 //0x3C 
      m_bt458    :Byte; 
      FAppr:Word; 
      procedure LoadAllData; 
      procedure LoadAllDataBmp; 
      procedure LoadIndex (idxfile: string); 
      procedure LoadDxImage (position: integer; pdximg: PTDxImage); 
      procedure LoadBmpImage (position: integer; pbmpimg: PTBmpImage); 
      procedure FreeOldMemorys; 
      function  FGetImageSurface (index: integer): TDirectDrawSurface; 
      procedure FSetDxDraw (fdd: TDxDraw); 
      procedure FreeOldBmps; 
      function  FGetImageBitmap (index: integer): TBitmap; 
   protected 
      //MemorySize: integer;      //0x3C      ? 
      lsDib: TDib;              //0x40 
      m_dwMemChecktTick: LongWord;   //0x44 
   public 
      m_ImgArr    :pTDxImageArr;     //0x48 
      m_BmpArr    :pTBmpImageArr;    //0x4C 
      m_IndexList :TList;         //0x50 
      //BmpList: TList; 
      m_FileStream: TFileStream;      //0x54 
      //MainSurfacePalette: TDirectDrawPalette; 
      MainPalette: TRgbQuads; 
      constructor Create (AOwner: TComponent); override; 
      destructor Destroy; override; 
 
      procedure Initialize; 
      procedure Finalize; 
      procedure ClearCache; 
      procedure LoadPalette; 
      procedure FreeBitmap (index: integer); 
      function  GetImage (index: integer; var px, py: integer): TDirectDrawSurface; 
      function  GetCachedImage (index: integer; var px, py: integer): TDirectDrawSurface; 
      function  GetCachedSurface (index: integer): TDirectDrawSurface; 
      function  GetCachedBitmap (index: integer): TBitmap; 
      procedure DrawZoom (paper: TCanvas; x, y, index: integer; zoom: Real); 
      procedure DrawZoomEx (paper: TCanvas; x, y, index: integer; zoom: Real; leftzero: Boolean); 
      property Images[index: integer]: TDirectDrawSurface read FGetImageSurface; 
    	property Bitmaps[Index: Integer]: TBitmap read FGetImageBitmap; 
      property DDraw: TDirectDraw read FDDraw write FDDraw; 
   published 
      property FileName: string read FFileName write FFileName; 
      property ImageCount: integer read FImageCount; 
      property DxDraw: TDxDraw read FDxDraw write FSetDxDraw; 
      property LibType: TLibType read FLibType write FLibType; 
      property MaxMemorySize: integer read FMaxMemorySize write FMaxMemorySize; 
      property Appr:Word read FAppr write FAppr; 
   end; 
 
function TDXDrawRGBQuadsToPaletteEntries(const RGBQuads: TRGBQuads; AllowPalette256: Boolean): TPaletteEntries; 
 
procedure Register; 
 
 
implementation 
 
//uses 
//   ClMain;//¼Ç¼µ÷ÊÔÐÅÏ¢ 
 
 
procedure Register; 
begin 
   RegisterComponents('MirGame', [TWmImages]); 
end; 
 
constructor TWMImages.Create (AOwner: TComponent); 
begin 
   inherited Create (AOwner); 
   FFileName := ''; 
   FLibType := ltLoadBmp; 
   FImageCount := 0; 
   //MemorySize := 0;//? 
   FMaxMemorySize := 1024*1000; //1M 
 
   FDDraw := nil; 
   FDxDraw := nil; 
   m_FileStream := nil; 
   m_ImgArr := nil; 
   m_BmpArr := nil; 
   m_IndexList := TList.Create; 
   lsDib := TDib.Create; 
   lsDib.BitCount := 8; 
   //BmpList := TList.Create;  //Bmp¿ëÀ¸·Î »ç¿ëÇÒ ¶§¹® »ç¿ë 
 
   m_dwMemChecktTick := GetTickCount; 
   btVersion:=0; 
   m_bt458:=0;    
end; 
 
destructor TWMImages.Destroy; 
begin 
   m_IndexList.Free; 
//   BmpList.Free; 
   if m_FileStream <> nil then m_FileStream.Free; 
   lsDib.Free; 
   inherited Destroy; 
end; 
 
procedure TWMImages.Initialize; 
var 
  Idxfile: String; 
  Header :TWMImageHeader; 
begin 
   if not (csDesigning in ComponentState) then begin 
      if FFileName = '' then begin 
         raise Exception.Create ('FileName not assigned..'); 
         exit; 
      end; 
      if (LibType <> ltLoadBmp) and (FDDraw = nil) then begin 
         raise Exception.Create ('DDraw not assigned..'); 
         exit; 
      end; 
      if FileExists (FFileName) then begin 
         if m_FileStream = nil then 
            m_FileStream := TFileStream.Create (FFileName, fmOpenRead or fmShareDenyNone); 
         m_FileStream.Read (Header, SizeOf(TWMImageHeader)); 
         { 
         case m_bt458 of 
           1: begin 
             g_n4CBCEC:=20030; 
             g_n4CBCF0:=20031; 
           end; 
           2: begin 
             g_n4CBCEC:=20040; 
             g_n4CBCF0:=20041; 
           end; 
           3: begin 
             g_n4CBCEC:=20050; 
             g_n4CBCF0:=20051; 
           end; 
         end; 
         if (LongWord(g_n4CBCEC + Header.ImageCount) xor 3223982451) <> LongWord(Header.VerFlag) then begin 
           btVersion:=1; 
           m_FileStream.Seek(-4,soFromCurrent); 
         end; 
         } 
         if header.VerFlag = 0 then begin 
           btVersion:=1; 
           m_FileStream.Seek(-4,soFromCurrent); 
         end; 
 
         FImageCount := Header.ImageCount; 
         if LibType = ltLoadBmp then begin 
            m_BmpArr := AllocMem (SizeOf(TBmpImage) * FImageCount); 
            if m_BmpArr = nil then 
               raise Exception.Create (self.Name + ' BmpArr = nil'); 
         end else begin 
            m_ImgArr:=AllocMem(SizeOf(TDxImage) * FImageCount); 
            if m_ImgArr = nil then 
               raise Exception.Create (self.Name + ' ImgArr = nil'); 
         end; 
 
         idxfile := ExtractFilePath(FFileName) + ExtractFileNameOnly(FFileName) + '.WIX'; 
         LoadPalette; 
         if LibType = ltLoadMemory then 
            LoadAllData 
         else begin 
            LoadIndex (idxfile); 
         end; 
      end else begin 
//         MessageDlg (FFileName + ' Cannot find file.', mtWarning, [mbOk], 0); 
      end; 
   end; 
end; 
 
procedure TWMImages.Finalize; 
var 
   i: integer; 
begin 
   for i:=0 to FImageCount-1 do begin 
      if m_ImgArr[i].Surface <> nil then begin 
         m_ImgArr[i].Surface.Free; 
         m_ImgArr[i].Surface := nil; 
      end; 
   end; 
   if m_FileStream <> nil then begin 
      m_FileStream.Free; 
      m_FileStream := nil; 
   end; 
end; 
 
function TDXDrawRGBQuadsToPaletteEntries(const RGBQuads: TRGBQuads; 
  AllowPalette256: Boolean): TPaletteEntries; 
var 
  Entries: TPaletteEntries; 
  dc: THandle; 
  i: Integer; 
begin 
  Result := RGBQuadsToPaletteEntries(RGBQuads); 
 
  if not AllowPalette256 then 
  begin 
    dc := GetDC(0); 
    GetSystemPaletteEntries(dc, 0, 256, Entries); 
    ReleaseDC(0, dc); 
 
    for i:=0 to 9 do 
      Result[i] := Entries[i]; 
 
    for i:=256 - 10 to 255 do 
      Result[i] := Entries[i]; 
  end; 
 
  for i:=0 to 255 do 
    Result[i].peFlags := D3DPAL_READONLY; 
end; 
 
//Cache¾øÀÌ ÇѲ¨¹ø¿¡ ·ÎµùÇÔ. 
procedure TWMImages.LoadAllData; 
var 
   i: integer; 
   imgi: TWMImageInfo; 
   dib: TDIB; 
   dximg: TDxImage; 
begin 
   dib := TDIB.Create; 
   for i:=0 to FImageCount-1 do begin 
   if btVersion <> 0 then m_FileStream.Read (imgi, sizeof(TWMImageInfo) - 4) 
   else m_FileStream.Read (imgi, sizeof(TWMImageInfo)); 
 
      dib.Width := imgi.nWidth; 
      dib.Height := imgi.nHeight; 
      dib.ColorTable := MainPalette; 
      dib.UpdatePalette; 
      m_FileStream.Read (dib.PBits^, imgi.nWidth * imgi.nHeight); 
 
      dximg.nPx := imgi.px; 
      dximg.nPy := imgi.py; 
      dximg.surface := TDirectDrawSurface.Create (FDDraw); 
      dximg.surface.SystemMemory := TRUE; 
      dximg.surface.SetSize (imgi.nWidth, imgi.nHeight); 
      dximg.surface.Canvas.Draw (0, 0, dib); 
      dximg.surface.Canvas.Release; 
      dib.Clear; //FreeImage; 
 
      dximg.surface.TransparentColor := 0; 
      m_ImgArr[i] := dximg; 
   end; 
   dib.Free; 
end; 
 
procedure TWMImages.LoadPalette; 
var 
   Entries: TPaletteEntries; 
begin 
   if btVersion <> 0 then 
     m_FileStream.Seek (sizeof(TWMImageHeader) - 4, 0) 
   else 
     m_FileStream.Seek (sizeof(TWMImageHeader), 0); 
      
   m_FileStream.Read (MainPalette, sizeof(TRgbQuad) * 256); // 
 
   //Entries := TDXDrawRGBQuadsToPaletteEntries (MainPalette, TRUE); 
   //MainSurfacePalette := TDirectDrawPalette.Create (FDDraw); 
   ////MainSurfacePalette.SetEntries(0, 256, Entries); 
   //MainSurfacePalette.CreatePalette(DDPCAPS_8BIT, Entries); 
end; 
 
//Cache Bmp 
procedure TWMImages.LoadAllDataBmp; 
var 
   i: integer; 
   pbuf: PByte; 
   imgi: TWMImageInfo; 
   bmp: TBitmap; 
begin 
{   GetMem (pbuf, 1024*768);  // 
   Stream.Seek (sizeof(TWMImageHeader), 0); 
   Stream.Read (MainPalette, sizeof(TRgbQuad) * 256); // 
   for i:=0 to ImageCount-1 do begin 
      Stream.Read (imgi, sizeof(TWMImageInfo)-4); 
      Stream.Read (pbuf^, imgi.Width * imgi.Height); 
      bmp := MakeBmp (imgi.Width, imgi.Height, pbuf, MainPalette); 
      BmpList.Add (bmp);     //BMP 
   end; 
   FreeMem (pbuf); } 
end; 
 
procedure TWMImages.LoadIndex (idxfile: string); 
var 
   fhandle, i, value: integer; 
   header: TWMIndexHeader; 
   pidx: PTWMIndexInfo; 
   pvalue: PInteger; 
begin 
   m_IndexList.Clear; 
   if FileExists (idxfile) then begin 
      fhandle := FileOpen (idxfile, fmOpenRead or fmShareDenyNone); 
      if fhandle > 0 then begin 
         if btVersion <> 0 then 
           FileRead (fhandle, header, sizeof(TWMIndexHeader) - 4) 
         else 
           FileRead (fhandle, header, sizeof(TWMIndexHeader)); 
            
         GetMem (pvalue, 4*header.IndexCount); 
         FileRead (fhandle, pvalue^, 4*header.IndexCount); 
         for i:=0 to header.IndexCount-1 do begin 
            new (pidx); 
            value := PInteger(integer(pvalue) + 4*i)^; 
            m_IndexList.Add (pointer(value)); 
         end; 
         FreeMem (pvalue); 
         FileClose (fhandle); 
      end; 
   end; 
end; 
 
{----------------- Private Variables ---------------------} 
 
function  TWMImages.FGetImageSurface (index: integer): TDirectDrawSurface; 
begin 
   Result := nil; 
   if LibType = ltUseCache then begin 
      Result := GetCachedSurface (index); 
   end else 
      if LibType = ltLoadMemory then begin 
         if (index >= 0) and (index < ImageCount) then 
            Result := m_ImgArr[index].Surface; 
      end; 
          
end; 
 
function  TWMImages.FGetImageBitmap (index: integer): TBitmap; 
begin 
   Result:=nil; 
   if LibType <> ltLoadBmp then exit; 
   Result := GetCachedBitmap (index); 
   {if index in [0..BmpList.Count-1] then begin 
      Result := TBitmap (BmpList[index]); 
   end else 
      Result := nil;} 
end; 
 
procedure TWMImages.FSetDxDraw (fdd: TDxDraw); 
begin 
   FDxDraw := fdd; 
end; 
 
// *** DirectDrawSurface Functions 
 
procedure TWMImages.LoadDxImage (position: integer; pdximg: PTDxImage); 
var 
   imginfo: TWMImageInfo; 
   ddsd: TDDSurfaceDesc; 
   SBits, PSrc, DBits: PByte; 
   n, slen, dlen: integer; 
   nErrorCode:Integer; 
 
begin 
   m_FileStream.Seek (position, 0); 
   if btVersion <> 0 then m_FileStream.Read (imginfo, SizeOf(TWMImageInfo)-4) 
   else m_FileStream.Read (imginfo, SizeOf(TWMImageInfo)); 
 
 
   if g_boUseDIBSurface then begin //DIB 
      //·ÇÈ«ÆÁʱ 
      try 
      lsDib.Clear; 
      lsDib.Width := imginfo.nWidth; 
      lsDib.Height := imginfo.nHeight; 
      except 
      end; 
      lsDib.ColorTable := MainPalette; 
      lsDib.UpdatePalette; 
      DBits := lsDib.PBits; 
      m_FileStream.Read (DBits^, imginfo.nWidth * imgInfo.nHeight); 
 
 
      pdximg.nPx := imginfo.px; 
      pdximg.nPy := imginfo.py; 
      pdximg.surface := TDirectDrawSurface.Create (FDDraw); 
      pdximg.surface.SystemMemory := TRUE; 
      pdximg.surface.SetSize (imginfo.nWidth, imginfo.nHeight); 
      pdximg.surface.Canvas.Draw (0, 0, lsDib); 
      pdximg.surface.Canvas.Release; 
 
      pdximg.surface.TransparentColor := 0; 
   end else begin // 
      //·ÇÈ«ÆÁʱ    
      slen  := WidthBytes(imginfo.nWidth); 
      GetMem (PSrc, slen * imgInfo.nHeight); 
      SBits := PSrc; 
      m_FileStream.Read (PSrc^, slen * imgInfo.nHeight); 
      try 
         pdximg.surface := TDirectDrawSurface.Create (FDDraw); 
         pdximg.surface.SystemMemory := TRUE; 
         pdximg.surface.SetSize (slen, imginfo.nHeight); 
         //pdximg.surface.Palette := MainSurfacePalette; 
 
         pdximg.nPx := imginfo.px; 
         pdximg.nPy := imginfo.py; 
         ddsd.dwSize := SizeOf(ddsd); 
 
         pdximg.surface.Lock (TRect(nil^), ddsd); 
         DBits := ddsd.lpSurface; 
         for n:=imginfo.nHeight - 1 downto 0 do begin 
            SBits := PByte (Integer(PSrc) + slen * n); 
            Move(SBits^, DBits^, slen); 
            Inc (integer(DBits), ddsd.lPitch); 
         end; 
         pdximg.surface.TransparentColor := 0; 
      finally 
        pdximg.surface.UnLock(); 
        FreeMem (PSrc); 
      end; 
   end; 
end; 
 
procedure TWMImages.LoadBmpImage (position: integer; pbmpimg: PTBmpImage); 
var 
   imginfo: TWMImageInfo; 
   ddsd: TDDSurfaceDesc; 
   DBits: PByte; 
   n, slen, dlen: integer; 
begin 
   m_FileStream.Seek (position, 0); 
   m_FileStream.Read (imginfo, sizeof(TWMImageInfo)-4); 
 
   lsDib.Width := imginfo.nWidth; 
   lsDib.Height := imginfo.nHeight; 
   lsDib.ColorTable := MainPalette; 
   lsDib.UpdatePalette; 
   DBits := lsDib.PBits; 
   m_FileStream.Read (DBits^, imginfo.nWidth * imgInfo.nHeight); 
 
   pbmpimg.bmp := TBitmap.Create; 
   pbmpimg.bmp.Width := lsDib.Width; 
   pbmpimg.bmp.Height := lsDib.Height; 
   pbmpimg.bmp.Canvas.Draw (0, 0, lsDib); 
   lsDib.Clear; 
end; 
 
procedure TWMImages.ClearCache; 
var 
   i: integer; 
begin 
   for i:=0 to ImageCount - 1 do begin 
      if m_ImgArr[i].Surface <> nil then begin 
         m_ImgArr[i].Surface.Free; 
         m_ImgArr[i].Surface := nil; 
      end; 
   end; 
   //MemorySize := 0; 
end; 
 
function  TWMImages.GetImage (index: integer; var px, py: integer): TDirectDrawSurface; 
begin 
   if (index >= 0) and (index < ImageCount) then begin 
      px := m_ImgArr[index].nPx; 
      py := m_ImgArr[index].nPy; 
      Result := m_ImgArr[index].surface; 
   end else 
      Result := nil; 
end; 
 
{--------------- BMP functions ----------------} 
 
// 
procedure TWMImages.FreeOldBmps; 
var 
   i, n, ntime, curtime, limit: integer; 
begin 
   n := -1; 
   ntime := 0; 
   //limit := FMaxMemorySize * 9 div 10; 
   for i:=0 to ImageCount-1 do begin 
      curtime := GetTickCount; 
      if m_BmpArr[i].Bmp <> nil then begin 
         if GetTickCount - m_BmpArr[i].dwLatestTime > 5 * 1000 then begin 
            //MemorySize := MemorySize - BmpArr[i].Bmp.Width * BmpArr[i].Bmp.Height; 
            m_BmpArr[i].Bmp.Free; 
            m_BmpArr[i].Bmp := nil; 
         end else begin 
            if GetTickCount - m_BmpArr[i].dwLatestTime > ntime then begin 
               ntime := GetTickCount - m_BmpArr[i].dwLatestTime; 
               n := i; 
            end; 
         end; 
      end; 
      //if MemorySize < limit then begin 
      //   n := -1; 
      //   break; 
      //end; 
   end; 
   //if n >= 0 then begin 
   //   MemorySize := MemorySize - BmpArr[n].Bmp.Width * BmpArr[n].Bmp.Height; 
   //   BmpArr[n].Bmp.FreeImage; 
   //   BmpArr[n].Bmp.Free; 
   //   BmpArr[n].Bmp := nil; 
   //end; 
end; 
 
procedure TWMImages.FreeBitmap (index: integer); 
begin 
   if (index >= 0) and (index < ImageCount) then begin 
      if m_BmpArr[index].Bmp <> nil then begin 
         //MemorySize  := MemorySize - BmpArr[index].Bmp.Width * BmpArr[index].Bmp.Height; 
         //if MemorySize < 0 then MemorySize := 0; 
         m_BmpArr[index].Bmp.FreeImage; 
         m_BmpArr[index].Bmp.Free; 
         m_BmpArr[index].Bmp := nil; 
      end; 
   end; 
end; 
 
 
//¿À·¡µÈ ij½Ã Áö¿ò 
procedure TWMImages.FreeOldMemorys; 
var 
   i, n, ntime, curtime, limit: integer; 
begin 
   n := -1; 
   ntime := 0; 
   //limit := FMaxMemorySize * 9 div 10; 
   curtime := GetTickCount; 
   for i:=0 to ImageCount-1 do begin 
      if m_ImgArr[i].Surface <> nil then begin 
         if GetTickCount - m_ImgArr[i].dwLatestTime > 5 * 60 * 1000 then begin 
            //MemorySize := MemorySize - ImgArr[i].Surface.Width * ImgArr[i].Surface.Height; 
            m_ImgArr[i].Surface.Free; 
            m_ImgArr[i].Surface := nil; 
         end; 
      end; 
      //if MemorySize < limit then begin 
      //   n := -1; 
      //   break; 
      //end; 
   end; 
end; 
 
//Cache¸¦ ÀÌ¿ëÇÔ 
function  TWMImages.GetCachedSurface (index: integer): TDirectDrawSurface; 
var 
  nPosition:Integer; 
  nErrCode:Integer; 
begin 
  Result := nil; 
  nErrCode:=0; 
  try 
  if (index < 0) or (index >= ImageCount) then exit; 
  if GetTickCount - m_dwMemChecktTick > 10000 then  begin 
      m_dwMemChecktTick := GetTickCount; 
      //if MemorySize > FMaxMemorySize then begin 
      FreeOldMemorys; 
      //end; 
   end; 
   nErrCode:=1; 
   if m_ImgArr[index].Surface = nil then begin //cacheµÇ¾î ÀÖÁö ¾ÊÀ½. »õ·Î Àоî¾ßÇÔ. 
      if index < m_IndexList.Count then begin 
         nPosition:= Integer(m_IndexList[index]); 
         LoadDxImage (nPosition, @m_ImgArr[index]); 
         m_ImgArr[index].dwLatestTime := GetTickCount; 
         nErrCode:=2; 
         Result := m_ImgArr[index].Surface; 
         //MemorySize := MemorySize + ImgArr[index].Surface.Width * ImgArr[index].Surface.Height; 
      end; 
   end else begin 
      m_ImgArr[index].dwLatestTime := GetTickCount; 
      nErrCode:=3; 
      Result := m_ImgArr[index].Surface; 
   end; 
 
   except 
    //DebugOutStr ('GetCachedSurface 3 Index: ' + IntToStr(index) + ' Error Code: ' + IntToStr(nErrCode)); 
   end; 
end; 
 
function  TWMImages.GetCachedImage (index: integer; var px, py: integer): TDirectDrawSurface; 
var 
   position: integer; 
   nErrCode:Integer;    
begin 
   Result := nil; 
   nErrCode:=0; 
   try 
   if (index < 0) or (index >= ImageCount) then exit; 
   if GetTickCount - m_dwMemChecktTick > 10000 then  begin 
      m_dwMemChecktTick := GetTickCount; 
      //if MemorySize > FMaxMemorySize then begin 
      FreeOldMemorys; 
      //end; 
   end; 
   nErrCode:=1; 
   if m_ImgArr[index].Surface = nil then begin //cache 
      if index < m_IndexList.Count then begin 
         position := Integer(m_IndexList[index]); 
         LoadDxImage (position, @m_ImgArr[index]); 
         m_ImgArr[index].dwLatestTime := GetTickCount; 
         px := m_ImgArr[index].nPx; 
         py := m_ImgArr[index].nPy; 
         Result := m_ImgArr[index].Surface; 
         //MemorySize := MemorySize + ImgArr[index].Surface.Width * ImgArr[index].Surface.Height; 
      end; 
 
   end else begin 
      m_ImgArr[index].dwLatestTime := GetTickCount; 
      px := m_ImgArr[index].nPx; 
      py := m_ImgArr[index].nPy; 
      Result := m_ImgArr[index].Surface; 
   end; 
   except 
    //DebugOutStr ('GetCachedImage 3 Index: ' + IntToStr(index) + ' Error Code: ' + IntToStr(nErrCode)); 
   end; 
end; 
 
function  TWMImages.GetCachedBitmap (index: integer): TBitmap; 
var 
   position: integer; 
begin 
   Result := nil; 
   if (index < 0) or (index >= ImageCount) then exit; 
   if m_BmpArr[index].Bmp = nil then begin //cacheµÇ¾î ÀÖÁö ¾ÊÀ½. »õ·Î Àоî¾ßÇÔ. 
      if index < m_IndexList.Count then begin 
         position := Integer(m_IndexList[index]); 
         LoadBmpImage (position, @m_BmpArr[index]); 
         m_BmpArr[index].dwLatestTime := GetTickCount; 
         Result := m_BmpArr[index].Bmp; 
         //MemorySize := MemorySize + BmpArr[index].Bmp.Width * BmpArr[index].Bmp.Height; 
         //if (MemorySize > FMaxMemorySize) then begin 
         FreeOldBmps; 
         //end; 
      end; 
   end else begin 
      m_BmpArr[index].dwLatestTime:=GetTickCount; 
      Result := m_BmpArr[index].Bmp; 
   end; 
end; 
 
procedure TWMImages.DrawZoom (paper: TCanvas; x, y, index: integer; zoom: Real); 
var 
   rc: TRect; 
   bmp: TBitmap; 
begin 
   if LibType <> ltLoadBmp then exit; 
   //if index > BmpList.Count-1 then exit; 
   bmp := Bitmaps[index]; 
   if bmp <> nil then begin 
      rc.Left := x; 
      rc.Top  := y; 
      rc.Right := x + Round (bmp.Width * zoom); 
      rc.Bottom := y + Round (bmp.Height * zoom); 
      if (rc.Right > rc.Left) and (rc.Bottom > rc.Top) then begin 
         paper.StretchDraw (rc, Bmp); 
         FreeBitmap (index); 
      end; 
   end; 
end; 
 
procedure TWMImages.DrawZoomEx (paper: TCanvas; x, y, index: integer; zoom: Real; leftzero: Boolean); 
var 
   rc: TRect; 
   bmp, bmp2: TBitmap; 
begin 
   if LibType <> ltLoadBmp then exit; 
   //if index > BmpList.Count-1 then exit; 
   bmp := Bitmaps[index]; 
   if bmp <> nil then begin 
      Bmp2 := TBitmap.Create; 
      Bmp2.Width := Round (Bmp.Width * zoom); 
      Bmp2.Height := Round (Bmp.Height * zoom); 
      rc.Left := x; 
      rc.Top  := y; 
      rc.Right := x + Round (bmp.Width * zoom); 
      rc.Bottom := y + Round (bmp.Height * zoom); 
      if (rc.Right > rc.Left) and (rc.Bottom > rc.Top) then begin 
         Bmp2.Canvas.StretchDraw (Rect(0, 0, Bmp2.Width, Bmp2.Height), Bmp); 
         if leftzero then begin 
            SpliteBitmap (paper.Handle, X, Y, Bmp2, $0) 
         end else begin 
            SpliteBitmap (paper.Handle, X, Y-Bmp2.Height, Bmp2, $0); 
         end; 
      end; 
      FreeBitmap (index); 
      bmp2.Free; 
   end; 
end; 
 
 
 
 
end.