Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Class Members | File Members

redEye_internal.h File Reference

#include <qimage.h>
#include <qvaluestack.h>
#include <qpoint.h>

Include dependency graph for redEye_internal.h:

Include dependency graph

This graph shows which files directly or indirectly include this file:

Included by dependency graph

Go to the source code of this file.

Functions

void findRegionOfInterest (QPoint topLeftExtreme, QPoint bottomRightExtreme)
void findBlobs ()
void pushPixel (int x, int y, int id)
void sortBlobsByDecreasingSize ()
void findBestTwoBlobs ()
void desaturateBlobs ()
void desaturateEntireImage (QPoint topLeftExtreme, QPoint bottomRightExtreme)
bool IDedPixel (int x, int y)
double desaturateAlpha (int x, int y)

Variables

StatusWidgetstatus
int updateIncrement
int newProgress
QImage rawImage
QImage * editedImage
QPoint topLeft
QPoint bottomRight
int regionWidth
int regionHeight
int blobPixelCount
QPoint blobTopLeft
QPoint blobBottomRight
int * regionOfInterest
QValueStack< QPoint > spreadablePixels
QValueStack< int > blobIDs
QValueStack< int > blobSizes
QValueStack< double > blobAspectRatios
int blobCount
int * ids
int * sizes
double * ratios
int id1
int id2


Function Documentation

double desaturateAlpha int  x,
int  y
 

Definition at line 376 of file redEye.cpp.

References IDedPixel().

Referenced by desaturateBlobs().

00377 {
00378   int n = 0;
00379   if( IDedPixel(x  ,y  ) ) n++;
00380   
00381   if(n == 1)
00382     return 1.0;
00383   
00384   if( IDedPixel(x-1,y-1) ) n++;
00385   if( IDedPixel(x  ,y-1) ) n++;
00386   if( IDedPixel(x+1,y-1) ) n++;
00387   if( IDedPixel(x-1,y  ) ) n++;
00388   if( IDedPixel(x+1,y  ) ) n++;
00389   if( IDedPixel(x-1,y+1) ) n++;
00390   if( IDedPixel(x  ,y+1) ) n++;
00391   if( IDedPixel(x+1,y+1) ) n++;
00392   
00393   if( IDedPixel(x-2,y-2) ) n++;
00394   if( IDedPixel(x-1,y-2) ) n++;
00395   if( IDedPixel(x  ,y-2) ) n++;
00396   if( IDedPixel(x+1,y-2) ) n++;
00397   if( IDedPixel(x+2,y-2) ) n++;
00398   
00399   if( IDedPixel(x-2,y-1) ) n++;
00400   if( IDedPixel(x+2,y-1) ) n++;
00401   if( IDedPixel(x-2,y  ) ) n++;
00402   if( IDedPixel(x+2,y  ) ) n++;
00403   if( IDedPixel(x-2,y+1) ) n++;
00404   if( IDedPixel(x+2,y+1) ) n++;
00405   
00406   if( IDedPixel(x-2,y+2) ) n++;
00407   if( IDedPixel(x-1,y+2) ) n++;
00408   if( IDedPixel(x  ,y+2) ) n++;
00409   if( IDedPixel(x+1,y+2) ) n++;
00410   if( IDedPixel(x+2,y+2) ) n++;
00411   
00412   
00413   return ((double)n) / 25;
00414 }

void desaturateBlobs  ) 
 

Definition at line 416 of file redEye.cpp.

References bottomRight, desaturateAlpha(), editedImage, and topLeft.

Referenced by removeRedeyeRegions().

