提高大二进制文件的读取速度,还是应该用内存文件映射,
我有控件,你自己安装了.
////////////////////////////////////////////
// The Unofficial Newsletter of Delphi Users - Issue #19 - January 1997
//--------------------------------------------------------------------------------
//Source for Big Bitmaps
// BITMAP VIEWER
// Enables bitmaps which are disc files to be displayed in a
// TImage-like control without loading the bitmap into memory.
// Great for very large bitmaps.
// Grahame Marsh 1996
unit BigGraphic;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics,
Controls, Dialogs, Forms, DsgnIntf;
type
TBMPFilename = type string; // filename will have its owner property editor
type
TBigBitmapViewer = class (TGraphicControl)
private
FFileName: TBMPFilename; // bitmap filename, own type so it can have own prop editor
FPalette : HPalette; // handle to bitmap palette
FData : pointer; // pointer to start of data in memory mapped file
FBitmapWidth, // copy of bitmap width info for convience
FBitmapHeight, // copy of bitmap height info for convience
FColours : integer; // number of colours in palette
FCentre, // centre the bitmap in the control
FStretch, // stretch the bitmap to fill the control
FAutoSize, // automatically size the control to display the bitmap
FActive : boolean; // true opens the viewer, false it's closed
FFileHeader : PBitmapFileHeader; // pointer to TBitmapFileHeader struct
FInfoHeader : PBitmapInfoHeader; // pointer to TBitmapInfoHeader struct
FInfo : PBitmapInfo; // pointer to the TBitmapInfo struct
FPixelStart : pointer; // pointer to the start of the pixel data
procedure SetActive (Value : boolean);
procedure SetAutoSize (Value : boolean);
procedure SetFilename (const Value : TBMPFilename);
procedure SetStretch (Value : boolean);
procedure SetCentre (Value : boolean);
procedure SetDummyInt (Value : integer);
protected
procedure OpenViewer; virtual;
procedure CloseViewer; virtual;
procedure GetPalette;
procedure Paint; override;
procedure Changes; virtual;
public
constructor Create (AOwner : TComponent); override;
destructor Destroy; override;
// open the viewer
procedure Close;
// close the viewer
procedure Open;
// pointer to the file header info
property BitmapFileHeader : PBitmapFileHeader read FFileHeader;
// pointer to the bitmap info header
property BitmapInfoHeader : PBitmapInfoHeader read FInfoHeader;
// pointer to the bitmap info
property BitmapInfo : PBitmapInfo read FInfo;
// pointer to the bitmap pixel data array
property PixelStart : pointer read FPixelStart;
// palette handle
property Palette : HPalette read FPalette;
published
//READ-WRITE PROPS
// size control to bitmap
property AutoSize : boolean read FAutoSize write SetAutoSize default false;
// bitmap centred
property Centre : boolean read FCentre write SetCentre default false;
// filename of bitmap
property Filename : TBMPFilename read FFilename write SetFilename;
// stretch bitmap
property Stretch : boolean read FStretch write SetStretch default false;
// READ-ONLY PROPS
// number of colours in the bitmap palette
property Colours : integer read FColours write SetDummyInt stored false;
// bitmap width
property BitmapHeight : integer read FBitmapHeight write SetDummyInt stored false;
// bitmap height
property BitmapWidth : integer read FBitmapWidth write SetDummyInt stored false;
// TGraphicControl PROPS NOW PUBLISHED
property Align;
property DragCursor;
property DragMode;
property Enabled;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Visible;
property OnClick;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnStartDrag;
// viewer activate - stream active last!
property Active : boolean read FActive write SetActive default false;
end;
// filename property editor .. fileopen dialog box
type
TBMPFilenameProperty = class (TStringProperty)
public
procedure Edit; override;
function GetAttributes: TPropertyAttributes; override;
end;
procedure Register;
implementation
const
BitmapSignature = $4D42;
procedure InvalidBitmap;
begin
raise Exception.Create ('Bitmap image is not valid')
end;
procedure NotWhenActive;
begin
raise Exception.Create ('Not on an active big bitmap viewer')
end;
constructor TBigBitmapViewer.Create (AOwner : TComponent);
begin
inherited Create (AOwner);
Width := 150;
Height := 150
end;
destructor TBigBitmapViewer.Destroy;
begin
CloseViewer; // ensure file view is freed
inherited Destroy
end;
procedure TBigBitmapViewer.GetPalette;
var
SysPalSize,
Loop,
LogSize : integer;
LogPalette : PLogPalette;
DC : HDC;
Focus : HWND;
begin
// fetch palette for colour bitmaps only
if FColours > 2 then
begin
// create palette from bitmap info
LogSize := SizeOf (TLogPalette) + pred(FColours) * SizeOf(TPaletteEntry);
LogPalette := AllocMem (LogSize);
try
with LogPalette^ do
begin
palNumEntries := FColours;
palVersion := $0300;
{$IFOPT R+}
{$DEFINE R_PLUS}
{$R-}
{$ENDIF}
Focus := GetFocus;
DC := GetDC (Focus);
try
SysPalSize := GetDeviceCaps (DC, SIZEPALETTE);
if (FColours = 16) and (SysPalSize >= 16) then
begin
GetSystemPaletteEntries (DC, 0, 8, palPalEntry);
loop := 8;
GetSystemPaletteEntries (DC, SysPalSize - loop, loop, palPalEntry[loop])
end else
with FInfo^ do
for loop := 0 to pred (FColours) do
begin
palPalEntry[loop].peRed := bmiColors[loop].rgbRed;
palPalEntry[loop].peGreen := bmiColors[loop].rgbGreen;
palPalEntry[loop].peBlue := bmiColors[loop].rgbBlue
end
finally
ReleaseDC(Focus, DC)
end
{$IFDEF R_PLUS}
{$R+}
{$UNDEF R_PLUS}
{$ENDIF}
end;
FPalette := CreatePalette (LogPalette^)
finally
FreeMem (LogPalette, LogSize)
end
end
end;
procedure TBigBitmapViewer.OpenViewer;
var
FileHandle,
MapHandle : THandle;
begin
if FActive then exit;
// open file
FileHandle := FileOpen (FFilename, fmOpenRead + fmShareDenyNone);
if FileHandle = INVALID_HANDLE_VALUE then
raise Exception.Create ('Failed to open ' + FFilename);
// create file map
try
MapHandle := CreateFileMapping (FileHandle, nil, PAGE_READONLY, 0, 0, nil);
if MapHandle = 0 then
raise Exception.Create ('Failed to map file')
finally
CloseHandle (FileHandle)
end;
// view file map
try
FData := MapViewOfFile (MapHandle, FILE_MAP_READ, 0, 0, 0);
if FData = nil then
raise Exception.Create ('Failed to view map file')
finally
CloseHandle (MapHandle)
end;
// set pointers into file view
FFileHeader := FData;
// test for valid bitmap file:
if FFileHeader^.bfType <> BitmapSignature then
begin
UnmapViewOfFile (FData);
FData := nil;
InvalidBitmap
end;
// set up a few other pointers
FInfoHeader := pointer (integer (FData) + sizeof (TBitmapFileHeader));
FInfo := pointer (FInfoHeader);
FPixelStart := pointer (integer(FData) + FFileHeader^.bfOffBits);
// get number of colours
with FInfoHeader^ do
if biClrUsed <> 0 then
FColours := biClrUsed
else
case biBitCount of
1,
4,
8 : FColours := 1 shl biBitCount
else
FColours := 0
end;
// get bitmap size into easy to access variables
FBitmapHeight := FInfoHeader^.biHeight;
FBitmapWidth := FInfoHeader^.biWidth;
// fetch the palette
GetPalette;
// other setups
FActive := true;
Changes
end;
procedure TBigBitmapViewer.Paint;
var
OldPalette : HPalette;
Dest : TRect;
begin
with Canvas do
if (csDesigning in ComponentState) and not FActive then
begin
Pen.Style := psDash;
Brush.Style := bsClear;
Rectangle (0, 0, Width, Height)
end else begin
if FPalette <> 0 then
OldPalette := SelectPalette (Handle, FPalette, false)
else
OldPalette := 0;
try
RealizePalette (Handle);
if FStretch then
Dest := ClientRect
else
if Centre then
Dest := Rect ((Width - FBitmapWidth) div 2,
(Height - FBitmapHeight) div 2,
FBitmapWidth, FBitmapHeight)
else
Dest := Rect (0, 0, FBitmapWidth, FBitmapHeight);
with Dest do
StretchDIBits (Handle,
Left, Top, Right, Bottom,
0, 0, FBitmapWidth, FBitmapHeight,
FPixelStart, FInfo^,
DIB_RGB_COLORS, SRCCOPY)
finally
if OldPalette <> 0 then
SelectPalette (Handle, OldPalette, false)
end
end
end;
procedure TBigBitmapViewer.CloseViewer;
begin
if FActive then
begin
FActive := false;
if FData <> nil then
begin
UnmapViewOfFile (FData); // remove the memory mapped file view
FData := nil
end;
if FPalette <> 0 then
DeleteObject (FPalette) // free the palette
end
end;
procedure TBigBitmapViewer.Open;
begin
Active := true
end;
procedure TBigBitmapViewer.Close;
begin
Active := false
end;
procedure TBigBitmapViewer.SetActive (Value : boolean);
begin
if Value <> FActive then
if Value then
OpenViewer
else
CloseViewer
end;
procedure TBigBitmapViewer.SetAutoSize (Value : boolean);
begin
if Value <> FAutoSize then
begin
FAutoSize := Value;
Changes
end
end;
procedure TBigBitmapViewer.SetStretch (Value : boolean);
begin
if Value <> FStretch then
begin
FStretch := Value;
Changes
end
end;
procedure TBigBitmapViewer.SetCentre (Value : boolean);
begin
if Value <> FCentre then
begin
FCentre := Value;
Changes
end
end;
procedure TBigBitmapViewer.SetFilename (const Value : TBMPFilename);
begin
if Value <> FFilename then
begin
if FActive then
NotWhenActive;
FFilename := Value
end
end;
procedure TBigBitmapViewer.SetDummyInt (Value : integer);
begin
end;
procedure TBigBitmapViewer.Changes;
begin
if (BitmapWidth >= Width) and (BitmapHeight >= Height) then
ControlStyle := ControlStyle + [csOpaque]
else
ControlStyle := ControlStyle - [csOpaque];
if AutoSize and (BitmapWidth > 0) and (BitmapHeight > 0) then
SetBounds (Left, Top, BitmapWidth, BitmapHeight)
else
Invalidate
end;
//--- filename property editor
procedure TBMPFilenameProperty.Edit;
begin
with TOpenDialog.Create(Application) do
begin
Filename := GetValue;
Filter := 'Windows bitmaps (*.BMP)|*.BMP';
Options := Options + [ofPathMustExist, ofFileMustExist, ofHideReadOnly];
try
if Execute then
SetValue(Filename)
finally
Free
end
end
end;
function TBMPFilenameProperty.GetAttributes: TPropertyAttributes;
begin
Result := [paDialog, paRevertable]
end;
// - register component and filename editor
procedure Register;
begin
RegisterComponents ('Custom', [TBigBitmapViewer]);
RegisterPropertyEditor (TypeInfo (TBMPFilename), nil, '', TBMPFilenameProperty);
end;
end.
//Return to Article
//Return to Component Cookbook
//Return to Front Page
/////////////////////////////
具体使用 :
BigBitmapViewer.FileName :=OpenPictureDialog.FileName;
BigBitmapViewer.Active :=True;
/////////////////////// ok !