I draw from banks all the time in my 2D games, though have my own routines (which I'd be willing to share if they were tidy enough), and even on an older PC if it's done right can still be very quick - for the right sorts of graphics, and it saves on video memory since you are simply pixelplotting from system memory.
Code archives/Graphics/DrawBank
This code has been declared by its author to be Public Domain code.
Download source code
| I couldn't find a previous example of this, oddly enough, though someone's surely done it. Not much use for real time games, but may come in handy for... other stuff. If anyone can speed this up then please post here! (I get about 10 milliseconds for the boing.png image from BlitzMax "RockOut", on an Intel Core2Duo 6300 @ 1.86 GHz with Geforce 7600 GS, and about 330 milliseconds for any image that completely fills the screen without a mask.) EDIT: Added background mask hack/fix and trivial, worthless optimisations. |
f$ = "boing.png" Graphics 1024, 768, 0, 2 ; IMPORTANT! Required by DrawBank! Global GW = GraphicsWidth () Global GH = GraphicsHeight () Global DB_RGB SetDrawBankMask 255, 0, 255 Function SetDrawBankMask (r, g, b) tempbuffer = GraphicsBuffer () temp = CreateImage (1, 1) SetBuffer ImageBuffer (temp) Plot 0, 0: GetColor 0, 0 tr = ColorRed () tg = ColorGreen () tb = ColorBlue () Color r, g, b: Plot 0, 0: GetColor 0, 0 r = ColorRed () g = ColorGreen () b = ColorBlue () FreeImage temp DB_RGB = ((r Shl 16) + (g Shl 8) + b) Or ~$00FFFFFF SetBuffer tempbuffer Color tr, tg, tb End Function Function DrawBank (bank, x, y, width, height, center = 0, masked = True) ; Centre image on screen if required... If center x = x - width / 2 y = y - height / 2 EndIf ; Alpha mask... mask = ((r Shl 16) + (g Shl 8) + b) Or ~$00FFFFFF ; Scan across image... For w = 0 To width - 1 ; x-position plus current 'pixel' NOT off right of screen? If x + w < GW ; Not off left of screen? If x + w > -1 ; Scan down image... For h = 0 To height - 1 ; Not off bottom of screen? If y + h < GH ; Not off top of screen? If y + h > -1 ; Get current value in bank... argb = PeekInt (bank, pointer) ; Assuming most cases use transparent mask... If argb <> DB_RGB WritePixelFast x + w, y + h, argb Else ; User wants mask drawn... If Not masked WritePixelFast x + w, y + h, argb EndIf EndIf ; Move to next value in bank (argb = 4 bytes = integer, hence PeekInt above)... pointer = pointer + 4 Else ; Off top of screen, so skip all pixels until on screen... h = h + (-y) - 1 pointer = pointer + (h Shl 2) + 4 EndIf Else ; Off bottom of screen, stop drawing this column... pointer = pointer + (height - h) Shl 2 Exit EndIf Next Else ; Off left of screen, so skip all pixels until on screen... pointer = pointer + (height - h) Shl 2 EndIf Else ; Off right of screen, so stop drawing... Exit EndIf Next End Function Function ImageToBank (bufferImage) ; Slightly modified from http://www.blitzbasic.com/codearcs/codearcs.php?code=396 ; By Perturbatio bankImage = CreateBank () bufOldBuffer = GraphicsBuffer () SizeOfImage = ImageWidth (bufferImage) * ImageHeight (bufferImage) ResizeBank bankImage, (SizeOfImage * 4) SetBuffer ImageBuffer (bufferImage) LockBuffer ImageBuffer (bufferImage) For iLoopX = 0 To ImageWidth (bufferImage) - 1 For iLoopY = 0 To ImageHeight (bufferImage) - 1 PokeInt bankImage, ibankPointer, ReadPixelFast (iLoopX, iLoopY) iBankPointer = iBankPointer + 4 Next Next UnlockBuffer ImageBuffer (bufferImage) SetBuffer bufOldBuffer Return bankImage End Function ; Test... ClsColor 64, 96, 128 SetBuffer BackBuffer () image = LoadImage (f$) width = ImageWidth (image) height = ImageHeight (image) bank = ImageToBank (image) FreeImage image Repeat Cls mx = MouseX () my = MouseY () If KeyDown (203) Then xs# = xs - 0.1 If KeyDown (205) Then xs = xs + 0.1 If KeyDown (200) Then ys# = ys - 0.1 If KeyDown (208) Then ys = ys + 0.1 If mx <> lastx x# = mx xs = 0 Else x = x + xs EndIf If my <> lasty y# = my ys = 0 Else y = y + ys EndIf lastx = mx lasty = my LockBuffer BackBuffer () ms = MilliSecs () DrawBank bank, x, y, width, height, 1 ticks = MilliSecs () - ms UnlockBuffer BackBuffer () Text 20, 20, ticks Flip Until KeyHit (1) End |
Comments
Good point regarding video memory, and I suppose it's fine for board/grid-based games...
I tried another angle on this by pre-calculating the rectangle to be scanned 'inside' the bank, skipping tons of If/Then checks within the nested loops, and I got a staggering increase of... well, zero per-cent.
Looks like this is limited more by the actual drawing rather than the plotting algorithm...
EDIT: Oops, background mask was failing on different bit-depth screens. Ungodly hack added -- SetDrawBankMask (r, g, b)!
I tried another angle on this by pre-calculating the rectangle to be scanned 'inside' the bank, skipping tons of If/Then checks within the nested loops, and I got a staggering increase of... well, zero per-cent.
Looks like this is limited more by the actual drawing rather than the plotting algorithm...
EDIT: Oops, background mask was failing on different bit-depth screens. Ungodly hack added -- SetDrawBankMask (r, g, b)!
f$ = "boing.png" Graphics 1024, 768, 0, 2 ; IMPORTANT! Required by DrawBank! Global GW = GraphicsWidth () Global GH = GraphicsHeight () Global DB_RGB SetDrawBankMask 255, 0, 255 Function SetDrawBankMask (r, g, b) tempbuffer = GraphicsBuffer () temp = CreateImage (1, 1) SetBuffer ImageBuffer (temp) Plot 0, 0: GetColor 0, 0 tr = ColorRed () tg = ColorGreen () tb = ColorBlue () Color r, g, b: Plot 0, 0: GetColor 0, 0 r = ColorRed () g = ColorGreen () b = ColorBlue () FreeImage temp DB_RGB = ((r Shl 16) + (g Shl 8) + b) Or ~$00FFFFFF SetBuffer tempbuffer Color tr, tg, tb End Function Function DrawBank (bank, x, y, width, height, center = 0, masked = True) ; Centre image on screen if required... If center x = x - width / 2 y = y - height / 2 EndIf ;--------------------------------------------------------------------------- ; Check where edges are on screen. leftx/rightx and topy/bottomy describe ; a rectangle within the bank 'texture'... ;--------------------------------------------------------------------------- ; Left edge (all edges are checked similarly)... If x > -1 ; On screen? If not, exit function... If x > GW - 1 Return Else leftx = 0 ; Otherwise, use left edge of bank... EndIf Else ; Off left of screen, so go this many pixels 'into' the bank... leftx = 0 - x EndIf ; Right edge... If x + width > 0 If x + width > GW rightx = GW - x Else rightx = width EndIf Else Return EndIf ; Top edge... If y > -1 If y > GH - 1 Return Else topy = 0 EndIf Else topy = 0 - y EndIf ; Bottom edge... If y + height > 0 If y + height > GH bottomy = GH - y Else bottomy = height EndIf Else Return EndIf ; Set start of texture, 'into' the bank... pointer = pointer + leftx * height Shl 2 ; (x Shl 2) = (x * 4) ; Scan across image... For w = leftx To rightx - 1 xw = x + w ; Move pointer 'down' by top offset... pointer = pointer + topy Shl 2 ; Scan down image... For h = topy To bottomy - 1 ; Get current value in bank... argb = PeekInt (bank, pointer) ; Assuming most cases use background mask... If argb <> DB_RGB WritePixelFast xw, y + h, argb Else ; User wants mask drawn... If Not masked WritePixelFast xw, y + h, argb EndIf EndIf ; Move to next value in bank (argb = 4 bytes = integer, hence PeekInt above)... pointer = pointer + 4 Next ; Jump remainder of 'pixels' off bottom... pointer = pointer + (height - bottomy) Shl 2 ; Ah, good old trial-and-error... Next End Function Function ImageToBank (bufferImage) ; Slightly modified from <a href="http://www.blitzbasic.com/codearcs/codearcs.php?code=396" target="_blank">http://www.blitzbasic.com/codearcs/codearcs.php?code=396</a> ; By Perturbatio bankImage = CreateBank () bufOldBuffer = GraphicsBuffer () SizeOfImage = ImageWidth (bufferImage) * ImageHeight (bufferImage) ResizeBank bankImage, (SizeOfImage * 4) SetBuffer ImageBuffer (bufferImage) LockBuffer ImageBuffer (bufferImage) For iLoopX = 0 To ImageWidth (bufferImage) - 1 For iLoopY = 0 To ImageHeight (bufferImage) - 1 PokeInt bankImage, ibankPointer, ReadPixelFast (iLoopX, iLoopY) iBankPointer = iBankPointer + 4 Next Next UnlockBuffer ImageBuffer (bufferImage) SetBuffer bufOldBuffer Return bankImage End Function ; Test... ClsColor 64, 96, 128 SetBuffer BackBuffer () image = LoadImage (f$) width = ImageWidth (image) height = ImageHeight (image) bank = ImageToBank (image) FreeImage image Repeat Cls mx = MouseX () my = MouseY () shifted = KeyDown (42) If shifted xs# = 0 ys# = 0 If KeyHit (203) Then x# = x - 1 If KeyHit (205) Then x = x + 1 If KeyHit (200) Then y# = y - 1 If KeyHit (208) Then y = y + 1 Else If KeyDown (203) Then xs = xs - 0.1 If KeyDown (205) Then xs = xs + 0.1 If KeyDown (200) Then ys = ys - 0.1 If KeyDown (208) Then ys = ys + 0.1 EndIf If mx <> lastx x = mx xs = 0 Else x = x + xs EndIf If my <> lasty y = my ys = 0 Else y = y + ys EndIf lastx = mx lasty = my LockBuffer BackBuffer () ms = MilliSecs () DrawBank bank, x, y, width, height, 1 ticks = MilliSecs () - ms UnlockBuffer BackBuffer () Text 20, 20, ticks Flip Until KeyHit (1) End
Hi! have optimized all function and organize
f$ = "boing.png" Graphics 1024, 768, 0, 2 Function BankImage_SetMask(a_BankImage, r, g, b) Local l_IdBank = 3*4 PokeInt a_BankImage, l_IdBank,((r Shl 16) + (g Shl 8) + b) Or ~$00FFFFFF End Function Function BankImage_SetAlpha(a_BankImage, Alpha%=0 ) Local l_IdBank = 4*4 PokeInt a_BankImage, l_IdBank, Alpha Shl 8 End Function Function BankImage_Draw(a_BankImage, x, y, center = False, a_Masked = False) ; ===> Local l_LoopX%, l_LoopY%, l_ARGB% Local l_IdBank%, l_IdBankXa%, l_IdBankXb%, l_IdBankYa%, l_IdBankYb%; Local l_PX%, l_PY%; ; ===> Local l_ImgWidth% = PeekInt (a_BankImage, l_IdBank) : l_IdBank = l_IdBank + 4 Local l_ImgHeight% = PeekInt (a_BankImage, l_IdBank) : l_IdBank = l_IdBank + 4 Local l_ColorMask% = PeekInt (a_BankImage, l_IdBank) : l_IdBank = l_IdBank + 4 Local l_Alpha% = PeekInt (a_BankImage, l_IdBank) : l_IdBank = l_IdBank + 4 Local GW% = GraphicsWidth()-1 Local GH% = GraphicsHeight()-1 Local l_OffsetBankY = l_ImgWidth*4 ; ===> ; Local l_StXa%, l_StXb%,l_StYa%,l_StYb% If (center) Then l_StXa% = x - (l_ImgWidth /2) l_StXb% = x + (l_ImgWidth /2) - 1 l_StYa% = y - (l_ImgHeight/2) l_StYb% = y + (l_ImgHeight/2) - 1 Else l_StXa% = x l_StXb% = x + l_ImgWidth - 1 l_StYa% = y l_StYb% = y + l_ImgHeight - 1 EndIf ; ===> ; image overscreen If ((l_StXa > GW ) Or (l_StYa > GH ) Or (l_StXb < 0 ) Or (l_StYb < 0 )) Then Return ; ===> If (l_StXa < 0 ) Then l_IdBankXa = Abs(l_StXa)*4 : l_StXa% = 0; Abs(l_StXa)*4 If (l_StYa < 0 ) Then l_IdBankYa = Abs(l_StYa)*l_OffsetBankY : l_StYa% = 0; Abs(l_StYa)*l_OffsetBankY If (l_StXb >=GW) Then l_IdBankXb = (l_StXb-GW)*4 : l_StXb = GW If (l_StYb >=GH) Then l_StYb = GH ; ===> l_IdBank = l_IdBank + l_IdBankXa+l_IdBankYa If (a_Masked) Then Local l_color% = 0 ; ===> For l_LoopY = l_StYa To l_StYb;l_ImgHeight - 1 ; ===> For l_LoopX = l_StXa To l_StXb ; ===> l_color = PeekInt( a_BankImage, l_IdBank) If(l_color<>l_ColorMask) Then WritePixelFast l_LoopX, l_LoopY, l_color;+l_Alpha l_IdBank = l_IdBank + 4 ; ===> Next ; ===> l_IdBank = l_IdBank + (l_IdBankXb+l_IdBankXa) ; ===> Next ; ===> Else ; ===> For l_LoopY = l_StYa To l_StYb;l_ImgHeight - 1 ; ===> For l_LoopX = l_StXa To l_StXb ; ===> WritePixelFast l_LoopX, l_LoopY, PeekInt(a_BankImage, l_IdBank);+l_Alpha l_IdBank = l_IdBank + 4 ; ===> Next ; ===> l_IdBank = l_IdBank + (l_IdBankXb+l_IdBankXa) ; ===> Next ; ===> EndIf ; ===> ;l_StXa = 0 : l_StYa=0 ; ===> ; ; If (a_Masked) Then ; Local l_color% = 0 ; ; ===> ; ; Scan across image... ; For l_LoopY = l_StYa To l_StYb;l_ImgHeight - 1 ; l_IdBank = l_LoopY * l_BankY + l_IdBankX + l_IdBankY ; ; ===> ; For l_LoopX = l_StXa To l_StXb ; ; ===> ; l_color = PeekInt( a_BankImage, l_IdBank) ; If(l_color<>l_ColorMask) Then WritePixelFast l_LoopX+x, l_LoopY+y, l_color ; l_IdBank = l_IdBank + 4 ; ; ===> ; Next ; ; ===> ; Next ; Else ; ===> ; Scan across image... ; For l_LoopY = l_StYa To l_StYb;l_ImgHeight - 1 ; ; ===> ; l_IdBank = 16+(l_LoopY * l_OffsetBankY) ;+ l_IdBankY + l_IdBankX; + 16 ; ; ===> ; For l_LoopX = l_StXa To l_StXb ; ; ===> ; WritePixelFast l_LoopX, l_LoopY, PeekInt (a_BankImage, l_IdBank)+l_Alpha ; l_IdBank = l_IdBank + 4 ; ; ===> ; Next ; ; ===> ; Next ; EndIf ; ===> End Function Function BankImage_Load(Filename$) ; ===> Local l_BufferImage = LoadImage (Filename) ; ===> ; Slightly modified from Code Archives entry 396 by Perturbatio! Local l_ImgWidth% = ImageWidth (l_BufferImage) Local l_ImgHeight% = ImageHeight(l_BufferImage) Local l_SizeOfImage% = l_ImgWidth * l_ImgHeight * 4 ; il 4 e il contenitore del colore ARGB Local l_SizeVariable% = 4*4; Local l_BankImage% = CreateBank (l_SizeOfImage+l_SizeVariable) Local l_ColorMask% = 0 Local l_Alpha% = 0 ; ===> Local l_OldBuffer% = GraphicsBuffer () Local l_LoopX, l_LoopY, l_IdBank; ; ===> SetBuffer ImageBuffer (l_BufferImage) LockBuffer ImageBuffer (l_BufferImage) PokeInt l_BankImage, l_IdBank, l_ImgWidth : l_IdBank = l_IdBank + 4 ; Store Variable Width PokeInt l_BankImage, l_IdBank, l_ImgHeight: l_IdBank = l_IdBank + 4 ; Store Variable Height PokeInt l_BankImage, l_IdBank, l_ColorMask: l_IdBank = l_IdBank + 4 ; Store Variable Color Mask PokeInt l_BankImage, l_IdBank, l_Alpha : l_IdBank = l_IdBank + 4 ; Store Variable Alpha ; ===> For l_LoopY = 0 To l_ImgHeight - 1 For l_LoopX = 0 To l_ImgWidth - 1 PokeInt l_BankImage, l_IdBank, ReadPixelFast( l_LoopX, l_LoopY) l_IdBank = l_IdBank + 4 Next Next ; ===> UnlockBuffer ImageBuffer (l_BufferImage) SetBuffer l_OldBuffer ; ===> FreeImage l_BufferImage ; ===> Return l_BankImage ; ===> End Function ; Test... ClsColor 64, 96, 128 SetBuffer BackBuffer () Local bank = BankImage_Load(f$) Local ScreenMW% = GraphicsWidth() *.5 Local ScreenMH% = GraphicsHeight()*.5 Local ticks#, ticksAdd#, cnt# Repeat Cls mx = MouseX () my = MouseY () If KeyDown (203) Then xs# = xs - 0.1 If KeyDown (205) Then xs# = xs + 0.1 If KeyDown (200) Then ys# = ys - 0.1 If KeyDown (208) Then ys# = ys + 0.1 If KeyDown (57) Then Stop If mx <> lastx x# = mx xs = 0 Else x = x + xs EndIf If my <> lasty y# = my ys = 0 Else y = y + ys EndIf lastx = mx lasty = my LockBuffer BackBuffer () ms = MilliSecs () ;DrawBank bank, x, y, 1,128,128,128,True BankImage_SetMask ( bank, 0, 0, 0) ;BankImage_Draw ( bank, GraphicsWidth()*.5, GraphicsHeight()*.5, True, True) BankImage_Draw ( bank, x, y, True, True) ticks = MilliSecs () - ms ;===> If (ticksAdd<10000) Then ticksAdd = ticksAdd + ticks cnt=cnt+1 EndIf ;===> UnlockBuffer BackBuffer () Local l_Line=10 Local l_InterLine = 15 Color 255,0,0 If ticks>0 Then Text 20, l_Line, "Ms: " + Float(Int(ticks)) + " FPS: " + Float(Int((1000.0*100.0)/ticks))/100 : l_Line = l_Line+l_InterLine Text 20, l_Line, "Statistic Time for 10 seconds" : l_Line = l_Line+l_InterLine Text 20, l_Line, "Midle time" : l_Line = l_Line+l_InterLine Text 20, l_Line, "Ms: " + Float(Int(100.0*ticksAdd/cnt))/100.0 + " FPS: " + Float(Int(1000.0/(ticksAdd/cnt)*100))/100.0 : l_Line = l_Line+l_InterLine Else Text 20, l_Line, "Ms: " + Float(Int(ticks)) + " FPS: " + 0 : l_Line = l_Line+l_InterLine Text 20, l_Line, "Statistic Time for 10 seconds" : l_Line = l_Line+l_InterLine Text 20, l_Line, "Midle time" : l_Line = l_Line+l_InterLine Text 20, l_Line, "Ms: " + Float(Int(100.0*ticksAdd/cnt))/100.0 + " FPS: " + 0 : l_Line = l_Line+l_InterLine EndIf Color 255,255,255 Flip Until KeyHit (1) End
Wow, that's excellent. You got boing.png from 10-12 ms down to 2-3 ms! I also tried a picture larger than the display, which took 300+ ms before, and now takes only 23 ms!
Me: Looks like this is limited more by the actual drawing rather than the plotting algorithm...
Boy, do I feel stupid...
However, there's one minor problem, which I addressed in my update: if you use a non-zero RGB mask (eg. 255, 0, 255) then the results may be wrong in full-screen mode.
For example, your code works fine with Graphics w, h, 0, 2, but with Graphics w, h Blitz will choose the fastest bit-depth, which is 16 in my case, and the mask colours are then incorrect when you read them back, so the mask is drawn when it shouldn't be. (You can test this by forcing the full-screen bit-depth.)
I'm sure it's possible to calculate the correct values for 16/24/32-bit, rather than using my clumsy pixel read/write routine.
Anyway, many thanks for your contribution, which I'll be trying to understand!
Please could you consider declaring your code as Public Domain so that people can use it without worry or restriction?
Me: Looks like this is limited more by the actual drawing rather than the plotting algorithm...
Boy, do I feel stupid...
However, there's one minor problem, which I addressed in my update: if you use a non-zero RGB mask (eg. 255, 0, 255) then the results may be wrong in full-screen mode.
For example, your code works fine with Graphics w, h, 0, 2, but with Graphics w, h Blitz will choose the fastest bit-depth, which is 16 in my case, and the mask colours are then incorrect when you read them back, so the mask is drawn when it shouldn't be. (You can test this by forcing the full-screen bit-depth.)
I'm sure it's possible to calculate the correct values for 16/24/32-bit, rather than using my clumsy pixel read/write routine.
Anyway, many thanks for your contribution, which I'll be trying to understand!
Please could you consider declaring your code as Public Domain so that people can use it without worry or restriction?
Pleace test the modify function
Thanks!
Thanks!
Function BankImage_SetMask(a_BankImage, r, g, b) Local l_IdBank = 3*4 ;===> If (r<0 ) Then r=0 If (r>255) Then r=255 ;===> If (g<0 ) Then g=0 If (g>255) Then g=255 ;===> If (b<0 ) Then b=0 If (b>255) Then b=255 ;===> Select GraphicsDepth() ;===> Case 16 PokeInt a_BankImage, l_IdBank,(((r Shl 16) + (g Shl 8) + b) Shl 16) Or ~$FFFF ;===> Case 24 PokeInt a_BankImage, l_IdBank,(((r Shl 16) + (g Shl 8) + b) Shl 8) Or ~$FFFFFF ;===> Default; 32Bit PokeInt a_BankImage, l_IdBank, ((r Shl 16) + (g Shl 8) + b) Or ~$00FFFFFF ;===> End Select End Function Function BankImage_SetAlpha(a_BankImage, Alpha%=0 ) ;===> Local l_IdBank = 4*4 ;===> If (Alpha<0 ) Then Alpha=0 If (Alpha>255) Then Alpha=255 ;===> Select GraphicsDepth() ;===> Case 16 PokeInt a_BankImage, l_IdBank, (Alpha Shr 4) Shr 12 ;===> Case 24 PokeInt a_BankImage, l_IdBank,0 ;===> Default ; 32Bit PokeInt a_BankImage, l_IdBank, Alpha Shl 24 ;===> End Select ;===> End Function
PS: the modify and all code is public domain ;)
good work
good work
Hi DareDevil,
Thanks very much! I found a couple of minor problems in the last update:
A slightly more difficult problem is that the mask still doesn't work in 16-bit mode here. After a lot of trial-and-error, it seems to me that you have to use my plot/read pixel method to get the correct RGB values. This is because you can't tell what exact display mode is being used: for example, plotting 255, 0, 255 in 16-bit mode, then reading back, gives 248, 0, 248 for me.
It seems that I am probably being given an RGB565 mode in 16-bit depth, ie. 5 red bits, 6 green bits and 5 blue bits (so 255, 0, 255 becomes 248, 0, 248). I'm not totally sure, but I think this depends on the graphics card/drivers, but you may get a different 16-bit format instead of RGB565 on a different graphics card, and you can't tell how to read the bits since you don't know the RGB format.
Since there's no way to tell what RGB format you have from within Blitz, I think you have to use the plot/read method for now to determine the correct mask values. I think I'll have a look at the Blitz3D SDK source and see if I can get any ideas...
Thanks very much! I found a couple of minor problems in the last update:
Function BankImage_SetMask(a_BankImage, r, g, b) Local l_IdBank = 3*4 ; Should be... Function BankImage_SetMask(a_BankImage, r, g, b) Local l_IdBank = 2*4 ; CORRECT = 2*4
Function BankImage_SetAlpha(a_BankImage, Alpha%=0 ) ;===> Local l_IdBank = 4*4 ; Should be... Function BankImage_SetAlpha(a_BankImage, Alpha%=0 ) ;===> Local l_IdBank = 3*4 ; CORRECT = 3*4
A slightly more difficult problem is that the mask still doesn't work in 16-bit mode here. After a lot of trial-and-error, it seems to me that you have to use my plot/read pixel method to get the correct RGB values. This is because you can't tell what exact display mode is being used: for example, plotting 255, 0, 255 in 16-bit mode, then reading back, gives 248, 0, 248 for me.
It seems that I am probably being given an RGB565 mode in 16-bit depth, ie. 5 red bits, 6 green bits and 5 blue bits (so 255, 0, 255 becomes 248, 0, 248). I'm not totally sure, but I think this depends on the graphics card/drivers, but you may get a different 16-bit format instead of RGB565 on a different graphics card, and you can't tell how to read the bits since you don't know the RGB format.
Since there's no way to tell what RGB format you have from within Blitz, I think you have to use the plot/read method for now to determine the correct mask values. I think I'll have a look at the Blitz3D SDK source and see if I can get any ideas...
I had forgotten the format rgb 555 and 565, of your system plot and read are more effective
;)
;)
I wrote this: ImageToBank, BankToImage functions Many, many moons ago (when I first started using B3D I think).
It's vaguely in the same vein.
It's vaguely in the same vein.
Perturbatio: I know -- I ripped ImageToBank off and credited you -- thanks! (See above.)
On the subject of determining the backbuffer format, I think I'm getting somewhere, as I've just managed to create a PureBasic DLL that gets the DirectDraw DDSURFACEDESC2 information, which includes some useful stuff:
It correctly gets width/height/refresh rate (only in full-screen?), and I think I can get the correct mask information from the pixel format structure, though that's a job for another day...
If anyone has PB 4 and wants to try it (sorry, I don't have FTP at the moment, and it's really not worth a download anyway), this is what I've got so far... not much, but it seems to work!
On the subject of determining the backbuffer format, I think I'm getting somewhere, as I've just managed to create a PureBasic DLL that gets the DirectDraw DDSURFACEDESC2 information, which includes some useful stuff:
dwHeight.l dwWidth.l dwRefreshRate.l ddpfPixelFormat.DDPIXELFORMAT
It correctly gets width/height/refresh rate (only in full-screen?), and I think I can get the correct mask information from the pixel format structure, though that's a job for another day...
If anyone has PB 4 and wants to try it (sorry, I don't have FTP at the moment, and it's really not worth a download anyway), this is what I've got so far... not much, but it seems to work!
; Blitz test code (in same folder as dd7test.dll)... Graphics 640, 480, 0, 1 result = Test (SystemProperty ("DirectDraw7")) Print result
; Blitz dd7test.decls file (plain text) -> goes in Blitz\userlibs folder... .lib "dd7test.dll" Test% (device)
; PureBasic 4 code (compile as 'Shared DLL'): Structure DDCOLORKEY dwColorSpaceLowValue.l dwColorSpaceHighValue.l EndStructure Structure DDPIXELFORMAT dwSize.l dwFlags.l dwFourCC.l dwRGBBitCount.l dwRBitMask.l dwGBitMask.l dwBBitMask.l dwRGBAlphaBitMask.l EndStructure Structure DDSCAPS dwCaps.l EndStructure Structure DDSCAPS2 dwCaps.l dwCaps2.l dwCaps3.l dwCaps4.l EndStructure Structure DDSURFACEDESC2 dwSize.l dwFlags.l dwHeight.l dwWidth.l lPitch.l dwBackBufferCount.l dwRefreshRate.l dwAlphaBitDepth.l dwReserved.l lpSurface.l ddckCKDestOverlay.DDCOLORKEY ddckCKDestBlt.DDCOLORKEY ddckCKSrcOverlay.DDCOLORKEY ddckCKSrcBlt.DDCOLORKEY ddpfPixelFormat.DDPIXELFORMAT ddsCaps.DDSCAPS2 dwTextureStage.l EndStructure ProcedureDLL Test (IDD.IDirectDraw7) test.DDSURFACEDESC2 test\dwSize = SizeOf (DDSURFACEDESC2) result = IDD\GetDisplayMode(@test) MessageRequester ("Test", "Screen size: " + Str (test\dwWidth) + " x " + Str (test\dwHeight) + " @ " + Str (test\dwRefreshRate) + " Hz") ProcedureReturn test\dwWidth EndProcedure DataSection IID_IDirectDraw7: Data.l $15e65ec0 Data.w $3b9c, $11d2 Data.b $b9, $2f, $00, $60, $97, $97, $ea, $5b EndDataSection