AlbumShaper  1.0a3
Functions | Variables
blur.cpp File Reference
#include <qimage.h>
#include <qstring.h>
#include <math.h>
#include "blur.h"
Include dependency graph for blur.cpp:

Go to the source code of this file.

Functions

void computeCoeffs (float sigma)
void fillBuffer (QImage &image, int channel)
void blurBuffer ()
void blurRow (int row)
void blurColumn (int column)
void blurRegionsInRow (int y)
void blurRegionsInCol (int x)
void resetImageData (QImage &image, int channel, bool blurEdges)
float edgeValue (int x, int y)
void blurImage (QImage &image, float sigma)
void blurImage (QImage &image, float sigma, QPoint offset, QSize fullImageRes, QImage *edges, int *regions, int numRegions, bool targetEdges)
int regionIndex (int x, int y)

Variables

float q
float b0
float b1
float b2
float b3
float B
int width
int height
float * buffer
float * rowBuffer
float * colBuffer
float * regionRowBuffer
float * regionColBuffer
QImage * edgeImage
int * regionMap
int regionCount
QPoint displayOffset
QSize fullRes

Function Documentation

void blurBuffer ( )

Definition at line 204 of file blur.cpp.

References blurColumn(), blurRegionsInCol(), blurRegionsInRow(), blurRow(), edgeImage, height, regionMap, and width.

Referenced by blurImage().

{
  //blur rows, then columns
  int index;
  
  if(regionMap == NULL || edgeImage == NULL )
  {
    for(index=0; index < height; index++)
    { blurRow( index ); }
    
    for(index=0; index< width; index++)
    { blurColumn( index ); }
  }
  else
  {
    for(index=0; index < height; index++)
    { blurRegionsInRow( index ); }
    
    for(index=0; index< width; index++)
    { blurRegionsInCol( index ); }
  }
}
void blurColumn ( int  column)

Definition at line 409 of file blur.cpp.

References B, b0, b1, b2, b3, buffer, colBuffer, height, and width.

Referenced by blurBuffer().

{
  int i;

  //forward
  colBuffer[0] = buffer[ column + 0*width ];
  for(i=1; i<height; i++)
  {
     colBuffer[i] = B*buffer[ column + i*width ] +
     ( b1 * colBuffer[ QMAX(i-1, 0) ] +
       b2 * colBuffer[ QMAX(i-2, 0) ] +
       b3 * colBuffer[ QMAX(i-3, 0) ]) / b0;    
  }
  
  //reverse
  for(i=height-1; i>=0; i--)
  {
     buffer[ column + i*width ] = B*colBuffer[ i ] +
     ( b1 * buffer[ column + QMIN(i+1, height-1)*width ] +
       b2 * buffer[ column + QMIN(i+2, height-1)*width ] +
       b3 * buffer[ column + QMIN(i+3, height-1)*width ]) / b0;        
  }
  
}
void blurImage ( QImage &  image,
float  sigma 
)

Definition at line 94 of file blur.cpp.

References blurImage().

Referenced by GrainEditor::adjustImage(), blurImage(), EdgeDetect::constructEdgeImage(), and sharpenImage().

{
  //supply dummy data for edges, notably NULL for the edge image pointer.
  //other values have no effect
  blurImage( image, sigma, QPoint(0,0), image.size(), NULL, NULL, 0, false );
}
void blurImage ( QImage &  image,
float  sigma,
QPoint  offset,
QSize  fullImageRes,
QImage *  edges,
int *  regions,
int  numRegions,
bool  targetEdges 
)

Definition at line 101 of file blur.cpp.

References blurBuffer(), buffer, colBuffer, computeCoeffs(), displayOffset, edgeImage, fillBuffer(), fullRes, height, regionColBuffer, regionCount, regionMap, regionRowBuffer, resetImageData(), rowBuffer, and width.

