This is a surprising and increasingly anachronistic behavior ...

For historical reasons, the pixel value 0 means transparent in Squeak forms that have no color map. That was a convention from back in the day when 32 bit forms were too expensive (that's twice as many bits to shuffle around than 16 bit forms) and when a SmallInteger could not hold 32bit color values (SmallInteger maxVal used to be 16r3FFFFFFF = 1073741823). That's why Color's "rgb" instance variable only holds 30 bits of color (3x10 bits for r, g, and b) and its TranslucentColor subclass adds an "alpha" instance variable which holds 8 bits of alpha.

Most of the BitBlt modes operating on 32 bit forms ignore the upper 8 bit of its pixel values, basically treating it as a 24 bit form where black is represented by the pixel value 16x000001 (very dark blue) and the pixel value 0x000000 means "transparent".

The "magic" happens in Color>>pixelValueForDepth: which has this comment

    "Transparency:
        The pixel value zero is reserved for transparent.
        For depths greater than 8, black maps to the darkest possible blue."


and this code

      d = 32 ifTrue: "eight bits per component; top 8 bits set to all ones (opaque alpha)"
            
["this subexpression is a SmallInteger in both 32- and 64-bits."
            
val :=    ((rgb bitShift: -6) bitAnd: 16rFF0000) bitOr:
                    
(((rgb bitShift: -4) bitAnd: 16rFF00) bitOr:
                    
((rgb bitShift: -2) bitAnd: 16rFF)).
            
"16rFF000000 & 16rFF000001 are LargeIntegers in 32-bits, SmallIntegers in 64-bits."
            
^val = 0 ifTrue: [16rFF000001] ifFalse: [16rFF000000 + val]].

which tries hard to avoid LargeInteger arithmetic in 32 bit images. Note that TranslucentColor overrides this method to add the proper alpha value.

It is somewhat unsatisfying, agreed, but there is some method to the madness ;)

All of that being said, maybe we should indeed fix isTransparentAt: for 32 bit forms (ColorForm gets it right).

Vanessa

On Sun, Apr 14, 2024 at 5:18 PM Lauren Pullen <drurowin@gmail.com> wrote:
Hi List,

I have a 32-bit Form I imported from a PNG without an alpha layer that
has a black background for transparency, but this is what I get when I
examine it in the inspector:

self pixelValueAt: 1@1.                 4278190080 .
self pixelValueFor: Color black.        4278190081 .
self colorAt: 1@1.                      Color transparent .
self isTransparentAt: 1@1.              false .
self pixelValueFor: Color transparent.  0 .

I feel like having #colorAt: answer transparent while #isTransparentAt:
answers false is a bug.