AlbumShaper  1.0a3
Functions | Variables
redEye_internal.h File Reference
#include <qimage.h>
#include <q3valuestack.h>
#include <qpoint.h>
Include dependency graph for redEye_internal.h:
This graph shows which files directly or indirectly include this file:

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
 
Q3ValueStack< QPoint > spreadablePixels
 
Q3ValueStack< int > blobIDs
 
Q3ValueStack< int > blobSizes
 
Q3ValueStack< double > blobAspectRatios
 
int blobCount
 
int * ids
 
int * sizes
 
double * ratios
 
int id1
 
int id2
 

Function Documentation

§ desaturateAlpha()

double desaturateAlpha ( int  x,
int  y 
)

Definition at line 572 of file redEye.cpp.

References IDedPixel().

Referenced by desaturateBlobs().

573 {
574  int n = 0;
575  if( IDedPixel(x ,y ) ) n++;
576 
577  if(n == 1)
578  return 1.0;
579 
580  if( IDedPixel(x-1,y-1) ) n++;
581  if( IDedPixel(x ,y-1) ) n++;
582  if( IDedPixel(x+1,y-1) ) n++;
583  if( IDedPixel(x-1,y ) ) n++;
584  if( IDedPixel(x+1,y ) ) n++;
585  if( IDedPixel(x-1,y+1) ) n++;
586  if( IDedPixel(x ,y+1) ) n++;
587  if( IDedPixel(x+1,y+1) ) n++;
588 
589  if( IDedPixel(x-2,y-2) ) n++;
590  if( IDedPixel(x-1,y-2) ) n++;
591  if( IDedPixel(x ,y-2) ) n++;
592  if( IDedPixel(x+1,y-2) ) n++;
593  if( IDedPixel(x+2,y-2) ) n++;
594 
595  if( IDedPixel(x-2,y-1) ) n++;
596  if( IDedPixel(x+2,y-1) ) n++;
597  if( IDedPixel(x-2,y ) ) n++;
598  if( IDedPixel(x+2,y ) ) n++;
599  if( IDedPixel(x-2,y+1) ) n++;
600  if( IDedPixel(x+2,y+1) ) n++;
601 
602  if( IDedPixel(x-2,y+2) ) n++;
603  if( IDedPixel(x-1,y+2) ) n++;
604  if( IDedPixel(x ,y+2) ) n++;
605  if( IDedPixel(x+1,y+2) ) n++;
606  if( IDedPixel(x+2,y+2) ) n++;
607 
608 
609  return ((double)n) / 25;
610 }
bool IDedPixel(int x, int y)
Definition: redEye.cpp:561

§ desaturateBlobs()

void desaturateBlobs ( )

Definition at line 612 of file redEye.cpp.

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

Referenced by removeRedeyeRegions().

613 {
614  //desaturate bad pixels
615  int x, y;
616  double r;
617  QRgb* rgb;
618  uchar* scanLine;
619  for( y = QMAX( topLeft.y()-1, 0);
620  y<= QMIN( bottomRight.y()+1, editedImage->height()-1 );
621  y++)
622  {
623  scanLine = editedImage->scanLine(y);
624  for( x = QMAX( topLeft.x()-1, 0);
625  x <= QMIN( bottomRight.x()+1, editedImage->width()-1 );
626  x++)
627  {
628  double alpha = desaturateAlpha( x, y );
629  if( alpha > 0)
630  {
631  rgb = ((QRgb*)scanLine+x);
632 
633  r = alpha*(0.05*qRed(*rgb) + 0.6*qGreen(*rgb) + 0.3*qBlue(*rgb)) +
634  (1-alpha)*qRed(*rgb);
635  *rgb = qRgb( (int)r,
636  qGreen(*rgb),
637  qBlue(*rgb) );
638  } //alpha > 0
639  } //x
640  } //y
641 }
QPoint bottomRight
QPoint topLeft
double desaturateAlpha(int x, int y)
Definition: redEye.cpp:572
QImage * editedImage

