image_DXT.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. /*
  2. Jonathan Dummer
  3. 2007-07-31-10.32
  4. simple DXT compression / decompression code
  5. public domain
  6. */
  7. #include "image_DXT.h"
  8. #include <math.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <stdio.h>
  12. /* set this =1 if you want to use the covarince matrix method...
  13. which is better than my method of using standard deviations
  14. overall, except on the infintesimal chance that the power
  15. method fails for finding the largest eigenvector */
  16. #define USE_COV_MAT 1
  17. /********* Function Prototypes *********/
  18. /*
  19. Takes a 4x4 block of pixels and compresses it into 8 bytes
  20. in DXT1 format (color only, no alpha). Speed is valued
  21. over prettyness, at least for now.
  22. */
  23. void compress_DDS_color_block(
  24. int channels,
  25. const unsigned char *const uncompressed,
  26. unsigned char compressed[8] );
  27. /*
  28. Takes a 4x4 block of pixels and compresses the alpha
  29. component it into 8 bytes for use in DXT5 DDS files.
  30. Speed is valued over prettyness, at least for now.
  31. */
  32. void compress_DDS_alpha_block(
  33. const unsigned char *const uncompressed,
  34. unsigned char compressed[8] );
  35. /********* Actual Exposed Functions *********/
  36. int
  37. save_image_as_DDS
  38. (
  39. const char *filename,
  40. int width, int height, int channels,
  41. const unsigned char *const data
  42. )
  43. {
  44. /* variables */
  45. FILE *fout;
  46. unsigned char *DDS_data;
  47. DDS_header header;
  48. int DDS_size;
  49. /* error check */
  50. if( (NULL == filename) ||
  51. (width < 1) || (height < 1) ||
  52. (channels < 1) || (channels > 4) ||
  53. (data == NULL ) )
  54. {
  55. return 0;
  56. }
  57. /* Convert the image */
  58. if( (channels & 1) == 1 )
  59. {
  60. /* no alpha, just use DXT1 */
  61. DDS_data = convert_image_to_DXT1( data, width, height, channels, &DDS_size );
  62. } else
  63. {
  64. /* has alpha, so use DXT5 */
  65. DDS_data = convert_image_to_DXT5( data, width, height, channels, &DDS_size );
  66. }
  67. /* save it */
  68. memset( &header, 0, sizeof( DDS_header ) );
  69. header.dwMagic = ('D' << 0) | ('D' << 8) | ('S' << 16) | (' ' << 24);
  70. header.dwSize = 124;
  71. header.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_LINEARSIZE;
  72. header.dwWidth = width;
  73. header.dwHeight = height;
  74. header.dwPitchOrLinearSize = DDS_size;
  75. header.sPixelFormat.dwSize = 32;
  76. header.sPixelFormat.dwFlags = DDPF_FOURCC;
  77. if( (channels & 1) == 1 )
  78. {
  79. header.sPixelFormat.dwFourCC = ('D' << 0) | ('X' << 8) | ('T' << 16) | ('1' << 24);
  80. } else
  81. {
  82. header.sPixelFormat.dwFourCC = ('D' << 0) | ('X' << 8) | ('T' << 16) | ('5' << 24);
  83. }
  84. header.sCaps.dwCaps1 = DDSCAPS_TEXTURE;
  85. /* write it out */
  86. fout = fopen( filename, "wb");
  87. fwrite( &header, sizeof( DDS_header ), 1, fout );
  88. fwrite( DDS_data, 1, DDS_size, fout );
  89. fclose( fout );
  90. /* done */
  91. free( DDS_data );
  92. return 1;
  93. }
  94. unsigned char* convert_image_to_DXT1(
  95. const unsigned char *const uncompressed,
  96. int width, int height, int channels,
  97. int *out_size )
  98. {
  99. unsigned char *compressed;
  100. int i, j, x, y;
  101. unsigned char ublock[16*3];
  102. unsigned char cblock[8];
  103. int cindex = 0, chan_step = 1;
  104. int block_count = 0;
  105. /* error check */
  106. *out_size = 0;
  107. if( (width < 1) || (height < 1) ||
  108. (NULL == uncompressed) ||
  109. (channels < 1) || (channels > 4) )
  110. {
  111. return NULL;
  112. }
  113. /* for channels == 1 or 2, I do not step forward for R,G,B values */
  114. if( channels < 3 )
  115. {
  116. chan_step = 0;
  117. }
  118. /* get the RAM for the compressed image
  119. (8 bytes per 4x4 pixel block) */
  120. *out_size = ((width+3) >> 2) * ((height+3) >> 2) * 8;
  121. compressed = (unsigned char*)malloc( *out_size );
  122. /* go through each block */
  123. for( j = 0; j < height; j += 4 )
  124. {
  125. for( i = 0; i < width; i += 4 )
  126. {
  127. /* copy this block into a new one */
  128. int idx = 0;
  129. int mx = 4, my = 4;
  130. if( j+4 >= height )
  131. {
  132. my = height - j;
  133. }
  134. if( i+4 >= width )
  135. {
  136. mx = width - i;
  137. }
  138. for( y = 0; y < my; ++y )
  139. {
  140. for( x = 0; x < mx; ++x )
  141. {
  142. ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels];
  143. ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels+chan_step];
  144. ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels+chan_step+chan_step];
  145. }
  146. for( x = mx; x < 4; ++x )
  147. {
  148. ublock[idx++] = ublock[0];
  149. ublock[idx++] = ublock[1];
  150. ublock[idx++] = ublock[2];
  151. }
  152. }
  153. for( y = my; y < 4; ++y )
  154. {
  155. for( x = 0; x < 4; ++x )
  156. {
  157. ublock[idx++] = ublock[0];
  158. ublock[idx++] = ublock[1];
  159. ublock[idx++] = ublock[2];
  160. }
  161. }
  162. /* compress the block */
  163. ++block_count;
  164. compress_DDS_color_block( 3, ublock, cblock );
  165. /* copy the data from the block into the main block */
  166. for( x = 0; x < 8; ++x )
  167. {
  168. compressed[cindex++] = cblock[x];
  169. }
  170. }
  171. }
  172. return compressed;
  173. }
  174. unsigned char* convert_image_to_DXT5(
  175. const unsigned char *const uncompressed,
  176. int width, int height, int channels,
  177. int *out_size )
  178. {
  179. unsigned char *compressed;
  180. int i, j, x, y;
  181. unsigned char ublock[16*4];
  182. unsigned char cblock[8];
  183. int cindex = 0, chan_step = 1;
  184. int block_count = 0, has_alpha;
  185. /* error check */
  186. *out_size = 0;
  187. if( (width < 1) || (height < 1) ||
  188. (NULL == uncompressed) ||
  189. (channels < 1) || ( channels > 4) )
  190. {
  191. return NULL;
  192. }
  193. /* for channels == 1 or 2, I do not step forward for R,G,B vales */
  194. if( channels < 3 )
  195. {
  196. chan_step = 0;
  197. }
  198. /* # channels = 1 or 3 have no alpha, 2 & 4 do have alpha */
  199. has_alpha = 1 - (channels & 1);
  200. /* get the RAM for the compressed image
  201. (16 bytes per 4x4 pixel block) */
  202. *out_size = ((width+3) >> 2) * ((height+3) >> 2) * 16;
  203. compressed = (unsigned char*)malloc( *out_size );
  204. /* go through each block */
  205. for( j = 0; j < height; j += 4 )
  206. {
  207. for( i = 0; i < width; i += 4 )
  208. {
  209. /* local variables, and my block counter */
  210. int idx = 0;
  211. int mx = 4, my = 4;
  212. if( j+4 >= height )
  213. {
  214. my = height - j;
  215. }
  216. if( i+4 >= width )
  217. {
  218. mx = width - i;
  219. }
  220. for( y = 0; y < my; ++y )
  221. {
  222. for( x = 0; x < mx; ++x )
  223. {
  224. ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels];
  225. ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels+chan_step];
  226. ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels+chan_step+chan_step];
  227. ublock[idx++] =
  228. has_alpha * uncompressed[(j+y)*width*channels+(i+x)*channels+channels-1]
  229. + (1-has_alpha)*255;
  230. }
  231. for( x = mx; x < 4; ++x )
  232. {
  233. ublock[idx++] = ublock[0];
  234. ublock[idx++] = ublock[1];
  235. ublock[idx++] = ublock[2];
  236. ublock[idx++] = ublock[3];
  237. }
  238. }
  239. for( y = my; y < 4; ++y )
  240. {
  241. for( x = 0; x < 4; ++x )
  242. {
  243. ublock[idx++] = ublock[0];
  244. ublock[idx++] = ublock[1];
  245. ublock[idx++] = ublock[2];
  246. ublock[idx++] = ublock[3];
  247. }
  248. }
  249. /* now compress the alpha block */
  250. compress_DDS_alpha_block( ublock, cblock );
  251. /* copy the data from the compressed alpha block into the main buffer */
  252. for( x = 0; x < 8; ++x )
  253. {
  254. compressed[cindex++] = cblock[x];
  255. }
  256. /* then compress the color block */
  257. ++block_count;
  258. compress_DDS_color_block( 4, ublock, cblock );
  259. /* copy the data from the compressed color block into the main buffer */
  260. for( x = 0; x < 8; ++x )
  261. {
  262. compressed[cindex++] = cblock[x];
  263. }
  264. }
  265. }
  266. return compressed;
  267. }
  268. /********* Helper Functions *********/
  269. int convert_bit_range( int c, int from_bits, int to_bits )
  270. {
  271. int b = (1 << (from_bits - 1)) + c * ((1 << to_bits) - 1);
  272. return (b + (b >> from_bits)) >> from_bits;
  273. }
  274. int rgb_to_565( int r, int g, int b )
  275. {
  276. return
  277. (convert_bit_range( r, 8, 5 ) << 11) |
  278. (convert_bit_range( g, 8, 6 ) << 05) |
  279. (convert_bit_range( b, 8, 5 ) << 00);
  280. }
  281. void rgb_888_from_565( unsigned int c, int *r, int *g, int *b )
  282. {
  283. *r = convert_bit_range( (c >> 11) & 31, 5, 8 );
  284. *g = convert_bit_range( (c >> 05) & 63, 6, 8 );
  285. *b = convert_bit_range( (c >> 00) & 31, 5, 8 );
  286. }
  287. void compute_color_line_STDEV(
  288. const unsigned char *const uncompressed,
  289. int channels,
  290. float point[3], float direction[3] )
  291. {
  292. const float inv_16 = 1.0f / 16.0f;
  293. int i;
  294. float sum_r = 0.0f, sum_g = 0.0f, sum_b = 0.0f;
  295. float sum_rr = 0.0f, sum_gg = 0.0f, sum_bb = 0.0f;
  296. float sum_rg = 0.0f, sum_rb = 0.0f, sum_gb = 0.0f;
  297. /* calculate all data needed for the covariance matrix
  298. ( to compare with _rygdxt code) */
  299. for( i = 0; i < 16*channels; i += channels )
  300. {
  301. sum_r += uncompressed[i+0];
  302. sum_rr += uncompressed[i+0] * uncompressed[i+0];
  303. sum_g += uncompressed[i+1];
  304. sum_gg += uncompressed[i+1] * uncompressed[i+1];
  305. sum_b += uncompressed[i+2];
  306. sum_bb += uncompressed[i+2] * uncompressed[i+2];
  307. sum_rg += uncompressed[i+0] * uncompressed[i+1];
  308. sum_rb += uncompressed[i+0] * uncompressed[i+2];
  309. sum_gb += uncompressed[i+1] * uncompressed[i+2];
  310. }
  311. /* convert the sums to averages */
  312. sum_r *= inv_16;
  313. sum_g *= inv_16;
  314. sum_b *= inv_16;
  315. /* and convert the squares to the squares of the value - avg_value */
  316. sum_rr -= 16.0f * sum_r * sum_r;
  317. sum_gg -= 16.0f * sum_g * sum_g;
  318. sum_bb -= 16.0f * sum_b * sum_b;
  319. sum_rg -= 16.0f * sum_r * sum_g;
  320. sum_rb -= 16.0f * sum_r * sum_b;
  321. sum_gb -= 16.0f * sum_g * sum_b;
  322. /* the point on the color line is the average */
  323. point[0] = sum_r;
  324. point[1] = sum_g;
  325. point[2] = sum_b;
  326. #if USE_COV_MAT
  327. /*
  328. The following idea was from ryg.
  329. (https://mollyrocket.com/forums/viewtopic.php?t=392)
  330. The method worked great (less RMSE than mine) most of
  331. the time, but had some issues handling some simple
  332. boundary cases, like full green next to full red,
  333. which would generate a covariance matrix like this:
  334. | 1 -1 0 |
  335. | -1 1 0 |
  336. | 0 0 0 |
  337. For a given starting vector, the power method can
  338. generate all zeros! So no starting with {1,1,1}
  339. as I was doing! This kind of error is still a
  340. slight posibillity, but will be very rare.
  341. */
  342. /* use the covariance matrix directly
  343. (1st iteration, don't use all 1.0 values!) */
  344. sum_r = 1.0f;
  345. sum_g = 2.718281828f;
  346. sum_b = 3.141592654f;
  347. direction[0] = sum_r*sum_rr + sum_g*sum_rg + sum_b*sum_rb;
  348. direction[1] = sum_r*sum_rg + sum_g*sum_gg + sum_b*sum_gb;
  349. direction[2] = sum_r*sum_rb + sum_g*sum_gb + sum_b*sum_bb;
  350. /* 2nd iteration, use results from the 1st guy */
  351. sum_r = direction[0];
  352. sum_g = direction[1];
  353. sum_b = direction[2];
  354. direction[0] = sum_r*sum_rr + sum_g*sum_rg + sum_b*sum_rb;
  355. direction[1] = sum_r*sum_rg + sum_g*sum_gg + sum_b*sum_gb;
  356. direction[2] = sum_r*sum_rb + sum_g*sum_gb + sum_b*sum_bb;
  357. /* 3rd iteration, use results from the 2nd guy */
  358. sum_r = direction[0];
  359. sum_g = direction[1];
  360. sum_b = direction[2];
  361. direction[0] = sum_r*sum_rr + sum_g*sum_rg + sum_b*sum_rb;
  362. direction[1] = sum_r*sum_rg + sum_g*sum_gg + sum_b*sum_gb;
  363. direction[2] = sum_r*sum_rb + sum_g*sum_gb + sum_b*sum_bb;
  364. #else
  365. /* use my standard deviation method
  366. (very robust, a tiny bit slower and less accurate) */
  367. direction[0] = sqrt( sum_rr );
  368. direction[1] = sqrt( sum_gg );
  369. direction[2] = sqrt( sum_bb );
  370. /* which has a greater component */
  371. if( sum_gg > sum_rr )
  372. {
  373. /* green has greater component, so base the other signs off of green */
  374. if( sum_rg < 0.0f )
  375. {
  376. direction[0] = -direction[0];
  377. }
  378. if( sum_gb < 0.0f )
  379. {
  380. direction[2] = -direction[2];
  381. }
  382. } else
  383. {
  384. /* red has a greater component */
  385. if( sum_rg < 0.0f )
  386. {
  387. direction[1] = -direction[1];
  388. }
  389. if( sum_rb < 0.0f )
  390. {
  391. direction[2] = -direction[2];
  392. }
  393. }
  394. #endif
  395. }
  396. void LSE_master_colors_max_min(
  397. int *cmax, int *cmin,
  398. int channels,
  399. const unsigned char *const uncompressed )
  400. {
  401. int i, j;
  402. /* the master colors */
  403. int c0[3], c1[3];
  404. /* used for fitting the line */
  405. float sum_x[] = { 0.0f, 0.0f, 0.0f };
  406. float sum_x2[] = { 0.0f, 0.0f, 0.0f };
  407. float dot_max = 1.0f, dot_min = -1.0f;
  408. float vec_len2 = 0.0f;
  409. float dot;
  410. /* error check */
  411. if( (channels < 3) || (channels > 4) )
  412. {
  413. return;
  414. }
  415. compute_color_line_STDEV( uncompressed, channels, sum_x, sum_x2 );
  416. vec_len2 = 1.0f / ( 0.00001f +
  417. sum_x2[0]*sum_x2[0] + sum_x2[1]*sum_x2[1] + sum_x2[2]*sum_x2[2] );
  418. /* finding the max and min vector values */
  419. dot_max =
  420. (
  421. sum_x2[0] * uncompressed[0] +
  422. sum_x2[1] * uncompressed[1] +
  423. sum_x2[2] * uncompressed[2]
  424. );
  425. dot_min = dot_max;
  426. for( i = 1; i < 16; ++i )
  427. {
  428. dot =
  429. (
  430. sum_x2[0] * uncompressed[i*channels+0] +
  431. sum_x2[1] * uncompressed[i*channels+1] +
  432. sum_x2[2] * uncompressed[i*channels+2]
  433. );
  434. if( dot < dot_min )
  435. {
  436. dot_min = dot;
  437. } else if( dot > dot_max )
  438. {
  439. dot_max = dot;
  440. }
  441. }
  442. /* and the offset (from the average location) */
  443. dot = sum_x2[0]*sum_x[0] + sum_x2[1]*sum_x[1] + sum_x2[2]*sum_x[2];
  444. dot_min -= dot;
  445. dot_max -= dot;
  446. /* post multiply by the scaling factor */
  447. dot_min *= vec_len2;
  448. dot_max *= vec_len2;
  449. /* OK, build the master colors */
  450. for( i = 0; i < 3; ++i )
  451. {
  452. /* color 0 */
  453. c0[i] = (int)(0.5f + sum_x[i] + dot_max * sum_x2[i]);
  454. if( c0[i] < 0 )
  455. {
  456. c0[i] = 0;
  457. } else if( c0[i] > 255 )
  458. {
  459. c0[i] = 255;
  460. }
  461. /* color 1 */
  462. c1[i] = (int)(0.5f + sum_x[i] + dot_min * sum_x2[i]);
  463. if( c1[i] < 0 )
  464. {
  465. c1[i] = 0;
  466. } else if( c1[i] > 255 )
  467. {
  468. c1[i] = 255;
  469. }
  470. }
  471. /* down_sample (with rounding?) */
  472. i = rgb_to_565( c0[0], c0[1], c0[2] );
  473. j = rgb_to_565( c1[0], c1[1], c1[2] );
  474. if( i > j )
  475. {
  476. *cmax = i;
  477. *cmin = j;
  478. } else
  479. {
  480. *cmax = j;
  481. *cmin = i;
  482. }
  483. }
  484. void
  485. compress_DDS_color_block
  486. (
  487. int channels,
  488. const unsigned char *const uncompressed,
  489. unsigned char compressed[8]
  490. )
  491. {
  492. /* variables */
  493. int i;
  494. int next_bit;
  495. int enc_c0, enc_c1;
  496. int c0[4], c1[4];
  497. float color_line[] = { 0.0f, 0.0f, 0.0f, 0.0f };
  498. float vec_len2 = 0.0f, dot_offset = 0.0f;
  499. /* stupid order */
  500. int swizzle4[] = { 0, 2, 3, 1 };
  501. /* get the master colors */
  502. LSE_master_colors_max_min( &enc_c0, &enc_c1, channels, uncompressed );
  503. /* store the 565 color 0 and color 1 */
  504. compressed[0] = (enc_c0 >> 0) & 255;
  505. compressed[1] = (enc_c0 >> 8) & 255;
  506. compressed[2] = (enc_c1 >> 0) & 255;
  507. compressed[3] = (enc_c1 >> 8) & 255;
  508. /* zero out the compressed data */
  509. compressed[4] = 0;
  510. compressed[5] = 0;
  511. compressed[6] = 0;
  512. compressed[7] = 0;
  513. /* reconstitute the master color vectors */
  514. rgb_888_from_565( enc_c0, &c0[0], &c0[1], &c0[2] );
  515. rgb_888_from_565( enc_c1, &c1[0], &c1[1], &c1[2] );
  516. /* the new vector */
  517. vec_len2 = 0.0f;
  518. for( i = 0; i < 3; ++i )
  519. {
  520. color_line[i] = (float)(c1[i] - c0[i]);
  521. vec_len2 += color_line[i] * color_line[i];
  522. }
  523. if( vec_len2 > 0.0f )
  524. {
  525. vec_len2 = 1.0f / vec_len2;
  526. }
  527. /* pre-proform the scaling */
  528. color_line[0] *= vec_len2;
  529. color_line[1] *= vec_len2;
  530. color_line[2] *= vec_len2;
  531. /* compute the offset (constant) portion of the dot product */
  532. dot_offset = color_line[0]*c0[0] + color_line[1]*c0[1] + color_line[2]*c0[2];
  533. /* store the rest of the bits */
  534. next_bit = 8*4;
  535. for( i = 0; i < 16; ++i )
  536. {
  537. /* find the dot product of this color, to place it on the line
  538. (should be [-1,1]) */
  539. int next_value = 0;
  540. float dot_product =
  541. color_line[0] * uncompressed[i*channels+0] +
  542. color_line[1] * uncompressed[i*channels+1] +
  543. color_line[2] * uncompressed[i*channels+2] -
  544. dot_offset;
  545. /* map to [0,3] */
  546. next_value = (int)( dot_product * 3.0f + 0.5f );
  547. if( next_value > 3 )
  548. {
  549. next_value = 3;
  550. } else if( next_value < 0 )
  551. {
  552. next_value = 0;
  553. }
  554. /* OK, store this value */
  555. compressed[next_bit >> 3] |= swizzle4[ next_value ] << (next_bit & 7);
  556. next_bit += 2;
  557. }
  558. /* done compressing to DXT1 */
  559. }
  560. void
  561. compress_DDS_alpha_block
  562. (
  563. const unsigned char *const uncompressed,
  564. unsigned char compressed[8]
  565. )
  566. {
  567. /* variables */
  568. int i;
  569. int next_bit;
  570. int a0, a1;
  571. float scale_me;
  572. /* stupid order */
  573. int swizzle8[] = { 1, 7, 6, 5, 4, 3, 2, 0 };
  574. /* get the alpha limits (a0 > a1) */
  575. a0 = a1 = uncompressed[3];
  576. for( i = 4+3; i < 16*4; i += 4 )
  577. {
  578. if( uncompressed[i] > a0 )
  579. {
  580. a0 = uncompressed[i];
  581. } else if( uncompressed[i] < a1 )
  582. {
  583. a1 = uncompressed[i];
  584. }
  585. }
  586. /* store those limits, and zero the rest of the compressed dataset */
  587. compressed[0] = a0;
  588. compressed[1] = a1;
  589. /* zero out the compressed data */
  590. compressed[2] = 0;
  591. compressed[3] = 0;
  592. compressed[4] = 0;
  593. compressed[5] = 0;
  594. compressed[6] = 0;
  595. compressed[7] = 0;
  596. /* store the all of the alpha values */
  597. next_bit = 8*2;
  598. scale_me = 7.9999f / (a0 - a1);
  599. for( i = 3; i < 16*4; i += 4 )
  600. {
  601. /* convert this alpha value to a 3 bit number */
  602. int svalue;
  603. int value = (int)((uncompressed[i] - a1) * scale_me);
  604. svalue = swizzle8[ value&7 ];
  605. /* OK, store this value, start with the 1st byte */
  606. compressed[next_bit >> 3] |= svalue << (next_bit & 7);
  607. if( (next_bit & 7) > 5 )
  608. {
  609. /* spans 2 bytes, fill in the start of the 2nd byte */
  610. compressed[1 + (next_bit >> 3)] |= svalue >> (8 - (next_bit & 7) );
  611. }
  612. next_bit += 3;
  613. }
  614. /* done compressing to DXT1 */
  615. }