ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
Forum membership is Free!  Click Join to sign-up
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 Loading 32 bit BI_BITFIELDS bitmap having non-8-bit channels
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

Harald Lampke

Germany
3 Posts

Posted - Sep 15 2022 :  07:43:52  Show Profile  Reply
When loading a 32 bit bitmap with "biCompression = BI_BITFIELDS", and when the bitmask of a channel (including the alpha channel) has more or less than 8 bits set, the resulting colors respectively alpha values are wrong.

To fix this, in module bmpfilt.pas, procedure BMPReadStream, the lines

  rshift := IEGetFirstSetBit(BitFields[0]) - 1;
  gshift := IEGetFirstSetBit(BitFields[1]) - 1;
  bshift := IEGetFirstSetBit(BitFields[2]) - 1;
  ashift := IEGetFirstSetBit(BitFields[3]) - 1;


must be supplemented to

  rshift := IEGetFirstSetBit(BitFields[0]) - 1 + (_GetBitCount(BitFields[0]) - 8);
  gshift := IEGetFirstSetBit(BitFields[1]) - 1 + (_GetBitCount(BitFields[1]) - 8);
  bshift := IEGetFirstSetBit(BitFields[2]) - 1 + (_GetBitCount(BitFields[2]) - 8);
  ashift := IEGetFirstSetBit(BitFields[3]) - 1 + (_GetBitCount(BitFields[3]) - 8);


in order to scale the resulting channel values to the range of [0..255].

Additional, a 32 bit bitmap with "biCompression = BI_BITFIELDS" and a header of type BITMAPINFOHEADER only has three DWORD bitmasks (red, green and blue) and no alpha mask, not four bitmasks (see https://docs.microsoft.com/de-de/previous-versions//dd183376%28v=vs.85%29 ). So the code loading the bitmasks should be

  if xCompression = BI_BITFIELDS then
  begin
    case xBitCount of
      ...
      32: begin
        // red, green and blue masks
        fs.Read(BitFields[0], sizeof(dword) * 3);
        // no alpha mask 
        BitFields[3] := 0;
        IgnoreAlpha := true;
        end; // 32
    end; // case
  end; // if


and in line 1079

  if BitFields[3] = 0 then
    ashift := 0
  else
    ashift := IEGetFirstSetBit(BitFields[3]) - 1 + (_GetBitCount(BitFields[3]) - 8);

xequte

38608 Posts

Posted - Sep 15 2022 :  18:09:20  Show Profile  Reply
Thanks, I'll have my partner take a look at this. Can you upload/forward your test images?

Nigel
Xequte Software
www.imageen.com
Go to Top of Page

Harald Lampke

Germany
3 Posts

Posted - Sep 16 2022 :  01:52:02  Show Profile  Reply
Attached you'll find five 32 bit images: Genuine is 32 bit BI_RGB, and four BI_BITFIELDS encoded images in 7-7-7, 8-8-8, 9-9-9 and 12-11-9, all showing the same subject.

attach/Harald Lampke/202291614916_32 Bit BI_BITFIELDS.zip
985.15 KB
Go to Top of Page

xequte

38608 Posts

Posted - Sep 20 2022 :  21:30:50  Show Profile  Reply
Thank you for your code suggestions.

This will be implemented in the next update.

Nigel
Xequte Software
www.imageen.com
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: