# Blur

## Recommended Posts

ff8    134
hello everyone i want to make simple blur ,how can i do it ? i googled for this but i didn't find any good one :P bye

##### Share on other sites
Guest Anonymous Poster
Well, if I were to explain all your choices here I would finish writing yet another book on the subject.

Blur operations are a kind of image filtering operation.

The usual (but not unique) way of doing these filtering operations is as a weighed average.

For each pixel at position (x,y) in your destination image, you take the pixels at and around that position in your source image, multiply the numbers that specify their colour by a factor (not necesarily the same for all these pixels), and add all these values to produce the output pixel.

Of course, the trick is in knowing how much pixels around the destination to take, and what the factors should be.

For example, To make it simple, you could take the pixels at (x-1,y), (x+1, y), (x,y), (x,y-1), (x,y+1) and multiply all of them by (1/5). This way, you are producing an image that's the average of all those pixels, and that will create a blur effect. Not necesarily the kind of blur you may want and certainly not the "best".

How to choose these factors (how many pixels around, and which factors to use) will create a whole lot of possibilities.

Probably, searching for "gaussian blur" will give you a more complex, higher quality blur to think about.

##### Share on other sites
ff8    134
i am sorry but i still don't understand it :( i search for it but i can't get it :'(
can anyone give me simple code for this effect ?
bye

##### Share on other sites
Look at a NeHe samples, there is a good one about blending (it's about transparecy! ^^)...

##### Share on other sites
ff8    134
I want pure blur not motion blur :P.
I think NeHe's tutorial was about motion blur .
bye

##### Share on other sites
Gorax    202
An easy way to do it: render the scene, copy it to a texture, clear the colour buffer, then render the texture using trilinear filtering.

A harder and *much* slower way: render the scene, copy it to a texture, copy the texture data to a buffer, create a buffer with an equal size, iterate over the entire image adding up the values for the new pixels using some number of pixels around the current one, as well as the current one, and dividing the total by the number of pixels in the sum, then use glDrawPixels to draw the blurred result.

The first way is easy, and a lot faster, but the second lets you choose exactly how blurred the final result is, but you shouldn't use it if you need your app running in realtime. ;)

##### Share on other sites
JavaCoolDude    670
There are several ways to perform blur as some of the gentlemen above have pointed out. Before I provide any source code, tell me something; what is your target graphic hardware?

##### Share on other sites
ff8    134
Thank you all for your replies,
Quote:
 There are several ways to perform blur as some of the gentlemen above have pointed out. Before I provide any source code, tell me something; what is your target graphic hardware?

My grapic card is ATI X600 XT.
I hope to see your code :D.

Quote:
 A harder and *much* slower way: render the scene, copy it to a texture, copy the texture data to a buffer, create a buffer with an equal size, iterate over the entire image adding up the values for the new pixels using some number of pixels around the current one, as well as the current one, and dividing the total by the number of pixels in the sum, then use glDrawPixels to draw the blurred result.

Can you explain it more ?if you don't mind .

##### Share on other sites
JavaCoolDude    670
Are you familiar with ARB programs or GLSL shaders?

ff8    134
Nah not yet :P.
bye

##### Share on other sites
I recently wrote a blur method for my image class. I started off with a google search for gaussian blur techniques and found plenty of hits from which to develop my routine. There is no shortage of pages out there for this topic.

My routine is *not* pretty, but it works for my app. It uses fixed filter settings and a macro that clamps to my fixed texture size of 128x128. Again, not pretty and certainly not flexible. I have posted a quick executable up also for you to see this routine in action and the effect you can get (B for blur/W wireframe/PgUp/Dn to move). I *highly* recommend you write something better and use this only as a guide ;-)

hth
F451

// macro to keep gaussian blur array elements in fixed image range (128x128)#define ac(c) ((c<0)?(c+1):((c>127)?(c-1):c))// filter for gaussian blur functionfloat filter[3][3]={{0.1f,0.3f,0.1f},                    {0.3f,4.0f,0.3f},                    {0.1f,0.3f,0.1f}};// struct for storing RGB values of a pixel when blurringstruct RGB {	float redRGB;	float greenRGB;	float blueRGB;};// array for storing current pixel and surrounding pixel RGB valuesRGB currRGB[3][3];// Gaussian Blur of one pixelvoid CIMAGE::GaussianBlurPixel(int x, int z){ // accumulators for RGB values float newR, newG, newB; // store current RGB values for 8 surrounding pixels plus the pixel we are working on for (int ii=-1; ii<2; ii++) {  for (int jj=-1; jj<2; jj++) {    GetColor2(ac(x+ii),ac(z+jj),currRGB[ii+1][jj+1].redRGB,currRGB[ii+1][jj+1].greenRGB,currRGB[ii+1][jj+1].blueRGB);  } } // work neighbour pixels blending as we go for (int ii=-1; ii<2; ii++) {  for (int jj=-1; jj<2; jj++) {    // adjust pixels using stored values and the formula : orig+((current-orig)*filter)    newR=(float)currRGB[ii+1][jj+1].redRGB+((currRGB[1][1].redRGB-currRGB[ii+1][jj+1].redRGB)*filter[ii+1][jj+1]);    newG=(float)currRGB[ii+1][jj+1].greenRGB+((currRGB[1][1].greenRGB-currRGB[ii+1][jj+1].greenRGB)*filter[ii+1][jj+1]);    newB=(float)currRGB[ii+1][jj+1].blueRGB+((currRGB[1][1].blueRGB-currRGB[ii+1][jj+1].blueRGB)*filter[ii+1][jj+1]);    // assign new color    SetColor(ac(z+jj),ac(x+ii),(unsigned char)newR,(unsigned char)newG,(unsigned char)newB);  } }}// Gaussian blur of a texture or image//   fixed 1 pixel blur ratio and filter settingsvoid CIMAGE::GaussianBlur(){ // blur entire image if loaded if (m_bIsLoaded) {  // traverse image blurring each pixel based on neighbours  for (unsigned int x=0; x<m_uiWidth; x++) {    for (unsigned int z=0; z<m_uiHeight; z++) {      GaussianBlurPixel(x,z);    }  }  // remake the texture if not new  if (m_ID > 0) {    glBindTexture(GL_TEXTURE_2D,m_ID);    glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,m_uiWidth,m_uiHeight,0,GL_RGB,GL_UNSIGNED_BYTE,m_imgData);  } }}

