This function bellow will calculate the BIT MASK for whatever surface (screen or image) depth you provide it. This is useful when we're designing our games to run in 32bit display depth, regardless of what the players computer can actually display. By default the PB graphics library will automatically step down the display depth to whatever the gamers system is using when were running our game in window modes, or if video card doesn't support the depth in full screen modes. While unlikely on modern systems, this can occur when running our programs on older machines. So it's worth putting a some thought into.
Surfaces that are 32bit, have all A,R,G,B channels (all channel are 8bit 0 to 255). But 24bit surfaces only have 8bit Red, 8 bit Green and 8Bit Blue. Where as 15bit and 16 bit surfaces have reduced ranges on R,G,B. 15 surfaces have 5bit Red, 5Bits Green and 5Bits Blue. 16Bit surfaces have 5bits Red, 6bits Green and 5bits Blue. So if we're reading pixels from the a 15bit or 16 bit surface and comparing the returned pixel values with a 32bit RGB (that's not colour 0 :) ),then we'll have to mask our 32bit value to make it compatible with the the surface.
[pbcode]
; create four images, these images have a depth that's independent of the
; computers display depth.
Width=100
Height=100
CreateFXImageEx 1,Width,Height,15 ; 15 bit image depth
CreateFXImageEx 2,Width,Height,16 ; 16 bit image depth
CreateFXImageEx 3,Width,Height,24 ; 24 bit image depth
CreateFXImageEx 4,Width,Height,32 ; 32 bit image depth
; query our four images( #1 to #4) about their depth and
; the ARGB pixel mask for those surface depths.
For ThisIMage=1 to 4
; Get IMage #1 Pixel Mask
print "ThisImage:"+Str$(Thisimage)
print "Depth:"+str$(GetIMageDepth(ThisImage))
print "Mask:"+hex$(Get_Pixel_Mask(ThisImage))
next
Sync
waitkey
Function Get_Pixel_Mask(ThisIMage=0)
select getImageDepth(ThisIMage)
case 15
Mask=$00f8f8f8
case 16
Mask=$00f8fCf8
case 24
Mask=$00ffffff
case 32
Mask=$ffffffff
EndSelect
EndFunction Mask
[/pbcode]
This Example Demonstrates the potential problem
Here we're create a 15bit surface, drawing a purple circle onto this surface then trying to run through the pixels of the surface and change them to some random colour.
[pbcode]
; Usage example.
Width=100
Height=100
; create a image that's 15bits depth, regardless of what the display depth
; is
CreateFXImageEx 1,Width,Height,15 ; 15 bit image depth
rendertoimage 1
; make 24bit RGB colour value, to represent purple. R=255, G=0, B=255
; each channel is 8bit
ThisColour=ARgb(255,255,0,255)
; draw a coloured circle to the current surface.
Circlec Width/2,Height/2,Width/2,true,ThisColour
; Get the middle pixel RGB
MiddlePixelRGB=Point(Width/2,Height/2)
; run through and convert all the Purple pixels to a random colour
For ylp=0 to Height-1
For xlp=0 to Width-1
If Point(xlp,ylp) = ThisColour
Dotc Xlp,Ylp,rndrgb()
endif
next
next
rendertoscreen
drawimage 1,100,100,false
print "32bit Purple"
print hex$(ThisColour)
print "Colour Read from surface"
print hex$(MiddlePixelRGB)
Sync
waitkey
[/pbcode]
If you run this, it won't work. It fails because we're comparing the 32bit RGB value, with the truncated value that's returned to us when reading from the 15bit surface. Obviously a 15bit surface have less colour ranges in R,G,B.
This Example Demonstrates the solution using the mask function above
To solve this type of issue we just mask our 32bit colour by the surface mask that we're reading from. This will convert our 32bit colour into something that's comparable.
[pbcode]
; Usage example.
Width=100
Height=100
; create a image that's 15bits depth, regardless of what the display depth
; is
CreateFXImageEx 1,Width,Height,15 ; 15 bit image depth
rendertoimage 1
; make 24bit RGB colour value, to represent purple. R=255, G=0, B=255
; each channel is 8bit
ThisColour=ARgb(255,255,0,255)
; draw a coloured circle to the current surface.
Circlec Width/2,Height/2,Width/2,true,ThisColour
; Get the middle pixel RGB
MiddlePixelRGB=Point(Width/2,Height/2)
; run through and convert all the Purple pixels to a random colour
ThisColourMaskedForsurface=ThisColour and Get_Pixel_Mask(1)
For ylp=0 to Height-1
For xlp=0 to Width-1
If Point(xlp,ylp) = ThisColourMaskedForsurface
Dotc Xlp,Ylp,rndrgb()
endif
next
next
rendertoscreen
drawimage 1,100,100,false
print "32bit Purple"
print hex$(ThisColour)
print "32bit Purple masked for the 15bit surface"
print hex$(ThisColourMaskedForsurface)
print "Colour Read from surface"
print hex$(MiddlePixelRGB)
Sync
waitkey
Function Get_Pixel_Mask(ThisIMage=0)
select getImageDepth(ThisIMage)
case 15
Mask=$00f8f8f8
case 16
Mask=$00f8fCf8
case 24
Mask=$00ffffff
case 32
Mask=$ffffffff
EndSelect
EndFunction Mask
[/pbcode]