Recent

Author Topic: Problem reading BMP header  (Read 552 times)

Conrad_404

  • New Member
  • *
  • Posts: 11
Problem reading BMP header
« on: January 01, 2026, 12:08:44 pm »
Sometimes I stumble over the simplest things %). I need a simple tool that will show me the field values ​​from the header of a BMP file. I previously wrote this program in TMT Pascal and it worked without any problems. I'm trying to port it to Free Pascal and I'm getting incorrect values (see attached jpg file). Furthermore, when using the winapi function, I get no readings at all. Does anyone know how to solve this problem? All files are attached below.

BTW. happy New Year to everyone :-)

Bart

  • Hero Member
  • *****
  • Posts: 5666
    • Bart en Mariska's Webstek
Re: Problem reading BMP header
« Reply #1 on: January 01, 2026, 12:16:21 pm »
Maybe this can help.
It's an excerpt from my piclib unit (you can find it and it's associate include filese here).
Code: Pascal  [Select][+][-]
  1. type
  2.   TImageFormat = (ifUnknown, ifBmp, ifPng, ifGif, ifJpg, ifTiff, ifEMF, ifPCX, ifWmf, ifXPM);
  3. {...}
  4. type
  5.   TBitmapFileHeader = Packed Record
  6.                         ID: word;
  7.                         FileSize: dword;
  8.                         Reserved: dword;
  9.                         BitmapDataOffset: dword;
  10.                       end;
  11.  
  12.   TBitmapInfo        = Packed Record
  13.                          BitmapHeaderSize: dword;
  14.                          Width: Int32;
  15.                          Height: Int32;
  16.                          Planes: word;
  17.                          BitsPerPixel: word;
  18.                          Compression: dword;
  19.                          BitmapDataSize: dword;
  20.                          XpelsPerMeter: dword;
  21.                          YPelsPerMeter: dword;
  22.                          ColorsUsed: dword;
  23.                          ColorsImportant: dword;
  24.                        end;
  25.  
  26. const
  27.   BmpIDWordA = Ord('B') or (Ord('M') shl 8); // $4D42
  28.   BmpIDWordB = Ord('B') or (Ord('B') shl 8); // $4242
  29.   BmpSupportedHeaderSizes = [$28,$0c,$f0];
  30.   BmpSupportedBitsPerPixel = [1,4,8,16,24,32];
  31.  
  32.  
  33. function MaybeBmp(St: TStream; out Width, Height: DWord; out dpiX, dpiY: Double): TImageFormat;
  34. var
  35.   BFH: TBitmapFileHeader;
  36.   BInfo: TBitmapInfo;
  37. begin
  38.   {$ifdef DebugPicsLib}
  39.   if IsConsole then writeln('MaybeBmp A');
  40.   {$endif}
  41.   Result := ifUnknown;
  42.   dpiX := 0;
  43.   dpiY := 0;
  44.   Width := 0;
  45.   Height := 0;
  46.  
  47.   if (St.Read(BFH{%H-}, Sizeof(TBitmapFileHeader)) <> Sizeof(TBitmapFileHeader)) then
  48.   begin
  49.     {$ifdef DebugPicsLib}
  50.     if IsConsole then writeln('Fail to read TBitmapFileHeader');
  51.     {$endif}
  52.     Exit;
  53.   end;
  54.   if (St.Read(BInfo{%H-}, SizeOf(TBitmapInfo)) <> SizeOf(TBitmapInfo)) then
  55.   begin
  56.     {$ifdef DebugPicsLib}
  57.     if IsConsole then writeln('Fail to read TBitmapInfo');
  58.     {$endif}
  59.     Exit;
  60.   end;
  61.   BFH.ID := LeToN(BFH.ID);
  62.   {$ifdef DebugPicsLib}
  63.   if IsConsole then writeln('BFH.ID = $',BFH.ID.ToHexString(4));
  64.   if IsConsole then writeln('BInfo.BitmapHeaderSize = $',IntToHex(BInfo.BitmapHeaderSize,2));
  65.   if IsConsole then writeln('BInfo.BitsPerPixel = ',BInfo.BitsPerPixel);
  66.   {$endif}
  67.   BInfo.BitmapHeaderSize := LeToN(BInfo.BitmapHeaderSize);
  68.   BInfo.BitsPerPixel := LeToN(BInfo.BitsPerPixel);
  69.   if ((BFH.ID = BmpIDWordA) or (BFH.ID = BmpIDWordB)) and
  70.      (BInfo.BitmapHeaderSize in BmpSupportedHeaderSizes) and
  71.      (BInfo.BitsPerPixel in BmpSupportedBitsPerPixel)then
  72.   begin
  73.     Width := LeToN(BInfo.Width);
  74.     //Apparently Height can be negative (picture is stored bottum-up)
  75.     Height := Abs(LeToN(BInfo.Height));
  76.     Result := ifBmp;
  77.     if BInfo.BitmapHeaderSize >= 40 then
  78.     begin
  79.       dpiX := LEToN(BInfo.XPelsPerMeter) * 0.0254;
  80.       dpiY := LEToN(BInfo.YPelsPerMeter) * 0.0254;
  81.     end;
  82.     if dpiX = 0 then dpiX := 72;
  83.     if dpiY = 0 then dpiY := 72;
  84.   end;
  85.   {$ifdef DebugPicsLib}
  86.   if IsConsole then writeln('MaybeBmp: Result = ',Result);
  87.   {$endif}
  88. end;

Bart

Bart

  • Hero Member
  • *****
  • Posts: 5666
    • Bart en Mariska's Webstek
Re: Problem reading BMP header
« Reply #2 on: January 01, 2026, 12:27:38 pm »
You might also have a look at wp's fpsimages unit (part of fpspreadsheet).
It handles jpg files a lot better than my unit does IIRC.
(I basicaly wrote my code only because I needed width and height of the images, all the rest I did not need.)

Bart

jamie

  • Hero Member
  • *****
  • Posts: 7493
Re: Problem reading BMP header
« Reply #3 on: January 01, 2026, 01:00:49 pm »
Sometimes I stumble over the simplest things %). I need a simple tool that will show me the field values ​​from the header of a BMP file. I previously wrote this program in TMT Pascal and it worked without any problems. I'm trying to port it to Free Pascal and I'm getting incorrect values (see attached jpg file). Furthermore, when using the winapi function, I get no readings at all. Does anyone know how to solve this problem? All files are attached below.

BTW. happy New Year to everyone :-)

Your code works correctly if you put "PACKED" on the BMHeader structure.

Btw, Thanks for reminding me how to do the old-style Windows front end stuff, it's been a treat and makes for a simple short program.


Jamie
The only true wisdom is knowing you know nothing

Conrad_404

  • New Member
  • *
  • Posts: 11
Re: Problem reading BMP header
« Reply #4 on: January 01, 2026, 06:15:16 pm »
Thanks! It works now!

 

TinyPortal © 2005-2018