[xiph-cvs] cvs commit: w3d/tools/psnr error.c error.d error.h error.o image_ops.c image_ops.d image_ops.h image_ops.o makefile pnmio.c pnmio.d pnmio.h pnmio.o psnr psnr.c psnr.d psnr.o psnr_seq psnr_seq.c psnr_seq.d psnr_seq.o

Holger Waechtler holger at xiph.org
Tue Aug 7 08:03:38 PDT 2001



holger      01/08/07 08:03:37

  Added:       tools/psnr error.c error.d error.h error.o image_ops.c
                        image_ops.d image_ops.h image_ops.o makefile
                        pnmio.c pnmio.d pnmio.h pnmio.o psnr psnr.c psnr.d
                        psnr.o psnr_seq psnr_seq.c psnr_seq.d psnr_seq.o
  Log:
   - these psnr tools were contributed by Trent and Simon some while ago
     sorry for not committing then earlier !!!

Revision  Changes    Path
1.1                  w3d/tools/psnr/error.c

Index: error.c
===================================================================
/*  very simple error handling functions */

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#include "error.h"

/* print "ERROR: " followed by error msg "fmt", a printf style format string */
void
error(char *fmt, ...)
{
        va_list ap;

        (void) fflush(stdout);
        fprintf(stderr, "ERROR: ");

        va_start(ap, fmt);
        (void) vfprintf(stderr, fmt, ap);
        va_end(ap);

        (void) putc('\n', stderr);
}

/* call error and die */
void
fatal(char *fmt, ...)
{
        va_list ap;

        (void) fflush(stdout);
        fprintf(stderr, "ERROR: ");

        va_start(ap, fmt);
        (void) vfprintf(stderr, fmt, ap);
        va_end(ap);

        (void) putc('\n', stderr);
        exit(EXIT_FAILURE);
}

void *
emalloc(size_t size)
{
        register void *p = malloc(size);

        if (p == 0)
                fatal("out of memory");
        return p;
}

void *
erealloc(void *ptr, size_t size)
{
        if (0 == ptr)
                return emalloc(size);
        if (0 == size) {
                free(ptr);
                return 0;
        }
        ptr = realloc(ptr, size);
        if (0 == ptr)
                fatal("out of memory");

        return ptr;
}

FILE *
efopen(const char *path, const char *mode)
{
        FILE *p = fopen(path, mode);
        if (p == 0) {
                perror("efopen");
                error("unable to open file: %s", path);
        }
        return p;
}

1.1                  w3d/tools/psnr/error.d

Index: error.d
===================================================================
error.o error.d : error.c error.h

1.1                  w3d/tools/psnr/error.h

Index: error.h
===================================================================
#ifndef error_h
#define error_h

void error(char *fmt, ...);
void fatal(char *fmt, ...);

void *emalloc(size_t size);
void *erealloc(void *ptr, size_t size);
FILE *efopen(const char *path, const char *mode);

#endif

1.1                  w3d/tools/psnr/error.o

Index: error.o
===================================================================
ELF
èüÿÿÿƒÄÉÍv
èüÿÿÿƒÄƒÄôjèüÿÿÿƒÄÉÉöU‰åƒìSƒÄô‹EPèüÿÿÿƒÄ‰À‰Ã…ÛuƒÄôh



$
11,9)=(2,2)

1.1                  w3d/tools/psnr/image_ops.c

Index: image_ops.c
===================================================================
#include <math.h>
#include "image_ops.h"

inline double
mse(unsigned char *p1, unsigned char *p2, size_t length)
{
        int i;
        double tmp, err = 0;

        for (i = 0; i < length; ++i,++p1,++p2) {
                tmp = *p1 - *p2;
                err += tmp*tmp;		
        }

        return err/length;
}

inline double
rmse(unsigned char *p1, unsigned char *p2, size_t length)
{
        return sqrt(mse(p1,p2,length));
}

inline double
psnr(unsigned char *p1, unsigned char *p2, size_t length, size_t maxval)
{	
        return 10*log10(maxval*maxval/mse(p1,p2,length));
}