§ desaturateEntireImage()

void desaturateEntireImage ( QPoint  topLeftExtreme,
QPoint  bottomRightExtreme 
)

Definition at line 643 of file redEye.cpp.

References editedImage.

Referenced by removeRedeyeRegions().

644 {
645  //desaturate bad pixels
646  int x, y;
647  QRgb* rgb;
648  uchar* scanLine;
649  for( y=topLeftExtreme.y(); y<=bottomRightExtreme.y(); y++)
650  {
651  scanLine = editedImage->scanLine(y);
652  for( x=topLeftExtreme.x(); x<=bottomRightExtreme.x(); x++)
653  {
654  rgb = ((QRgb*)scanLine+x);
655  if( qRed(*rgb) > 2*qGreen(*rgb) )
656  {
657  *rgb = qRgb( (int) (0.05*qRed(*rgb) + 0.6*qGreen(*rgb) + 0.3*qBlue(*rgb)),
658  qGreen(*rgb),
659  qBlue(*rgb) );
660  } // > thresh
661  } //x
662  } //y
663 }
QImage * editedImage

§ findBestTwoBlobs()

void findBestTwoBlobs ( )

Definition at line 506 of file redEye.cpp.

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

Referenced by removeRedeyeRegions().

507 {
508  id1 = -1;
509  id2 = -1;
510  int i;
511 
512  //special case: 2 blobs found, both larger than 1 pixel
513  if(blobCount == 2 &&
514  sizes[0] > 1 &&
515  sizes[1] > 1)
516  {
517  id1 = ids[0];
518  id2 = ids[1];
519  }
520  else
521  {
522  for(i=0; i<blobCount-2; i++)
523  {
524  //once we hit blobs that are only one pixel large stop because they are probably just noise
525  if( sizes[i+1] <= 1 ) break;
526 
527  double as1 = ratios[i];
528  double as2 = ratios[i+1];
529 
530  if(as1 < 1) as1 = 1.0/as1;
531  if(as2 < 1) as2 = 1.0/as2;
532 
533  if( //both blobs must be semi-circular, prefer those that are wider
534  ratios[i] > 0.75 && ratios[i] < 2 &&
535  ratios[i+1] > 0.75 && ratios[i+1] < 2 &&
536  //both blobs must be similar in shape
537  QMAX(as2,as1)/QMIN(as2,as1) < 2 &&
538  //both blobs must be similar in size
539  ((double)QMAX( sizes[i], sizes[i+1] )) / QMIN( sizes[i], sizes[i+1] ) < 1.5 &&
540  //both blobs must be above a certain thresh size, this prevents selecting blobs that are very very tiny
541  //if only tiny blobs are around we'll end up desaturating entire region
542  QMAX( sizes[i], sizes[i+1] ) > 20 )
543  {
544  id1 = ids[i];
545  id2 = ids[i+1];
546  break;
547  }
548  }
549  }
550 
551  //Comment this sectionin to see what blobs were found and selected
552 /* cout << "-----\n";
553  for(i=0; i<blobCount-1; i++)
554  {
555  if( ids[i] == id1 || ids[i] == id2 )
556  cout << "--->";
557  cout << "ID: " << ids[i] << "count: " << sizes[i] << " w:h: " << ratios[i] << "\n";
558  }*/
559 }
int id2
int * ids
int blobCount
int * sizes
double * ratios
int id1

§ findBlobs()

void findBlobs ( )

Definition at line 372 of file redEye.cpp.

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

Referenced by removeRedeyeRegions().

