Image to bank problems

BlitzPlus Forums/BlitzPlus Programming/Image to bank problems

xlsior(Posted 2003) [#1]
I've been playing around with Skidracer's 'bank to buffer' code snippet that appeared in the Blitz newsletter, and am running into some weird issues...

I am trying to copy an image into the buffer to start out with, but apparently am doing something wrong: while the image shows up in the buffer, the colors are all off, and not what they supposed to be. The problem appears to be somewher in the 'image2bank' function below:


Const screenwidth=640
Const screenheight=480
Global img%

Function CopyBankToBuffer(bank3,buffer)
; lock the image for byte transfer
   LockBuffer buffer
; test locked imagebuffer is 16 bits per pixel
   If LockedFormat(buffer)<>1
      UnlockBuffer buffer
      Notify("this test is 16 bit display mode only")
      End
   EndIf
; cache buffer variables   
   imagebank=LockedPixels(buffer)
   pitch=LockedPitch(buffer)
; copy bank to image line by line   
   For y=1 To screenheight
      CopyBank bank3,srcoff,imagebank,destoff,screenwidth*2
      srcoff=srcoff+screenwidth*2
      destoff=destoff+pitch
   Next
   UnlockBuffer buffer
End Function

Function image2bank(bank3)
DrawImage img%,0,0
   LockBuffer BackBuffer()
   For y=0 To screenheight-1
      For x=0 To screenwidth-1
         arg=ReadPixelFast (x,y,BackBuffer())

         ; Extract 1 byte Red, Green, Blue values, and divide by 16 to convert to
         ; a value between 0 and F - blue does not get divided and stays original
         argr=(arg And $ff0000) Shr 20
         argg=(arg And $ff00) Shr 12
         argb=(arg And $ff) Shr 4

         ; reconstruct the color value in 16 bit format
         ; ??? is the Blue part correct ???
         arg=(argr Shl 12)+(argg Shl 8)+argb
         PokeShort bank3,o,arg
         o=o+2
      Next
   Next
   UnlockBuffer BackBuffer()
End Function

Graphics screenwidth,screenheight,16,2
SetBuffer BackBuffer()

bank2=CreateBank(screenwidth*screenheight*2)

img%=LoadImage("x:\monkey5.jpg")
SetBuffer BackBuffer()
DrawBlock img%,0,0
image2bank(bank2)
Flip
WaitKey()

copybanktobuffer(bank2,BackBuffer())
Flip
WaitKey()
End


Now... Through experimentations and such I determined that for a 16 bit image, the colors are stored in two bytes. One byte containing Red/Green, and one byte containing Blue/???.
Some basic testing showed this:
$F000 - Red
$0F00 - Green
$FF00 - Yellow
$00FF - Bright blue
$00F0 - darker blue
$FFF0 - pale yellow
$FFFF - white

To me, this appears to indicate that the BLUE color is actually stored in a 256-color gradation instead of 16, like red and green are, unless I'm misinterpreting these results.

So... I tried to convert these red/green/blue values back into a short, and poke it into the image bank... But like I said before *something* is very wrong, since the colors are completely messed up. I tried a bunch of variations, including poking the red/green and blue bytes seperately using pokebyte, but am running in the exact same issue.

I'm about ready to beat my head against a wall here: what am I doing wrong?!

Any help would be much appreciated.


Rottbott(Posted 2003) [#2]
What about alpha?

Actually... I thought it was something like 5 bits for red, 6 for green, 5 for blue. But it can be different for different types of buffers or different video cards.


Rob Farley(Posted 2003) [#3]
I've found for this sort of thing you have to do a 16 bit colour test to set up the program before you do anything.

Create a 1x1 image.
Write a pixel full red.
read it back and see what is says.

Likewise with blue and green. The value tend to be different for different video cards. That said I don't use blitz+ so I might be talking out of my arse.


Seldon(Posted 2003) [#4]
For each pixel you have a long (4 bytes) :

I byte= Alpha (set to 255 or $FF)
II byte= Red (0<->255)
III byte= Green (0<->255)
IV byte= Blu (0<->255)

Due to little/big-endian matter, the sequence could look inverted, i.e. Blu,Green,Red,Alpha .


Simon S(Posted 2003) [#5]
I've been messing about with this too.

set your r,g and b values and

rgb=(r Shl 11)+(g shl 5)+b

will set an rgb in 5,6,5 format, ready for poking (most common for 16bit I believe)

oh, and 0-255 cannot be poked in, so just divide the values as follows, r/5,g/4,b/5


MSW(Posted 2003) [#6]
Hate to point out the obvious but in your code...you are ALREADY useing 16-bit color for the application....as such the ReadPixelFast call should return an already converted 16-bit color...no need to convert the color to 16-bits...just take the ReadPixelFast color...shift it left by 16 then PokeShort into your array (might not have to do that depends on how PokeShort uses the 32-bit numbers passed to it...if it reads from the last 16-bits, then no need to left shift it)...


oh, and 0-255 cannot be poked in, so just divide the values as follows, r/5,g/4,b/5



Yeap, 0-255 can't be poked in...but you have the conversion math wrong...5-bits for the Red and Blue has a range of 0-31...so those values must be divided by 8 not 5 when going from 0-255 to 0-31....a 6-bit green has a range of 0-63, so going from a range of 0-255 you must divide by 4 to get a 0-63 value...


Paradox7(Posted 2003) [#7]
so... Does this mean the code provided in the newsletter is all wrong?? If so, anybody mind reposting the correct code to do the job ;)


xlsior(Posted 2003) [#8]
Well... The code in the newsletter is correct, and is indeed very fast at doing what it does -- however, it is poking a bunch of abstract data to the buffer to show how it works.

Very nice, but unless I can figure out how to manipulate *usable* graphic data directly in the buffer, it doesn't really help me.

I've looked at the different suggestions people brought up above, but so far I still have not been able to convert any of it to a working function.

All my attempts so far have resulted inimages with messed up palettes, although there are differences between the various versions... Just haven't nailed it yet.


Perturbatio(Posted 2003) [#9]
I wrote this code a while ago, don't know if it will help or not.


xlsior(Posted 2003) [#10]
Thanks -- this will be very helpful.

I did notice one thing in your code already that I (stupid stupid stupid!) missed myself: I didn't skip the first couple of bytes in the bank, which definitely doesn't help things.