image_helper.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. /*
  2. Jonathan Dummer
  3. image helper functions
  4. MIT license
  5. */
  6. #include "image_helper.h"
  7. #include <stdlib.h>
  8. #include <math.h>
  9. /* Upscaling the image uses simple bilinear interpolation */
  10. int
  11. up_scale_image
  12. (
  13. const unsigned char* const orig,
  14. int width, int height, int channels,
  15. unsigned char* resampled,
  16. int resampled_width, int resampled_height
  17. )
  18. {
  19. float dx, dy;
  20. int x, y, c;
  21. /* error(s) check */
  22. if ( (width < 1) || (height < 1) ||
  23. (resampled_width < 2) || (resampled_height < 2) ||
  24. (channels < 1) ||
  25. (NULL == orig) || (NULL == resampled) )
  26. {
  27. /* signify badness */
  28. return 0;
  29. }
  30. /*
  31. for each given pixel in the new map, find the exact location
  32. from the original map which would contribute to this guy
  33. */
  34. dx = (width - 1.0f) / (resampled_width - 1.0f);
  35. dy = (height - 1.0f) / (resampled_height - 1.0f);
  36. for ( y = 0; y < resampled_height; ++y )
  37. {
  38. /* find the base y index and fractional offset from that */
  39. float sampley = y * dy;
  40. int inty = (int)sampley;
  41. /* if( inty < 0 ) { inty = 0; } else */
  42. if( inty > height - 2 ) { inty = height - 2; }
  43. sampley -= inty;
  44. for ( x = 0; x < resampled_width; ++x )
  45. {
  46. float samplex = x * dx;
  47. int intx = (int)samplex;
  48. int base_index;
  49. /* find the base x index and fractional offset from that */
  50. /* if( intx < 0 ) { intx = 0; } else */
  51. if( intx > width - 2 ) { intx = width - 2; }
  52. samplex -= intx;
  53. /* base index into the original image */
  54. base_index = (inty * width + intx) * channels;
  55. for ( c = 0; c < channels; ++c )
  56. {
  57. /* do the sampling */
  58. float value = 0.5f;
  59. value += orig[base_index]
  60. *(1.0f-samplex)*(1.0f-sampley);
  61. value += orig[base_index+channels]
  62. *(samplex)*(1.0f-sampley);
  63. value += orig[base_index+width*channels]
  64. *(1.0f-samplex)*(sampley);
  65. value += orig[base_index+width*channels+channels]
  66. *(samplex)*(sampley);
  67. /* move to the next channel */
  68. ++base_index;
  69. /* save the new value */
  70. resampled[y*resampled_width*channels+x*channels+c] =
  71. (unsigned char)(value);
  72. }
  73. }
  74. }
  75. /* done */
  76. return 1;
  77. }
  78. int
  79. mipmap_image
  80. (
  81. const unsigned char* const orig,
  82. int width, int height, int channels,
  83. unsigned char* resampled,
  84. int block_size_x, int block_size_y
  85. )
  86. {
  87. int mip_width, mip_height;
  88. int i, j, c;
  89. /* error check */
  90. if( (width < 1) || (height < 1) ||
  91. (channels < 1) || (orig == NULL) ||
  92. (resampled == NULL) ||
  93. (block_size_x < 1) || (block_size_y < 1) )
  94. {
  95. /* nothing to do */
  96. return 0;
  97. }
  98. mip_width = width / block_size_x;
  99. mip_height = height / block_size_y;
  100. if( mip_width < 1 )
  101. {
  102. mip_width = 1;
  103. }
  104. if( mip_height < 1 )
  105. {
  106. mip_height = 1;
  107. }
  108. for( j = 0; j < mip_height; ++j )
  109. {
  110. for( i = 0; i < mip_width; ++i )
  111. {
  112. for( c = 0; c < channels; ++c )
  113. {
  114. const int index = (j*block_size_y)*width*channels + (i*block_size_x)*channels + c;
  115. int sum_value;
  116. int u,v;
  117. int u_block = block_size_x;
  118. int v_block = block_size_y;
  119. int block_area;
  120. /* do a bit of checking so we don't over-run the boundaries
  121. (necessary for non-square textures!) */
  122. if( block_size_x * (i+1) > width )
  123. {
  124. u_block = width - i*block_size_y;
  125. }
  126. if( block_size_y * (j+1) > height )
  127. {
  128. v_block = height - j*block_size_y;
  129. }
  130. block_area = u_block*v_block;
  131. /* for this pixel, see what the average
  132. of all the values in the block are.
  133. note: start the sum at the rounding value, not at 0 */
  134. sum_value = block_area >> 1;
  135. for( v = 0; v < v_block; ++v )
  136. for( u = 0; u < u_block; ++u )
  137. {
  138. sum_value += orig[index + v*width*channels + u*channels];
  139. }
  140. resampled[j*mip_width*channels + i*channels + c] = sum_value / block_area;
  141. }
  142. }
  143. }
  144. return 1;
  145. }
  146. int
  147. scale_image_RGB_to_NTSC_safe
  148. (
  149. unsigned char* orig,
  150. int width, int height, int channels
  151. )
  152. {
  153. const float scale_lo = 16.0f - 0.499f;
  154. const float scale_hi = 235.0f + 0.499f;
  155. int i, j;
  156. int nc = channels;
  157. unsigned char scale_LUT[256];
  158. /* error check */
  159. if( (width < 1) || (height < 1) ||
  160. (channels < 1) || (orig == NULL) )
  161. {
  162. /* nothing to do */
  163. return 0;
  164. }
  165. /* set up the scaling Look Up Table */
  166. for( i = 0; i < 256; ++i )
  167. {
  168. scale_LUT[i] = (unsigned char)((scale_hi - scale_lo) * i / 255.0f + scale_lo);
  169. }
  170. /* for channels = 2 or 4, ignore the alpha component */
  171. nc -= 1 - (channels & 1);
  172. /* OK, go through the image and scale any non-alpha components */
  173. for( i = 0; i < width*height*channels; i += channels )
  174. {
  175. for( j = 0; j < nc; ++j )
  176. {
  177. orig[i+j] = scale_LUT[orig[i+j]];
  178. }
  179. }
  180. return 1;
  181. }
  182. unsigned char clamp_byte( int x ) { return ( (x) < 0 ? (0) : ( (x) > 255 ? 255 : (x) ) ); }
  183. /*
  184. This function takes the RGB components of the image
  185. and converts them into YCoCg. 3 components will be
  186. re-ordered to CoYCg (for optimum DXT1 compression),
  187. while 4 components will be ordered CoCgAY (for DXT5
  188. compression).
  189. */
  190. int
  191. convert_RGB_to_YCoCg
  192. (
  193. unsigned char* orig,
  194. int width, int height, int channels
  195. )
  196. {
  197. int i;
  198. /* error check */
  199. if( (width < 1) || (height < 1) ||
  200. (channels < 3) || (channels > 4) ||
  201. (orig == NULL) )
  202. {
  203. /* nothing to do */
  204. return -1;
  205. }
  206. /* do the conversion */
  207. if( channels == 3 )
  208. {
  209. for( i = 0; i < width*height*3; i += 3 )
  210. {
  211. int r = orig[i+0];
  212. int g = (orig[i+1] + 1) >> 1;
  213. int b = orig[i+2];
  214. int tmp = (2 + r + b) >> 2;
  215. /* Co */
  216. orig[i+0] = clamp_byte( 128 + ((r - b + 1) >> 1) );
  217. /* Y */
  218. orig[i+1] = clamp_byte( g + tmp );
  219. /* Cg */
  220. orig[i+2] = clamp_byte( 128 + g - tmp );
  221. }
  222. } else
  223. {
  224. for( i = 0; i < width*height*4; i += 4 )
  225. {
  226. int r = orig[i+0];
  227. int g = (orig[i+1] + 1) >> 1;
  228. int b = orig[i+2];
  229. unsigned char a = orig[i+3];
  230. int tmp = (2 + r + b) >> 2;
  231. /* Co */
  232. orig[i+0] = clamp_byte( 128 + ((r - b + 1) >> 1) );
  233. /* Cg */
  234. orig[i+1] = clamp_byte( 128 + g - tmp );
  235. /* Alpha */
  236. orig[i+2] = a;
  237. /* Y */
  238. orig[i+3] = clamp_byte( g + tmp );
  239. }
  240. }
  241. /* done */
  242. return 0;
  243. }
  244. /*
  245. This function takes the YCoCg components of the image
  246. and converts them into RGB. See above.
  247. */
  248. int
  249. convert_YCoCg_to_RGB
  250. (
  251. unsigned char* orig,
  252. int width, int height, int channels
  253. )
  254. {
  255. int i;
  256. /* error check */
  257. if( (width < 1) || (height < 1) ||
  258. (channels < 3) || (channels > 4) ||
  259. (orig == NULL) )
  260. {
  261. /* nothing to do */
  262. return -1;
  263. }
  264. /* do the conversion */
  265. if( channels == 3 )
  266. {
  267. for( i = 0; i < width*height*3; i += 3 )
  268. {
  269. int co = orig[i+0] - 128;
  270. int y = orig[i+1];
  271. int cg = orig[i+2] - 128;
  272. /* R */
  273. orig[i+0] = clamp_byte( y + co - cg );
  274. /* G */
  275. orig[i+1] = clamp_byte( y + cg );
  276. /* B */
  277. orig[i+2] = clamp_byte( y - co - cg );
  278. }
  279. } else
  280. {
  281. for( i = 0; i < width*height*4; i += 4 )
  282. {
  283. int co = orig[i+0] - 128;
  284. int cg = orig[i+1] - 128;
  285. unsigned char a = orig[i+2];
  286. int y = orig[i+3];
  287. /* R */
  288. orig[i+0] = clamp_byte( y + co - cg );
  289. /* G */
  290. orig[i+1] = clamp_byte( y + cg );
  291. /* B */
  292. orig[i+2] = clamp_byte( y - co - cg );
  293. /* A */
  294. orig[i+3] = a;
  295. }
  296. }
  297. /* done */
  298. return 0;
  299. }
  300. float
  301. find_max_RGBE
  302. (
  303. unsigned char *image,
  304. int width, int height
  305. )
  306. {
  307. float max_val = 0.0f;
  308. unsigned char *img = image;
  309. int i, j;
  310. for( i = width * height; i > 0; --i )
  311. {
  312. /* float scale = powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
  313. float scale = ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
  314. for( j = 0; j < 3; ++j )
  315. {
  316. if( img[j] * scale > max_val )
  317. {
  318. max_val = img[j] * scale;
  319. }
  320. }
  321. /* next pixel */
  322. img += 4;
  323. }
  324. return max_val;
  325. }
  326. int
  327. RGBE_to_RGBdivA
  328. (
  329. unsigned char *image,
  330. int width, int height,
  331. int rescale_to_max
  332. )
  333. {
  334. /* local variables */
  335. int i, iv;
  336. unsigned char *img = image;
  337. float scale = 1.0f;
  338. /* error check */
  339. if( (!image) || (width < 1) || (height < 1) )
  340. {
  341. return 0;
  342. }
  343. /* convert (note: no negative numbers, but 0.0 is possible) */
  344. if( rescale_to_max )
  345. {
  346. scale = 255.0f / find_max_RGBE( image, width, height );
  347. }
  348. for( i = width * height; i > 0; --i )
  349. {
  350. /* decode this pixel, and find the max */
  351. float r,g,b,e, m;
  352. /* e = scale * powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
  353. e = scale * ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
  354. r = e * img[0];
  355. g = e * img[1];
  356. b = e * img[2];
  357. m = (r > g) ? r : g;
  358. m = (b > m) ? b : m;
  359. /* and encode it into RGBdivA */
  360. iv = (m != 0.0f) ? (int)(255.0f / m) : 1.0f;
  361. iv = (iv < 1) ? 1 : iv;
  362. img[3] = (iv > 255) ? 255 : iv;
  363. iv = (int)(img[3] * r + 0.5f);
  364. img[0] = (iv > 255) ? 255 : iv;
  365. iv = (int)(img[3] * g + 0.5f);
  366. img[1] = (iv > 255) ? 255 : iv;
  367. iv = (int)(img[3] * b + 0.5f);
  368. img[2] = (iv > 255) ? 255 : iv;
  369. /* and on to the next pixel */
  370. img += 4;
  371. }
  372. return 1;
  373. }
  374. int
  375. RGBE_to_RGBdivA2
  376. (
  377. unsigned char *image,
  378. int width, int height,
  379. int rescale_to_max
  380. )
  381. {
  382. /* local variables */
  383. int i, iv;
  384. unsigned char *img = image;
  385. float scale = 1.0f;
  386. /* error check */
  387. if( (!image) || (width < 1) || (height < 1) )
  388. {
  389. return 0;
  390. }
  391. /* convert (note: no negative numbers, but 0.0 is possible) */
  392. if( rescale_to_max )
  393. {
  394. scale = 255.0f * 255.0f / find_max_RGBE( image, width, height );
  395. }
  396. for( i = width * height; i > 0; --i )
  397. {
  398. /* decode this pixel, and find the max */
  399. float r,g,b,e, m;
  400. /* e = scale * powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
  401. e = scale * ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
  402. r = e * img[0];
  403. g = e * img[1];
  404. b = e * img[2];
  405. m = (r > g) ? r : g;
  406. m = (b > m) ? b : m;
  407. /* and encode it into RGBdivA */
  408. iv = (m != 0.0f) ? (int)sqrtf( 255.0f * 255.0f / m ) : 1.0f;
  409. iv = (iv < 1) ? 1 : iv;
  410. img[3] = (iv > 255) ? 255 : iv;
  411. iv = (int)(img[3] * img[3] * r / 255.0f + 0.5f);
  412. img[0] = (iv > 255) ? 255 : iv;
  413. iv = (int)(img[3] * img[3] * g / 255.0f + 0.5f);
  414. img[1] = (iv > 255) ? 255 : iv;
  415. iv = (int)(img[3] * img[3] * b / 255.0f + 0.5f);
  416. img[2] = (iv > 255) ? 255 : iv;
  417. /* and on to the next pixel */
  418. img += 4;
  419. }
  420. return 1;
  421. }