373 {
374  //create small matrix for region of interest
375  regionWidth = bottomRight.x() - topLeft.x() + 1;
376  regionHeight = bottomRight.y() - topLeft.y() + 1;
378 
379  //set all pixels that meet thresh to 1, all others to 0
380  int x, y;
381  int x2, y2;
382  QRgb* rgb;
383  uchar* scanLine;
384  for( y=topLeft.y(); y<=bottomRight.y(); y++)
385  {
386  y2 = y - topLeft.y();
387 
388  scanLine = rawImage.scanLine(y);
389  for( x=topLeft.x(); x<=bottomRight.x(); x++)
390  {
391 
392  x2 = x - topLeft.x();
393 
394  rgb = ((QRgb*)scanLine+x);
395 
396  bool threshMet = qRed(*rgb) > 2*qGreen(*rgb) &&
397  qRed(*rgb) > MIN_RED_VAL;
398 
399  if(threshMet)
400  regionOfInterest[ x2 + y2*regionWidth ] = 1;
401  else
402  regionOfInterest[ x2 + y2*regionWidth ] = 0;
403  }
404  }
405 
406  //walk over region of interest and propogate blobs
407  int nextValidID = 2;
408  for(x = 0; x<regionWidth; x++)
409  {
410  for(y = 0; y<regionHeight; y++)
411  {
412  //if any blobs can be propogated handle them first
413  while( !spreadablePixels.empty() )
414  {
415  QPoint point = spreadablePixels.pop();
416  int id = regionOfInterest[ point.x() + point.y()*regionWidth ];
417 
418  pushPixel( point.x()-1, point.y()-1, id );
419  pushPixel( point.x(), point.y()-1, id );
420  pushPixel( point.x()+1, point.y()-1, id );
421  pushPixel( point.x()-1, point.y(), id );
422  pushPixel( point.x()+1, point.y(), id );
423  pushPixel( point.x()-1, point.y()+1, id );
424  pushPixel( point.x(), point.y()+1, id );
425  pushPixel( point.x()+1, point.y()+1, id );
426  }
427 
428  //if this pixel has met thresh and has not yet been assigned a unique ID,
429  //assign it the next unique id and push all valid neighbors
430  if( regionOfInterest[ x + y*regionWidth ] == 1 )
431  {
432  //print last blob stats
433  if( nextValidID > 2)
434  {
435  blobIDs.push( (nextValidID - 1) );
436  blobSizes.push( blobPixelCount );
437  blobAspectRatios.push( ((double)(blobBottomRight.x() - blobTopLeft.x()+1)) /
438  (blobBottomRight.y() - blobTopLeft.y()+1) );
439  }
440 
441  regionOfInterest[x + y*regionWidth] = nextValidID;
442  pushPixel( x-1, y-1, nextValidID );
443  pushPixel( x, y-1, nextValidID );
444  pushPixel( x+1, y-1, nextValidID );
445  pushPixel( x-1, y, nextValidID );
446  pushPixel( x+1, y, nextValidID );
447  pushPixel( x-1, y+1, nextValidID );
448  pushPixel( x, y+1, nextValidID );
449  pushPixel( x+1, y+1, nextValidID );
450  nextValidID++;
451 
452  blobPixelCount = 1;
453  blobTopLeft = QPoint( x, y );
454  blobBottomRight = QPoint( x, y );
455  }
456  } //y
457  } //x
458 
459  //insert last blob stats
460  if( nextValidID > 2)
461  {
462  blobIDs.push( (nextValidID - 1) );
463  blobSizes.push( blobPixelCount );
464  blobAspectRatios.push( ((double)(blobBottomRight.x() - blobTopLeft.x()+1)) / (blobBottomRight.y() - blobTopLeft.y()+1) );
465  }
466 }
QPoint bottomRight
QPoint topLeft
Q3ValueStack< double > blobAspectRatios
Q3ValueStack< int > blobIDs
int * regionOfInterest
QImage rawImage
int regionHeight
Q3ValueStack< QPoint > spreadablePixels
void pushPixel(int x, int y, int id)
Definition: redEye.cpp:350
QPoint blobTopLeft
int blobPixelCount
QPoint blobBottomRight
int regionWidth
Q3ValueStack< int > blobSizes
#define MIN_RED_VAL
Definition: redEye.cpp:302

§ findRegionOfInterest()

void findRegionOfInterest ( QPoint  topLeftExtreme,
QPoint  bottomRightExtreme 
)

