{$R-} Unit BMP; { лллллллллллллллллллллллллллллллллллллллллллллллллл лллнммммммммммммммммммммммммммммммммммммммммммолллББ лллнлл ллолллББ лллнлл Complete unit for BMP images ллолллББ лллнлл ллолллББ лллнлл Aleksandar Dlabac ллолллББ лллнлл (C)1995. Dlabac Bros. Company ллолллББ лллнлл ------------------------------ ллолллББ лллнлл adlabac@urcpg.urc.cg.ac.yu ллолллББ лллнлл adlabac@urcpg.pmf.cg.ac.yu ллолллББ лллнлл ллолллББ лллнпппппппппппппппппппппппппппппппппппппппппполллББ ллллллллллллллллллллллллллллллллллллллллллллллллллББ ББББББББББББББББББББББББББББББББББББББББББББББББББ } Interface Type BMPInfoType = Record Width : longint; Height : longint; Colors : longint; Palette : array [0..255] of Record Red : byte; Green : byte; Blue : byte End End; Procedure ReadBMP (FileName : string); Function BMPResult : integer; Function BMPErrorMsg (ErrorCode : integer) : string; Procedure BMPInfo (var Info : BMPInfoType); Implementation Uses Graph; Const Rasters : array [0..15] of array [0..7] of byte = ((0,0,0,0,0,0,0,0),(128,0,8,0,128,0,8,0),(136,0,34,0,136,0,34,0), (168,0,42,0,138,0,42,0),(136,34,136,34,136,34,136,34), (168,136,42,34,168,136,42,34),(170,68,170,68,170,68,170,68), (170,85,170,85,170,85,170,85),(170,213,170,93,170,213,170,93), (85,187,85,187,85,187,85,187),(87,119,213,221,117,119,213,221), (119,221,119,221,119,221,119,221),(87,255,213,255,117,255,213,255), (119,255,221,255,119,255,221,255),(127,255,247,255,127,255,247,255), (255,255,255,255,255,255,255,255)); { This rasters is used for mono image dithering. Whenever program determines that number of colors available is smaller than number of colors in picture, picture is shown in mono (1 color) dither. } Var B : array [1..4] of byte; K : byte; BMPError : integer; I, J : longint; Colors : longint; MaxColor : longint; CoreHeader : Boolean; BMPFileHeader : Record BfType : integer; { Signature "BM" ($4D $42) } BfSize : longint; { File size } BfReserved1 : integer; { Reserved } BfReserved2 : integer; { Reserved } BfOffBits : longint { Data offset address: } End; { 2 colors $3E } { 16 colors $76 } { 256 colors $436 } { true color $36 } BMPInfoHeader : Record BiSize : longint; { $28 - Header length in bytes } BiWidth : longint; { Picture width } BiHeight : longint; { Picture height } BiPlanes : word; { Number of planes } BiBitCount : word; { Bits per pixel } BiCompression : longint; { Compression type (0-none) } BiSizeImage : longint; { Picture size in bytes (can be 0 for no compression) } BiXPelsPerMeter : longint; BiYPelsPerMeter : longint; BiClrUsed : longint; BiClrImportant : longint End; RGBColors : array [0..255] of Record RGBBlue : byte; RGBGreen : byte; RGBRed : byte; RGBReserved : byte End; Procedure PutPix (X,Y,Col:longint); Var Pix : byte; Intensity : real; Begin If (Y=0) and (Col<>255) then Write (''); If X>GetMaxX then Exit; If Y>GetMaxY then Exit; If X>BMPInfoHeader.BiWidth-1 then Exit; If Y>BMPInfoHeader.BiHeight-1 then Exit; If MaxColor0 then Begin BMPError:=1; Exit End; Size:=FileSize (F); If Size<246 then Begin BMPError:=2; Exit End; BlockRead (F,BMPFileHeader,14); If BMPFileHeader.BfType<>$4D42 then Begin BMPError:=4; Exit End; If Size0 then PutPix (I,J,1) else PutPix (I,J,0); Inc (I); B [K]:=B [K] shl 1; If I mod 8=0 then Inc (K) Until K=5 End; 4 : For K:=1 to 4 do Begin PutPix (I,J,(B [K] and $F0) shr 4); Inc (I); PutPix (I,J,B [K] and $0F); Inc (I) End; 8 : For K:=1 to 4 do Begin PutPix (I,J,B [K]); Inc (I) End; 24 : PutPix (I,J,longint (B [3])*65536+B [2]*256+B [1]) End Until I>BiWidth-1; If Colors>256 then For K:=1 to (I*3) and 3 do BlockRead (F,B[1],1) End; BMPError:=0 End; Function BMPResult : integer; Begin BMPResult:=BMPError; BMPError:=0 End; Function BMPErrorMsg (ErrorCode : integer) : string; Var Temp : string; Begin Case ErrorCode of 0 : Temp:='No error'; 1 : Temp:='Error opening file'; 2 : Temp:='File too short'; 3 : Temp:='File not loaded'; 4 : Temp:='Not a BMP file'; 5 : Temp:='Invalid header'; 6 : Temp:='Invalid number of colors'; 7 : Temp:='Graphics mode not initialized'; else Temp:='Unknown error' End; BMPErrorMsg:=Temp; End; Procedure BMPInfo (var Info : BMPInfoType); Var I : integer; Begin With Info do Begin Width:=0; Height:=0; Colors:=0; If BMPError=0 then With BMPInfoHeader do Begin Width:=BiWidth; Height:=BiHeight; Case BiBitCount of 1 : Colors:=2; 4 : Colors:=16; 8 : Colors:=256; 24 : Colors:=16777216; else Colors:=0 End; For I:=0 to Info.Colors-1 do With Palette [I], RGBColors [I] do Begin Red:=RGBRed; Green:=RGBGreen; Blue:=RGBBlue End End End End; Begin BMPError:=3 End. { ---------------------- Demo program ---------------------- } Program LoadBMP; Uses Crt, Graph, BMP; Const VGA256 = False; Var Gd, Gm, Result : integer; AutoDetectPointer : pointer; {$F+} Function DetectCard:integer; Var DetectedDriver, SuggestedMode : integer; Begin DetectGraph (DetectedDriver,SuggestedMode); If (DetectedDriver=VGA) or (DetectedDriver=MCGA) then DetectCard:=grOk else DetectCard:=grError End; {$F-} Procedure InitGraph256; Var Gd, Gm, ErrorCode : integer; Begin AutoDetectPointer:=@DetectCard; Gd:=InstallUserDriver ('VGA256',AutoDetectPointer); If GraphResult<>grOk then Begin Writeln ('Error installing driver'); Halt End; Gd:=Detect; InitGraph (Gd,Gm,''); ErrorCode:=GraphResult; If ErrorCode<>grOk then Begin Writeln ('Error: ',GraphErrorMsg (ErrorCode)); Halt End End; Begin If VGA256 then InitGraph256 else Begin DetectGraph (Gd,Gm); InitGraph (Gd,Gm,'') End; ReadBMP ('\WINDOWS\TARTAN.BMP'); Write (#7); Result:=BMPResult; If Result=0 then Repeat Until ReadKey<>''; CloseGraph; Writeln ('BMP status = ',BMPErrorMsg (Result)) End.