Results 1 to 5 of 5

Thread: Blur Image

  1. #1

    Blur Image

    Hi!

    I need to blur a texture using ZenGL. It does not need to be very fast because I need to blur it once and I will use it for several frames (I want to blur everything bellow a Game Dialog).

    Andrey converted this code of a BoxBlur to me, it works very well, but it does have two side-effects!

    - To works well I need to use it twice (or the blur will be very weak).
    - The blurred image seems to be some pixels off, so I get a strange effect, it seems the background was moved.

    Code:
    procedure BoxBlur(var Texture: zglPTexture);
      var
        X, Y: Integer;
        yLine, xLine: PByteArray;
        data : PByteArray;
        realWidth : Integer;
        realHeight : Integer;
    begin
      realWidth := Round( Texture.Width / Texture.U );
      realHeight := Round( Texture.Height / Texture.V );
      tex_GetData(Texture, data);
      for Y := 1 to realHeight - 2 do
      begin
        yLine := @data[ realWidth * ( Y - 1 ) * 4 ];
        xLine := @data[ realWidth * Y * 4 ];
        for X := 1 to realWidth - 2 do
        begin
          xLine^[X * 4    ] := (xLine^[X * 4 - 4] + xLine^[X * 4 + 4] + yLine^[X * 4 - 4] + yLine^[X * 4 + 4] + yLine^[X * 4    ] + xLine^[X * 4 - 4] + xLine^[X * 4 + 4] + xLine^[X * 4]) div 8;
          xLine^[X * 4 + 1] := (xLine^[X * 4 - 3] + xLine^[X * 4 + 5] + yLine^[X * 4 - 3] + yLine^[X * 4 + 5] + yLine^[X * 4 + 1] + xLine^[X * 4 - 3] + xLine^[X * 4 + 5] + xLine^[X * 4 + 1]) div 8;
          xLine^[X * 4 + 2] := (xLine^[X * 4 - 2] + xLine^[X * 4 + 6] + yLine^[X * 4 - 2] + yLine^[X * 4 + 6] + yLine^[X * 4 + 2] + xLine^[X * 4 - 2] + xLine^[X * 4 + 6] + xLine^[X * 4 + 2]) div 8;
        end;
      end;
      tex_SetData(Texture, data, 0, 0, realWidth, Texture.Height);
      zgl_FreeMem( data );
    end;
    Anybody have to suggest some alternative blurring routine? A Gaussian Blur seems to be ideal, but I wasn't able to convert it to ZenGL after some tries.

    Thanks

  2. #2
    hm maybe try imagemagick?

  3. #3
    Only blur algorithm i know that works well, reads 1+4 pixels RGB(A) values around it (up, down, left, right and self), and averages them. To get perfect result, you can't be writing to same data array that you are reading from, i mean after you have blurred top row, you would be using blurred values and nonblurred values mixed. So you need to allocate the texture memory again for writing, free the old data after blur, and then set the real texture use the newly allocated pointer.

    To get even better blur, you can read the corners aswell, and average that 9 pixel data. That's obviously slower, but possibly not as slow as doing a second pass.
    Last edited by User137; 01-03-2013 at 10:56 PM.

  4. #4
    Thanks a lot User137! Your tips were very valuable! =)

    To achieve the best result I did use the 17 pixels around the current pixel.

    Here is the final code :

    Code:
      procedure BoxBlur(var Texture: zglPTexture);
      var
        X, Y: Integer;
        yLine, xLine, yLine2, yLine3: PByteArray;
        data: PByteArray;
        realWidth: Integer;
        realHeight: Integer;
      begin
        realWidth := Round(Texture.Width / Texture.U);
        realHeight := Round(Texture.Height / Texture.V);
        tex_GetData(Texture, data);
    
        for Y := 1 to realHeight - 2 do
        begin
          yLine := @data[realWidth * (Y) * 4]; // Current Line
          yLine2 := @data[realWidth * (Y - 1) * 4]; // Prior Line
          yLine3 := @data[realWidth * (Y + 1) * 4]; // Next Line
    
          xLine := @data[realWidth * Y * 4];
    
          for X := 1 to realWidth - 2 do
          begin
            xLine^[X * 4] := ((xLine^[X * 4] + xLine^[(X - 1) * 4] + xLine^[(X + 1) * 4] + yLine^[(X - 1) * 4] + yLine^[(X + 1) * 4] + yLine2^[(X - 1) * 4] + yLine2^[(X + 1) * 4] + yLine3^[(X - 1) * 4]
                  + yLine3^[(X + 1) * 4]) + (xLine^[(X - 2) * 4] + xLine^[(X + 2) * 4] + yLine^[(X - 2) * 4] + yLine^[(X + 2) * 4] + yLine2^[(X - 2) * 4] + yLine2^[(X + 2) * 4] + yLine3^[(X - 2) * 4]
                  + yLine3^[(X + 2) * 4])) div 17;
    
            xLine^[X * 4 + 1] := ((xLine^[X * 4 + 1] + xLine^[(X - 1) * 4 + 1] + xLine^[(X + 1) * 4 + 1] + yLine^[(X - 1) * 4 + 1] + yLine^[(X + 1) * 4 + 1] + yLine2^[(X + 1) * 4 + 1] + yLine2^[(X - 1)
                  * 4 + 1] + yLine3^[(X + 1) * 4 + 1] + yLine3^[(X - 1) * 4 + 1]) + (xLine^[(X - 2) * 4 + 1] + xLine^[(X + 2) * 4 + 1] + yLine^[(X - 2) * 4 + 1] + yLine^[(X + 2) * 4 + 1] + yLine2^[
                  (X + 2) * 4 + 1] + yLine2^[(X - 2) * 4 + 1] + yLine3^[(X + 2) * 4 + 1] + yLine3^[(X - 2) * 4 + 1])) div 17;
    
            xLine^[X * 4 + 2] := ((xLine^[X * 4 + 2] + xLine^[(X - 1) * 4 + 2] + xLine^[(X + 1) * 4 + 2] + yLine^[(X - 1) * 4 + 2] + yLine^[(X + 1) * 4 + 2] + yLine2^[(X + 1) * 4 + 2] + yLine2^[(X - 1)
                  * 4 + 2] + yLine3^[(X + 1) * 4 + 2] + yLine3^[(X - 1) * 4 + 2]) + (xLine^[(X - 2) * 4 + 2] + xLine^[(X + 2) * 4 + 2] + yLine^[(X - 2) * 4 + 2] + yLine^[(X + 2) * 4 + 2] + yLine2^[
                  (X + 2) * 4 + 2] + yLine2^[(X - 2) * 4 + 2] + yLine3^[(X + 2) * 4 + 2] + yLine3^[(X - 2) * 4 + 2])) div 17;
    
          end;
        end;
    
        tex_SetData(Texture, data, 0, 0, realWidth, Texture.Height);
        FreeMem(data);
      end;

  5. #5
    PGD Staff / News Reporter phibermon's Avatar
    Join Date
    Sep 2009
    Location
    England
    Posts
    524
    ZenGL - the clue is in the name. Why don't you just use mip-map levels + filtering to do the blur in hardware? you can do it in a shader incredibly easily. You're already tied into GL with Zen so not doing it in hardware is folly
    When the moon hits your eye like a big pizza pie - that's an extinction level impact event.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •