// Time-stamp: <03.06.1999, 19:07:25, mrz@isun34>
/**
* (C) 1999 René Scholz, <www.thur.de/~Voland/>
*
*
* Bestimmt die Bild-Differenz zweier PGM5-Bilder
* und gibt diesen als RMSE-Wert und PSNR-Wert aus.
*
* Außerdem kann das Differenzbild (ABS der Grauwerte der entsprechenden
* Pixel) in eine Datei geschrieben werden.
*
* Es wird zusätzlich noch die Entropie der Bilder berechnet, allerdings
* nur 1dim (nach der Def. der Entropie = -\sum p_i ld(p_i) )
*
* Kommentare nach "P5" sind möglich.
@author <A HREF="http://www.thur.de/~Voland/">René Scholz</A>.
@version 1.0
*/
import java.text.*;
import java.util.*;
import java.io.*;
class pgmdiff {
final static String VERSION="1.0";
static boolean Debug=false;
static String Pic1=null;
static String Pic2=null;
static String DiffPic=null;
/** Used for nicer printing of numerical output. */
static NumberFormat form=NumberFormat.getNumberInstance();
public static void main (String args[]) {
form.setMaximumFractionDigits(4);
form.setMinimumFractionDigits(4);
form.setGroupingUsed(false);
scan_options(args);
PicData P1=new PicData(Pic1); P1.Dim=1;
PicData P2=new PicData(Pic2); P2.Dim=1;
PicData DP=null;
System.out.println("Reading pictures ...");
pgm.read(P1); pgm.read(P2);
if(P1.X!=P2.X || P1.Y!=P2.Y) {
System.out.println("ERROR: The pictures have not the same dimensions!");
System.exit(-1);
}
if(DiffPic!=null) {
DP=new PicData(DiffPic);
DP.X=P1.X; DP.Y=P1.Y;
DP.Dim=1;
DP.data1D=new byte[DP.X*DP.Y];
DP.Comment="# difference picture of the pictures:\n#\t" + P1.Name +
"\n#\t" + P2.Name + "\n";
}
System.out.println("Calculating ...");
calc_psnr(P1.data1D, P2.data1D, DP);
if(DiffPic!=null) pgm.write(DP);
}
/**
* Methode zum Berechnen der PSNR zweier gleichgroßer Graustufenbilder
(PGM5).
*
* @param ORG Originalbild
* @param OTHER Das andere (entpackte) Bild
* @param dp Das Differenzbild (null falls nicht benutzt)
* @return Die PSNR beider Bilder zueinander.<BR>
(PSNR=Peak Signal Noise Ratio)
Author: René Scholz
*/
public static float calc_psnr(byte[] ORG, byte[] OTHER, PicData dp) {
long sum=0; double rmse=0; double psnr=0;
int pixels=ORG.length;
final double M=0.43429448190325182765d; // Math.log ist ln != log_10
int Max_Gray_Value=0;
int Hellster_Pixel=0;
int A; int B;
int t;
if(dp==null)
for(int i=0; i<pixels; i++) {
t=ORG[i] - OTHER[i];
sum+=t*t;
}
else {
for(int i=0; i<pixels; i++) {
A=ORG[i]; B=OTHER[i];
t=(A>=B) ? A-B : B-A;
/*
// Code needed for calculating entrophy:
if(A>Max_Gray_Value) Max_Gray_Value=A;
if(B>Max_Gray_Value) Max_Gray_Value=B;
*/
sum+=t*t;
if(t>Hellster_Pixel) Hellster_Pixel=t;
dp.data1D[i]=(byte)(t-128);
}
if(Hellster_Pixel<=0) Hellster_Pixel=1;
if(Hellster_Pixel>255) Hellster_Pixel=255;
dp.Colors=Hellster_Pixel;
}
rmse=Math.sqrt((double)sum / (double)pixels);
if(rmse>0) psnr=20.0d*M*Math.log(255.0d / rmse);
else psnr=0;
System.out.println("\nRMSE: " + form.format(rmse));
if(psnr!=0)
System.out.println("PSNR: " + form.format(psnr));
else
System.out.println("PSNR: Inf");
return((float)psnr);
}
/** Shows the possible options for the command line. */
static void show_options () {
System.out.println("\nVersion: " +VERSION);
System.out.println("Usage: java pgmdiff -p1 picture1 -p2 picture2 [Optionen]\n");
System.out.println("Options:\n");
System.out.println(" -h | --help Show this help.");
System.out.println(" -p1 <pic1> Read picture 1 from file <pic1>.");
System.out.println(" -p2 <pic2> Read picture 2 from file <pic2>.");
System.out.println(" [-dp diffpic] Write the difference picture <diffpic> (as PGM5).");
//System.out.println("-debug Anzeige von Debug-Informationen.");
}
/**
Reads the command line input from the user and checks for
bad parameter constallations.
@param <TT>args[]</TT> The arguments from the command line.
*/
static void scan_options (String args[]) {
String s; int L=args.length;
if(L==0) { show_options(); System.exit(1); }
//System.out.println("args.length="+L);
for(int i=0; i<L; i++) {
//System.out.println("ARG["+i+"]="+args[i]);
s=args[i];
//System.out.println("ARG["+i+"]="+s);
if(s.compareTo("-debug")==0) { Debug=true; continue; }
if(s.compareTo("-h")==0 || s.compareTo("--help")==0)
{ show_options(); System.exit(0); }
if(s.compareTo("-p1")==0) {
if(++i<L) Pic1=args[i];
else {
System.err.println("ERROR: Filename of picture 1 missing!");
show_options(); System.exit(1);
}
continue;
}
if(s.compareTo("-p2")==0) {
if(++i<L) Pic2=args[i];
else {
System.err.println("ERROR: Filename of picture 2 missing!");
show_options(); System.exit(1);
}
continue;
}
if(s.compareTo("-dp")==0) {
if(++i<L) DiffPic=args[i];
else {
System.err.println("ERROR: Filename of diffpic missing!");
show_options(); System.exit(1);
}
continue;
}
// else it's a wrong option:
System.err.println("\nERROR: wrong option "+s+" !\n\n");
show_options(); System.exit(1);
}
// Nachbearbeitungen:
if(Pic1==null) {
System.err.println("ERROR: Filename of picture 1 missing!");
show_options(); System.exit(1);
}
if(Pic2==null) {
System.err.println("ERROR: Filename of picture 2 missing!");
show_options(); System.exit(1);
}
}
}