1.1                  w3d/tools/psnr/image_ops.d

Index: image_ops.d
===================================================================
image_ops.o image_ops.d : image_ops.c image_ops.h

1.1                  w3d/tools/psnr/image_ops.h

Index: image_ops.h
===================================================================
#ifndef image_ops_h
#define image_ops_h

#include <stdlib.h>

double mse(unsigned char *p1, unsigned char *p2, size_t  length);
double rmse(unsigned char *p1, unsigned char *p2, size_t length);
double psnr(unsigned char *p1, unsigned char *p2, size_t length, size_t maxval);

#endif

1.1                  w3d/tools/psnr/image_ops.o

Index: image_ops.o
===================================================================
ELF

1.1                  w3d/tools/psnr/makefile

Index: makefile
===================================================================
RM              =	rm
#CFLAGS          =  -O2 
CFLAGS          =  -g -Wall 
LDLIBS	= -lm

COMMON_SRCS = error.c pnmio.c image_ops.c 
SRCS =  psnr.c  psnr_seq.c  $(COMMON_SRCS)
COMMON_OBJS =  $(COMMON_SRCS:%.c=%.o)
OBJS =  $(SRCS:%.c=%.o) $(COMMON_OBJS)
PROGS = psnr psnr_seq

ALL_DEP = $(SRCS:%.c=%.d)

all: bin

bin: $(PROGS)

$(PROGS) : %: %.o $(COMMON_OBJS)
        $(LINK.o) $^ $(LDLIBS) -o $@

clean:
        $(RM) -f $(OBJS) 
        $(RM) -f $(PROGS)

veryclean: clean
        $(RM) -f core TAGS
        $(RM) -f $(ALL_DEP)

realclean: veryclean
        $(RM) -f *.out *.pgm *~

#automate dependancies
DEPENDS.c = $(CC) -MM $(CFLAGS) $(CPPFLAGS)

%.d: %.c
        $(DEPENDS.c) $< \
                | sed "s#\(.*\.o\)[ :]*#\1 $@ : #" > $@; \
                [ -s $@ ] || rm -f $@

ifneq (clean,$(findstring clean,$(MAKECMDGOALS)))
include $(ALL_DEP)
endif

1.1                  w3d/tools/psnr/pnmio.c

Index: pnmio.c
===================================================================
#include <stdio.h>
#include <ctype.h>

int
eat_ws_comments(FILE *fp)
{
        int c;
        
        while( (c = fgetc(fp)) != EOF) {
                if( c == '#') {/* eat the comment */
                        do {
                                c = fgetc(fp);
                                if( c == EOF) /* but bail if we hit EOF */
                                        return EOF;
                        } while ( c != '\n');
                }
                
                if (!isspace(c)) /*we are done*/
                        return ungetc(c,fp);
        }
        
        return EOF;  /* fell out of the loop*/
}

/* this is a kludge, but raw pnm's are not well defined... */
int
eat_ws_to_eol(FILE *fp)
{
        int c;
        do {
                c = fgetc(fp);
                if( c == '\n' || c == '\r') /* some dos/win pnms generated with just '\r' after maxval */
                        return c;
        } while(isspace(c));

        return ungetc(c,fp);
}

int
write_pnm_header(FILE *fp, size_t type, size_t w, size_t h, size_t maxval, char *comment)
{
        if(comment)	   
                return fprintf(fp,"P%c\n%s\n%lu %lu\n%lu\n",type,comment,w,h,maxval);
        else
                return fprintf(fp,"P%c\n%lu %lu\n%lu\n",type,w,h,maxval);
}

int
read_pnm_header(FILE *fp, size_t *type, size_t *w, size_t *h, size_t *maxval)
{
        if(fgetc(fp) != 'P')
                return 0;
        *type = fgetc(fp);
        switch(*type){
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
                break;
        default: /*invalid type if not above*/
                return 0; 
        }

        eat_ws_comments(fp);
        fscanf(fp,"%d",w);
        eat_ws_comments(fp);
        fscanf(fp,"%d",h);
        eat_ws_comments(fp);
        fscanf(fp,"%d",maxval);	
        eat_ws_to_eol(fp);	

        return 1; /* valid file found */
}

