Sprite Mirroring
Sprite Mirroring
I am trying to mirror (a lot of) sprites during runtime to safe some hard disk space, but unfortunately using an array and the Plot command is very slow. Is there a fast way to do this?
The current code looks like this:
; get source pixels
StartDrawing(SpriteOutput(srcImg))
For i2=0 To SpriteWidth(srcImg)-1
For i3=0 To SpriteHeight(srcImg)-1
arr(i2,i3)=Point(i2,i3)
Next i3
Next i2
StopDrawing()
; set destination pixels
StartDrawing(SpriteOutput(destImg))
For i2=0 To SpriteWidth(destImg)-1
For i3=0 To SpriteHeight(destImg)-1
If arr(i2,i3)<>0
Plot(SpriteWidth(destImg)-i2,i3,arr(i2,i3))
EndIf
Next i3
Next i2
StopDrawing()
The pixels of a sprite are copied into an array. The array is then copied to the new sprite.
The current code looks like this:
; get source pixels
StartDrawing(SpriteOutput(srcImg))
For i2=0 To SpriteWidth(srcImg)-1
For i3=0 To SpriteHeight(srcImg)-1
arr(i2,i3)=Point(i2,i3)
Next i3
Next i2
StopDrawing()
; set destination pixels
StartDrawing(SpriteOutput(destImg))
For i2=0 To SpriteWidth(destImg)-1
For i3=0 To SpriteHeight(destImg)-1
If arr(i2,i3)<>0
Plot(SpriteWidth(destImg)-i2,i3,arr(i2,i3))
EndIf
Next i3
Next i2
StopDrawing()
The pixels of a sprite are copied into an array. The array is then copied to the new sprite.
i think you can use the plgblt api to mirror stuff, but that would not work on all windows versions, do a search on the forum for plgblt_
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
( The path to enlightenment and the PureBasic Survival Guide right here... )
plgblt and some other blitting functions are great for Windows development (BitBlt was my best friend some years ago), but I am planning to do a game that works on Linux and Windows (at least the base; advanced stuff must be done with DirectX). I wondered, whether it is possible to get the Sprite buffer of an image, to do some memory copying like in C (memcpy). Nevertheless it seems that PureBasic does not allow this?! Do you see an alternative?
- Hroudtwolf
- Addict
- Posts: 803
- Joined: Sat Feb 12, 2005 3:35 am
- Location: Germany(Hessen)
- Contact:
There is a procedure in the german PureBasic-Lounge(Forum).
I think that can help you.
PureBasic-Lounge\Prozeduren\Grafik,Sound&Sprites
I think that can help you.
PureBasic-Lounge\Prozeduren\Grafik,Sound&Sprites
hmm... you may want to figure out where the bitmap is in memory, the directly read and write it... then again, that's window based...
another approach would be to write the image to the disk, then you know exactly what is where, read it back in, swap bytes (8 bits = 1 byte, 24 or 32 bits are 3 or 4 bytes as you are perfectly aware
) and rewrite the bmp file... it's kind of a work around though...
another attempt may be to read from memory, adding the file as part of a datasection, then reading it from the datasection and rewriting it back to the datasection in a different sequence (that actually may work)
another approach would be to write the image to the disk, then you know exactly what is where, read it back in, swap bytes (8 bits = 1 byte, 24 or 32 bits are 3 or 4 bytes as you are perfectly aware

another attempt may be to read from memory, adding the file as part of a datasection, then reading it from the datasection and rewriting it back to the datasection in a different sequence (that actually may work)
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
( The path to enlightenment and the PureBasic Survival Guide right here... )
flipping great!
well, with the huge amount of memory a PC has nowadays, its not likely memory you're looking to save, is it? But hard-disk space, and basically trying to keep the project as small as possible?
You sound like me, if thats the case!
So, I'd pre-mirror all your images, saving them in a new image / sprite.
Your current code would do that just fine - but the code on the german site would probably do it a lot faster, and maybe is usable in real-time?
The choice is yours!
You sound like me, if thats the case!
So, I'd pre-mirror all your images, saving them in a new image / sprite.
Your current code would do that just fine - but the code on the german site would probably do it a lot faster, and maybe is usable in real-time?
The choice is yours!
What about the PureBasic function TransformSprite3D() ?
It seems to be able to swap/warp/transform it in any shape you want.
So basically just "swap" the coordinates/values. so that x1 become x2,
and x4 become x3.
I.E. performing a "flip".
I haven't tested it tough, I just peeked in the PureBasic help.
As the doc say it's ment for realtime. however.
There is nothing preventing you from displaying a "loading" screen with buffer 1,
and then in the 2nd buffer render/flip/grab/whatever you want,
and when done, clear the 2nd buffer and continue with whatever
you originaly intended to render in the 2nd buffer before the buffer flip.
It seems to be able to swap/warp/transform it in any shape you want.
Code: Select all
Syntax
TransformSprite3D(#Sprite3D, x1, y1, [z1], x2, y2, [z2], x3, y3, [z3], x4, y4, [z4])
Description
Transforms the #Sprite3D to the new given coordinates. This is tipically used to perform real time transformations. Warning, as a Sprite3D is 2 vertex (2 triangles), the tranformation could looks very strange... If one of the optional 'z' parameter is specified, all need to be specified.
;
; x1 x2
; ---------
; | /|
; | / |
; | / |
; |/ |
; ---------
; x4 x3
;
and x4 become x3.
I.E. performing a "flip".
I haven't tested it tough, I just peeked in the PureBasic help.
As the doc say it's ment for realtime. however.
There is nothing preventing you from displaying a "loading" screen with buffer 1,
and then in the 2nd buffer render/flip/grab/whatever you want,
and when done, clear the 2nd buffer and continue with whatever
you originaly intended to render in the 2nd buffer before the buffer flip.
Thank you guys. I'll use Hroudtwolf's suggestion (StretchBlt), even though this solution is Windows only. Using Linux compatible code seems to be too much of a mess. TransformSprite3D is a nice idea, but it doesn't work (I tested it). Using TransformSprite3D the way it should work results in a black image.
The new (and quite short) code looks like this:
For those asking themselves what StrechBlt is: You can find documentation on StretchBlt and the Windows API in general in the infamous win32.hlp, which can be found here: http://www.codingcrew.de/programmierung/win32hlp.php, for example.
The new (and quite short) code looks like this:
oldW=SpriteWidth(srcImg)-1
oldH=SpriteHeight(srcImg)-1
CopySprite(srcImg,destImg)
handle.l=StartDrawing(SpriteOutput(destImg))
StretchBlt_(handle, oldW, 0, -oldW, oldH, handle, 0, 0, oldW, oldH, #SRCCOPY)
StopDrawing()
For those asking themselves what StrechBlt is: You can find documentation on StretchBlt and the Windows API in general in the infamous win32.hlp, which can be found here: http://www.codingcrew.de/programmierung/win32hlp.php, for example.
hehe... did it
flip a sprite or image, and works on linux just as well...

Code: Select all
; purebasic survival guide - pb3.92
; graphics 6.pb - 27.02.2005 ejn (blueznl)
; http://www.xs4alnl/~bluez/datatalk/pure1.htm
;
; - mirroring a bitmap in memory
; - reading a bitmap file structure without purebasic commands
; - using images in a datasection
;
w_main_nr = 1
w_main_h = OpenWindow(w_main_nr,10,10,245,200,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"test")
;
; remember, reading from a file or from memory is basically the same thing, now if the image
; is already in memory, i can rotate it in memory, at least that's the theory :-)
;
; let's draw something first
;
image1_h = CatchImage(2,?image1_data)
StartDrawing(WindowOutput())
DrawImage(image1_h,10,10)
StopDrawing()
;
;
; checking the size of the image told me, that it was exactly the same size as the file, as expected :-)
;
; Debug ?image2_data_end - ?image2_data
;
; now the trick is: what's inside that file ie. inside that bitmap? a little search on the internet
; showed the following...
;
; a bitmap is always build up with four parts:
;
; - bitmapfileheader
; - bitmapinfoheader
; - rgbquad
; - byte
;
; let's start with the file header
;
*bitmapfileheader.BITMAPFILEHEADER ; actually, i only care about the offset
*bitmapfileheader = ?image1_data
;
; Debug *bitmapfileheader\bfType ; should always report 19778
; size = *bitmapfileheader\bfSize ; size of whole structure including headers
;
offset = *bitmapfileheader\bfOffBits ; this is where bitmap data is supposed to be
;
*bitmapinfoheader.BITMAPINFOHEADER
*bitmapinfoheader = *bitmapfileheader+SizeOf(BITMAPFILEHEADER)
;
; If *bitmapinfoheader\biCompression = 0 ; check for compressed images
; EndIf ; not implemented
;
image1_width = *bitmapinfoheader\biWidth ; size
image1_height = *bitmapinfoheader\biHeight ;
bits_pixel = *bitmapinfoheader\biBitCount ; bits per pixel
bytes_pixel = bits_pixel/8 ; bytes per pixel
bytes_row = image1_width*bytes_pixel ; bytes per row (unadjusted)
bytes_row = bytes_row+(bytes_row % 4) ; padd to multiples of 4
;
; colour table size depends on the number of bits per pixel
;
; - 1 - colour table has two entries
; - 4 - colour table has 16 entries
; - 8 - colour table has 256 entries
; - 24 - colour table has no entries
;
; Select pixel_bits
; Case 24
; colourtable_size = 0
; Default
; colourtable_size = Pow(2,pixel_bits) * 4
; EndSelect
; offset = 54+colourtable_size
;
; you can calculate the position of the first pixel, or use the value we found before
;
; so the first pixel must be at image2_data+offset
; well we now know where it is so we can change it!
;
; let's give the image a blue stripe on one side, why not?
;
*p = *bitmapfileheader+offset
For y = 0 To image1_width-1
For x = 0 To image1_width / 2
PokeB(*p+y*bytes_row+x*bytes_pixel,255)
Next x
Next y
;
; and show it...
;
image1_h = CatchImage(2,?image1_data)
StartDrawing(WindowOutput())
DrawImage(image1_h,90,10)
StopDrawing()
;
;
; now let's mirror it
;
For y = 0 To image1_height-1
For x = 0 To Int(image1_width/2)
Select bits_pixel
Case 1 ; you add the variants yourself
Case 2
Case 4
Case 8
Case 24 ; 24 bits rgb
;
; where are those darn pixels
;
*p1.BYTE = *p+y*bytes_row+x*3
*p2.BYTE = *p+y*bytes_row+(image1_width-x-1)*3
;
; now swap 'm... blue...
;
b = *p1\b
*p1\b = *p2\b
*p2\b = b
;
; green...
;
g = *p1\b
*p1\b = *p2\b
*p2\b = g
;
; and red...
;
r = *p1\b
*p1\b = *p2\b
*p2\b = r
;
EndSelect
Next x
Next y
;
; and show it one more time
;
image1_h = CatchImage(2,?image1_data)
StartDrawing(WindowOutput())
DrawImage(image1_h,170,10)
StopDrawing()
;
Repeat
event = WaitWindowEvent()
Until event = #PB_Event_CloseWindow Or event = 513
;
; store the image in a datasection
;
DataSection
;
image1_data:
IncludeBinary("graphics\lightcircle.bmp")
image1_data_end:
;
EndDataSection
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
( The path to enlightenment and the PureBasic Survival Guide right here... )
Good job blueznl
, even though I can't use the code.
If I would use BMPs instead of JPGs the game would become about 7x larger than now. Even if I mirror my JPGs I use less space. I also can't use DataSections, because this would require a rebuild as soon as one single image changes. Nevertheless your solution could well be used under certain conditions.
In this case, though, I will probably make a standard Windows- and a double sized Linux version (where mirror images are precalculated).


In this case, though, I will probably make a standard Windows- and a double sized Linux version (where mirror images are precalculated).
jpeg hmm... the problem is, i do not know if the linux version stores bitmaps in memory the same way as the windows version does, you see, you could also find out where the bitmap is in memory, then change it there directory, via the handle of the bitmap
however, i am afraid that that may not work under linux (although it just might)
does anybody know?
however, i am afraid that that may not work under linux (although it just might)
does anybody know?
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
( The path to enlightenment and the PureBasic Survival Guide right here... )