|
AlbumShaper
1.0a3
|

Go to the source code of this file.
Functions | |
| QImage * | oilPaintingEffect (QString filename, ManipulationOptions *options) |
| QImage* oilPaintingEffect | ( | QString | filename, |
| ManipulationOptions * | options | ||
| ) |
Definition at line 103 of file painting.cpp.
References Triplet::b, editedImage, findHighestCounts(), Triplet::g, ManipulationOptions::getStatus(), Histogram::highestCountIndex, StatusWidget::incrementProgress(), newProgress, Triplet::r, resetHistogram(), StatusWidget::showProgressBar(), status, updateIncrement, and Histogram::values.
Referenced by EditingInterface::applyEffect().
{
//load original image
QImage originalImage( filename );
//convert to 32-bit depth if necessary
if( originalImage.depth() < 32 ) { originalImage = originalImage.convertDepth( 32, Qt::AutoColor ); }
//determine if busy indicators will be used
bool useBusyIndicators = false;
StatusWidget* status = NULL;
if( options != NULL && options->getStatus() != NULL )
{
useBusyIndicators = true;
status = options->getStatus();
}
//setup progress bar
if(useBusyIndicators)
{
QString statusMessage = qApp->translate( "oilPaintingEffect", "Applying Oil Painting Effect:" );
status->showProgressBar( statusMessage, 100 );
qApp->processEvents();
}
//update progress bar for every 1% of completion
const int updateIncrement = (int) ( 0.01 * originalImage.width() * originalImage.height() );
int newProgress = 0;
//construct edited image
QImage* editedImage = new QImage( filename );
//convert to 32-bit depth if necessary
if( editedImage->depth() < 32 )
{
QImage* tmp = editedImage;
editedImage = new QImage( tmp->convertDepth( 32, Qt::AutoColor ) );
delete tmp; tmp=NULL;
}
//compute the radius using image resolution
double minDimen = (double) QMIN( editedImage->width(), editedImage->height() );
const int RADIUS = (int) QMAX( 2, (sqrt(minDimen)/4) );
//iterate over image
int originalImageX, originalImageY;
int editedImageX, editedImageY;
int clampedX, clampedY;
int trailingEdgeY, leadingEdgeY;
QRgb* rgb;
uchar* scanLine;
uchar* trailingScanLine;
uchar* leadingScanLine;
//iterate over columns
for( editedImageX=0; editedImageX < editedImage->width(); editedImageX++)
{
//------------------
//reset histogram object
resetHistogram();
//------------------
//fill histogram with data that would have results from Y=-1
for(originalImageY = 0 - 1 - RADIUS;
originalImageY <= 0 - 1 + RADIUS;
originalImageY++)
{
clampedY = QMAX( QMIN( originalImageY, originalImage.height() - 1 ), 0 );
scanLine = originalImage.scanLine( clampedY );
for(originalImageX = editedImageX - RADIUS;
originalImageX <= editedImageX + RADIUS;
originalImageX++)
{
clampedX = QMAX( QMIN( originalImageX, originalImage.width() - 1 ), 0 );
//get rgb value
rgb = ((QRgb*)scanLine+clampedX);
//update counts for this r/g/b value
histogram.values[ qRed(*rgb) ].r++;
histogram.values[ qGreen(*rgb) ].g++;
histogram.values[ qBlue(*rgb) ].b++;
} //originalX
} //originalY
//------------------
//now iterate over rows by simply removing trailing edge data and adding leading edge data
for( editedImageY=0; editedImageY < editedImage->height(); editedImageY++)
{
trailingEdgeY = QMAX( QMIN( editedImageY-1-RADIUS, originalImage.height() - 1 ), 0 );
leadingEdgeY = QMAX( QMIN( editedImageY+RADIUS, originalImage.height() - 1 ), 0 );
trailingScanLine = originalImage.scanLine( trailingEdgeY );
leadingScanLine = originalImage.scanLine( leadingEdgeY );
for(originalImageX = editedImageX - RADIUS;
originalImageX <= editedImageX + RADIUS;
originalImageX++)
{
clampedX = QMAX( QMIN( originalImageX, originalImage.width() - 1 ), 0 );
//remove trail edge data
rgb = ((QRgb*)trailingScanLine+clampedX);
histogram.values[ qRed(*rgb) ].r--;
histogram.values[ qGreen(*rgb) ].g--;
histogram.values[ qBlue(*rgb) ].b--;
//add leading edge data
rgb = ((QRgb*)leadingScanLine+clampedX);
histogram.values[ qRed(*rgb) ].r++;
histogram.values[ qGreen(*rgb) ].g++;
histogram.values[ qBlue(*rgb) ].b++;
} //originalX
//find highest color counts
findHighestCounts();
//replace each color channel value with average of
//current value and most occuring value within neighborhood
scanLine = editedImage->scanLine( editedImageY );
rgb = ((QRgb*)scanLine+editedImageX);
*rgb = qRgb( (qRed(*rgb) + histogram.highestCountIndex.r) / 2,
(qGreen(*rgb) + histogram.highestCountIndex.g) / 2,
(qBlue(*rgb) + histogram.highestCountIndex.b) / 2 );
//update status bar if significant progress has been made since last update
if(useBusyIndicators)
{
newProgress++;
if(newProgress >= updateIncrement)
{
newProgress = 0;
status->incrementProgress();
qApp->processEvents();
}
}
} //editedImageX
} //editedImageY
//return pointer to edited image
return editedImage;
}
1.7.5.1