qjpeg/plugins/PSNR.cpp
author viric@mandarina
Fri, 12 Dec 2008 16:07:09 +0000
changeset 251 4aa28098b2c2
parent 234 e78ee672b1ab
permissions -rw-r--r--
Arreglo un greu problema al càlcul de la PSNR (girava files i columnes)

/*
    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();
}