1 | /*
|
---|
2 | * Copyright (c) 2003 Michael Niedermayer <[email protected]>
|
---|
3 | *
|
---|
4 | * This library is free software; you can redistribute it and/or
|
---|
5 | * modify it under the terms of the GNU Lesser General Public
|
---|
6 | * License as published by the Free Software Foundation; either
|
---|
7 | * version 2 of the License, or (at your option) any later version.
|
---|
8 | *
|
---|
9 | * This library is distributed in the hope that it will be useful,
|
---|
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
12 | * Lesser General Public License for more details.
|
---|
13 | *
|
---|
14 | * You should have received a copy of the GNU Lesser General Public
|
---|
15 | * License along with this library; if not, write to the Free Software
|
---|
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
---|
17 | *
|
---|
18 | */
|
---|
19 |
|
---|
20 | #include <stdio.h>
|
---|
21 | #include <stdlib.h>
|
---|
22 | #include <inttypes.h>
|
---|
23 | #include <assert.h>
|
---|
24 |
|
---|
25 | #define F 100
|
---|
26 | #define SIZE 2048
|
---|
27 |
|
---|
28 | uint64_t exp16_table[21]={
|
---|
29 | 65537,
|
---|
30 | 65538,
|
---|
31 | 65540,
|
---|
32 | 65544,
|
---|
33 | 65552,
|
---|
34 | 65568,
|
---|
35 | 65600,
|
---|
36 | 65664,
|
---|
37 | 65793,
|
---|
38 | 66050,
|
---|
39 | 66568,
|
---|
40 | 67616,
|
---|
41 | 69763,
|
---|
42 | 74262,
|
---|
43 | 84150,
|
---|
44 | 108051,
|
---|
45 | 178145,
|
---|
46 | 484249,
|
---|
47 | 3578144,
|
---|
48 | 195360063,
|
---|
49 | 582360139072LL,
|
---|
50 | };
|
---|
51 | #if 1
|
---|
52 | // 16.16 fixpoint exp()
|
---|
53 | static unsigned int exp16(unsigned int a){
|
---|
54 | int i;
|
---|
55 | int out= 1<<16;
|
---|
56 |
|
---|
57 | for(i=19;i>=0;i--){
|
---|
58 | if(a&(1<<i))
|
---|
59 | out= (out*exp16_table[i] + (1<<15))>>16;
|
---|
60 | }
|
---|
61 |
|
---|
62 | return out;
|
---|
63 | }
|
---|
64 | // 16.16 fixpoint log()
|
---|
65 | static int64_t log16(uint64_t a){
|
---|
66 | int i;
|
---|
67 | int out=0;
|
---|
68 |
|
---|
69 | if(a < 1<<16)
|
---|
70 | return -log16((1LL<<32) / a);
|
---|
71 | a<<=16;
|
---|
72 |
|
---|
73 | for(i=20;i>=0;i--){
|
---|
74 | int64_t b= exp16_table[i];
|
---|
75 | if(a<(b<<16)) continue;
|
---|
76 | out |= 1<<i;
|
---|
77 | a = ((a/b)<<16) + (((a%b)<<16) + b/2)/b;
|
---|
78 | }
|
---|
79 | return out;
|
---|
80 | }
|
---|
81 |
|
---|
82 | #endif
|
---|
83 | static uint64_t int_sqrt(uint64_t a)
|
---|
84 | {
|
---|
85 | uint64_t ret=0;
|
---|
86 | int s;
|
---|
87 | uint64_t ret_sq=0;
|
---|
88 |
|
---|
89 | for(s=31; s>=0; s--){
|
---|
90 | uint64_t b= ret_sq + (1ULL<<(s*2)) + (ret<<s)*2;
|
---|
91 | if(b<=a){
|
---|
92 | ret_sq=b;
|
---|
93 | ret+= 1ULL<<s;
|
---|
94 | }
|
---|
95 | }
|
---|
96 | return ret;
|
---|
97 | }
|
---|
98 |
|
---|
99 | int main(int argc,char* argv[]){
|
---|
100 | int i, j;
|
---|
101 | uint64_t sse=0;
|
---|
102 | uint64_t dev;
|
---|
103 | FILE *f[2];
|
---|
104 | uint8_t buf[2][SIZE];
|
---|
105 | uint64_t psnr;
|
---|
106 | int len= argc<4 ? 1 : atoi(argv[3]);
|
---|
107 | int64_t max= (1<<(8*len))-1;
|
---|
108 | int shift= argc<5 ? 0 : atoi(argv[4]);
|
---|
109 |
|
---|
110 | if(argc<3){
|
---|
111 | printf("tiny_psnr <file1> <file2> [<elem size> [<shift>]]\n");
|
---|
112 | return -1;
|
---|
113 | }
|
---|
114 |
|
---|
115 | f[0]= fopen(argv[1], "rb");
|
---|
116 | f[1]= fopen(argv[2], "rb");
|
---|
117 | fseek(f[shift<0], shift < 0 ? -shift : shift, SEEK_SET);
|
---|
118 |
|
---|
119 | for(i=0;;){
|
---|
120 | if( fread(buf[0], SIZE, 1, f[0]) != 1) break;
|
---|
121 | if( fread(buf[1], SIZE, 1, f[1]) != 1) break;
|
---|
122 |
|
---|
123 | for(j=0; j<SIZE; i++,j++){
|
---|
124 | int64_t a= buf[0][j];
|
---|
125 | int64_t b= buf[1][j];
|
---|
126 | if(len==2){
|
---|
127 | a= (int16_t)(a | (buf[0][++j]<<8));
|
---|
128 | b= (int16_t)(b | (buf[1][ j]<<8));
|
---|
129 | }
|
---|
130 | sse += (a-b) * (a-b);
|
---|
131 | }
|
---|
132 | }
|
---|
133 |
|
---|
134 | if(!i) i=1;
|
---|
135 | dev= int_sqrt( ((sse/i)*F*F) + (((sse%i)*F*F) + i/2)/i );
|
---|
136 | if(sse)
|
---|
137 | psnr= ((2*log16(max<<16) + log16(i) - log16(sse))*284619LL*F + (1<<31)) / (1LL<<32);
|
---|
138 | else
|
---|
139 | psnr= 100*F-1; //floating point free infinity :)
|
---|
140 |
|
---|
141 | printf("stddev:%3d.%02d PSNR:%2d.%02d bytes:%d\n",
|
---|
142 | (int)(dev/F), (int)(dev%F),
|
---|
143 | (int)(psnr/F), (int)(psnr%F),
|
---|
144 | i*len);
|
---|
145 | return 0;
|
---|
146 | }
|
---|
147 |
|
---|
148 |
|
---|