/*
QJpegRest - An interactive JPEG decoder, with restoration algorithms
Copyright (C) 2007 Lluís Batlle i Rossell
Please find the license in the provided LICENSE file.
*/
#include <ActionType.h>
#include <MeasureResult.h>
#include <Actions.h>
#include <ActionCreator.h>
#include <ActionManager.h>
#include <GrayImage.h>
#include <cmath>
#include <ARGBImage.h>
#include <cstdio>
#include "PSNR.h"
PSNR::PSNR()
{
name = "PSNR";
}
void PSNR::prepare(const ARGBImage *img1, const ARGBImage *img2)
{
rgbimg1 = img1;
rgbimg2 = img2;
type = ARGB;
}
void PSNR::prepare(const GrayImage *img1, const GrayImage *img2)
{
gray1 = img1;
gray2 = img2;
type = Gray;
}
/* Given an original and an approximation value,
returns Signal_Power/Noise_Power */
static inline int se_single(int original, int approximation)
{
return (original - approximation) * (original - approximation);
}
float PSNR::fromGray()
{
int row, column;
int sum;
sum = 0;
for (row = 0; row < gray1->getHeight(); row++)
for (column = 0; column < gray1->getWidth(); column++)
{
sum += se_single(gray1->getPixel(column, row), gray2->getPixel(column, row));
}
float mean = (float) sum / (float) (gray1->getHeight() * gray1->getWidth());
return 255. / sqrt(mean);
}
void PSNR::fromARGB(float psnrs[3])
{
int row, column;
int sumR, sumG, sumB;
sumR = sumG = sumB = 0;
for (row = 0; row < rgbimg1->getHeight(); row++)
for (column = 0; column < rgbimg1->getWidth(); column++)
{
unsigned int pixel1 = rgbimg1->getIntPixel(column, row);
unsigned int pixel2 = rgbimg2->getIntPixel(column, row);
sumR += se_single(rgbimg1->getR(pixel1), rgbimg2->getR(pixel2));
sumG += se_single(rgbimg1->getG(pixel1), rgbimg2->getG(pixel2));
sumB += se_single(rgbimg1->getB(pixel1), rgbimg2->getB(pixel2));
}
int sizes = rgbimg1->getHeight() * rgbimg1->getWidth();
float meanR = (float) sumR / (float) sizes;
float meanG = (float) sumG / (float) sizes;
float meanB = (float) sumB / (float) sizes;
fprintf(stderr,"means: %f %f %f, size: %i\n", meanR, meanG, meanB, sizes);
psnrs[0] = 255. / std::sqrt(meanR);
psnrs[1] = 255. / std::sqrt(meanG);
psnrs[2] = 255. / std::sqrt(meanB);
}
MeasureResult * PSNR::apply()
{
MeasureResult *res = new MeasureResult();
if (type == Gray)
{
res->text += QString("Gray: \%1 dB\n").arg(fromGray());
} else {
float psnrs[3];
fromARGB(psnrs);
res->text += QString("Red: \%1 dB\n").arg(psnrs[0]);
res->text += QString("Green: \%1 dB\n").arg(psnrs[1]);
res->text += QString("Blue: \%1 dB\n").arg(psnrs[2]);
}
return res;
}
PSNRCreator::PSNRCreator()
{
type = e_Compare;
}
bool PSNRCreator::isapplicable(const JPEGParameters &p)
{
return true;
}
void PSNRCreator::init()
{
ActionCreator *a = new PSNRCreator();
ActionManager::sreg("PSNR", a);
}
Compare * PSNRCreator::createCompare() const
{
return new PSNR();
}