00417 {
00418   //desaturate bad pixels
00419   int x, y;
00420   double r;
00421   QRgb* rgb;
00422   uchar* scanLine;
00423   for( y = QMAX( topLeft.y()-1, 0); 
00424        y<= QMIN( bottomRight.y()+1, editedImage->height()-1 ); 
00425        y++)
00426   {
00427     scanLine = editedImage->scanLine(y);
00428     for( x =  QMAX( topLeft.x()-1, 0); 
00429          x <= QMIN( bottomRight.x()+1, editedImage->width()-1 ); 
00430          x++)
00431     {      
00432       double alpha = desaturateAlpha( x, y );
00433       if( alpha > 0)
00434       {
00435         rgb = ((QRgb*)scanLine+x);
00436         
00437         r = alpha*(0.05*qRed(*rgb) + 0.6*qGreen(*rgb) + 0.3*qBlue(*rgb)) +
00438           (1-alpha)*qRed(*rgb);
00439         *rgb = qRgb( (int)r,
00440                      qGreen(*rgb),
00441                      qBlue(*rgb) );
00442       } //alpha > 0
00443     } //x
00444   } //y  
00445 }

void desaturateEntireImage QPoint  topLeftExtreme,
QPoint  bottomRightExtreme
 

Definition at line 447 of file redEye.cpp.

References editedImage.

Referenced by removeRedeyeRegions().

00448 {
00449   //desaturate bad pixels
00450   int x, y;
00451   QRgb* rgb;
00452   uchar* scanLine;
00453   for( y=topLeftExtreme.y(); y<=bottomRightExtreme.y(); y++)
00454   {
00455     scanLine = editedImage->scanLine(y);
00456     for( x=topLeftExtreme.x(); x<=bottomRightExtreme.x(); x++)
00457     {
00458       rgb = ((QRgb*)scanLine+x);
00459       if( qRed(*rgb) > 2*qGreen(*rgb) )
00460       {
00461         *rgb = qRgb( (int) (0.05*qRed(*rgb) + 0.6*qGreen(*rgb) + 0.3*qBlue(*rgb)),
00462                      qGreen(*rgb),
00463                      qBlue(*rgb) );
00464       } // > thresh
00465     } //x
00466   } //y
00467 }

void findBestTwoBlobs  ) 
 

Definition at line 310 of file redEye.cpp.

References blobCount, id1, id2, ids, ratios, and sizes.

Referenced by removeRedeyeRegions().

00311 {
00312   id1 = -1;
00313   id2 = -1;
00314   int i;
00315   
00316   //special case: 2 blobs found, both larger than 1 pixel
00317   if(blobCount == 2 &&
00318      sizes[0] > 1 &&
00319      sizes[1] > 1)
00320   {
00321     id1 = ids[0];
00322     id2 = ids[1];
00323   }
00324   else
00325   {
00326     for(i=0; i<blobCount-2; i++)
00327     {
00328       //once we hit blobs that are only one pixel large stop because they are probably just noise
00329       if( sizes[i+1] <= 1 ) break;
00330       
00331       double as1 = ratios[i];
00332       double as2 = ratios[i+1];
00333 
00334       if(as1 < 1) as1 = 1.0/as1;
00335       if(as2 < 1) as2 = 1.0/as2;
00336       
00337       if( //both blobs must be semi-circular, prefer those that are wider
00338           ratios[i] > 0.75 &&   ratios[i] < 2 &&
00339           ratios[i+1] > 0.75 && ratios[i+1] < 2 &&
00340           //both blobs must be similar in shape
00341           QMAX(as2,as1)/QMIN(as2,as1) < 2 &&
00342           //both blobs must be similar in size
00343           ((double)QMAX( sizes[i], sizes[i+1] )) / QMIN( sizes[i], sizes[i+1] ) < 1.5 &&
00344           //both blobs must be above a certain thresh size, this prevents selecting blobs that are very very tiny
00345           //if only tiny blobs are around we'll end up desaturating entire region
00346           QMAX( sizes[i], sizes[i+1] ) > 20 )
00347       {
00348         id1 = ids[i];
00349         id2 = ids[i+1];
00350         break;
00351       }    
00352     }
00353   }
00354   
00355   //Comment this sectionin to see what blobs were found and selected
00356 /* cout << "-----\n";
00357   for(i=0; i<blobCount-1; i++)
00358   {
00359     if( ids[i] == id1 || ids[i] == id2 )
00360       cout << "--->";
00361     cout << "ID: " << ids[i] << "count: " << sizes[i] << " w:h: " << ratios[i] << "\n";      
00362   }*/
00363 }

