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