Recent

Author Topic: Setting TBitmap.PixelFormat is broken?  (Read 2485 times)

domasz

  • Sr. Member
  • ****
  • Posts: 423
Setting TBitmap.PixelFormat is broken?
« on: November 30, 2022, 01:05:11 pm »
Very simple code. Reading a 24bit BMP, converting to 32bit and saving:

Code: Pascal  [Select][+][-]
  1.   Bmp := TBitmap.Create;
  2.   Bmp.LoadFromStream(Str);
  3.   Bmp.PixelFormat := pf32bit;
  4.   Bmp.SaveToFile('hejka.bmp');

Saved image is still 24bpp.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Setting TBitmap.PixelFormat is broken?
« Reply #1 on: November 30, 2022, 04:05:46 pm »
Setting the pixel format afaik doesn't convert. It just prepares the buffer for the next (write to the image) action to be 32-bit sized.

domasz

  • Sr. Member
  • ****
  • Posts: 423
Re: Setting TBitmap.PixelFormat is broken?
« Reply #2 on: November 30, 2022, 04:08:23 pm »
So this needs to be changed because in Delphi this does convert and is used by a lot of graphic libraries and functions.

theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1927
Re: Setting TBitmap.PixelFormat is broken?
« Reply #3 on: November 30, 2022, 04:40:05 pm »
You could try this:

Code: Pascal  [Select][+][-]
  1. uses FPReadBMP, FPImage, FPWriteBMP;
  2. ....
  3. var
  4.   Image: TFPCustomImage;
  5.   Reader: TFPCustomImageReader;
  6.   Writer: TFPWriterBMP;
  7. begin
  8.   Image := TFPMemoryImage.Create(10, 10);
  9.   Reader := TFPReaderBMP.Create;
  10.   Writer := TFPWriterBMP.Create;
  11.   Image.LoadFromFile('test.bmp', Reader);
  12.   Writer.BitsPerPixel:=32;
  13.   Image.SaveToFile('test32.bmp', Writer);
  14.   Image.free;
  15.   Reader.free;
  16.   Writer.free;
  17. end;    

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2007
  • Fifty shades of code.
    • Delphi & FreePascal
Re: Setting TBitmap.PixelFormat is broken?
« Reply #4 on: November 30, 2022, 05:16:05 pm »
Hello theo, thank you for your snippet, I just tried it, partially I can transform BPP from-to but now I run into an error where the created file is 0 byte.
Is there also a method to convert/adjust palette for destination BPP?

My try was to convert from 32bpp to 8bpp.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2007
  • Fifty shades of code.
    • Delphi & FreePascal
Re: Setting TBitmap.PixelFormat is broken?
« Reply #5 on: November 30, 2022, 05:20:08 pm »
Setting the pixel format afaik doesn't convert. It just prepares the buffer for the next (write to the image) action to be 32-bit sized.
I did try what you was writing, unsuccessful.
I loaded 32bpp Bitmap and create a second TBitmap with 16bits PixelFormat, draw the source on and saved = 32bpp  %)
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1927
Re: Setting TBitmap.PixelFormat is broken?
« Reply #6 on: November 30, 2022, 05:30:59 pm »
My try was to convert from 32bpp to 8bpp.
For 8bpp you need a palette (Color Quantization).
I don't know how to do this with fpImage.
It seems to work with BGRABitmap though.
See: https://forum.lazarus.freepascal.org/index.php/topic,61252.0.html

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2007
  • Fifty shades of code.
    • Delphi & FreePascal
Re: Setting TBitmap.PixelFormat is broken?
« Reply #7 on: December 01, 2022, 10:24:54 am »
My try was to convert from 32bpp to 8bpp.
For 8bpp you need a palette (Color Quantization).
I don't know how to do this with fpImage.
It seems to work with BGRABitmap though.
See: https://forum.lazarus.freepascal.org/index.php/topic,61252.0.html
Thanks! That was what I needed for my little project to easy reduce/slim very big pictures! (yes, with loss of colors...)
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

geraldholdsworth

  • Full Member
  • ***
  • Posts: 195
