News:

Building a 3D Ray Tracer  By stevmjon

Main Menu

Calculate RGB mask for different image depths

Started by kevin, July 07, 2010, 04:52:29 PM

Previous topic - Next topic

kevin

  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.    

   

PlayBASIC Code: [Select]
   ; 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







 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.  

PlayBASIC Code: [Select]
   ; 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




 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.

PlayBASIC Code: [Select]
   ; 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