int
read_ppm(FILE *fp, char *buf,size_t *w, size_t *h, size_t *m)
{
        size_t type,width,height,maxval;

        if (!read_pnm_header(fp,&width,&height,&maxval,&type) || type != '6')
                return 0;

        if ( fread(buf,3,width*height,fp) != width*height)
                return 0;

        *w=width; *h=height; *m=maxval;
        return 1;
}

int
read_pgm(FILE *fp, char *buf,size_t *w, size_t *h, size_t *m)
{
        size_t type,width,height,maxval;

        if (!read_pnm_header(fp,&width,&height,&maxval,&type) || type != '5')
                return 0;

        if ( fread(buf,1,width*height,fp) != width*height)
                return 0;

        *w=width; *h=height; *m=maxval;
        return 1;
}

1.1                  w3d/tools/psnr/pnmio.d

Index: pnmio.d
===================================================================
pnmio.o pnmio.d : pnmio.c

1.1                  w3d/tools/psnr/pnmio.h

Index: pnmio.h
===================================================================
#ifndef pnmio_h
#define pnmio_h

#define PNM_BITMAP '1'
#define PNM_GRAYSCALE '2'
#define PNM_PIXMAP '3'
#define PNM_RAW_BITMAP '4'
#define PNM_RAW_GRAYSCALE '5'
#define PNM_RAW_PIXMAP '6'

int read_pnm_header(FILE *fp, size_t *type, size_t *w, size_t *h, size_t *maxval);
int write_pnm_header(FILE *fp, size_t type, size_t w, size_t h, size_t maxval, char *comment);
int read_ppm(FILE *fp, char *buf,size_t *w, size_t *h, size_t *maxval);
int read_pgm(FILE *fp, char *buf,size_t *w, size_t *h, size_t *maxval);
#endif

1.1                  w3d/tools/psnr/pnmio.o

Index: pnmio.o
===================================================================
ELF
u	ë	´&
tƒ}ü
të‹Uü‰ÐëDt&



s/stdio_lim.h
%s
%lu %lu
%lu

%lu %lu
%lu

1.1                  w3d/tools/psnr/psnr

Index: psnr
===================================================================
ELF

ëDƒøt>ë<ƒÄüÝ…¸ßÿÿƒìÝ$hÊ–èøúÿÿƒÄëKƒÄüÝ…¸ßÿÿƒìÝ$hÍ–èÚúÿÿƒÄë-ƒÄôÝ…¸ßÿÿƒìÝ$…ÔßÿÿP…ÔïÿÿPhÙ–è®úÿÿƒÄ ë1Àë
è¬ùÿÿƒÄÉÍv
èHùÿÿƒÄƒÄôjè+ùÿÿƒÄÉÉöU‰åƒìSƒÄô‹EPèqøÿÿƒÄ‰À‰Ã…ÛuƒÄôhh—èeÿÿÿƒÄ‰Øë
u	ë	´&
tƒ}ü
të‹Uü‰ÐëDt&

%s
%lu %lu
%lu

%lu %lu
%lu

H

ushort:t(24,23)=(0,9)
32;__next:(17,28)=*(17,27),128,32;;




1.1                  w3d/tools/psnr/psnr.c

Index: psnr.c
===================================================================
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <math.h>

#include "error.h"
#include "pnmio.h"
#include "image_ops.h"

char *progname = 0;
int verbosity = 0;

void usage();
void load_data(void *data, size_t size, size_t nobj, FILE *fp);

