home *** CD-ROM | disk | FTP | other *** search
- {************************************************}
- { }
- { ObjectWindows Paint demo }
- { Copyright (c) 1992 by Borland International }
- { }
- {************************************************}
-
- unit Bitmaps;
-
- { This unit augments the HBitmap type by implementing load and store of the
- bitmap to a file.
-
- Presently operates only on Windows format for bitmaps.
- }
- {$S-,R-}
-
- interface
-
- uses WinTypes, WinProcs;
-
- { Read a bitmap from file (full pathname).
- Returns 0 if error or HBitmap.
- }
- function LoadBitmapFile(FileName: PChar): HBitmap;
-
- { Write a bitmap to file (full pathname).
- Returns 0 if error else non-zero.
- }
- function StoreBitmapFile(FileName: PChar; HBM: HBitmap): Integer;
-
- implementation
-
- procedure AHIncr; far; external 'KERNEL' index 114;
-
- const
- MaxIO = 65534; { Max number bytes handled in single IO operation }
- OneIO = 32768; { Number bytes handled per huge IO operation }
- BMType = $4D42; { = 'BM' }
-
- type
- PtrRec = record
- Lo, Hi: Word
- end;
- IOFunction = function(FP: integer; Buf: PChar; Size: Integer): Word;
-
- { Perform IO operation in chunks to avoid memory segment crossings.
- Returns 0 if error else non-zero.
- }
- function HugeIO(IOFunc: IOFunction; F: Integer; P: Pointer; Size: Longint)
- : Word;
- var
- L, N: Longint; { L maintains total bytes }
- begin { N maintains bytes for current pass }
- HugeIO := 1;
- L := 0;
- while L < Size do
- begin
- N := Size - L;
- if N > OneIO then N := OneIO;
- if IOFunc(F,
- { Compute the segment and offset reached.
- The Hi word of P contains the initial segment.
- Think of the following as performing arithmetic
- modulo segment-size, since the size of a segment
- fills one word:
- The Hi word of L contains the number of segments crossed
- (the size of one segment fills the Lo word, so Hi word
- will roll over as segments are filled).
- Multiply by Ofs(AHIncr) to obtain the number used to
- indicate this number of segments.
- The Lo word of L contains the number of bytes already
- passed in the present segment.
- }
- Ptr(PtrRec(P).Hi + PtrRec(L).Hi * Ofs(AHIncr),
- PtrRec(L).Lo),
- Integer(N)) { Guaranteed to be in Integer range }
- <> N then
- begin
- HugeIO := 0;
- Exit; { abnormal termination }
- end;
- Inc(L, N);
- end;
- end;
-
- function _LFileSize(F : integer) : longint;
- {- an equivalent to TP's FileSize() function }
- var
- CurPos : longint;
- begin
- CurPos := _llseek(F,0,1);
- _LFileSize := _llseek(F,0,2);
- _llseek(F,CurPos,0);
- end;
-
- { Read a bitmap from file (full pathname).
- Returns 0 if error or HBitmap.
- }
- function LoadBitmapFile(FileName: PChar): HBitmap;
- var
- F: Integer; { File Handle for Windows file functions }
- H: THandle; { Handle to memory for bitmap }
- DC: HDC; { Drawing context for application }
- Size, N: Longint; { Size of bitmap, Size of color spec }
- P: PBitmapInfo; { Windows bitmap format info header }
- Header: TBitmapFileHeader; { Bitmap file header }
-
- begin
- LoadBitmapFile := 0;
- F := _LOpen(FileName, of_Read);
- if F = -1 then Exit;
-
- { read in the Bitmap file header }
- if (_LRead(F, @Header, SizeOf(Header)) <> SizeOf(Header)) or
- (Header.bfType <> BMType) then
- begin
- _LClose(F);
- Exit;
- end;
-
- { read the rest of the file }
- Size := _LFileSize(F) - SizeOf(TBitmapFileHeader);
- H := GlobalAlloc(gmem_Moveable, Size); { Allocate the memory }
- if H = 0 then
- begin
- _LClose(F);
- Exit;
- end;
-
- P := GlobalLock(H); { Lock it down }
-
- if (HugeIO(_LRead, F, P, Size) <> 0) and
- (P^.bmiHeader.biSize = SizeOf(TBitmapInfoHeader)) then
- begin
- { Compute the offset from the beginning of P^ }
- { where the actual image begins }
- N := Header.bfOffBits - SizeOf(TBitmapFileHeader);
-
- { actually create the Bitmap }
- DC := GetDC(0);
- LoadBitmapFile := CreateDIBitmap(DC, P^.bmiHeader,
- cbm_Init, Ptr(PtrRec(P).Hi,N),P^, dib_RGB_Colors);
-
- { clean up }
- ReleaseDC(0, DC);
- end;
-
- GlobalUnlock(H);
- GlobalFree(H);
- _LClose(F);
- end;
-
-
- { Write a bitmap to file (full pathname).
- Returns 0 if error else non-zero.
- }
- function StoreBitmapFile(FileName: PChar; HBM: HBitmap): Integer;
- var
- BM: TBitmap; { Bitmap information }
- BFH: TBitmapFileHeader; { Bitmap file information }
- BIP: PBitmapInfo; { Part of bitmap file information }
- DC: HDC; { Drawing context }
-
- HMem: THandle; { Handle to memory for bitmap }
- Buf: Pointer; { Memory for bitmap }
-
- ColorSize, DataSize: Longint; { Size needed to store Color/Data }
- BitCount: Word; { Number of bits per pixel }
- FP: Integer; { File }
-
- { Takes the size in bits and returns the (aligned) size in bytes.
- Bitmap data format requires word alignment.
- }
- function bmAlignDouble(Size: Longint): Longint;
- begin
- bmAlignDouble := (Size + 31) div 32 * 4;
- end;
-
- begin
- StoreBitmapFile := 0;
- { Get the information about the Bitmap }
- if GetObject(HBM, SizeOf(TBitmap), @BM) = 0 then Exit;
-
- BitCount := bm.bmPlanes * bm.bmBitsPixel;
- if (BitCount <> 24) then
- ColorSize := SizeOf(TRGBQuad) * (1 shl BitCount)
- else
- ColorSize := 0;
- DataSize := bmAlignDouble(bm.bmWidth * BitCount) * bm.bmHeight;
-
- { Create the file }
- FP := _lcreat(FileName, 0);
- if FP = -1 then Exit;
-
- { Allocate memory for the bitmap info structure }
- GetMem(BIP, SizeOf(TBitmapInfoHeader) + ColorSize);
- if BIP <> nil then
- begin
- { Fill in the Bitmap info header }
- with BIP^.bmiHeader do
- begin
- biSize := SizeOf(TBitmapInfoHeader);
- biWidth := bm.bmWidth;
- biHeight := bm.bmHeight;
- biPlanes := 1;
- biBitCount := BitCount;
- biCompression := 0;
- biSizeImage := DataSize;
- biXPelsPerMeter := 0;
- biYPelsPerMeter := 0;
- biClrUsed := 0;
- biClrImportant := 0;
- end;
-
- { Fill in the file header }
- with BFH do
- begin
- bfOffBits := SizeOf(BFH) + SizeOf(TBitmapInfo) + ColorSize;
- bfReserved1 := 0;
- bfReserved2 := 0;
- bfSize := bfOffBits + DataSize;
- bfType := BMType;
- end;
-
- { Create the memory Bitmap }
- HMem := GlobalAlloc(gmem_Fixed, DataSize);
- if HMem <> 0 then
- begin
- Buf := GlobalLock(HMem);
-
- { Get the bitmap bits in device independent format }
- DC := GetDC(0);
- if GetDIBits(DC, hbm, 0, DataSize, Buf, BIP^, dib_RGB_Colors) <> 0 then
- begin
- ReleaseDC(0, DC);
- { Write to file }
- _lwrite(FP, @BFH, SizeOf(BFH));
- _lwrite(FP, PChar(BIP), SizeOf(TBitmapInfo) + ColorSize);
- HugeIO(_lwrite, FP, Buf, DataSize);
- StoreBitmapFile := 1;
- end;
-
- { Clean up }
- GlobalUnlock(HMem);
- GlobalFree(HMem);
- end;
-
- FreeMem(BIP, SizeOf(TBitmapInfoHeader) + ColorSize);
- end;
-
- _lclose(FP);
-
- end;
-
- end.
-