{
  edgeImage = edges;
  regionMap = regions;
  regionCount = numRegions;
  displayOffset = offset;
  fullRes = fullImageRes;
  
  //compute blurring coeffecients
  computeCoeffs(sigma);
  
  //store image dimensions
  width = image.width();
  height = image.height();
  
  //Construct float buffer that is the size of the image/
  //In order to conserve memory process image three times, once for
  //each color channel.
  buffer = new float[ width * height ];

  rowBuffer = new float[width];
  colBuffer = new float[height];
  
  regionRowBuffer = new float[width * numRegions];
  regionColBuffer = new float[height * numRegions];
  
  //iterate over each color channel
  int channel;
  for( channel = 0; channel <=2; channel++)
  {
    //copy color data into float buffer
    fillBuffer( image, channel );
    
    //blur buffer data
    blurBuffer();
    
    //reset image data used blurred buffer
    resetImageData(image, channel, targetEdges);
  }
  
  //delete buffer
  delete[] buffer;
  delete[] rowBuffer;
  delete[] colBuffer;
}
void blurRegionsInCol ( int  x)

Definition at line 434 of file blur.cpp.

References B, b0, b1, b2, b3, buffer, colBuffer, height, regionColBuffer, regionCount, regionIndex(), regionMap, and width.

Referenced by blurBuffer().

{
  //---------------------------------
  //populate region col buffer. a col has been allocated for 
  //each region. Pixels between regions
  //take the closest pixel value in that col from that region
//  int yTimesWidth = y*width;
  int regionTimesHeight;
  int region,y,y2;
  
  //for each region
  for(region=0; region<regionCount; region++)
  {
    regionTimesHeight = region*height;
    int lastY = -1;
    for(y=0; y<height; y++)
    {
      //if pixel belongs to this region then update lastY index and copy value over
      //if lastY is more than one pixel away than fill inbetween region
      if( region == regionMap[regionIndex(x, y)] )
      {
        //fill empty region preceeding this region blob
        if( lastY < y-1)
        {
          //no preceeding region, spread left!
          if(lastY == -1)
          {
            for(y2=0; y2<y; y2++) { regionColBuffer[y2 + regionTimesHeight] = buffer[x + y*width]; }
          }
          //else spread from both left and right of empty stretch
          else
          {
            int yMid = lastY + ((y-1) - lastY)/2;
            
            for(y2=lastY+1; y2<=yMid; y2++)
            { regionColBuffer[y2 + regionTimesHeight] = buffer[x + lastY*width]; }
            
            for(y2=yMid+1; y2<y; y2++)
            { regionColBuffer[y2 + regionTimesHeight] = buffer[x + y*width]; }
          }
        }
        
        regionColBuffer[y + regionTimesHeight] = buffer[x + y*width];
        lastY = y;
      } 
    } //y
    
    //if last stretch is empty, fill right
    if( region != regionMap[regionIndex(x, height-1)] )
    {
      for(y2=lastY+1; y2<height; y2++)
      { regionColBuffer[y2 + regionTimesHeight] = buffer[x + lastY*width]; }
    }
    
  } //region
  //---------------------------------
  //blur the region col buffers
  
  //for each region
  for(region=0; region<regionCount; region++)
  {
    regionTimesHeight = region*height;
    
    //forward
    colBuffer[0] = regionColBuffer[ 0 + regionTimesHeight ];
    for(y=1; y<height; y++)
    {
      colBuffer[y] = B*regionColBuffer[ y + regionTimesHeight ] +
      ( b1 * colBuffer[ QMAX(y-1, 0) ] +
        b2 * colBuffer[ QMAX(y-2, 0) ] +
        b3 * colBuffer[ QMAX(y-3, 0) ]) / b0;    
    }
    
    //reverse
    for(y=height-1; y>=0; y--)
    {
      regionColBuffer[ y + regionTimesHeight ] = B*colBuffer[ y ] +
      ( b1 * regionColBuffer[ QMIN(y+1, height-1) + regionTimesHeight ] +
        b2 * regionColBuffer[ QMIN(y+2, height-1) + regionTimesHeight ] +
        b3 * regionColBuffer[ QMIN(y+3, height-1) + regionTimesHeight ]) / b0;    
    }
  }
  //---------------------------------
  //copy data from the region row buffers back to the
  //buffer. for each pixel we choose the correct region
  //row buffer basedon the original regionidentity of hte pixel
  for(y=0; y<height; y++)
  {
    buffer[x + y*width] = regionColBuffer[y + regionMap[regionIndex(x,y)]*height]; 
  }
  //---------------------------------
}
void blurRegionsInRow ( int  y)

Definition at line 311 of file blur.cpp.