int
main(int argc, char **argv)
{
        int c;
        size_t width0,height0,type0,maxval0;
        size_t width1,height1,type1,maxval1;
        size_t image_size,pixel_size;

        char fname0[FILENAME_MAX] = "";
        char fname1[FILENAME_MAX] = "";
        
        FILE *fp0, *fp1;
        unsigned char *data0, *data1;
        double error;

        progname = argv[0];
        
        while ((c = getopt(argc, argv, "hv")) != EOF) {
                switch (c) {
                case 'v':
                        verbosity++;
                        break;
                case 'h':
                default:
                        usage();
                }
        }

        if (argc - optind != 2)
                usage();
        
        strncpy(fname0, argv[optind], FILENAME_MAX);
        strncpy(fname1, argv[optind+1], FILENAME_MAX);

        if ((fp0=efopen(fname0,"r")) == NULL)
                exit(EXIT_FAILURE);

        if ((fp1=efopen(fname1,"r")) == NULL)
                exit(EXIT_FAILURE);
        
        
        if (!read_pnm_header(fp0, &type0, &width0, &height0, &maxval0))
                fatal("invalid pnm file in file %s", fname0);

        if (!read_pnm_header(fp1, &type1, &width1, &height1, &maxval1))
                fatal("invalid pnm file in file %s", fname1);
        
        if (type0 != type1)
                fatal("pnm files are not of the same type (%c,%c)", type0, type1);

        if (maxval0 != maxval1)
                fatal("pnm files are not of the same maxval (%d,%d)", maxval0, maxval1);
        
        if (width0 != width1)
                fatal("pnm files are not of the same width (%d,%d)", width0, width1);

        if (height0 != height1)
                fatal("pnm files are not of the same height (%d,%d)", height0, height1);

        /*if we get here it we have two valid files of the same type and size*/
        
        image_size = width0*height0;
        switch(type0){
        case PNM_RAW_GRAYSCALE:
                pixel_size = 1;
                break;
        case PNM_RAW_PIXMAP: 
                pixel_size = 3;
                break;
        default:
                fatal("unable to handle pnm type %d", type0);
        }
        
        data0 = (unsigned char *) emalloc(pixel_size*image_size);
        data1 = (unsigned char *) emalloc(pixel_size*image_size);

        load_data(data0,pixel_size,image_size,fp0);
        load_data(data1,pixel_size,image_size,fp1);

        error = psnr(data0,data1,pixel_size*image_size,maxval0);
        switch(verbosity){
        case 0:
                printf("%g",error);
                break;
        case 1:
                printf("psnr is %g\n",error);
                break;
        case 2:
        default:
                printf("psnr between %s and %s is %g\n",fname0, fname1,error);
                break;				
        }
        return 0;
}

void 
usage()
{
        fprintf(stderr,"usage: %s [-vh] file1 file2\n",progname);
        exit(EXIT_FAILURE);
}

void
load_data(void *data, size_t size, size_t nobj, FILE *fp)
{
        size_t len=fread(data,size,nobj,fp);
//	if (fread(data,size,nobj,fp) != nobj){
        if (len != nobj){
                if ( feof(fp))
                        fatal("premature eof in file");
                if (ferror(fp))
                        perror("loading pgm");
                fatal("failed to load file");
        }
}

1.1                  w3d/tools/psnr/psnr.d

Index: psnr.d
===================================================================
psnr.o psnr.d : psnr.c error.h pnmio.h image_ops.h

1.1                  w3d/tools/psnr/psnr.o

Index: psnr.o
===================================================================
ELF
ëDƒøt>ë<ƒÄüÝ…¸ßÿÿƒìÝ$hJ

"
2)=s12_next:(10,3)=*(10,2),0,32;_sbuf:(10,4)=*(1,2),32,32;_pos:(0,1),64,32;;
6,35)

1.1                  w3d/tools/psnr/psnr_seq

Index: psnr_seq
===================================================================
ELF

j
j

è¨ôÿÿƒÄÉÍv
èDôÿÿƒÄƒÄôjè'ôÿÿƒÄÉÉöU‰åƒìSƒÄô‹EPèMóÿÿƒÄ‰À‰Ã…ÛuƒÄôhhžèeÿÿÿƒÄ‰Øë
u	ë	´&
tƒ}ü
të‹Uü‰ÐëDt&

Average PSNR: %g
Best PSNR: %g Frame: %lu
Worst PSNR %g Frame: %lu