void findBlobs  ) 
 

Definition at line 177 of file redEye.cpp.

References blobAspectRatios, blobBottomRight, blobIDs, blobPixelCount, blobSizes, blobTopLeft, bottomRight, pushPixel(), rawImage, regionHeight, regionOfInterest, regionWidth, spreadablePixels, and topLeft.

Referenced by removeRedeyeRegions().

00178 {
00179   //create small matrix for region of interest
00180   regionWidth = bottomRight.x() - topLeft.x() + 1;
00181   regionHeight = bottomRight.y() - topLeft.y() + 1;  
00182   regionOfInterest = new int[ regionWidth * regionHeight ];
00183   
00184   //set all pixels that meet thresh to 1, all others to 0
00185   int x, y;
00186   int x2, y2;
00187   QRgb* rgb;
00188   uchar* scanLine;
00189   for( y=topLeft.y(); y<=bottomRight.y(); y++)
00190   {
00191     y2 = y - topLeft.y();
00192     
00193     scanLine = rawImage.scanLine(y);
00194     for( x=topLeft.x(); x<=bottomRight.x(); x++)
00195     {
00196     
00197       x2 = x - topLeft.x();
00198       
00199       rgb = ((QRgb*)scanLine+x);
00200       
00201       bool threshMet = qRed(*rgb) > 2*qGreen(*rgb) &&
00202                        qRed(*rgb) > MIN_RED_VAL;
00203       
00204       if(threshMet)
00205         regionOfInterest[ x2 + y2*regionWidth ] = 1;
00206       else
00207         regionOfInterest[ x2 + y2*regionWidth ] = 0;
00208     }
00209   } 
00210   
00211   //walk over region of interest and propogate blobs
00212   int nextValidID = 2;
00213   for(x = 0; x<regionWidth; x++)
00214   {
00215     for(y = 0; y<regionHeight; y++)
00216     {
00217       //if any blobs can be propogated handle them first
00218       while( !spreadablePixels.empty() )
00219       {
00220         QPoint point = spreadablePixels.pop();
00221         int id = regionOfInterest[ point.x() + point.y()*regionWidth ];
00222         
00223         pushPixel( point.x()-1, point.y()-1, id );
00224         pushPixel( point.x(),   point.y()-1, id );
00225         pushPixel( point.x()+1, point.y()-1, id );
00226         pushPixel( point.x()-1, point.y(), id );
00227         pushPixel( point.x()+1, point.y(), id );
00228         pushPixel( point.x()-1, point.y()+1, id );
00229         pushPixel( point.x(),   point.y()+1, id );
00230         pushPixel( point.x()+1, point.y()+1, id );
00231       }
00232       
00233       //if this pixel has met thresh and has not yet been assigned a unique ID,
00234       //assign it the next unique id and push all valid neighbors
00235       if( regionOfInterest[ x + y*regionWidth ] == 1 )
00236       {
00237         //print last blob stats
00238         if( nextValidID > 2)
00239         {
00240           blobIDs.push( (nextValidID - 1) );
00241           blobSizes.push( blobPixelCount );
00242           blobAspectRatios.push( ((double)(blobBottomRight.x() - blobTopLeft.x()+1)) / (blobBottomRight.y() - blobTopLeft.y()+1) );
00243         }
00244         
00245         regionOfInterest[x + y*regionWidth] = nextValidID;
00246         pushPixel( x-1, y-1, nextValidID );
00247         pushPixel( x,   y-1, nextValidID );
00248         pushPixel( x+1, y-1, nextValidID );
00249         pushPixel( x-1, y, nextValidID );
00250         pushPixel( x+1, y, nextValidID );
00251         pushPixel( x-1, y+1, nextValidID );
00252         pushPixel( x,   y+1, nextValidID );
00253         pushPixel( x+1, y+1, nextValidID );
00254         nextValidID++;        
00255         
00256         blobPixelCount = 1;
00257         blobTopLeft = QPoint( x, y );
00258         blobBottomRight = QPoint( x, y );
00259       }
00260     } //y
00261   } //x
00262   
00263   //insert last blob stats
00264   if( nextValidID > 2)
00265   {
00266     blobIDs.push( (nextValidID - 1) );
00267     blobSizes.push( blobPixelCount );
00268     blobAspectRatios.push( ((double)(blobBottomRight.x() - blobTopLeft.x()+1)) / (blobBottomRight.y() - blobTopLeft.y()+1) );
00269   }
00270 }

