Programming => Graphics and Multimedia => Graphics => Topic started by: JJB on September 16, 2015, 02:53:41 am

Title: BMP and JPEG file resolution mismatch
Post by: JJB on September 16, 2015, 02:53:41 am
I am trying to save an image from a tForm as a BMP file and a JPG file, using SaveToFile.  When I import the image file into a Word document the apparent sizes in the document are substantially different.

I am using:
- Lazarus Version 1.4.0
- FPV Version 2.6.4     
- SVN Revision: 48774 
- i386-win32

In a new project I placed a tImage sized to 96 pixels in height and width, and two tButtons - one to draw a box, and the other one to create two files from the single tImage, a BMP file and a JPG file both using SaveToFile.  The tImage was sized to 96 pixels to produce a inch square box (Windows reported the display resolution as 96 DPI).

Both files appears the same in Paint or Windows Photo Viewer.  The BMP file contains "BM" as the first two characters, and the JPG file contains "JFIF" characters, and the file lengths are difference sizes.

Windows Explorer shows both files as 96 x 96 pixels, but in Word - right-click on the BMP - Format Picture - Size shows the Original Size ss 37.8 inches and is scaled to 17% but the JPG file Original Size is 1 inch and scaled at 100% (See attachment.)

The software for the two tButton OnClick events is also attached.

Apparently I missed setting a property.  Does anyone have a suggestion.

Thanks in advance.
Title: Re: BMP and JPEG file resolution mismatch
Post by: derek.john.evans on September 16, 2015, 04:30:56 am
I had a dig around for you. The bitmap settings you are referring to are XPelsPerMeter & YPelsPerMeter.

A search of the FPC source code brings up the unit FPWriteBMP. In TFPWriterBMP.SaveHeader(), there is this code:
Code: Pascal  [Select]
  1.     XPelsPerMeter:=100;
  2.     YPelsPerMeter:=100;  

Which kinda explains the (most likely rounded) 2-3 dpi.  I cant see any way to change those presets.

But, this is a hack that works:
Code: Pascal  [Select]
  1. uses BMPcomn, Math;
  3. procedure BitmapSaveToFile(const ABitmap: TBitmap; const AFileName: TFileName;
  4.   const ADPI: Integer);
  5. var
  6.   LMemoryStream: TMemoryStream;
  7.   LHeader: ^TBitMapInfoHeader;
  8. begin
  9.   LMemoryStream := TMemoryStream.Create;
  10.   try
  11.     ABitmap.SaveToStream(LMemoryStream);
  12.     LHeader := LMemoryStream.Memory + SizeOf(TBitMapFileHeader);
  13.     LHeader^.XPelsPerMeter := Ceil(ADPI * 100 / 2.54);
  14.     LHeader^.YPelsPerMeter := LHeader^.XPelsPerMeter;
  15.     LMemoryStream.SaveToFile(AFileName);
  16.   finally
  17.     FreeAndNil(LMemoryStream);
  18.   end;
  19. end;  

Use like:
Code: Pascal  [Select]
  1. BitmapSaveToFile(Image1.Picture.Bitmap, 'test.bmp', 96);  
Title: Re: BMP and JPEG file resolution mismatch
Post by: JJB on September 17, 2015, 02:58:11 am
Thanks Geepster!  I really appreciate the quick turn-around.

I was thinking that modifying the file header was going to be necessary, and started researching the file format.  So I don;t think my solution would be as elegant as your solution, very nice.

Thanks again.