### Author Topic: [C/ Win32 GDI] How to make a bitmap 'wobble'?  (Read 761 times)

0 Members and 1 Guest are viewing this topic.

#### SilentWorld

• ZX 81
• Posts: 5
• Karma: 0
##### [C/ Win32 GDI] How to make a bitmap 'wobble'?
« on: September 29, 2020 »
The wobble effect is one of my all-time favourites. It is simple but always nice and hypnotic to look at. I am using C and plain GDI for my projects and want to learn how to apply this effect to a bitmap. From my basic understanding, each column or row of pixels moves using sine modulation. I've heard that this probably isn't the best way to do it, but I'm admittedly terrible at math. My programming ability is that of a beginner, however I've been hacking around with the GDI and managed to learn a thing or two. Any help is appreciated!

#### Optimus

• Posts: 2453
• Karma: 128
##### Re: [C/ Win32 GDI] How to make a bitmap 'wobble'?
« Reply #1 on: October 02, 2020 »
There are many ways to do wobble. There is wobble only on X and wobble both on X and Y. The later is the yummie one

Sines would do it but used as look up tables (depending on the system your are working, in my opinion in modern GPUs with shaders, just go pure math,. but in software rendering even in modern PCs integer LUTs for sines would still be faster).

It's going to be a regular loop over X,Y bitmap pixels. Pseudocode
for (int y=0; y<height; ++y) {
int offsetY = sin(x * freq) * offsetHeight;
for (int x=0; x<width; ++x) {
int offsetX = sin(y * freq) * offsetWidth;
putpixel(x,y, bitmap[x + offsetX][y + offsetY]);
}
}

Of course don't use putpixel or sin directly,. that's just pseudo code. You can do more complex sines on the offsets, like offset = sin(x * freq1) + sin(x * freq2)

The other way, if you don't want to do per pixel offset is to split the screen into a grid of quad polygons, e.g. every 16*16 pixels, then offset the vertices (or the texture coordinates alternativelly). Interpolate texture between grid points. This way you could use float maths only for few point and not per pixel and still be fast enough, if you don't want to use LUTs. But I think the first per pixel method with some precalc of the sines in LUTs could be much easier, unless you are on a system with a texture rendering engine already.
Challenge Trophies Won:

#### va!n

• Pentium
• Posts: 1422
• Karma: 109
##### Re: [C/ Win32 GDI] How to make a bitmap 'wobble'?
« Reply #2 on: October 10, 2020 »
Thanks for explaining Optimus!
Here is a small test done in purebasic, which is probaly not the same effect as you guys are talking about and the result is a bit wired. (Image is mirrored a special point)
Move mouse hoizontal to change frequence... move mouse vertical to change offsetHeight.

Code: [Select]
`; Small bitmap effect example - va!n in 10/2020 InitSprite()InitKeyboard()InitMouse()OpenScreen(640,480,32,"")LoadSprite(1,"d:\Unbenannt.bmp",0)sprH = SpriteHeight(1)Repeat  ExamineKeyboard()  ExamineMouse()      ClearScreen(0)   ;   For (int y=0; y<height; ++y) {;   int offsetY = Sin(x * freq) * offsetHeight;;   For (int x=0; x<width; ++x) {;     int offsetX = Sin(y * freq) * offsetWidth;;     putpixel(x,y, bitmap[x + offsetX][y + offsetY]);;   }; }      offsetHeight = MouseY()     freq.f =   MouseX() / 10000  ; 0.004;MouseX() / 1000    For y = 0 To sprH    offsetY = Sin(y * freq) * offsetHeight    ClipSprite(1,0,offsetY,SpriteWidth(1),1)    DisplaySprite(1, 0, y)  Next    FlipBuffers()Until KeyboardPushed(#PB_Key_Escape)End`
- hp EliteBook 8540p, 4 GB RAM, Windows 8.1 x64
- Asus P5Q, Intel Q8200, 6 GB DDR2, Radeon 4870, Windows 8.1 x64
http://www.secretly.de
Challenge Trophies Won:

#### SilentWorld