void findRegionOfInterest QPoint  topLeftExtreme,
QPoint  bottomRightExtreme
 

Definition at line 110 of file redEye.cpp.

References bottomRight, StatusWidget::incrementProgress(), newProgress, rawImage, status, and topLeft.

Referenced by removeRedeyeRegions().

00111 {
00112   topLeft = QPoint(-1,-1);
00113   bottomRight = QPoint(-1,-1);
00114   
00115   int x, y;
00116   QRgb* rgb;
00117   uchar* scanLine;
00118   for( y=topLeftExtreme.y(); y<=bottomRightExtreme.y(); y++)
00119   {
00120     scanLine = rawImage.scanLine(y);
00121     for( x=topLeftExtreme.x(); x<=bottomRightExtreme.x(); x++)
00122     {
00123       rgb = ((QRgb*)scanLine+x);
00124       
00125       bool threshMet = qRed(*rgb) > 2*qGreen(*rgb) &&
00126         qRed(*rgb) > MIN_RED_VAL;
00127       if(threshMet)
00128       {
00129         //first pixel
00130         if(topLeft.x() == -1) 
00131         {
00132           topLeft = QPoint(x,y);
00133           bottomRight = QPoint(x,y);
00134         }
00135         
00136         if(x < topLeft.x() ) topLeft.setX( x );
00137         if(y < topLeft.y() ) topLeft.setY( y );
00138         if(x > bottomRight.x() ) bottomRight.setX( x );
00139         if(y > bottomRight.y() ) bottomRight.setY( y );
00140       }
00141       
00142       //update status bar if significant progress has been made since last update
00143       newProgress++;
00144       if(newProgress >= updateIncrement)
00145       {
00146         newProgress = 0;
00147         status->incrementProgress();
00148         qApp->processEvents();  
00149       }
00150       
00151     }
00152   }  
00153 }

bool IDedPixel int  x,
int  y
 

Definition at line 365 of file redEye.cpp.

References bottomRight, id1, regionIndex(), regionOfInterest, and topLeft.

Referenced by desaturateAlpha().

00366 {
00367   if( x < topLeft.x() || y < topLeft.y() ||
00368       x > bottomRight.x() || y > bottomRight.y() )
00369     return false;
00370   
00371   int regionIndex = x - topLeft.x() + (y-topLeft.y())*regionWidth;
00372   return ( regionOfInterest[regionIndex] == id1 ||
00373            regionOfInterest[regionIndex] == id2 );
00374 }

void pushPixel int  x,
int  y,
int  id
 

Definition at line 155 of file redEye.cpp.

References blobBottomRight, blobPixelCount, blobTopLeft, regionHeight, regionOfInterest, regionWidth, and spreadablePixels.

Referenced by findBlobs().

00156 {
00157   //if pixel off image or below thresh ignore push attempt
00158   if(  x < 0  || 
00159        y <  0 ||
00160        x >= regionWidth ||
00161        y >= regionHeight ||
00162        regionOfInterest[ x + y*regionWidth ] != 1 )
00163     return;
00164   
00165   //passes! set id and actually put pixel onto stack
00166   regionOfInterest[ x + y*regionWidth] = id;  
00167   spreadablePixels.push( QPoint( x, y ) );
00168   
00169   //increase blob pixel count and update topLeft and bottomRight
00170   blobPixelCount++;
00171   blobTopLeft.setX( QMIN( x, blobTopLeft.x() ) );
00172   blobTopLeft.setY( QMIN( y, blobTopLeft.y() ) );
00173   blobBottomRight.setX( QMAX( x, blobBottomRight.x() ) );
00174   blobBottomRight.setY( QMAX( y, blobBottomRight.y() ) );
00175 }