##### Share on other sites
ff8    134
I am so happy for the code :D ,just i have one question .

Can you give me the code for GetColor2(*) and SetColor(*)?
Thank you again :)

JavaCoolDude if you don't mind can you show me your GLSL code ?

bye

##### Share on other sites
If you have covered image loading on your OpenGL/C++ adventure then you will know that you load the image from a file and store the data in memory in an array. Those routines simply read the sequential RGB values for a pixel from that array, and likewise set the RGB values for a pixel. I pass the row and column of the array cell I want to access, but in the routine (because I too took them from a book I am working from) calculates the position of the cell as if it was accessing it as a one dimentional array. Looks confusing, but run a few simple 3x3 examples on paper and you will get it. Factor in that the cell you access is the red, then the cell+1 is the green, cell+2 is the blue, and potentially cell+3 for the alpha. Depends on the image/textures your working with.

inline void GetColor2(unsigned int z, unsigned int x, float &ucpRed, float &ucpGreen, float &ucpBlue){  unsigned int BPP= imageBPP/8;  if ((z<m_uiWidth)&&(x<m_uiHeight)) {    ucpRed  = imgData[(( z*m_imageHeight)+x)*BPP];    ucpGreen= imgData[(((z*m_imageHeight)+x)*BPP)+1];    ucpBlue = imgData[(((z*m_imageHeight)+x)*BPP)+2];  }}inline void SetColor( unsigned int x, unsigned  int y, unsigned char ucRed, unsigned char ucGreen, unsigned char ucBlue ){  unsigned int BPP= imageBPP/8;  if( ( x<m_uiWidth ) && ( y<m_uiHeight ) ) {    imgData[( ( y*imageHeight )+x )*BPP]  = ucRed;    imgData[( ( y*imageHeight )+x )*BPP+1]= ucGreen;    imgData[( ( y*imageHeight )+x )*BPP+2]= ucBlue;  }}

hth
F451

##### Share on other sites
Gorax    202
Quote:
 Original post by ff8Can you explain it more ?if you don't mind .

Just like Fahrenheit451's method, although you could always take it one step further and do the calculations for a circle, rather than a square (requires even more computation, but would look a little better as you start to move beyond the 3x3 square, not that you'd really notice it, since it gets very blurry very fast). ;)

##### Share on other sites
JavaCoolDude    670
Nowadays I do write GLSL code just for debugging and making sure that things are properly working. I find it disturbing how many incompatibilities there are out there between sets of drivers running on the same hardware.
Anyways, here's the code:

