resizeImage.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. //-------------------------------------------------
  2. //
  3. // Generic Image Resize code.
  4. //
  5. // Used to refractalize the terrain.
  6. //
  7. // Based on Graphics Gems III General Filtered Image Rescaling
  8. //
  9. //---------------------------------------------------------------------------//
  10. // Copyright (C) Microsoft Corporation. All rights reserved. //
  11. //===========================================================================//
  12. #ifndef RESIZEIMAGE_H
  13. #define RESIZEIMAGE_H
  14. #ifndef DSTD_H
  15. #include "dstd.h"
  16. #endif
  17. #include <malloc.h>
  18. #include <memory.h>
  19. #include <math.h>
  20. #define BLACK_PIXEL 0.0f
  21. #define WHITE_PIXEL 255.0f
  22. #define RESIZE_PI 3.1415926
  23. float CLAMP (float x, float min, float max)
  24. {
  25. if (x < min)
  26. return min;
  27. if (x > max)
  28. return max;
  29. return x;
  30. }
  31. typedef struct {
  32. long xSize;
  33. long ySize;
  34. float *data;
  35. } Image;
  36. float getPixel (Image *image, long x, long y)
  37. {
  38. if ((x < 0) || (x >= image->xSize) || (y < 0) || (y > image->ySize))
  39. return 0.0f;
  40. float *p = image->data + (y*image->xSize);
  41. return p[x];
  42. }
  43. void getRow (float *row, Image *image, long y)
  44. {
  45. if ((y < 0) || (y >= image->ySize))
  46. return;
  47. memcpy(row,image->data + (y * image->xSize), image->ySize * sizeof(float));
  48. }
  49. void getCol (float *col, Image *image, long x)
  50. {
  51. if ((x < 0) || (x >= image->xSize))
  52. return;
  53. for (long i=0;i<image->ySize;i++)
  54. {
  55. *col = image->data[x + (i * image->xSize)];
  56. col++;
  57. }
  58. }
  59. float putPixel (Image *image, long x, long y, float data)
  60. {
  61. if ((x < 0) || (x >= image->xSize) || (y < 0) || (y >= image->ySize))
  62. return 0.0f;
  63. float *p = image->data + (y*image->xSize);
  64. return (p[x] = data);
  65. }
  66. //Filters
  67. #define filterSupport (1.0)
  68. #define boxSupport (0.5)
  69. #define triangleSupport (1.0)
  70. #define bellSupport (1.5)
  71. #define bSplineSupport (2.0)
  72. #define Lanczos3Support (3.0)
  73. #define MitchellSupport (2.0)
  74. double filter (double t)
  75. {
  76. if (t < 0.0)
  77. t = -t;
  78. if (t < 1.0)
  79. return((2.0 * t - 3.0) * t * t + 1.0);
  80. return 0.0;
  81. }
  82. double boxFilter (double t)
  83. {
  84. if ((t > -0.5) && (t <= 0.5))
  85. return 1.0;
  86. return 0.0;
  87. }
  88. double triangleFilter (double t)
  89. {
  90. if (t < 0.0)
  91. t = -t;
  92. if (t < 1.0)
  93. return (1.0 - t);
  94. return 0.0;
  95. }
  96. double bellFilter (double t)
  97. {
  98. if (t < 0.0)
  99. t = -t;
  100. if (t < 0.5)
  101. return (0.75 - (t*t));
  102. if (t < 1.5)
  103. {
  104. t = (t - 1.5);
  105. return (0.5 * (t*t));
  106. }
  107. return 0.0;
  108. }
  109. double bSplineFilter (double t)
  110. {
  111. double tt;
  112. if (t < 0.0)
  113. t = -t;
  114. if (t < 1.0)
  115. {
  116. tt = t * t;
  117. return ((0.5 * tt * t) - tt + (2.0/3.0));
  118. }
  119. else if (t < 2.0)
  120. {
  121. t = 2.0 - t;
  122. return ((1.0 / 6.0) * (t * t * t));
  123. }
  124. return 0.0;
  125. }
  126. double sinc (double t)
  127. {
  128. t *= RESIZE_PI;
  129. if (t != 0.0)
  130. return (sin(t) / t);
  131. return 1.0;
  132. }
  133. double lanczos3Filter (double t)
  134. {
  135. if (t < 0.0)
  136. t = -t;
  137. if (t < 3.0)
  138. return (sinc(t) * sinc(t/3.0));
  139. return 0.0;
  140. }
  141. double mitchellFilter (double t)
  142. {
  143. double B = (1.0 / 3.0);
  144. double C = (1.0 / 3.0);
  145. double tt;
  146. tt = t * t;
  147. if (t < 0.0)
  148. t = -t;
  149. if (t < 1.0)
  150. {
  151. t = (((12.0 - 9.0 * B - 6.0 * C) * (t * tt))
  152. + ((-18.0 + 12.0 * B + 6.0 * C) * tt)
  153. + (6.0 - 2.0 * B));
  154. return (t / 6.0);
  155. }
  156. else if (t < 2.0)
  157. {
  158. t = (((-1.0 * B - 6.0 * C) * (t * tt))
  159. + ((6.0 * B + 30.0 * C) * tt)
  160. + ((-12.0 * B - 48.0 * C) * t)
  161. + (8.0 * B + 24.0 * C));
  162. return (t / 6.0);
  163. }
  164. return 0.0;
  165. }
  166. typedef struct {
  167. long pixel;
  168. double weight;
  169. } CONTRIB;
  170. typedef struct {
  171. long n;
  172. CONTRIB *p;
  173. } CLIST;
  174. CLIST *contrib;
  175. Image *newImage(long xSize, long ySize)
  176. {
  177. Image *image = (Image *)malloc(sizeof(Image));
  178. if (image)
  179. {
  180. image->data = (float *)malloc(sizeof(float) * xSize * ySize);
  181. memset(image->data,0,sizeof(float) * xSize * ySize);
  182. image->xSize = xSize;
  183. image->ySize = ySize;
  184. }
  185. return image;
  186. }
  187. void freeImage (Image *image)
  188. {
  189. free(image->data);
  190. free(image);
  191. }
  192. void zoom (Image *dst, Image *src, double (*filter)(double t), double fwidth)
  193. {
  194. Image *tmp;
  195. double xscale, yscale;
  196. long i,j,k;
  197. long n;
  198. double center, left, right;
  199. double width, fscale, weight;
  200. float *raster;
  201. //Create Intermediate image to hold horizontal zoom
  202. tmp = newImage(dst->xSize,src->ySize);
  203. xscale = (double)dst->xSize / (double)src->xSize;
  204. yscale = (double)dst->ySize / (double)src->ySize;
  205. //pre-calculate filter contributions for a row
  206. contrib = (CLIST *)malloc(dst->xSize * sizeof(CLIST));
  207. memset(contrib,0,dst->xSize * sizeof(CLIST));
  208. if (xscale < 1.0)
  209. {
  210. width = fwidth / xscale;
  211. fscale = 1.0 / xscale;
  212. for (i=0;i<dst->xSize;++i)
  213. {
  214. contrib[i].n = 0;
  215. contrib[i].p = (CONTRIB *)malloc((width * 2 + 1) * sizeof(CONTRIB));
  216. center = (double)i / xscale;
  217. left = ceil(center - width);
  218. right = floor(center + width);
  219. for (j=left;j<=right;++j)
  220. {
  221. weight = center - (double)j;
  222. weight = (*filter)(weight / fscale) / fscale;
  223. if (j < 0)
  224. {
  225. n = -j;
  226. }
  227. else if (j >= src->xSize)
  228. {
  229. n = (src->xSize - j) + src->xSize - 1;
  230. }
  231. else
  232. {
  233. n = j;
  234. }
  235. k = contrib[i].n++;
  236. contrib[i].p[k].pixel = n;
  237. contrib[i].p[k].weight = weight;
  238. }
  239. }
  240. }
  241. else
  242. {
  243. for (i=0;i<dst->xSize;++i)
  244. {
  245. contrib[i].n = 0;
  246. contrib[i].p = (CONTRIB *)malloc((fwidth * 2 + 1) * sizeof(CONTRIB));
  247. center = (double)i / xscale;
  248. left = ceil(center - fwidth);
  249. right = floor(center + fwidth);
  250. for (j=left;j<=right;++j)
  251. {
  252. weight = center - (double)j;
  253. weight = (*filter)(weight);
  254. if (j < 0)
  255. {
  256. n = -j;
  257. }
  258. else if (j >= src->xSize)
  259. {
  260. n = (src->xSize - j) + src->xSize - 1;
  261. }
  262. else
  263. {
  264. n = j;
  265. }
  266. k = contrib[i].n++;
  267. contrib[i].p[k].pixel = n;
  268. contrib[i].p[k].weight = weight;
  269. }
  270. }
  271. }
  272. //Apply filter to zoom horizontally from src to tmp
  273. raster = (float *)malloc(src->xSize * sizeof(float));
  274. memset(raster,0,src->xSize * sizeof(float));
  275. for (k=0;k<tmp->ySize; ++k)
  276. {
  277. getRow(raster,src, k);
  278. for (i=0;i<tmp->xSize;++i)
  279. {
  280. weight = 0.0;
  281. for (j=0;j<contrib[i].n;++j)
  282. {
  283. weight += raster[contrib[i].p[j].pixel] * contrib[i].p[j].weight;
  284. }
  285. putPixel(tmp,i,k,(float)CLAMP(weight,BLACK_PIXEL,WHITE_PIXEL));
  286. }
  287. }
  288. free(raster);
  289. raster = NULL;
  290. for (i=0;i<tmp->xSize; ++i)
  291. {
  292. free(contrib[i].p);
  293. contrib[i].p = NULL;
  294. }
  295. free(contrib);
  296. contrib = NULL;
  297. //pre-calculate filter contributions for horizontal filter weights
  298. contrib = (CLIST *)malloc(dst->ySize * sizeof(CLIST));
  299. memset(contrib,0,dst->ySize * sizeof(CLIST));
  300. if (yscale < 1.0)
  301. {
  302. width = fwidth / yscale;
  303. fscale = 1.0 / yscale;
  304. for (i=0;i<dst->ySize;++i)
  305. {
  306. contrib[i].n = 0;
  307. contrib[i].p = (CONTRIB *)malloc((width * 2 + 1) * sizeof(CONTRIB));
  308. center = (double)i / yscale;
  309. left = ceil(center - width);
  310. right = floor(center + width);
  311. for (j=left;j<=right;++j)
  312. {
  313. weight = center - (double)j;
  314. weight = (*filter)(weight / fscale) / fscale;
  315. if (j < 0)
  316. {
  317. n = -j;
  318. }
  319. else if (j >= tmp->ySize)
  320. {
  321. n = (tmp->ySize - j) + tmp->ySize - 1;
  322. }
  323. else
  324. {
  325. n = j;
  326. }
  327. k = contrib[i].n++;
  328. contrib[i].p[k].pixel = n;
  329. contrib[i].p[k].weight = weight;
  330. }
  331. }
  332. }
  333. else
  334. {
  335. for (i=0;i<dst->ySize;++i)
  336. {
  337. contrib[i].n = 0;
  338. contrib[i].p = (CONTRIB *)malloc((fwidth * 2 + 1) * sizeof(CONTRIB));
  339. center = (double)i / yscale;
  340. left = ceil(center - fwidth);
  341. right = floor(center + fwidth);
  342. for (j=left;j<=right;++j)
  343. {
  344. weight = center - (double)j;
  345. weight = (*filter)(weight);
  346. if (j < 0)
  347. {
  348. n = -j;
  349. }
  350. else if (j >= tmp->ySize)
  351. {
  352. n = (tmp->ySize - j) + tmp->ySize - 1;
  353. }
  354. else
  355. {
  356. n = j;
  357. }
  358. k = contrib[i].n++;
  359. contrib[i].p[k].pixel = n;
  360. contrib[i].p[k].weight = weight;
  361. }
  362. }
  363. }
  364. //Apply filter to zoom vertically from tmp to dst
  365. raster = (float *)malloc(sizeof(float) * tmp->ySize);
  366. memset(raster,0,sizeof(float) * tmp->ySize);
  367. for (k=0;k<dst->xSize;++k)
  368. {
  369. getCol(raster,tmp,k);
  370. for (i=0;i<dst->ySize;++i)
  371. {
  372. weight = 0.0;
  373. for (j=0;j<contrib[i].n;++j)
  374. {
  375. weight += raster[contrib[i].p[j].pixel] * contrib[i].p[j].weight;
  376. }
  377. putPixel(dst,k,i,(float)CLAMP(weight,BLACK_PIXEL,WHITE_PIXEL));
  378. }
  379. }
  380. free(raster);
  381. for (i=0;i<dst->ySize; ++i)
  382. {
  383. free(contrib[i].p);
  384. contrib[i].p = NULL;
  385. }
  386. free(contrib);
  387. contrib = NULL;
  388. freeImage(tmp);
  389. }
  390. void rescaleMap (float *dst, float *src, long dstSize, long srcSize);
  391. //----------------------------------------------------------------------------
  392. #endif