%s
%lu %lu
%lu

%lu %lu
%lu

‰‰*‰:‰J‰Z‰j‰z‰Š‰š‰ª‰º‰ʉÚ‰ê‰ú‰


8
:
;

,5)
:1,__GCONV_NODB:2,__GCONV_NOMEM:3,__GCONV_EMPTY_INPUT:4,__GCONV_FULL_OUTPUT:5,__GCONV_ILLEGAL_INPUT:6,__GCONV_INCOMPLETE_INPUT:7,__GCONV_ILLEGAL_DESCRIPTOR:8,__GCONV_INTERNAL_ERROR:9,;



1.1                  w3d/tools/psnr/psnr_seq.c

Index: psnr_seq.c
===================================================================
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <limits.h>
#include <values.h>

#include "error.h"
#include "pnmio.h"
#include "image_ops.h"

char *progname = 0;
int verbosity = 0;

void usage();
int valid_fmt(char *p);
int check_copy(char *fname, const char *fmt, size_t frame);
void load_data(void *data, size_t size, size_t nobj, FILE *fp);

int
main(int argc, char **argv)
{
        int c;
        unsigned long int num_frames = ULONG_MAX;
        unsigned long int initial_frame = 0;
        unsigned long int frame;

        int collect_stats=0;
        double max_psnr=0, min_psnr=DBL_MAX, avg_psnr=0;
        unsigned long int max_frame=0, min_frame=0;

        size_t width,height,type,maxval;
        size_t image_size,pixel_size;
        
        char fmt0[FILENAME_MAX+1] = "";
        char fmt1[FILENAME_MAX+1] = "";
        char fname0[FILENAME_MAX+1] = "";
        char fname1[FILENAME_MAX+1] = "";
        
        FILE *fp0, *fp1;
        unsigned char *data0, *data1;
        double curr_psnr;

        progname = argv[0];
        
        while ((c = getopt(argc, argv, "hvsi:n:")) != EOF) {
                switch (c) {
                case 'v':
                        verbosity++;
                        break;
                case 'i':
                        initial_frame = strtoul(optarg,(char**)NULL,10);
                        break;
                case 'n':
                        num_frames = strtoul(optarg,(char**)NULL,10);
                        break;			
                case 's':
                        collect_stats = 1;
                        break;
                case 'h':
                default:
                        usage();
                }
        }

        if (argc - optind != 2)
                usage();

        
        strncpy(fmt0,argv[optind],FILENAME_MAX);
        strncpy(fmt1,argv[optind+1],FILENAME_MAX);

        if (!valid_fmt(fmt0))
                fatal("invalid format: %s", fmt0);

        if (!valid_fmt(fmt1))
                fatal("invalid format: %s", fmt1);
        
        if (!check_copy(fname0,fmt0,0))
                fatal("filename size exceeded");

        if ((fp0=efopen(fname0,"r")) == NULL)
                exit(EXIT_FAILURE);
        
        if (!read_pnm_header(fp0, &type, &width, &height, &maxval))
                fatal("invalid pnm file in file %s", fname0);

        if (maxval != 255)
                fatal("unable to handle pnm maxval %d", maxval);

        image_size = width*height;
        switch(type){
        case PNM_RAW_GRAYSCALE:
                pixel_size = 1;
                break;
        case PNM_RAW_PIXMAP: 
                pixel_size = 3;
                break;
        default:
                fatal("unable to handle pnm type %d", type);
        }
        
        data0 = (unsigned char *) emalloc(pixel_size*image_size);
        data1 = (unsigned char *) emalloc(pixel_size*image_size);
        fclose(fp0);

        for (frame = initial_frame; frame < initial_frame+num_frames;++frame){
                size_t width0,height0,type0,maxval0;
                size_t width1,height1,type1,maxval1;

                if (!check_copy(fname0,fmt0,frame))
                        fatal("filename size exceeded");

                if (!check_copy(fname1,fmt1,frame))
                        fatal("filename size exceeded");

                if ((fp0=efopen(fname0,"r")) == NULL ||
                        (fp1=efopen(fname1,"r")) == NULL )
                        break;
                
                if (!read_pnm_header(fp0, &type0, &width0, &height0, &maxval0))
                        fatal("invalid pnm file in file %s", fname0);
                if (!read_pnm_header(fp1, &type1, &width1, &height1, &maxval1))
                        fatal("invalid pnm file in file %s", fname1);

                if (type0 != type || width0 != width || height0 != height || maxval0 != maxval)
                        fatal("pnm file %s has incorrect shape or type", fname0);
                if (type1 != type || width1 != width || height1 != height || maxval1 != maxval)
                        fatal("pnm file %s has incorrect shape or type", fname1);
                
                load_data(data0,pixel_size,image_size,fp0);
                load_data(data1,pixel_size,image_size,fp1);
                
                curr_psnr = psnr(data0,data1,pixel_size*image_size,maxval);
                
                switch(verbosity){
                case 0:
                        printf("%g\n",curr_psnr);
                        break;
                case 1:
                        printf("psnr is %g\n",curr_psnr);
                        break;
                case 2:
                default:
                        printf("psnr between %s and %s is %g\n",fname0, fname1,curr_psnr);
                        break;				
                }
                
                if (collect_stats) {
                        avg_psnr+=curr_psnr;
                        if (curr_psnr > max_psnr){
                                max_psnr=curr_psnr;
                                max_frame=frame;
                        } else if (curr_psnr < min_psnr){
                                min_psnr=curr_psnr;
                                min_frame=frame;
                        }
                }

        } /* loop over frames */
        
        if (collect_stats) {
                num_frames = frame - 1 - initial_frame; /* cover case when num_frames not specified */
                avg_psnr/=num_frames;
                
                printf ("Number of frames: %lu\n"
                                "Average PSNR: %g\n"
                                "Best PSNR: %g Frame: %lu\n"
                                "Worst PSNR %g Frame: %lu\n", frame, avg_psnr, max_psnr, max_frame, min_psnr, min_frame);
        }

        free(data0); 
        free(data1); 
        return 0;
}