<Shaders fragmentProcessor = "FRAGMENT_PROGRAM">  <FRAGMENT_SHADER>    <Uniform name = "texOffset"     size = "4" type = "float"/>    <Uniform name = "GlowTexture"   size = "1" type = "int"   x = "0"  />    <RawData>      uniform sampler2D GlowTexture;      uniform vec4      texOffset;      void main(void)      {        vec4  blurFilter[9],              finalColor = vec4(0.0,0.0,0.0,0.0);        float xOffset    = texOffset.x*texOffset.z,              yOffset    = texOffset.y*texOffset.w;        blurFilter[0]  = vec4( 4.0*xOffset, 4.0*yOffset, 0.0, 0.0217);        blurFilter[1]  = vec4( 3.0*xOffset, 3.0*yOffset, 0.0, 0.0434);        blurFilter[2]  = vec4( 2.0*xOffset, 2.0*yOffset, 0.0, 0.0869);        blurFilter[3]  = vec4( 1.0*xOffset, 1.0*yOffset, 0.0, 0.1739);        blurFilter[4]  = vec4(         0.0,         0.0, 0.0, 0.3478);        blurFilter[5]  = vec4(-1.0*xOffset,-1.0*yOffset, 0.0, 0.1739);        blurFilter[6]  = vec4(-2.0*xOffset,-2.0*yOffset, 0.0, 0.0869);        blurFilter[7]  = vec4(-3.0*xOffset,-3.0*yOffset, 0.0, 0.0434);        blurFilter[8]  = vec4(-4.0*xOffset,-4.0*yOffset, 0.0, 0.0217);        for (int i = 0;i< 9;i++)          finalColor += texture2D(GlowTexture, gl_TexCoord[0].xy + blurFilter[i].xy) * blurFilter[i].w;        gl_FragColor = finalColor*1.15;      }    </RawData>  </FRAGMENT_SHADER>  <!-- Assembly is l33t :P -->  <FRAGMENT_PROGRAM>    <Attributes local = "false" name  = "texOffset" />    <RawData>!!ARBfp1.0     PARAM textureOffset   = program.env[0];     PARAM offsetCoeffs[9] = {{ 4.0, 4.0, 0.0, 0.0217},                              { 3.0, 3.0, 0.0, 0.0434},                              { 2.0, 2.0, 0.0, 0.0869},                              { 1.0, 1.0, 0.0, 0.1739},                              { 0.0, 0.0, 0.0, 0.3478},                              {-1.0,-1.0, 0.0, 0.1739},                              {-2.0,-2.0, 0.0, 0.0869},                              {-3.0,-3.0, 0.0, 0.0434},                              {-4.0,-4.0, 0.0, 0.0217}};     TEMP  texCoords, colorSample, cumulativeColor;     TEMP  scale, sampler;     MOV   cumulativeColor, 0.0;     MUL   scale.x , textureOffset.x, textureOffset.z;     MUL   scale.y , textureOffset.y, textureOffset.w;     MAD   sampler, scale, offsetCoeffs[0], fragment.texcoord[0];     TEX   colorSample, sampler, texture[0], 2D;     MAD   cumulativeColor, colorSample, offsetCoeffs[0].w, cumulativeColor;     MAD   sampler, scale, offsetCoeffs[1], fragment.texcoord[0];     TEX   colorSample, sampler, texture[0], 2D;     MAD   cumulativeColor, colorSample, offsetCoeffs[1].w, cumulativeColor;     MAD   sampler, scale, offsetCoeffs[2], fragment.texcoord[0];     TEX   colorSample, sampler, texture[0], 2D;     MAD   cumulativeColor, colorSample, offsetCoeffs[2].w, cumulativeColor;     MAD   sampler, scale, offsetCoeffs[3], fragment.texcoord[0];     TEX   colorSample, sampler, texture[0], 2D;     MAD   cumulativeColor, colorSample, offsetCoeffs[3].w, cumulativeColor;     MAD   sampler, scale, offsetCoeffs[4], fragment.texcoord[0];     TEX   colorSample, sampler, texture[0], 2D;     MAD   cumulativeColor, colorSample, offsetCoeffs[4].w, cumulativeColor;     MAD   sampler, scale, offsetCoeffs[5], fragment.texcoord[0];     TEX   colorSample, sampler, texture[0], 2D;     MAD   cumulativeColor, colorSample, offsetCoeffs[5].w, cumulativeColor;     MAD   sampler, scale, offsetCoeffs[6], fragment.texcoord[0];     TEX   colorSample, sampler, texture[0], 2D;     MAD   cumulativeColor, colorSample, offsetCoeffs[6].w, cumulativeColor;     MAD   sampler, scale, offsetCoeffs[7], fragment.texcoord[0];     TEX   colorSample, sampler, texture[0], 2D;     MAD   cumulativeColor, colorSample, offsetCoeffs[7].w, cumulativeColor;     MAD   sampler, scale, offsetCoeffs[8], fragment.texcoord[0];     TEX   colorSample, sampler, texture[0], 2D;     MAD   cumulativeColor, colorSample, offsetCoeffs[8].w, cumulativeColor;     MUL   result.color, cumulativeColor, 1.15;     END      </RawData>   </FRAGMENT_PROGRAM></Shaders>

The x and y components of texOffset are 1.0f/blurTextureWidth and 1.0f/blurTextureHeight.
The z and w are equal to 1 and 0 or 0 and 1 depending on whetheir we want to blur the target in the x or y direction.
You need to refresh those values, z and w, everytime you call your shaders to obtain proper blur.
This is how I do it:

  blurShader.updateElementsf("texOffset", 4, Tuple4f(1.0f/blurScreenWidth,                                                     1.0f/blurScreenHeight,                                                     !vertical, vertical));

Take care

##### Share on other sites
ff8    134
Thank you JavaCoolDude and all , for your helps :D
bye

##### Share on other sites
CJM    454
My method would probably encompass:

render the scene to a pbuffer or something, with a smaller size than what you're wanting [you can also get antialiasing by making it larger] and then draw that pbuffer to the screen by a full 2D quad.

That should work on everything down to the bottom of the GeForce series...

CJM

##### Share on other sites
ff8    134
I used to use this way before but you can't have the full control of your blur.
Thank you again :).
bye