Re: Setting TBitmap.PixelFormat is broken?
« Reply #8 on: February 01, 2023, 12:36:12 pm »
I have noticed that with TBitmap, it will always report a PixelFormat of either pf24bit or pf32bit, despite what is actually in the bitmap. For example, on the project I am currently working on, it uses entirely 8 bit colour depth, and PixelFormat still tells me it is 24 bit. I have to resort to getting the actual bit depth from the bitmap header itself (which correctly says 8 ).

I also have to resort to building bitmaps at low level to ensure I get 8 bit colour depth.
« Last Edit: February 01, 2023, 12:38:01 pm by geraldholdsworth »

TRon

  • Hero Member
  • *****
  • Posts: 2435
Re: Setting TBitmap.PixelFormat is broken?
« Reply #9 on: February 01, 2023, 12:40:21 pm »
I have noticed that with TBitmap, it will always report a PixelFormat of either pf24bit or pf32bit, despite what is actually in the bitmap. For example, on the project I am currently working on, it uses entirely 8 bit colour depth, and PixelFormat still tells me it is 24 bit. I have to resort to getting the actual bit depth from the bitmap header itself (which correctly says 8 ).

I also have to resort to building bitmaps at low level to ensure I get 8 bit colour depth.
That is because TBitmap is not an independent bitmap but is related to your (desktop) environment. The underlying hardware determines the actual used pixeldepth for TBitmap. That is why you should never use it for such conversion purposes.

geraldholdsworth

  • Full Member
  • ***
  • Posts: 195
Re: Setting TBitmap.PixelFormat is broken?
« Reply #10 on: February 01, 2023, 12:52:04 pm »
That is because TBitmap is not an independent bitmap but is related to your (desktop) environment. The underlying hardware determines the actual used pixeldepth for TBitmap.

That did cross my mind. Thank you for clarifying it.

nanobit

  • Full Member
  • ***
  • Posts: 160
Re: Setting TBitmap.PixelFormat is broken?
« Reply #11 on: February 01, 2023, 03:10:55 pm »
TBitmap is supposed to support any standard PixelFormat, regardless of environments.
It's just, that format conversion in the PixelFormat setter is not implemented.

Another (current) limitation is the enforced use of 24bit for palettebased bitmaps,
see comment in DefaultReaderDescription(), but this is also independent of environments.
« Last Edit: February 01, 2023, 03:38:52 pm by nanobit »

TRon

  • Hero Member
  • *****
  • Posts: 2435
Re: Setting TBitmap.PixelFormat is broken?
« Reply #12 on: February 01, 2023, 03:43:08 pm »
TBitmap is supposed to support any standard PixelFormat, regardless of environments.
It's just, that format conversion in the PixelFormat setter is not implemented.
A common misconception, depending on what you actually meant by that.

The handle of a bitmap is opaque and is so for a reason. The bitmap is internally stored in/as the best possible format of the used interface.

Note that TBitmap class <> MS file stored bitmap. It just happens to be able to read/write them.

nanobit

  • Full Member
  • ***
  • Posts: 160
Re: Setting TBitmap.PixelFormat is broken?
« Reply #13 on: February 01, 2023, 04:54:41 pm »
TBitmap has many uses, GUI is just one (the most common) of them.
Pixelformat is a writable property (like in Delphi) and there is also this todo-comment in TCustomBitmap.SetPixelFormat(): "{$note todo copy image into new format }", for data conversion.

geraldholdsworth

  • Full Member
  • ***
  • Posts: 195
Re: Setting TBitmap.PixelFormat is broken?
« Reply #14 on: February 01, 2023, 05:50:26 pm »
I just wrote my own to scale up/down a bitmap and convert it (if needed) to 8bpp. Works fine for my needs, but might be a bit slow for bigger images - it goes through every pixel in the bitmap (low level access, after copying the bitmap to a TMemoryStream) and finds it in the palette, or the closest colour to it that is in the palette. The palette I'm using is a generic one which covers most colours, rather than generate one of my own. The scaling up/down is just using TBitmap's StretchDraw method.

Theo's method (above) should also work OK, although I haven't tried it yet.

 

TinyPortal © 2005-2018