References B, b0, b1, b2, b3, buffer, regionCount, regionIndex(), regionMap, regionRowBuffer, rowBuffer, and width.

Referenced by blurBuffer().

{
  //---------------------------------
  //populate region row buffer. a row has been allocated for 
  //each region. Pixels between regions
  //take the closest pixel value in that row from that region
  int yTimesWidth = y*width;
  int regionTimesWidth;
  int region,x,x2;
  
  //for each region
  for(region=0; region<regionCount; region++)
  {
    regionTimesWidth = region*width;
    int lastX = -1;
    for(x=0; x<width; x++)
    {
      //if pixel belongs to this region then update lastX index and copy value over
      //if lastX is mroe than one pixel away than fill inbetween region
      if( region == regionMap[regionIndex(x, y)] )
      {
        //fill empty region preceeding this region blob
        if( lastX < x-1)
        {
          //no preceeding region, spread left!
          if(lastX == -1)
          {
            for(x2=0; x2<x; x2++) { regionRowBuffer[x2 + regionTimesWidth] = buffer[x + yTimesWidth]; }
          }
          //else spread from both left and right of empty stretch
          else
          {
            int xMid = lastX + ((x-1) - lastX)/2;
            
            for(x2=lastX+1; x2<=xMid; x2++)
            { regionRowBuffer[x2 + regionTimesWidth] = buffer[lastX + yTimesWidth]; }

            for(x2=xMid+1; x2<x; x2++)
            { regionRowBuffer[x2 + regionTimesWidth] = buffer[x + yTimesWidth]; }
          }
        }
        
        regionRowBuffer[x + regionTimesWidth] = buffer[x + yTimesWidth];
        lastX = x;
      } 
    } //x
    
    //if last stretch is empty, fill right
    if( region != regionMap[regionIndex(width-1, y)] )
    {
      for(x2=lastX+1; x2<width; x2++)
      { regionRowBuffer[x2 + regionTimesWidth] = buffer[lastX + yTimesWidth]; }
    }
    
  } //region
  //---------------------------------
  //blur the region row buffers

  //for each region
  for(region=0; region<regionCount; region++)
  {
    regionTimesWidth = region*width;
    
    //forward
    rowBuffer[0] = regionRowBuffer[ 0 + regionTimesWidth ];
    for(x=1; x<width; x++)
    {
      rowBuffer[x] = B*regionRowBuffer[ x + regionTimesWidth ] +
      ( b1*rowBuffer[ QMAX(x-1, 0) ] +
        b2 * rowBuffer[ QMAX(x-2, 0) ] +
        b3 * rowBuffer[ QMAX(x-3, 0) ]) / b0;    
    }
    
    //reverse
    for(x=width-1; x>=0; x--)
    {
      regionRowBuffer[ x + regionTimesWidth ] = B*rowBuffer[ x ] +
      ( b1 * regionRowBuffer[ QMIN(x+1, width-1) + regionTimesWidth ] +
        b2 * regionRowBuffer[ QMIN(x+2, width-1) + regionTimesWidth ] +
        b3 * regionRowBuffer[ QMIN(x+3, width-1) + regionTimesWidth ]) / b0;    
    }
  }
  //---------------------------------
  //copy data from the region row buffers back to the
  //buffer. for each pixel we choose the correct region
  //row buffer basedon the original regionidentity of hte pixel
  for(x=0; x<width; x++)
  {
    int ri = regionIndex(x,y);
    int region = regionMap[ri];
    float bufferVal = regionRowBuffer[ x + region*width ];
    buffer[x + yTimesWidth] = bufferVal;
    
//    buffer[x + yTimesWidth] = regionRowBuffer[x + regionMap[regionIndex(x,y)]*width]; 
  }
  //---------------------------------
}
void blurRow ( int  row)

Definition at line 285 of file blur.cpp.

References B, b0, b1, b2, b3, buffer, rowBuffer, and width.

Referenced by blurBuffer().

