]> git.xonotic.org Git - xonotic/xonotic.git/blob - misc/tools/fft-normalmap-to-heightmap.c
e025150b64448bdc2404e489cd1a1cadcedaa229
[xonotic/xonotic.git] / misc / tools / fft-normalmap-to-heightmap.c
1 /*
2  *  FFT based normalmap to heightmap converter
3  *  Copyright (C) 2010  Rudolf Polzer
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #undef C99
21 #if __STDC_VERSION__ >= 199901L
22 #define C99
23 #endif
24
25 #ifdef C99
26 #include <complex.h>
27 #endif
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33
34 #include <fftw3.h>
35
36 #define TWO_PI (4*atan2(1,1) * 2)
37
38 int floatcmp(const void *a_, const void *b_)
39 {
40         float a = *(float *)a_;
41         float b = *(float *)b_;
42         if(a < b)
43                 return -1;
44         if(a > b)
45                 return +1;
46         return 0;
47 }
48
49 void nmap_to_hmap(unsigned char *map, const unsigned char *refmap, int w, int h, double scale, double offset, const double *filter, int filterw, int filterh, int renormalize, double highpass, int use_median)
50 {
51         int x, y;
52         int i, j;
53         double fx, fy;
54         double ffx, ffy;
55         double nx, ny, nz;
56         double v, vmin, vmax;
57 #ifndef C99
58         double save;
59 #endif
60
61         fftw_complex *imgspace1 = fftw_malloc(w*h * sizeof(fftw_complex));
62         fftw_complex *imgspace2 = fftw_malloc(w*h * sizeof(fftw_complex));
63         fftw_complex *freqspace1 = fftw_malloc(w*h * sizeof(fftw_complex));
64         fftw_complex *freqspace2 = fftw_malloc(w*h * sizeof(fftw_complex));
65         fftw_plan i12f1 = fftw_plan_dft_2d(h, w, imgspace1, freqspace1, FFTW_FORWARD, FFTW_ESTIMATE);
66         fftw_plan i22f2 = fftw_plan_dft_2d(h, w, imgspace2, freqspace2, FFTW_FORWARD, FFTW_ESTIMATE);
67         fftw_plan f12i1 = fftw_plan_dft_2d(h, w, freqspace1, imgspace1, FFTW_BACKWARD, FFTW_ESTIMATE);
68
69         for(y = 0; y < h; ++y)
70         for(x = 0; x < w; ++x)
71         {
72                 /*
73                  * unnormalized normals:
74                  * n_x = -dh/dx
75                  * n_y = -dh/dy
76                  * n_z = -dh/dh = -1
77                  * BUT: darkplaces uses inverted normals, n_y actually is dh/dy by image pixel coordinates
78                  */
79                 nx = ((int)map[(w*y+x)*4+2] - 127.5) / 128;
80                 ny = ((int)map[(w*y+x)*4+1] - 127.5) / 128;
81                 nz = ((int)map[(w*y+x)*4+0] - 127.5) / 128;
82
83                 /* reconstruct the derivatives from here */
84 #ifdef C99
85                 imgspace1[(w*y+x)] =  nx / nz * w; /* = dz/dx */
86                 imgspace2[(w*y+x)] = -ny / nz * h; /* = dz/dy */
87 #else
88                 imgspace1[(w*y+x)][0] =  nx / nz * w; /* = dz/dx */
89                 imgspace1[(w*y+x)][1] = 0;
90                 imgspace2[(w*y+x)][0] = -ny / nz * h; /* = dz/dy */
91                 imgspace2[(w*y+x)][1] = 0;
92 #endif
93
94                 if(renormalize)
95                 {
96                         double v = nx * nx + ny * ny + nz * nz;
97                         if(v > 0)
98                         {
99                                 v = 1/sqrt(v);
100                                 nx *= v;
101                                 ny *= v;
102                                 nz *= v;
103                                 map[(w*y+x)*4+2] = floor(nx * 127.5 + 128);
104                                 map[(w*y+x)*4+1] = floor(ny * 127.5 + 128);
105                                 map[(w*y+x)*4+0] = floor(nz * 127.5 + 128);
106                         }
107                 }
108         }
109
110         /* see http://www.gamedev.net/community/forums/topic.asp?topic_id=561430 */
111
112         fftw_execute(i12f1);
113         fftw_execute(i22f2);
114         
115         for(y = 0; y < h; ++y)
116         for(x = 0; x < w; ++x)
117         {
118                 fx = x * 1.0 / w;
119                 fy = y * 1.0 / h;
120                 if(fx > 0.5)
121                         fx -= 1;
122                 if(fy > 0.5)
123                         fy -= 1;
124                 if(filter)
125                 {
126                         // discontinous case
127                         // we must invert whatever "filter" would do on (x, y)!
128 #ifdef C99
129                         fftw_complex response_x = 0;
130                         fftw_complex response_y = 0;
131                         double sum;
132                         for(i = -filterh / 2; i <= filterh / 2; ++i)
133                                 for(j = -filterw / 2; j <= filterw / 2; ++j)
134                                 {
135                                         response_x += filter[(i + filterh / 2) * filterw + j + filterw / 2] * cexp(-_Complex_I * TWO_PI * (j * fx + i * fy));
136                                         response_y += filter[(i + filterh / 2) * filterw + j + filterw / 2] * cexp(-_Complex_I * TWO_PI * (i * fx + j * fy));
137                                 }
138
139                         // we know:
140                         //   fourier(df/dx)_xy = fourier(f)_xy * response_x
141                         //   fourier(df/dy)_xy = fourier(f)_xy * response_y
142                         // mult by conjugate of response_x, response_y:
143                         //   conj(response_x) * fourier(df/dx)_xy = fourier(f)_xy * |response_x^2|
144                         //   conj(response_y) * fourier(df/dy)_xy = fourier(f)_xy * |response_y^2|
145                         // and
146                         //   fourier(f)_xy = (conj(response_x) * fourier(df/dx)_xy + conj(response_y) * fourier(df/dy)_xy) / (|response_x|^2 + |response_y|^2)
147
148                         sum = cabs(response_x) * cabs(response_x) + cabs(response_y) * cabs(response_y);
149
150                         if(sum > 0)
151                                 freqspace1[(w*y+x)] = (conj(response_x) * freqspace1[(w*y+x)] + conj(response_y) * freqspace2[(w*y+x)]) / sum;
152                         else
153                                 freqspace1[(w*y+x)] = 0;
154 #else
155                         fftw_complex response_x = {0, 0};
156                         fftw_complex response_y = {0, 0};
157                         double sum;
158                         for(i = -filterh / 2; i <= filterh / 2; ++i)
159                                 for(j = -filterw / 2; j <= filterw / 2; ++j)
160                                 {
161                                         response_x[0] += filter[(i + filterh / 2) * filterw + j + filterw / 2] * cos(-TWO_PI * (j * fx + i * fy));
162                                         response_x[1] += filter[(i + filterh / 2) * filterw + j + filterw / 2] * sin(-TWO_PI * (j * fx + i * fy));
163                                         response_y[0] += filter[(i + filterh / 2) * filterw + j + filterw / 2] * cos(-TWO_PI * (i * fx + j * fy));
164                                         response_y[1] += filter[(i + filterh / 2) * filterw + j + filterw / 2] * sin(-TWO_PI * (i * fx + j * fy));
165                                 }
166
167                         sum = response_x[0] * response_x[0] + response_x[1] * response_x[1]
168                             + response_y[0] * response_y[0] + response_y[1] * response_y[1];
169
170                         if(sum > 0)
171                         {
172                                 double s = freqspace1[(w*y+x)][0];
173                                 freqspace1[(w*y+x)][0] = (response_x[0] * s                      + response_x[1] * freqspace1[(w*y+x)][1] + response_y[0] * freqspace2[(w*y+x)][0] + response_y[1] * freqspace2[(w*y+x)][1]) / sum;
174                                 freqspace1[(w*y+x)][1] = (response_x[0] * freqspace1[(w*y+x)][1] - response_x[1] * s                      + response_y[0] * freqspace2[(w*y+x)][1] - response_y[1] * freqspace2[(w*y+x)][0]) / sum;
175                         }
176                         else
177                         {
178                                 freqspace1[(w*y+x)][0] = 0;
179                                 freqspace1[(w*y+x)][1] = 0;
180                         }
181 #endif
182                 }
183                 else
184                 {
185                         // continuous integration case
186                         /* these must have the same sign as fx and fy (so ffx*fx + ffy*fy is nonzero), otherwise do not matter */
187                         /* it basically decides how artifacts are distributed */
188                         ffx = fx;
189                         ffy = fy;
190 #ifdef C99
191                         if(fx||fy)
192                                 freqspace1[(w*y+x)] = _Complex_I * (ffx * freqspace1[(w*y+x)] + ffy * freqspace2[(w*y+x)]) / (ffx*fx + ffy*fy) / TWO_PI;
193                         else
194                                 freqspace1[(w*y+x)] = 0;
195 #else
196                         if(fx||fy)
197                         {
198                                 save = freqspace1[(w*y+x)][0];
199                                 freqspace1[(w*y+x)][0] = -(ffx * freqspace1[(w*y+x)][1] + ffy * freqspace2[(w*y+x)][1]) / (ffx*fx + ffy*fy) / TWO_PI;
200                                 freqspace1[(w*y+x)][1] =  (ffx * save + ffy * freqspace2[(w*y+x)][0]) / (ffx*fx + ffy*fy) / TWO_PI;
201                         }
202                         else
203                         {
204                                 freqspace1[(w*y+x)][0] = 0;
205                                 freqspace1[(w*y+x)][1] = 0;
206                         }
207 #endif
208                 }
209                 if(highpass > 0)
210                 {
211                         double f1 = (fabs(fx)*highpass);
212                         double f2 = (fabs(fy)*highpass);
213                         // if either of them is < 1, phase out (min at 0.5)
214                         double f =
215                                 (f1 <= 0.5 ? 0 : (f1 >= 1 ? 1 : ((f1 - 0.5) * 2.0)))
216                                 *
217                                 (f2 <= 0.5 ? 0 : (f2 >= 1 ? 1 : ((f2 - 0.5) * 2.0)));
218 #ifdef C99
219                         freqspace1[(w*y+x)] *= f;
220 #else
221                         freqspace1[(w*y+x)][0] *= f;
222                         freqspace1[(w*y+x)][1] *= f;
223 #endif
224                 }
225         }
226
227         fftw_execute(f12i1);
228
229         /* renormalize, find min/max */
230         vmin = vmax = 0;
231         for(y = 0; y < h; ++y)
232         for(x = 0; x < w; ++x)
233         {
234 #ifdef C99
235                 v = creal(imgspace1[(w*y+x)] /= pow(w*h, 1.5));
236 #else
237                 v = (imgspace1[(w*y+x)][0] /= pow(w*h, 1.5));
238                 // imgspace1[(w*y+x)][1] /= pow(w*h, 1.5);
239                 // this value is never used
240 #endif
241                 if(v < vmin || (x == 0 && y == 0))
242                         vmin = v;
243                 if(v > vmax || (x == 0 && y == 0))
244                         vmax = v;
245         }
246
247         if(refmap)
248         {
249                 double f, a;
250                 double o, s;
251                 double sa, sfa, sffa, sfva, sva;
252                 double mi, ma;
253                 sa = sfa = sffa = sfva = sva = 0;
254                 mi = 1;
255                 ma = -1;
256                 for(y = 0; y < h; ++y)
257                 for(x = 0; x < w; ++x)
258                 {
259                         a = (int)refmap[(w*y+x)*4+3];
260                         v = (refmap[(w*y+x)*4+0]*0.114 + refmap[(w*y+x)*4+1]*0.587 + refmap[(w*y+x)*4+2]*0.299);
261                         v = (v - 128.0) / 127.0;
262 #ifdef C99
263                         f = creal(imgspace1[(w*y+x)]);
264 #else
265                         f = imgspace1[(w*y+x)][0];
266 #endif
267                         if(a <= 0)
268                                 continue;
269                         if(v < mi)
270                                 mi = v;
271                         if(v > ma)
272                                 ma = v;
273                         sa += a;
274                         sfa += f*a;
275                         sffa += f*f*a;
276                         sfva += f*v*a;
277                         sva += v*a;
278                 }
279                 if(mi < ma)
280                 {
281                         /* linear regression ftw */
282                         o = (sfa*sfva - sffa*sva) / (sfa*sfa-sa*sffa);
283                         s = (sfa*sva - sa*sfva) / (sfa*sfa-sa*sffa);
284                 }
285                 else /* all values of v are equal, so we cannot get scale; we can still get offset */
286                 {
287                         o = ((sva - sfa) / sa);
288                         s = 1;
289                 }
290
291                 /*
292                  * now apply user-given offset and scale to these values
293                  * (x * s + o) * scale + offset
294                  * x * s * scale + o * scale + offset
295                  */
296                 offset += o * scale;
297                 scale *= s;
298         }
299         else if(scale == 0)
300         {
301                 /*
302                  * map vmin to -1
303                  * map vmax to +1
304                  */
305                 scale = 2 / (vmax - vmin);
306                 offset = -(vmax + vmin) / (vmax - vmin);
307         }
308         else if(use_median)
309         {
310                 // negative scale = match median to offset
311
312                 fprintf(stderr, "Calculating median...\n");
313
314                 float *medianbuf = malloc(sizeof(float) * w * h);
315                 float vmed;
316
317                 fprintf(stderr, "  converting...\n");
318                 /* renormalize, find min/max */
319                 for(y = 0; y < h; ++y)
320                 for(x = 0; x < w; ++x)
321                 {
322 #ifdef C99
323                         v = creal(imgspace1[(w*y+x)]);
324 #else
325                         v = (imgspace1[(w*y+x)][0]);
326 #endif
327                         medianbuf[w*y+x] = v;
328                 }
329                 fprintf(stderr, "  sorting...\n");
330                 qsort(medianbuf, w*h, sizeof(*medianbuf), floatcmp);
331                 fprintf(stderr, "  done.\n");
332                 if(w*h % 2)
333                         vmed = medianbuf[(w*h-1)/2];
334                 else
335                         vmed = (medianbuf[(w*h)/2] + medianbuf[(w*h-2)/2]) * 0.5;
336
337                 // we actually want (v - vmed) * scale + offset
338                 offset -= vmed * scale;
339         }
340
341         printf("Min: %f\nAvg: %f\nMax: %f\nScale: %f\nOffset: %f\nScaled-Min: %f\nScaled-Avg: %f\nScaled-Max: %f\n", 
342                 vmin, 0.0, vmax, scale, offset, vmin * scale + offset, offset, vmax * scale + offset);
343
344         for(y = 0; y < h; ++y)
345         for(x = 0; x < w; ++x)
346         {
347 #ifdef C99
348                 v = creal(imgspace1[(w*y+x)]);
349 #else
350                 v = imgspace1[(w*y+x)][0];
351 #endif
352                 v = v * scale + offset;
353                 if(v < -1)
354                         v = -1;
355                 if(v > 1)
356                         v = 1;
357                 map[(w*y+x)*4+3] = floor(128.5 + 127 * v);
358         }
359
360         fftw_destroy_plan(i12f1);
361         fftw_destroy_plan(i22f2);
362         fftw_destroy_plan(f12i1);
363
364         fftw_free(freqspace2);
365         fftw_free(freqspace1);
366         fftw_free(imgspace2);
367         fftw_free(imgspace1);
368 }
369
370 void hmap_to_nmap(unsigned char *map, int w, int h, int src_chan, double scale)
371 {
372         int x, y;
373         double fx, fy;
374         double nx, ny, nz;
375         double v;
376 #ifndef C99
377         double save;
378 #endif
379
380         fftw_complex *imgspace1 = fftw_malloc(w*h * sizeof(fftw_complex));
381         fftw_complex *imgspace2 = fftw_malloc(w*h * sizeof(fftw_complex));
382         fftw_complex *freqspace1 = fftw_malloc(w*h * sizeof(fftw_complex));
383         fftw_complex *freqspace2 = fftw_malloc(w*h * sizeof(fftw_complex));
384         fftw_plan i12f1 = fftw_plan_dft_2d(h, w, imgspace1, freqspace1, FFTW_FORWARD, FFTW_ESTIMATE);
385         fftw_plan f12i1 = fftw_plan_dft_2d(h, w, freqspace1, imgspace1, FFTW_BACKWARD, FFTW_ESTIMATE);
386         fftw_plan f22i2 = fftw_plan_dft_2d(h, w, freqspace2, imgspace2, FFTW_BACKWARD, FFTW_ESTIMATE);
387
388         for(y = 0; y < h; ++y)
389         for(x = 0; x < w; ++x)
390         {
391                 switch(src_chan)
392                 {
393                         case 0:
394                         case 1:
395                         case 2:
396                         case 3:
397                                 v = map[(w*y+x)*4+src_chan];
398                                 break;
399                         case 4:
400                                 v = (map[(w*y+x)*4+0] + map[(w*y+x)*4+1] + map[(w*y+x)*4+2]) / 3;
401                                 break;
402                         default:
403                         case 5:
404                                 v = (map[(w*y+x)*4+0]*0.114 + map[(w*y+x)*4+1]*0.587 + map[(w*y+x)*4+2]*0.299);
405                                 break;
406                 }
407 #ifdef C99
408                 imgspace1[(w*y+x)] = (v - 128.0) / 127.0;
409 #else
410                 imgspace1[(w*y+x)][0] = (v - 128.0) / 127.0;
411                 imgspace1[(w*y+x)][1] = 0;
412 #endif
413                 if(v < 1)
414                         v = 1; /* do not write alpha zero */
415                 map[(w*y+x)*4+3] = floor(v + 0.5);
416         }
417
418         /* see http://www.gamedev.net/community/forums/topic.asp?topic_id=561430 */
419
420         fftw_execute(i12f1);
421         
422         for(y = 0; y < h; ++y)
423         for(x = 0; x < w; ++x)
424         {
425                 fx = x;
426                 fy = y;
427                 if(fx > w/2)
428                         fx -= w;
429                 if(fy > h/2)
430                         fy -= h;
431 #ifdef DISCONTINUOUS
432                 fx = sin(fx * TWO_PI / w);
433                 fy = sin(fy * TWO_PI / h);
434 #else
435 #ifdef C99
436                 /* a lowpass to prevent the worst */
437                 freqspace1[(w*y+x)] *= 1 - pow(abs(fx) / (double)(w/2), 1);
438                 freqspace1[(w*y+x)] *= 1 - pow(abs(fy) / (double)(h/2), 1);
439 #else
440                 /* a lowpass to prevent the worst */
441                 freqspace1[(w*y+x)][0] *= 1 - pow(abs(fx) / (double)(w/2), 1);
442                 freqspace1[(w*y+x)][1] *= 1 - pow(abs(fx) / (double)(w/2), 1);
443                 freqspace1[(w*y+x)][0] *= 1 - pow(abs(fy) / (double)(h/2), 1);
444                 freqspace1[(w*y+x)][1] *= 1 - pow(abs(fy) / (double)(h/2), 1);
445 #endif
446 #endif
447 #ifdef C99
448                 freqspace2[(w*y+x)] = TWO_PI*_Complex_I * fy * freqspace1[(w*y+x)]; /* y derivative */
449                 freqspace1[(w*y+x)] = TWO_PI*_Complex_I * fx * freqspace1[(w*y+x)]; /* x derivative */
450 #else
451                 freqspace2[(w*y+x)][0] = -TWO_PI * fy * freqspace1[(w*y+x)][1]; /* y derivative */
452                 freqspace2[(w*y+x)][1] =  TWO_PI * fy * freqspace1[(w*y+x)][0];
453                 save = freqspace1[(w*y+x)][0];
454                 freqspace1[(w*y+x)][0] = -TWO_PI * fx * freqspace1[(w*y+x)][1]; /* x derivative */
455                 freqspace1[(w*y+x)][1] =  TWO_PI * fx * save;
456 #endif
457         }
458
459         fftw_execute(f12i1);
460         fftw_execute(f22i2);
461
462         scale /= (w*h);
463
464         for(y = 0; y < h; ++y)
465         for(x = 0; x < w; ++x)
466         {
467 #ifdef C99
468                 nx = creal(imgspace1[(w*y+x)]);
469                 ny = creal(imgspace2[(w*y+x)]);
470 #else
471                 nx = imgspace1[(w*y+x)][0];
472                 ny = imgspace2[(w*y+x)][0];
473 #endif
474                 nx /= w;
475                 ny /= h;
476                 nz = -1 / scale;
477                 v = -sqrt(nx*nx + ny*ny + nz*nz);
478                 nx /= v;
479                 ny /= v;
480                 nz /= v;
481                 ny = -ny; /* DP inverted normals */
482                 map[(w*y+x)*4+2] = floor(128 + 127.5 * nx);
483                 map[(w*y+x)*4+1] = floor(128 + 127.5 * ny);
484                 map[(w*y+x)*4+0] = floor(128 + 127.5 * nz);
485         }
486
487         fftw_destroy_plan(i12f1);
488         fftw_destroy_plan(f12i1);
489         fftw_destroy_plan(f22i2);
490
491         fftw_free(freqspace2);
492         fftw_free(freqspace1);
493         fftw_free(imgspace2);
494         fftw_free(imgspace1);
495 }
496
497 void hmap_to_nmap_local(unsigned char *map, int w, int h, int src_chan, double scale, const double *filter, int filterw, int filterh)
498 {
499         int x, y;
500         double nx, ny, nz;
501         double v;
502         int i, j;
503         double *img_reduced = malloc(w*h * sizeof(double));
504
505         for(y = 0; y < h; ++y)
506         for(x = 0; x < w; ++x)
507         {
508                 switch(src_chan)
509                 {
510                         case 0:
511                         case 1:
512                         case 2:
513                         case 3:
514                                 v = map[(w*y+x)*4+src_chan];
515                                 break;
516                         case 4:
517                                 v = (map[(w*y+x)*4+0] + map[(w*y+x)*4+1] + map[(w*y+x)*4+2]) / 3;
518                                 break;
519                         default:
520                         case 5:
521                                 v = (map[(w*y+x)*4+0]*0.114 + map[(w*y+x)*4+1]*0.587 + map[(w*y+x)*4+2]*0.299);
522                                 break;
523                 }
524                 img_reduced[(w*y+x)] = (v - 128.0) / 127.0;
525                 if(v < 1)
526                         v = 1; /* do not write alpha zero */
527                 map[(w*y+x)*4+3] = floor(v + 0.5);
528         }
529
530         for(y = 0; y < h; ++y)
531         for(x = 0; x < w; ++x)
532         {
533                 nz = -1 / scale;
534                 nx = ny = 0;
535
536                 for(i = -filterh / 2; i <= filterh / 2; ++i)
537                         for(j = -filterw / 2; j <= filterw / 2; ++j)
538                         {
539                                 nx += img_reduced[w*((y+i+h)%h)+(x+j+w)%w] * filter[(i + filterh / 2) * filterw + j + filterw / 2];
540                                 ny += img_reduced[w*((y+j+h)%h)+(x+i+w)%w] * filter[(i + filterh / 2) * filterw + j + filterw / 2];
541                         }
542
543                 v = -sqrt(nx*nx + ny*ny + nz*nz);
544                 nx /= v;
545                 ny /= v;
546                 nz /= v;
547                 ny = -ny; /* DP inverted normals */
548                 map[(w*y+x)*4+2] = floor(128 + 127.5 * nx);
549                 map[(w*y+x)*4+1] = floor(128 + 127.5 * ny);
550                 map[(w*y+x)*4+0] = floor(128 + 127.5 * nz);
551         }
552
553         free(img_reduced);
554 }
555
556 unsigned char *FS_LoadFile(const char *fn, int *len)
557 {
558         unsigned char *buf = NULL;
559         int n;
560         FILE *f = fopen(fn, "rb");
561         *len = 0;
562         if(!f)
563                 return NULL;
564         for(;;)
565         {
566                 buf = realloc(buf, *len + 65536);
567                 if(!buf)
568                 {
569                         fclose(f);
570                         free(buf);
571                         *len = 0;
572                         return NULL;
573                 }
574                 n = fread(buf + *len, 1, 65536, f);
575                 if(n < 0)
576                 {
577                         fclose(f);
578                         free(buf);
579                         *len = 0;
580                         return NULL;
581                 }
582                 *len += n;
583                 if(n < 65536)
584                         break;
585         }
586         return buf;
587 }
588
589 int FS_WriteFile(const char *fn, unsigned char *data, int len)
590 {
591         FILE *f = fopen(fn, "wb");
592         if(!f)
593                 return 0;
594         if(fwrite(data, len, 1, f) != 1)
595         {
596                 fclose(f);
597                 return 0;
598         }
599         if(fclose(f))
600                 return 0;
601         return 1;
602 }
603
604 /* START stuff that originates from image.c in DarkPlaces */
605 int image_width, image_height;
606
607 typedef struct _TargaHeader
608 {
609         unsigned char   id_length, colormap_type, image_type;
610         unsigned short  colormap_index, colormap_length;
611         unsigned char   colormap_size;
612         unsigned short  x_origin, y_origin, width, height;
613         unsigned char   pixel_size, attributes;
614 }
615 TargaHeader;
616
617 void PrintTargaHeader(TargaHeader *t)
618 {
619         printf("TargaHeader:\nuint8 id_length = %i;\nuint8 colormap_type = %i;\nuint8 image_type = %i;\nuint16 colormap_index = %i;\nuint16 colormap_length = %i;\nuint8 colormap_size = %i;\nuint16 x_origin = %i;\nuint16 y_origin = %i;\nuint16 width = %i;\nuint16 height = %i;\nuint8 pixel_size = %i;\nuint8 attributes = %i;\n", t->id_length, t->colormap_type, t->image_type, t->colormap_index, t->colormap_length, t->colormap_size, t->x_origin, t->y_origin, t->width, t->height, t->pixel_size, t->attributes);
620 }
621
622 unsigned char *LoadTGA_BGRA (const unsigned char *f, int filesize)
623 {
624         int x, y, pix_inc, row_inci, runlen, alphabits;
625         unsigned char *image_buffer;
626         unsigned int *pixbufi;
627         const unsigned char *fin, *enddata;
628         TargaHeader targa_header;
629         unsigned int palettei[256];
630         union
631         {
632                 unsigned int i;
633                 unsigned char b[4];
634         }
635         bgra;
636
637         if (filesize < 19)
638                 return NULL;
639
640         enddata = f + filesize;
641
642         targa_header.id_length = f[0];
643         targa_header.colormap_type = f[1];
644         targa_header.image_type = f[2];
645
646         targa_header.colormap_index = f[3] + f[4] * 256;
647         targa_header.colormap_length = f[5] + f[6] * 256;
648         targa_header.colormap_size = f[7];
649         targa_header.x_origin = f[8] + f[9] * 256;
650         targa_header.y_origin = f[10] + f[11] * 256;
651         targa_header.width = image_width = f[12] + f[13] * 256;
652         targa_header.height = image_height = f[14] + f[15] * 256;
653         targa_header.pixel_size = f[16];
654         targa_header.attributes = f[17];
655
656         if (image_width > 32768 || image_height > 32768 || image_width <= 0 || image_height <= 0)
657         {
658                 printf("LoadTGA: invalid size\n");
659                 PrintTargaHeader(&targa_header);
660                 return NULL;
661         }
662
663         /* advance to end of header */
664         fin = f + 18;
665
666         /* skip TARGA image comment (usually 0 bytes) */
667         fin += targa_header.id_length;
668
669         /* read/skip the colormap if present (note: according to the TARGA spec it */
670         /* can be present even on 1color or greyscale images, just not used by */
671         /* the image data) */
672         if (targa_header.colormap_type)
673         {
674                 if (targa_header.colormap_length > 256)
675                 {
676                         printf("LoadTGA: only up to 256 colormap_length supported\n");
677                         PrintTargaHeader(&targa_header);
678                         return NULL;
679                 }
680                 if (targa_header.colormap_index)
681                 {
682                         printf("LoadTGA: colormap_index not supported\n");
683                         PrintTargaHeader(&targa_header);
684                         return NULL;
685                 }
686                 if (targa_header.colormap_size == 24)
687                 {
688                         for (x = 0;x < targa_header.colormap_length;x++)
689                         {
690                                 bgra.b[0] = *fin++;
691                                 bgra.b[1] = *fin++;
692                                 bgra.b[2] = *fin++;
693                                 bgra.b[3] = 255;
694                                 palettei[x] = bgra.i;
695                         }
696                 }
697                 else if (targa_header.colormap_size == 32)
698                 {
699                         memcpy(palettei, fin, targa_header.colormap_length*4);
700                         fin += targa_header.colormap_length * 4;
701                 }
702                 else
703                 {
704                         printf("LoadTGA: Only 32 and 24 bit colormap_size supported\n");
705                         PrintTargaHeader(&targa_header);
706                         return NULL;
707                 }
708         }
709
710         /* check our pixel_size restrictions according to image_type */
711         switch (targa_header.image_type & ~8)
712         {
713         case 2:
714                 if (targa_header.pixel_size != 24 && targa_header.pixel_size != 32)
715                 {
716                         printf("LoadTGA: only 24bit and 32bit pixel sizes supported for type 2 and type 10 images\n");
717                         PrintTargaHeader(&targa_header);
718                         return NULL;
719                 }
720                 break;
721         case 3:
722                 /* set up a palette to make the loader easier */
723                 for (x = 0;x < 256;x++)
724                 {
725                         bgra.b[0] = bgra.b[1] = bgra.b[2] = x;
726                         bgra.b[3] = 255;
727                         palettei[x] = bgra.i;
728                 }
729                 /* fall through to colormap case */
730         case 1:
731                 if (targa_header.pixel_size != 8)
732                 {
733                         printf("LoadTGA: only 8bit pixel size for type 1, 3, 9, and 11 images supported\n");
734                         PrintTargaHeader(&targa_header);
735                         return NULL;
736                 }
737                 break;
738         default:
739                 printf("LoadTGA: Only type 1, 2, 3, 9, 10, and 11 targa RGB images supported, image_type = %i\n", targa_header.image_type);
740                 PrintTargaHeader(&targa_header);
741                 return NULL;
742         }
743
744         if (targa_header.attributes & 0x10)
745         {
746                 printf("LoadTGA: origin must be in top left or bottom left, top right and bottom right are not supported\n");
747                 return NULL;
748         }
749
750         /* number of attribute bits per pixel, we only support 0 or 8 */
751         alphabits = targa_header.attributes & 0x0F;
752         if (alphabits != 8 && alphabits != 0)
753         {
754                 printf("LoadTGA: only 0 or 8 attribute (alpha) bits supported\n");
755                 return NULL;
756         }
757
758         image_buffer = (unsigned char *)malloc(image_width * image_height * 4);
759         if (!image_buffer)
760         {
761                 printf("LoadTGA: not enough memory for %i by %i image\n", image_width, image_height);
762                 return NULL;
763         }
764
765         /* If bit 5 of attributes isn't set, the image has been stored from bottom to top */
766         if ((targa_header.attributes & 0x20) == 0)
767         {
768                 pixbufi = (unsigned int*)image_buffer + (image_height - 1)*image_width;
769                 row_inci = -image_width*2;
770         }
771         else
772         {
773                 pixbufi = (unsigned int*)image_buffer;
774                 row_inci = 0;
775         }
776
777         x = 0;
778         y = 0;
779         pix_inc = 1;
780         if ((targa_header.image_type & ~8) == 2)
781                 pix_inc = (targa_header.pixel_size + 7) / 8;
782         switch (targa_header.image_type)
783         {
784         case 1: /* colormapped, uncompressed */
785         case 3: /* greyscale, uncompressed */
786                 if (fin + image_width * image_height * pix_inc > enddata)
787                         break;
788                 for (y = 0;y < image_height;y++, pixbufi += row_inci)
789                         for (x = 0;x < image_width;x++)
790                                 *pixbufi++ = palettei[*fin++];
791                 break;
792         case 2:
793                 /* BGR or BGRA, uncompressed */
794                 if (fin + image_width * image_height * pix_inc > enddata)
795                         break;
796                 if (targa_header.pixel_size == 32 && alphabits)
797                 {
798                         for (y = 0;y < image_height;y++)
799                                 memcpy(pixbufi + y * (image_width + row_inci), fin + y * image_width * pix_inc, image_width*4);
800                 }
801                 else
802                 {
803                         for (y = 0;y < image_height;y++, pixbufi += row_inci)
804                         {
805                                 for (x = 0;x < image_width;x++, fin += pix_inc)
806                                 {
807                                         bgra.b[0] = fin[0];
808                                         bgra.b[1] = fin[1];
809                                         bgra.b[2] = fin[2];
810                                         bgra.b[3] = 255;
811                                         *pixbufi++ = bgra.i;
812                                 }
813                         }
814                 }
815                 break;
816         case 9: /* colormapped, RLE */
817         case 11: /* greyscale, RLE */
818                 for (y = 0;y < image_height;y++, pixbufi += row_inci)
819                 {
820                         for (x = 0;x < image_width;)
821                         {
822                                 if (fin >= enddata)
823                                         break; /* error - truncated file */
824                                 runlen = *fin++;
825                                 if (runlen & 0x80)
826                                 {
827                                         /* RLE - all pixels the same color */
828                                         runlen += 1 - 0x80;
829                                         if (fin + pix_inc > enddata)
830                                                 break; /* error - truncated file */
831                                         if (x + runlen > image_width)
832                                                 break; /* error - line exceeds width */
833                                         bgra.i = palettei[*fin++];
834                                         for (;runlen--;x++)
835                                                 *pixbufi++ = bgra.i;
836                                 }
837                                 else
838                                 {
839                                         /* uncompressed - all pixels different color */
840                                         runlen++;
841                                         if (fin + pix_inc * runlen > enddata)
842                                                 break; /* error - truncated file */
843                                         if (x + runlen > image_width)
844                                                 break; /* error - line exceeds width */
845                                         for (;runlen--;x++)
846                                                 *pixbufi++ = palettei[*fin++];
847                                 }
848                         }
849
850                         if (x != image_width)
851                         {
852                                 /* pixbufi is useless now */
853                                 printf("LoadTGA: corrupt file\n");
854                                 break;
855                         }
856                 }
857                 break;
858         case 10:
859                 /* BGR or BGRA, RLE */
860                 if (targa_header.pixel_size == 32 && alphabits)
861                 {
862                         for (y = 0;y < image_height;y++, pixbufi += row_inci)
863                         {
864                                 for (x = 0;x < image_width;)
865                                 {
866                                         if (fin >= enddata)
867                                                 break; /* error - truncated file */
868                                         runlen = *fin++;
869                                         if (runlen & 0x80)
870                                         {
871                                                 /* RLE - all pixels the same color */
872                                                 runlen += 1 - 0x80;
873                                                 if (fin + pix_inc > enddata)
874                                                         break; /* error - truncated file */
875                                                 if (x + runlen > image_width)
876                                                         break; /* error - line exceeds width */
877                                                 bgra.b[0] = fin[0];
878                                                 bgra.b[1] = fin[1];
879                                                 bgra.b[2] = fin[2];
880                                                 bgra.b[3] = fin[3];
881                                                 fin += pix_inc;
882                                                 for (;runlen--;x++)
883                                                         *pixbufi++ = bgra.i;
884                                         }
885                                         else
886                                         {
887                                                 /* uncompressed - all pixels different color */
888                                                 runlen++;
889                                                 if (fin + pix_inc * runlen > enddata)
890                                                         break; /* error - truncated file */
891                                                 if (x + runlen > image_width)
892                                                         break; /* error - line exceeds width */
893                                                 for (;runlen--;x++)
894                                                 {
895                                                         bgra.b[0] = fin[0];
896                                                         bgra.b[1] = fin[1];
897                                                         bgra.b[2] = fin[2];
898                                                         bgra.b[3] = fin[3];
899                                                         fin += pix_inc;
900                                                         *pixbufi++ = bgra.i;
901                                                 }
902                                         }
903                                 }
904
905                                 if (x != image_width)
906                                 {
907                                         /* pixbufi is useless now */
908                                         printf("LoadTGA: corrupt file\n");
909                                         break;
910                                 }
911                         }
912                 }
913                 else
914                 {
915                         for (y = 0;y < image_height;y++, pixbufi += row_inci)
916                         {
917                                 for (x = 0;x < image_width;)
918                                 {
919                                         if (fin >= enddata)
920                                                 break; /* error - truncated file */
921                                         runlen = *fin++;
922                                         if (runlen & 0x80)
923                                         {
924                                                 /* RLE - all pixels the same color */
925                                                 runlen += 1 - 0x80;
926                                                 if (fin + pix_inc > enddata)
927                                                         break; /* error - truncated file */
928                                                 if (x + runlen > image_width)
929                                                         break; /* error - line exceeds width */
930                                                 bgra.b[0] = fin[0];
931                                                 bgra.b[1] = fin[1];
932                                                 bgra.b[2] = fin[2];
933                                                 bgra.b[3] = 255;
934                                                 fin += pix_inc;
935                                                 for (;runlen--;x++)
936                                                         *pixbufi++ = bgra.i;
937                                         }
938                                         else
939                                         {
940                                                 /* uncompressed - all pixels different color */
941                                                 runlen++;
942                                                 if (fin + pix_inc * runlen > enddata)
943                                                         break; /* error - truncated file */
944                                                 if (x + runlen > image_width)
945                                                         break; /* error - line exceeds width */
946                                                 for (;runlen--;x++)
947                                                 {
948                                                         bgra.b[0] = fin[0];
949                                                         bgra.b[1] = fin[1];
950                                                         bgra.b[2] = fin[2];
951                                                         bgra.b[3] = 255;
952                                                         fin += pix_inc;
953                                                         *pixbufi++ = bgra.i;
954                                                 }
955                                         }
956                                 }
957
958                                 if (x != image_width)
959                                 {
960                                         /* pixbufi is useless now */
961                                         printf("LoadTGA: corrupt file\n");
962                                         break;
963                                 }
964                         }
965                 }
966                 break;
967         default:
968                 /* unknown image_type */
969                 break;
970         }
971
972         return image_buffer;
973 }
974
975 int Image_WriteTGABGRA (const char *filename, int width, int height, const unsigned char *data)
976 {
977         int y;
978         unsigned char *buffer, *out;
979         const unsigned char *in, *end;
980         int ret;
981
982         buffer = (unsigned char *)malloc(width*height*4 + 18);
983
984         memset (buffer, 0, 18);
985         buffer[2] = 2;          /* uncompressed type */
986         buffer[12] = (width >> 0) & 0xFF;
987         buffer[13] = (width >> 8) & 0xFF;
988         buffer[14] = (height >> 0) & 0xFF;
989         buffer[15] = (height >> 8) & 0xFF;
990
991         for (y = 3;y < width*height*4;y += 4)
992                 if (data[y] < 255)
993                         break;
994
995         if (y < width*height*4)
996         {
997                 /* save the alpha channel */
998                 buffer[16] = 32;        /* pixel size */
999                 buffer[17] = 8; /* 8 bits of alpha */
1000
1001                 /* flip upside down */
1002                 out = buffer + 18;
1003                 for (y = height - 1;y >= 0;y--)
1004                 {
1005                         memcpy(out, data + y * width * 4, width * 4);
1006                         out += width*4;
1007                 }
1008         }
1009         else
1010         {
1011                 /* save only the color channels */
1012                 buffer[16] = 24;        /* pixel size */
1013                 buffer[17] = 0; /* 8 bits of alpha */
1014
1015                 /* truncate bgra to bgr and flip upside down */
1016                 out = buffer + 18;
1017                 for (y = height - 1;y >= 0;y--)
1018                 {
1019                         in = data + y * width * 4;
1020                         end = in + width * 4;
1021                         for (;in < end;in += 4)
1022                         {
1023                                 *out++ = in[0];
1024                                 *out++ = in[1];
1025                                 *out++ = in[2];
1026                         }
1027                 }
1028         }
1029         ret = FS_WriteFile (filename, buffer, out - buffer);
1030
1031         free(buffer);
1032
1033         return ret;
1034 }
1035 /* START stuff that originates from image.c in DarkPlaces */
1036
1037 int usage(const char *me)
1038 {
1039         printf("Usage: %s <infile_norm.tga> <outfile_normandheight.tga> filtertype [<scale> [<offset> [<infile_ref.tga>]]] (get heightmap from normalmap)\n", me);
1040         printf("or:    %s <infile_height.tga> <outfile_normandheight.tga> filtertype -1 [<scale>] (read from B)\n", me);
1041         printf("or:    %s <infile_height.tga> <outfile_normandheight.tga> filtertype -2 [<scale>] (read from G)\n", me);
1042         printf("or:    %s <infile_height.tga> <outfile_normandheight.tga> filtertype -3 [<scale>] (read from R)\n", me);
1043         printf("or:    %s <infile_height.tga> <outfile_normandheight.tga> filtertype -4 [<scale>] (read from A)\n", me);
1044         printf("or:    %s <infile_height.tga> <outfile_normandheight.tga> filtertype -5 [<scale>] (read from (R+G+B)/3)\n", me);
1045         printf("or:    %s <infile_height.tga> <outfile_normandheight.tga> filtertype -6 [<scale>] (read from Y)\n", me);
1046         return 1;
1047 }
1048
1049 static const double filter_scharr3[3][3] = {
1050         {  -3/32.0, 0,  3/32.0 },
1051         { -10/32.0, 0, 10/32.0 },
1052         {  -3/32.0, 0,  3/32.0 }
1053 };
1054
1055 static const double filter_prewitt3[3][3] = {
1056         { -1/6.0, 0, 1/6.0 },
1057         { -1/6.0, 0, 1/6.0 },
1058         { -1/6.0, 0, 1/6.0 }
1059 };
1060
1061 // pathologic for inverting
1062 static const double filter_sobel3[3][3] = {
1063         { -1/8.0, 0, 1/8.0 },
1064         { -2/8.0, 0, 2/8.0 },
1065         { -1/8.0, 0, 1/8.0 }
1066 };
1067
1068 // pathologic for inverting
1069 static const double filter_sobel5[5][5] = {
1070         { -1/128.0,  -2/128.0, 0,  2/128.0, 1/128.0 },
1071         { -4/128.0,  -8/128.0, 0,  8/128.0, 4/128.0 },
1072         { -6/128.0, -12/128.0, 0, 12/128.0, 6/128.0 },
1073         { -4/128.0,  -8/128.0, 0,  8/128.0, 4/128.0 },
1074         { -1/128.0,  -2/128.0, 0,  2/128.0, 1/128.0 }
1075 };
1076
1077 // pathologic for inverting
1078 static const double filter_prewitt5[5][5] = {
1079         { -1/40.0, -2/40.0, 0, 2/40.0, 1/40.0 },
1080         { -1/40.0, -2/40.0, 0, 2/40.0, 1/40.0 },
1081         { -1/40.0, -2/40.0, 0, 2/40.0, 1/40.0 },
1082         { -1/40.0, -2/40.0, 0, 2/40.0, 1/40.0 },
1083         { -1/40.0, -2/40.0, 0, 2/40.0, 1/40.0 }
1084 };
1085
1086 static const double filter_trivial[1][3] = {
1087         { -0.5, 0, 0.5 }
1088 };
1089
1090 int main(int argc, char **argv)
1091 {
1092         const char *infile, *outfile, *reffile;
1093         double scale, offset;
1094         int nmaplen, w, h;
1095         int use_median = 0;
1096         int renormalize = 0;
1097         double highpass = 0;
1098         unsigned char *nmapdata, *nmap, *refmap;
1099         const char *filtertype;
1100         const double *filter = NULL;
1101         int filterw = 0, filterh = 0;
1102 #define USE_FILTER(f) \
1103         do \
1104         { \
1105                 filterw = sizeof(*(f)) / sizeof(**(f)); \
1106                 filterh = sizeof((f)) / sizeof(*(f)); \
1107                 filter = &(f)[0][0]; \
1108         } \
1109         while(0)
1110
1111         if(argc > 1)
1112                 infile = argv[1];
1113         else
1114                 return usage(*argv);
1115
1116         if(argc > 2)
1117                 outfile = argv[2];
1118         else
1119                 return usage(*argv);
1120         
1121         if(argc > 3)
1122                 filtertype = argv[3];
1123         else
1124                 return usage(*argv);
1125         
1126         if(argc > 4)
1127                 scale = atof(argv[4]);
1128         else
1129                 scale = 0;
1130
1131         if(argc > 5)
1132                 offset = atof(argv[5]);
1133         else
1134                 offset = (scale<0) ? 1 : 0;
1135
1136         if(argc > 6)
1137                 reffile = argv[6];
1138         else
1139                 reffile = NULL;
1140
1141         // experimental features
1142         if(getenv("FFT_NORMALMAP_TO_HEIGHTMAP_RENORMALIZE"))
1143                 renormalize = atoi(getenv("FFT_NORMALMAP_TO_HEIGHTMAP_RENORMALIZE"));
1144         if(getenv("FFT_NORMALMAP_TO_HEIGHTMAP_HIGHPASS"))
1145                 highpass = atof(getenv("FFT_NORMALMAP_TO_HEIGHTMAP_HIGHPASS"));
1146         if(getenv("FFT_NORMALMAP_TO_HEIGHTMAP_USE_MEDIAN"))
1147                 use_median = atof(getenv("FFT_NORMALMAP_TO_HEIGHTMAP_USE_MEDIAN"));
1148
1149         nmapdata = FS_LoadFile(infile, &nmaplen);
1150         if(!nmapdata)
1151         {
1152                 printf("FS_LoadFile failed\n");
1153                 return 2;
1154         }
1155         nmap = LoadTGA_BGRA(nmapdata, nmaplen);
1156         free(nmapdata);
1157         if(!nmap)
1158         {
1159                 printf("LoadTGA_BGRA failed\n");
1160                 return 2;
1161         }
1162         w = image_width;
1163         h = image_height;
1164
1165         if(reffile)
1166         {
1167                 nmapdata = FS_LoadFile(reffile, &nmaplen);
1168                 if(!nmapdata)
1169                 {
1170                         printf("FS_LoadFile failed\n");
1171                         return 2;
1172                 }
1173                 refmap = LoadTGA_BGRA(nmapdata, nmaplen);
1174                 free(nmapdata);
1175                 if(!refmap)
1176                 {
1177                         printf("LoadTGA_BGRA failed\n");
1178                         return 2;
1179                 }
1180                 if(image_width != w || image_height != h)
1181                 {
1182                         printf("reference map must have same size as input normalmap\n");
1183                         return 2;
1184                 }
1185         }
1186         else
1187                 refmap = NULL;
1188
1189         if(!strcmp(filtertype, "trivial"))
1190                 USE_FILTER(filter_trivial);
1191         if(!strcmp(filtertype, "prewitt3"))
1192                 USE_FILTER(filter_prewitt3);
1193         if(!strcmp(filtertype, "scharr3"))
1194                 USE_FILTER(filter_scharr3);
1195         if(!strcmp(filtertype, "sobel3"))
1196                 USE_FILTER(filter_sobel3);
1197         if(!strcmp(filtertype, "prewitt5"))
1198                 USE_FILTER(filter_prewitt5);
1199         if(!strcmp(filtertype, "sobel5"))
1200                 USE_FILTER(filter_sobel5);
1201
1202         if(scale < 0)
1203         {
1204                 if(filter)
1205                         hmap_to_nmap_local(nmap, image_width, image_height, -scale-1, offset, filter, filterw, filterh);
1206                 else
1207                         hmap_to_nmap(nmap, image_width, image_height, -scale-1, offset);
1208         }
1209         else
1210                 nmap_to_hmap(nmap, refmap, image_width, image_height, scale, offset, filter, filterw, filterh, renormalize, highpass, use_median);
1211
1212         if(!Image_WriteTGABGRA(outfile, image_width, image_height, nmap))
1213         {
1214                 printf("Image_WriteTGABGRA failed\n");
1215                 free(nmap);
1216                 return 2;
1217         }
1218         free(nmap);
1219         return 0;
1220 }