int
valid_fmt(char *p)
{
        int found_percent=0;
        
        do{
                if (*p == '%'){
                        if (found_percent)
                                return 0;
                        else
                                found_percent=1;
                        ++p;
                        switch(*p){
                        case 'i': /* only accept %i */
                                break;
                        default:
                                return 0;
                        }		
                }			
        } while (*p++ != '\0');
        
        return 1;
}

int
check_copy(char *fname, const char *fmt, size_t frame)
{
        if ( (strlen(fmt) + (unsigned long int) log10(frame) + 1 ) > FILENAME_MAX)
                return 0;

        if (sprintf(fname,fmt,frame) < 0)
                return 0;

        return 1;
}

void 
usage()
{
        fprintf(stderr,"usage: %s [-vhs] [-n num frames] [-i initial frame] template1 template2\n",progname);
        fprintf(stderr,"\t -s: generate statistics\n");
        fprintf(stderr,"\t -v: add verbosity\n");
        fprintf(stderr,"\t template: foo%%i.ppm\n");
        exit(EXIT_FAILURE);
}

void
load_data(void *data, size_t size, size_t nobj, FILE *fp)
{
        if (fread(data,size,nobj,fp) != nobj){
                if ( feof(fp))
                        fatal("premature eof in file");
                if (ferror(fp))
                        perror("loading pgm");
                fatal("failed to load file");
        }
}

1.1                  w3d/tools/psnr/psnr_seq.d

Index: psnr_seq.d
===================================================================
psnr_seq.o psnr_seq.d : psnr_seq.c error.h pnmio.h image_ops.h

1.1                  w3d/tools/psnr/psnr_seq.o

Index: psnr_seq.o
===================================================================
ELF
j
j

'
;
fn:t(10,14)=(10,15)=f(0,1)
,1)

Average PSNR: %g
Best PSNR: %g Frame: %lu
Worst PSNR %g Frame: %lu

--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list