AlbumShaper 1.0a3
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.

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

References IDedPixel().

Referenced by desaturateBlobs().

◆ desaturateBlobs()

void desaturateBlobs ( )

Definition at line 612 of file redEye.cpp.

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}
double desaturateAlpha(int x, int y)
Definition redEye.cpp:572
QImage * editedImage
QPoint topLeft
QPoint bottomRight

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

Referenced by removeRedeyeRegions().

◆ desaturateEntireImage()

void desaturateEntireImage ( QPoint topLeftExtreme,
QPoint bottomRightExtreme )

Definition at line 643 of file redEye.cpp.

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}

References editedImage.

Referenced by removeRedeyeRegions().

◆ findBestTwoBlobs()

void findBestTwoBlobs ( )

Definition at line 506 of file redEye.cpp.

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 id1
int * ids
double * ratios
int blobCount
int id2
int * sizes

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

Referenced by removeRedeyeRegions().

◆ findBlobs()

void findBlobs ( )

Definition at line 372 of file redEye.cpp.

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) );
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) );
464 blobAspectRatios.push( ((double)(blobBottomRight.x() - blobTopLeft.x()+1)) / (blobBottomRight.y() - blobTopLeft.y()+1) );
465 }
466}
void pushPixel(int x, int y, int id)
Definition redEye.cpp:350
#define MIN_RED_VAL
Definition redEye.cpp:302
Q3ValueStack< double > blobAspectRatios
int regionWidth
QImage rawImage
int * regionOfInterest
Q3ValueStack< int > blobSizes
QPoint blobTopLeft
int blobPixelCount
Q3ValueStack< int > blobIDs
QPoint blobBottomRight
int regionHeight
Q3ValueStack< QPoint > spreadablePixels

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

Referenced by removeRedeyeRegions().

◆ findRegionOfInterest()

void findRegionOfInterest ( QPoint topLeftExtreme,
QPoint bottomRightExtreme )

Definition at line 305 of file redEye.cpp.

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}
void incrementProgress()
Updates the progress bar by one step.
int updateIncrement
StatusWidget * status
int newProgress

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

Referenced by removeRedeyeRegions().

◆ IDedPixel()

bool IDedPixel ( int x,
int y )

Definition at line 561 of file redEye.cpp.

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 ||
570}
int regionIndex(int x, int y)
Definition blur.cpp:227

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

Referenced by desaturateAlpha().

◆ pushPixel()

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

Definition at line 350 of file redEye.cpp.

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
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}

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

Referenced by findBlobs().

◆ sortBlobsByDecreasingSize()

void sortBlobsByDecreasingSize ( )

Definition at line 468 of file redEye.cpp.

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}

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

Referenced by removeRedeyeRegions().

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

◆ 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

◆ 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

◆ topLeft

◆ updateIncrement