• ZX 81
• Posts: 5
• Karma: 0
##### Re: [C/ Win32 GDI] How to make a bitmap 'wobble'?
« Reply #3 on: October 24, 2020 »
Hi guys. Thanks for your suggestions! I have been working on some variations of the effect using some FreeBasic source and a with a little help. The math is a clearer to me now too   Here is the code loosely modified from the original written by Dr_Davenstein. I might be wrong, but the win32 equivalents of PSET, PUT and GET would be SrcCopy, BitBlt, and SelectObject. Sorry for the late reply, I was getting a 403 error for a long time which prevented me.

Code: [Select]
`#Include "fbgfx.bi"Screenres 340,120,32,,Dim As Integer x, yDim As Ubyte Ptr buf  = imagecreate(239,44)Dim As Ubyte Ptr buf2  = imagecreate(239,44)Bload "blogo.bmp", bufColor &HFFFFFF, &HFF00FFDim As double AngDim As double Ang_xDim As double AmplitudeDim As Integer periodDim As double frequencyDim As double deltaAmplitude = 5.0 period = 60frequency = 1.0delta = 0.01Do    screensync    ScreenLock    cls        Ang+= 6.282 * frequency * delta    Ang_x = Ang        For x = 0 To 238        Ang_x+=(6.282/period)        Get buf, (x,0)-(x,43), buf2                  Put(x+10,(Amplitude*sin(Ang_x))+30), Buf2, pset    Next                                   ScreenUnlock    sleep delta * 1000    Loop Until Multikey(FB.SC_ESCAPE)imageDestroy(buf)imageDestroy(buf2)`

#### va!n

• Pentium
• Posts: 1422
• Karma: 109
##### Re: [C/ Win32 GDI] How to make a bitmap 'wobble'?
« Reply #4 on: October 25, 2020 »
- hp EliteBook 8540p, 4 GB RAM, Windows 8.1 x64
- Asus P5Q, Intel Q8200, 6 GB DDR2, Radeon 4870, Windows 8.1 x64
http://www.secretly.de
Challenge Trophies Won:

#### SilentWorld

• ZX 81
• Posts: 5
• Karma: 0
##### Re: [C/ Win32 GDI] How to make a bitmap 'wobble'?
« Reply #5 on: October 25, 2020 »

Sure! I've attached all the executables for each variation, along with their source code. Again this would not have been possible without help, but  I have learned a few things. Of course, the real challenge will be to make this work in pure GDI. Feel free to suggest improvements to this code

#### va!n

• Pentium
• Posts: 1422
• Karma: 109
##### Re: [C/ Win32 GDI] How to make a bitmap 'wobble'?
« Reply #6 on: October 26, 2020 »
thanks for the archive with all versions and sources.

i think you should try to DIB (Win32 GDI API) as screenbuffer. You could read/write pixels very fast, by just peek/poke values.
Btw, i think you can optimize your effects a lot without the need to manipulate each pixel. For example:

For your horizontal effect, just store the image into a DIB secion and copy the full image row to the required x position of the DIB screenbuffer.
CopyMemory() may be your friend. So you just only copy one full row in once, instead copy pixel by pixel.

For the Verticval effect you could do the same for best performance and when done, just rotate the image 90 degree.

For not effects you could use the same techniuqe. First change hoizontal offeset of each y row. rotate it internaly 90 degree. Your y value is now x and change again the x offset. rotate 90 degree and you are done.

in short:  i think you can improve performance a lot, by copying full parts (rows) of your image.

- hp EliteBook 8540p, 4 GB RAM, Windows 8.1 x64
- Asus P5Q, Intel Q8200, 6 GB DDR2, Radeon 4870, Windows 8.1 x64
http://www.secretly.de
Challenge Trophies Won:

#### SilentWorld

• ZX 81
• Posts: 5
• Karma: 0
##### Re: [C/ Win32 GDI] How to make a bitmap 'wobble'?
« Reply #7 on: November 01, 2020 »
No problem

I haven't used DIB at all before so I will need to reference either Petzold or Feng Yuan's book. Correct me if I'm wrong, but the main advantage of using them is that one has direct access to pixels in a DC? In the Freebasic code, this appears to be taken care of. My initial idea, was to load a normal bitmap and make it into a "tilesheet" in memory and iterate over each image in it. This would no doubt be too slow, even if the effect is only going to be used once.