{
  int i;
  int rtw = row*width;
  
  //forward
  rowBuffer[0] = buffer[ 0 + rtw ];
  for(i=1; i<width; i++)
  {
     rowBuffer[i] = B*buffer[ i + rtw ] +
     ( b1*rowBuffer[ QMAX(i-1, 0) ] +
       b2 * rowBuffer[ QMAX(i-2, 0) ] +
       b3 * rowBuffer[ QMAX(i-3, 0) ]) / b0;    
    
  }
  
  //reverse
  for(i=width-1; i>=0; i--)
  {
     buffer[ i + rtw ] = B*rowBuffer[ i ] +
     ( b1 * buffer[ QMIN(i+1, width-1) + rtw ] +
       b2 * buffer[ QMIN(i+2, width-1) + rtw ] +
       b3 * buffer[ QMIN(i+3, width-1) + rtw ]) / b0;    
  }
}
void computeCoeffs ( float  sigma)

Definition at line 150 of file blur.cpp.

References B, b0, b1, b2, b3, and q.

Referenced by blurImage().

{
  //compute q as a function of sigma
  if( sigma >= 2.5f )
  {
    q = 0.98711f*sigma - 0.96330f;  
  }
  else
  {
    q = 3.97156f - 4.14554f * sqrt( 1.0f - 0.26891f*sigma );
  }

  //compute b0, b1, b2, and b3
  b0 = 1.57825f + (2.44413f*q) + (1.4281f * q*q ) + (0.422205f * q*q*q );
  b1 = (2.44413f * q) + (2.85619f * q*q) + (1.26661 * q*q*q );
  b2 = -((1.4281 * q*q) + (1.26661 * q*q*q));
  b3 = 0.422205 * q*q*q;
  
  //compute B
  B = 1.0f - ((b1 + b2 + b3) / b0); 
}
float edgeValue ( int  x,
int  y 
)

Definition at line 234 of file blur.cpp.

References displayOffset, edgeImage, and fullRes.

Referenced by resetImageData().

{
  //compute floating point x and y coordinates for edge image
  float edgeX = ((edgeImage->width()-1.0f) * (x+displayOffset.x())) / (fullRes.width()-1);
  float edgeY = ((edgeImage->height()-1.0f) * (y+displayOffset.y())) / (fullRes.height()-1);
  
  //compute 4 int values of coordinates
  int x1 = (int)edgeX;
  int y1 = (int)edgeY;
  int x2, y2;
  if( edgeX > x1 )
    x2 = x1+1;
  else
    x2 = x1;
  if( edgeY > y1 )
    y2 = y1+1;
  else
    y2 = y1;
  
  //compute the four indices
  int index1, index2, index3, index4;
  index1 = x1 + y1*edgeImage->width();
  index2 = x2 + y1*edgeImage->width();
  index3 = x1 + y2*edgeImage->width();
  index4 = x2 + y2*edgeImage->width();
  
  //find edge quantity for each corner
  float v1, v2, v3, v4; 
  uchar* scanline = edgeImage->scanLine( y1 );
  QRgb* rgb = ((QRgb*)scanline+x1);
  v1 = ((float) qRed( *rgb )) / 255.0f;
  rgb = ((QRgb*)scanline+x2);
  v2 = ((float) qRed( *rgb )) / 255.0f;

  scanline = edgeImage->scanLine( y2 );
  rgb = ((QRgb*)scanline+x1);
  v3 = ((float) qRed( *rgb )) / 255.0f;
  rgb = ((QRgb*)scanline+x2);
  v4 = ((float) qRed( *rgb )) / 255.0f;
  
  //blur combine left-right
  v1 = (edgeX-x1)*v2 + (1 - edgeX + x1)*v1;
  v3 = (edgeX-x1)*v4 + (1 - edgeX + x1)*v3;
  
  //combine top-bottom
  v1 = (edgeY-y1)*v3 + (1 - edgeY + y1)*v1;
  
  //return result
  return v1;
}
void fillBuffer ( QImage &  image,
int  channel 
)

Definition at line 172 of file blur.cpp.

References buffer.

Referenced by blurImage().

{
  //precompute 1/255
  float multiplier = 1.0f / 255.0f;
  
  //iterate over each selected scanline 
  int x, y;
  QRgb* rgb;
  uchar* scanLine;
  for( y=0; y<image.height(); y++)
  {   
    //iterate over each pixel in scanline
    scanLine = image.scanLine(y);
    for( x=0; x<image.width(); x++)
    {
      //get handle on rgb value in image
      rgb = ((QRgb*)scanLine+x);

      //compute index where float value is stored in buffer
      int index = x + y*image.width();
      
      //convert and store correct channel in buffer
      if( channel == 0 )
        buffer[index] = multiplier * qRed( *rgb );
      else if( channel == 1 )
        buffer[index] = multiplier * qGreen( *rgb );
      else
        buffer[index] = multiplier * qBlue( *rgb );
    } //x
  } //y
}
int regionIndex ( int  x,
int  y 
)