void sortBlobsByDecreasingSize  ) 
 

Definition at line 272 of file redEye.cpp.

References blobAspectRatios, blobCount, blobIDs, blobSizes, ids, ratios, and sizes.

Referenced by removeRedeyeRegions().

00273 {
00274   blobCount = blobIDs.count();
00275   ids = new int[blobCount];
00276   sizes = new int[blobCount];
00277   ratios = new double[blobCount];
00278   
00279   int i,j;
00280   for(i=0; i<blobCount; i++)
00281   {
00282     ids[i] = blobIDs.pop();
00283     sizes[i] = blobSizes.pop();
00284     ratios[i] = blobAspectRatios.pop();
00285   }
00286   
00287   //quick and dirty bubble sort
00288   for(j = blobCount-1; j>0; j--)
00289   {
00290     for(i=0; i<j; i++)
00291     {
00292       if( sizes[i+1] > sizes[i] )
00293       {
00294         int t = sizes[i+1];
00295         sizes[i+1] = sizes[i];
00296         sizes[i] = t;
00297         
00298         t = ids[i+1];
00299         ids[i+1] = ids[i];
00300         ids[i] = t;
00301         
00302         double tR = ratios[i+1];
00303         ratios[i+1] = ratios[i];
00304         ratios[i] = tR;        
00305       }
00306     }
00307   }
00308 }


Variable Documentation

QValueStack<double> blobAspectRatios
 

Definition at line 58 of file redEye_internal.h.

Referenced by findBlobs(), and sortBlobsByDecreasingSize().

QPoint blobBottomRight
 

Definition at line 50 of file redEye_internal.h.

Referenced by findBlobs(), and pushPixel().

int blobCount
 

Definition at line 63 of file redEye_internal.h.

Referenced by findBestTwoBlobs(), and sortBlobsByDecreasingSize().

QValueStack<int> blobIDs
 

Definition at line 56 of file redEye_internal.h.

Referenced by findBlobs(), and sortBlobsByDecreasingSize().

int blobPixelCount
 

Definition at line 49 of file redEye_internal.h.

Referenced by findBlobs(), and pushPixel().

QValueStack<int> blobSizes
 

Definition at line 57 of file redEye_internal.h.

Referenced by findBlobs(), and sortBlobsByDecreasingSize().

QPoint blobTopLeft
 

Definition at line 50 of file redEye_internal.h.

Referenced by findBlobs(), and pushPixel().

QPoint bottomRight
 

Definition at line 42 of file redEye_internal.h.

Referenced by correctImageTilt(), EditingInterface::crop(), cropImage(), desaturateBlobs(), findBlobs(), findRegionOfInterest(), EditingInterface::findSelection(), SelectionInterface::getSelection(), EditingInterface::handleSelectionChanged(), IDedPixel(), SelectionInterface::keyPressEvent(), SelectionInterface::mouseActionByPosition(), SelectionInterface::mouseMoveEvent(), SelectionInterface::mousePressEvent(), SelectionInterface::mouseReleaseEvent(), SelectionPlacementInterface::paintEvent(), SelectionInterface::paintEvent(), EditingInterface::removeRedeye(), EditingInterface::rotateSelection(), SelectionInterface::scaleSelection(), EditingInterface::selectAll(), and EditingInterface::selectAspectRatio().

QImage* editedImage
 

Definition at line 37 of file redEye_internal.h.

Referenced by EditingInterface::applyEffect(), EditingInterface::applyImageUpdate(), blackWhiteEffect(), correctImageTilt(), desaturateBlobs(), desaturateEntireImage(), embossEffect(), enhanceImageContrast(), improveColorBalance(), invertEffect(), oilPaintingEffect(), pointillismEffect(), removeRedeyeRegions(), EditingInterface::selectEffect(), and sepiaEffect().