Definition at line 305 of file redEye.cpp.

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

Referenced by removeRedeyeRegions().

306 {
307  topLeft = QPoint(-1,-1);
308  bottomRight = QPoint(-1,-1);
309 
310  int x, y;
311  QRgb* rgb;
312  uchar* scanLine;
313  for( y=topLeftExtreme.y(); y<=bottomRightExtreme.y(); y++)
314  {
315  scanLine = rawImage.scanLine(y);
316  for( x=topLeftExtreme.x(); x<=bottomRightExtreme.x(); x++)
317  {
318  rgb = ((QRgb*)scanLine+x);
319 
320  bool threshMet = qRed(*rgb) > 2*qGreen(*rgb) &&
321  qRed(*rgb) > MIN_RED_VAL;
322  if(threshMet)
323  {
324  //first pixel
325  if(topLeft.x() == -1)
326  {
327  topLeft = QPoint(x,y);
328  bottomRight = QPoint(x,y);
329  }
330 
331  if(x < topLeft.x() ) topLeft.setX( x );
332  if(y < topLeft.y() ) topLeft.setY( y );
333  if(x > bottomRight.x() ) bottomRight.setX( x );
334  if(y > bottomRight.y() ) bottomRight.setY( y );
335  }
336 
337  //update status bar if significant progress has been made since last update
338  newProgress++;
340  {
341  newProgress = 0;
343  qApp->processEvents();
344  }
345 
346  }
347  }
348 }
QPoint bottomRight
int updateIncrement
QPoint topLeft
QImage rawImage
void incrementProgress()
Updates the progress bar by one step.
StatusWidget * status
#define MIN_RED_VAL
Definition: redEye.cpp:302
int newProgress

§ IDedPixel()

bool IDedPixel ( int  x,
int  y 
)

Definition at line 561 of file redEye.cpp.

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

Referenced by desaturateAlpha().

562 {
563  if( x < topLeft.x() || y < topLeft.y() ||
564  x > bottomRight.x() || y > bottomRight.y() )
565  return false;
566 
567  int regionIndex = x - topLeft.x() + (y-topLeft.y())*regionWidth;
568  return ( regionOfInterest[regionIndex] == id1 ||
569  regionOfInterest[regionIndex] == id2 );
570 }
QPoint bottomRight
QPoint topLeft
int * regionOfInterest
int regionIndex(int x, int y)
Definition: blur.cpp:227
int id2
int regionWidth
int id1

§ pushPixel()

void pushPixel ( int  x,
int  y,
int  id 
)

Definition at line 350 of file redEye.cpp.

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

Referenced by findBlobs().

351 {
352  //if pixel off image or below thresh ignore push attempt
353  if( x < 0 ||
354  y < 0 ||
355  x >= regionWidth ||
356  y >= regionHeight ||
357  regionOfInterest[ x + y*regionWidth ] != 1 )
358  return;
359 
360  //passes! set id and actually put pixel onto stack
361  regionOfInterest[ x + y*regionWidth] = id;
362  spreadablePixels.push( QPoint( x, y ) );
363 
364  //increase blob pixel count and update topLeft and bottomRight
365  blobPixelCount++;
366  blobTopLeft.setX( QMIN( x, blobTopLeft.x() ) );
367  blobTopLeft.setY( QMIN( y, blobTopLeft.y() ) );
368  blobBottomRight.setX( QMAX( x, blobBottomRight.x() ) );
369  blobBottomRight.setY( QMAX( y, blobBottomRight.y() ) );
370 }
int * regionOfInterest
int regionHeight
Q3ValueStack< QPoint > spreadablePixels
QPoint blobTopLeft
int blobPixelCount
QPoint blobBottomRight
int regionWidth

§ sortBlobsByDecreasingSize()

void sortBlobsByDecreasingSize ( )

Definition at line 468 of file redEye.cpp.

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

Referenced by removeRedeyeRegions().

