Click here to Skip to main content
15,881,248 members
Articles / Programming Languages / C++

Visiual Ripple Effect Like Mediaplayer's

Rate me:
Please Sign up or sign in to vote.
4.50/5 (18 votes)
24 Dec 2009CPOL2 min read 283.1K   968   30   11
Shows you how to make a player's ripple effect with bitmap not dx
p2.jpg

Introduction

One day when I was listening to a song, I saw the special effect on Media Player. So I began to think how it was created. As a matter of fact, I really don't know how to create it. I started finding a method to simulate it. This time I used the dib to realize it, but I think “DX” will be better. The article may use a lot of DIB manipulation. I will not give any more introduction, please look up in other articles.

Background

I love computer programming. I waste several hours doing it. May be it is useless but I like it because it's created by me. Next time, I'll create the effect by DX. Everyone, please give me more help and suggestions. You can use and modify the code in any way as per your wish.

Using the Code & Sample program

Add the two files to your test application, “RippeEffect.h” and “RippeEffect.cpp”. (Sorry because when I typed the word ripple, I lost a letter “l”.) Now include the header into your code.

C++
#include "RippeEffect.h"
//Created an object like that: 
RippeEffect Rip;

//Now let’s call its public member Init(); 
Rip.init();

…

//At last we call his update member function frequently and pass it 
//a DeviceContent where to show the image. 
//I call this function 30ms once in my test demo. 

Rip.UpdateData(hdc); 

Principle of the Effect

Let’s take a look at the class’s definition:

C++
class RippeEffect { 
public: 
void SetEffectSize(int iWidth,int iHeight);   //After Initiation,
					//this method sets the size of effect 
void UpdateData(HDC hdc); //To render the image, the method will call frequently 
BOOL Init(); 	//Initiation of all kinds of structures 
BYTE *pBits2; 	//The array to store the bits of bitmap. It’s buffer, 
		//the pBits pointer really is. 
RippeEffect(); 
virtual ~RippeEffect(); 
private: 
int kind; //Indicate the type of the shape to add to what should to be rendered 
inline void mysetPixel2(BYTE *pBits,int x,int y,COLORREF rgb); //Use to set the 
				//point’s color. X and Y are the values of axis. 
COLORREF mygetPixel(BYTE *pBits,int x,int y); 	//Get the point’s color 
inline POINT ComputerNewPoint(POINT pt,int angle); 	//Calculate the new location 
						//of a pixel after being rotated. 
inline void FadePixel(BYTE *pBits,int x,int y); 	//Decrease the color of the 
						//pixel so that it can disappear. 
UINT getBitCount();	//Get the bit count of the bitmap. 
UINT getBmHeight();	//Get height of the bitmap. 
UINT getBmWidth();		//Get width of the bitmap. 
inline void mysetPixel(BYTE *pBits,int x,int y,COLORREF rgb); //Different with 
		//mysetPixe2 this method will not add the value of the pixel before 
UINT i,x,y,r,k; 	//For loop 
POINT pt; 	//A point which will be used in the rotation... 
UINT m_nBmSize; 	//The size of bitmap. 
BITMAPINFOHEADER bih; 
BITMAPINFO bi; 
BYTE *pBits; 
UINT m_nBmHeight; 	//Private var of this class, the height of bitmap 
UINT m_nBmWidth; 	//The width of bitmap 
};

After seeing these functions, let's start to have a look at the main line of the code. First, we must fill the struct of BITMAPINFOHEADER and BITMAPINFO. For this reason, we will use SetDIBitsToDevice() function to display the effect as last. Look at the snippet below, it's the member function of the RippleEffect class. It is used to initialize all kinds of data structures, alloc memory.

