[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üÐëDt&
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üÐëDt&
%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üÐëDt&
Average PSNR: %g
Best PSNR: %g Frame: %lu
Worst PSNR %g Frame: %lu
%s
%lu %lu
%lu
%lu %lu
%lu
*:JZjzªºÊÚêú
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