469 {
470  blobCount = blobIDs.count();
471  ids = new int[blobCount];
472  sizes = new int[blobCount];
473  ratios = new double[blobCount];
474 
475  int i,j;
476  for(i=0; i<blobCount; i++)
477  {
478  ids[i] = blobIDs.pop();
479  sizes[i] = blobSizes.pop();
480  ratios[i] = blobAspectRatios.pop();
481  }
482 
483  //quick and dirty bubble sort
484  for(j = blobCount-1; j>0; j--)
485  {
486  for(i=0; i<j; i++)
487  {
488  if( sizes[i+1] > sizes[i] )
489  {
490  int t = sizes[i+1];
491  sizes[i+1] = sizes[i];
492  sizes[i] = t;
493 
494  t = ids[i+1];
495  ids[i+1] = ids[i];
496  ids[i] = t;
497 
498  double tR = ratios[i+1];
499  ratios[i+1] = ratios[i];
500  ratios[i] = tR;
501  }
502  }
503  }
504 }
Q3ValueStack< double > blobAspectRatios
Q3ValueStack< int > blobIDs
int * ids
int blobCount
int * sizes
Q3ValueStack< int > blobSizes
double * ratios

Variable Documentation

§ blobAspectRatios

Q3ValueStack<double> blobAspectRatios

Definition at line 58 of file redEye_internal.h.

Referenced by findBlobs(), and sortBlobsByDecreasingSize().

§ blobBottomRight

QPoint blobBottomRight

Definition at line 50 of file redEye_internal.h.

Referenced by findBlobs(), and pushPixel().

§ blobCount

int blobCount

Definition at line 63 of file redEye_internal.h.

Referenced by findBestTwoBlobs(), and sortBlobsByDecreasingSize().

§ blobIDs

Q3ValueStack<int> blobIDs

Definition at line 56 of file redEye_internal.h.

Referenced by findBlobs(), and sortBlobsByDecreasingSize().

§ blobPixelCount

int blobPixelCount

Definition at line 49 of file redEye_internal.h.

Referenced by findBlobs(), and pushPixel().

§ blobSizes

Q3ValueStack<int> blobSizes

Definition at line 57 of file redEye_internal.h.

Referenced by findBlobs(), and sortBlobsByDecreasingSize().

§ blobTopLeft

QPoint blobTopLeft

Definition at line 50 of file redEye_internal.h.

Referenced by findBlobs(), and pushPixel().

§ bottomRight

QPoint bottomRight

§ editedImage

QImage* editedImage

§ id1

int id1

Definition at line 71 of file redEye_internal.h.

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

§ id2

int id2

Definition at line 71 of file redEye_internal.h.

Referenced by findBestTwoBlobs(), and IDedPixel().

§ ids

int* ids

Definition at line 64 of file redEye_internal.h.

Referenced by findBestTwoBlobs(), and sortBlobsByDecreasingSize().

§ newProgress

int newProgress

§ ratios

double* ratios

Definition at line 66 of file redEye_internal.h.

Referenced by findBestTwoBlobs(), and sortBlobsByDecreasingSize().

§ rawImage

QImage rawImage

Definition at line 34 of file redEye_internal.h.

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

§ regionHeight

int regionHeight

Definition at line 47 of file redEye_internal.h.

Referenced by findBlobs(), and pushPixel().

§ regionOfInterest

int* regionOfInterest

Definition at line 52 of file redEye_internal.h.

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

§ regionWidth

int regionWidth

Definition at line 47 of file redEye_internal.h.

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

§ sizes

int* sizes

Definition at line 65 of file redEye_internal.h.

Referenced by findBestTwoBlobs(), and sortBlobsByDecreasingSize().

§ spreadablePixels

Q3ValueStack<QPoint> spreadablePixels

Definition at line 54 of file redEye_internal.h.

Referenced by findBlobs(), and pushPixel().

§ status

StatusWidget* status

§ topLeft

QPoint topLeft

§ updateIncrement

int updateIncrement