C++
BOOL RippeEffect::Init()
{
srand(::GetTickCount()); //random seeds
//Set the BITMAPINFOHEADER struct 
bih.biSize =sizeof(BITMAPINFOHEADER); 
bih.biBitCount =24 ;
bih.biCompression =BI_RGB;
bih.biHeight=m_nBmHeight;
bih.biWidth=m_nBmWidth;
bih.biPlanes =1;
bih.biSizeImage=m_nBmHeight*m_nBmWidth*bih.biBitCount /8;
bih.biXPelsPerMeter=0;
bih.biYPelsPerMeter =0;
bih.biClrUsed=256;
bih.biClrImportant =0;

bi.bmiHeader =bih; //Set BITMAPINFO struct
m_nBmSize=m_nBmWidth*m_nBmHeight*bih.biBitCount /8;
/*After that, calculate the space of the bitmap should be to store in.
In other words, it means to store the bits of bitmap.
Use malloc() function to allocate the space for bitmap.*/

pBits=(BYTE*)malloc(m_nBmSize); //Alloc memory to store bit of bitmap
if(!pBits) return FALSE;

pBits2=(BYTE*)malloc(m_nBmSize);//Alloc memory for a buffer.
if(!pBits2) return FALSE;

//We set all to zero at first.
for(i=0;i<m_nBmSize;i++)
{
pBits[i]=0x0;
}
//Draw a shape on the bitmap.
/*
How to understand code below? Here, it only call a sin() 
function to get a value of y axis. It's to decide what color will be filled in.
0~ PI  <=> 0->1->0
PI*x/255,whereas  0<x<255,so the value also range between in 0 and 1.
sin(..)*255,so the value will range between 0~255.
*/
for(y=0;y<getBmHeight();y++)
for(x=0;x<getBmWidth();x++)
{
mysetPixel(pBits,x,y,RGB((255-y)*sin(PI*x/255),0,0));
}
return TRUE;
}

When finished with the initialization, you get to show the image:

C++
//Display the bitmap.
::SetDIBitsToDevice (hdc,0,0,getBmWidth(),getBmHeight(),0,0,0,getBmHeight(),
 pBits,&bi,0);

Okay, now the image was shown. We must fade it. How do we do it? Look at the snippet below:

C++
//Fade each pixels in this for loop
for(y=1;y<getBmHeight();y++)
for(x=1;x<getBmWidth();x++)
{
   FadePixel(pBits,x,y);
}

FadePixel() method will reduce the value of point's RGB. Be sure that the min RGB value of pixel is 0. R G B are also zero.

Add a new shape to bitmap, I use the easy way to do that. You can understand it:

C++
//To paint the random sin() figure
for(x=0;x<getBmWidth();x++)
{
   mysetPixel(pBits,x,rand()%(getBmHeight()/2)*sin((k)*PI*x/255)+(getBmHeight()/2),
	RGB(255,rand()%255,0));
} 

How to rotate the bitmap? It's always a big problem. I have not found a better way. So I use the formula:

C++
newx = x.cos(angle) + y.sin(angle)
newy = y.cos(angle) - x.sin(angle)

With this formula, I calculate the new point. Copy pBits to pBits2 first, and calculate the new position of pixel in pBits2 assign it to pBits.

We have finished the work, so we could deal with the pBits (a pointer to a bitmap’s bits). We draw some shapes on it and call the FadePixel() function to swap it. Want to know more? Please download the demo and resource to check it out.

History

  • 24th December, 2009: Initial post
  • 25th December, 2009: Article updated

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Engineer
China China
Secret..

Comments and Discussions

 
GeneralSize Pin
Robairbutler12-Jan-10 18:01
Robairbutler12-Jan-10 18:01 
GeneralRe: Size Pin
Aric Wang13-Jan-10 4:05
Aric Wang13-Jan-10 4:05 
GeneralNice... Pin
Nishad S28-Dec-09 14:04
Nishad S28-Dec-09 14:04 
GeneralSmall non-programming remark Pin
Panic2k325-Dec-09 10:58
Panic2k325-Dec-09 10:58 
GeneralRe: Small non-programming remark Pin
Aric Wang25-Dec-09 15:04
Aric Wang25-Dec-09 15:04 
GeneralEnjoy it! Pin
JunWang16324-Dec-09 23:38
JunWang16324-Dec-09 23:38 
Question你是华人吗? Pin
chenyu220286324-Dec-09 22:28
chenyu220286324-Dec-09 22:28 
AnswerRe: 你是华人吗? Pin
Aric Wang24-Dec-09 23:24
Aric Wang24-Dec-09 23:24 
GeneralNeed to improve Pin
Md. Marufuzzaman24-Dec-09 20:29
professionalMd. Marufuzzaman24-Dec-09 20:29 
GeneralRe: Need to improve Pin
Aric Wang25-Dec-09 0:40
Aric Wang25-Dec-09 0:40 
GeneralRe: Need to improve Pin
Md. Marufuzzaman25-Dec-09 2:33
professionalMd. Marufuzzaman25-Dec-09 2:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.