void AdjustLuminance::onInput(InputImageInfo info, Magick::Image img) { std::vector<std::pair < Magick::Color, size_t>> histogram; Magick::colorHistogram(&histogram, img); Magick::Image original = img; /* gamma correction rules: * http://www.imagemagick.org/Usage/transform/#evaluate_pow * * updatedColor = color ^ (1 / gamma) * gamma = 1 / log(color, updatedColor) * gamma = 1 / (log(updatedColor) / log(color)) * * We can't compute gamma just from current and target luminance, * but we can estimate it. * * We can compute expected luminance after gamma * correction from image histogram, it is relatively fast. * So we iterate gamma estimation ten times. Results are relatively good. */ double gamma = 1.0; double targetLuminance = info.luminanceChange + info.luminance; double expectedLuminance = info.luminance; for (int iteration = 0; iteration < 10; iteration++) { gamma *= 1 / ( std::log(Magick::Color::scaleQuantumToDouble(targetLuminance)) / std::log(Magick::Color::scaleQuantumToDouble(expectedLuminance))); expectedLuminance = ComputeLuminance::computeLuminance(histogram, gamma); *verboseOutput << QString("%1 iteration %2 changing gamma to %3 (expected luminance: %4, target %5, abs(diff) %6)") .arg(info.file.filePath()) .arg(iteration) .arg(gamma) .arg(expectedLuminance) .arg(targetLuminance) .arg(std::abs(expectedLuminance - targetLuminance)) << endl; } img.gamma(gamma); if (debugView) { original.transform( Magick::Geometry(original.columns(), original.rows()), Magick::Geometry(original.columns() / 2, original.rows()) ); img.composite(original, 0, 0, Magick::DissolveCompositeOp); } //img.brightnessContrast(brighnessChange, /* contrast */0.0); emit input(info, img); }
void Magick::gammaImage::operator()( Magick::Image &image_ ) const { image_.gamma( _gammaRed, _gammaGreen, _gammaBlue ); }