int id1
 

Definition at line 71 of file redEye_internal.h.

Referenced by findBestTwoBlobs(), IDedPixel(), and removeRedeyeRegions().

int id2
 

Definition at line 71 of file redEye_internal.h.

Referenced by findBestTwoBlobs().

int* ids
 

Definition at line 64 of file redEye_internal.h.

Referenced by findBestTwoBlobs(), and sortBlobsByDecreasingSize().

int newProgress
 

Definition at line 31 of file redEye_internal.h.

Referenced by blackWhiteEffect(), correctImageTilt(), embossEffect(), enhanceImageContrast(), findRegionOfInterest(), improveColorBalance(), oilPaintingEffect(), removeRedeyeRegions(), and sepiaEffect().

double* ratios
 

Definition at line 66 of file redEye_internal.h.

Referenced by findBestTwoBlobs(), and sortBlobsByDecreasingSize().

QImage rawImage
 

Definition at line 34 of file redEye_internal.h.

Referenced by findBlobs(), findRegionOfInterest(), and removeRedeyeRegions().

int regionHeight
 

Definition at line 47 of file redEye_internal.h.

Referenced by findBlobs(), and pushPixel().

int* regionOfInterest
 

Definition at line 52 of file redEye_internal.h.

Referenced by findBlobs(), IDedPixel(), and pushPixel().

int regionWidth
 

Definition at line 47 of file redEye_internal.h.

Referenced by findBlobs(), and pushPixel().

int* sizes
 

Definition at line 65 of file redEye_internal.h.

Referenced by findBestTwoBlobs(), and sortBlobsByDecreasingSize().

QValueStack<QPoint> spreadablePixels
 

Definition at line 54 of file redEye_internal.h.

Referenced by findBlobs(), and pushPixel().

StatusWidget* status
 

Definition at line 25 of file redEye_internal.h.

Referenced by EditingInterface::applyEffect(), blackWhiteEffect(), correctImageTilt(), embossEffect(), enhanceImageContrast(), Album::exportCompressedWebAlbum(), Album::exportLargeImages(), Album::exportSubalbumImages(), Album::exportToDisk(), Album::exportToXML(), findRegionOfInterest(), Subalbum::importFromDisk(), Album::importFromDisk(), improveColorBalance(), oilPaintingEffect(), removeRedeyeRegions(), Album::removeStagnantOrigFiles(), Album::reorderSubalbumImages(), and sepiaEffect().

QPoint topLeft
 

Definition at line 42 of file redEye_internal.h.

Referenced by PhotosIconView::captureClick(), correctImageTilt(), EditingInterface::crop(), cropImage(), desaturateBlobs(), findBlobs(), findRegionOfInterest(), EditingInterface::findSelection(), SelectionInterface::getSelection(), EditingInterface::handleSelectionChanged(), IDedPixel(), SelectionInterface::keyPressEvent(), SelectionInterface::mouseActionByPosition(), SelectionInterface::mouseMoveEvent(), SelectionInterface::mousePressEvent(), SelectionInterface::mouseReleaseEvent(), SelectionPlacementInterface::paintEvent(), SelectionInterface::paintEvent(), EditingInterface::removeRedeye(), removeRedeyeRegions(), EditingInterface::rotateSelection(), SelectionInterface::scaleSelection(), EditingInterface::selectAll(), EditingInterface::selectAspectRatio(), and Item::setTextWidth().

int updateIncrement
 

Definition at line 28 of file redEye_internal.h.

Referenced by blackWhiteEffect(), correctImageTilt(), embossEffect(), enhanceImageContrast(), improveColorBalance(), oilPaintingEffect(), removeRedeyeRegions(), and sepiaEffect().


Generated on Sat Apr 2 05:44:35 2005 for AlbumShaper by  doxygen 1.3.9.1