Definition at line 227 of file blur.cpp.

References displayOffset, edgeImage, and fullRes.

Referenced by blurRegionsInCol(), blurRegionsInRow(), and IDedPixel().

{
  int edgeX = ((edgeImage->width()-1) * (x+displayOffset.x())) / (fullRes.width()-1);
  int edgeY = ((edgeImage->height()-1) * (y+displayOffset.y())) / (fullRes.height()-1);
  return edgeY*edgeImage->width() + edgeX;
}
void resetImageData ( QImage &  image,
int  channel,
bool  blurEdges 
)

Definition at line 527 of file blur.cpp.

References buffer, edgeImage, and edgeValue().

Referenced by blurImage().

{
  //iterate over each selected scanline 
  int x, y;
  QRgb *rgb;
  uchar* imageScanline = NULL;
  for( y=0; y<image.height(); y++)
  {   
    imageScanline = image.scanLine(y);
    for( x=0; x<image.width(); x++)
    {
      //get handle on rgb value in image
      rgb = ((QRgb*)imageScanline+x);
      
      //compute index where float value is stored in buffer
      int index = x + y*image.width();

      //convert blured value to 0-255 range
      int blurredColor = QMAX( QMIN( ((int) (255*buffer[index])), 255 ), 0 );
      
      //blur the entire thing!
      float alpha;
      if( edgeImage == NULL)
        alpha = 1.0f;
      else
      {
        alpha = edgeValue( x, y ); 
        if(!blurEdges)
          alpha = 1.0f - alpha;
      }

      //convert and store correct channel in buffer
      if( channel == 0 )
        *rgb = qRgb( (int) (alpha*blurredColor + (1-alpha)*qRed(*rgb)),
                     qGreen(*rgb), qBlue(*rgb) );
      else if( channel == 1 )
        *rgb = qRgb( qRed(*rgb), 
                     (int) (alpha*blurredColor + (1-alpha)*qGreen(*rgb)),
                     qBlue(*rgb) );
      else
        *rgb = qRgb( qRed(*rgb), qGreen(*rgb), 
                     (int) (alpha*blurredColor + (1-alpha)*qBlue(*rgb)) );
    } //x
  } //y
}

Variable Documentation

float B
float b0

Definition at line 78 of file blur.cpp.

Referenced by blurColumn(), blurRegionsInCol(), blurRegionsInRow(), blurRow(), and computeCoeffs().

float b1
float b2
float b3

Definition at line 78 of file blur.cpp.

Referenced by blurColumn(), blurRegionsInCol(), blurRegionsInRow(), blurRow(), and computeCoeffs().

float* buffer
float* colBuffer

Definition at line 82 of file blur.cpp.

Referenced by blurColumn(), blurImage(), and blurRegionsInCol().

QPoint displayOffset

Definition at line 90 of file blur.cpp.

Referenced by blurImage(), edgeValue(), and regionIndex().

QImage* edgeImage

Definition at line 87 of file blur.cpp.

Referenced by blurBuffer(), blurImage(), edgeValue(), regionIndex(), and resetImageData().

QSize fullRes

Definition at line 91 of file blur.cpp.

Referenced by blurImage(), edgeValue(), and regionIndex().

int height
float q

Definition at line 78 of file blur.cpp.

Referenced by computeCoeffs(), and HSVtoRGB().

Definition at line 85 of file blur.cpp.

Referenced by blurImage(), and blurRegionsInCol().

Definition at line 89 of file blur.cpp.

Referenced by blurImage(), blurRegionsInCol(), and blurRegionsInRow().

int* regionMap

Definition at line 88 of file blur.cpp.

Referenced by blurBuffer(), blurImage(), blurRegionsInCol(), and blurRegionsInRow().

Definition at line 84 of file blur.cpp.

Referenced by blurImage(), and blurRegionsInRow().

float* rowBuffer

Definition at line 81 of file blur.cpp.

Referenced by blurImage(), blurRegionsInRow(), and blurRow().

int width