alpha_test.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <math.h>
  4. #include "lcms2_internal.h"
  5. /**
  6. * Premultiplied alpha. This conversion generates irreversible information loss.
  7. *
  8. * 8 bits:
  9. * prgb = rgb * (alpha/255)
  10. * rgb = prgb * (255 / alpha)
  11. *
  12. * 16 bits:
  13. * prgb = rgb * (alpha/65535)
  14. * rgb = prgb * (65535/alpha)
  15. *
  16. */
  17. uint8_t to_premul8_float(uint8_t rgb8, uint8_t a8)
  18. {
  19. double alpha_factor, rgb;
  20. if (a8 == 0) return rgb8;
  21. alpha_factor = (double) a8 / 255.0;
  22. rgb = ((double) rgb8 * alpha_factor);
  23. return (uint8_t)round(rgb);
  24. }
  25. uint8_t from_premul8_float(uint8_t rgb8, uint8_t a8)
  26. {
  27. double alpha_factor, rgb;
  28. if (a8 == 0) return rgb8;
  29. alpha_factor = 255.0 / (double)a8;
  30. rgb = ((double)rgb8 * alpha_factor);
  31. if (rgb > 255.0) rgb = 255.0;
  32. return (uint8_t)round(rgb);
  33. }
  34. uint16_t to_premul16_float(uint16_t rgb16, uint16_t a16)
  35. {
  36. double alpha_factor, rgb;
  37. if (a16 == 0) return rgb16;
  38. alpha_factor = (double)a16 / 65535.0;
  39. rgb = ((double)rgb16 * alpha_factor);
  40. return (uint16_t)round(rgb);
  41. }
  42. uint16_t from_premul16_float(uint16_t rgb16, uint16_t a16)
  43. {
  44. double alpha_factor, rgb;
  45. if (a16 == 0) return rgb16;
  46. alpha_factor = 65535.0 / (double)a16;
  47. rgb = ((double)rgb16 * alpha_factor);
  48. if (rgb > 65535.0) rgb = 65535.0;
  49. return (uint16_t)round(rgb);
  50. }
  51. /**
  52. ** Optimized versions
  53. *
  54. * alpha_factor goes 0..1.0 in 1.15 fixed point format
  55. * (a16 / 0xffff) which equals to _cmsToFixedDomain() inline (15.16)
  56. *
  57. * rgb 16.0 fixed point x alpha factor 1.15 = (a*b + 0x8000) >> 15
  58. *
  59. */
  60. uint16_t to_premul16(uint16_t rgb16, uint16_t a16)
  61. {
  62. uint32_t alpha_factor, rgb;
  63. if (a16 == 0) return rgb16;
  64. alpha_factor = _cmsToFixedDomain(a16);
  65. rgb = ((uint32_t) rgb16 * alpha_factor + 0x8000) >> 16;
  66. return (uint16_t)rgb;
  67. }
  68. uint16_t from_premul16(uint16_t rgb16, uint16_t a16)
  69. {
  70. uint32_t alpha_factor, rgb;
  71. if (a16 == 0) return rgb16;
  72. alpha_factor = _cmsToFixedDomain(a16);
  73. rgb = (((uint32_t) rgb16) << 16) / alpha_factor;
  74. if (rgb > 0xffff) rgb = 0xffff;
  75. return (uint16_t)rgb;
  76. }
  77. uint8_t to_premul8(uint8_t rgb8, uint8_t a8)
  78. {
  79. uint32_t alpha_factor, rgb;
  80. if (a8 == 0) return rgb8;
  81. alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(a8));
  82. rgb = ((uint32_t)rgb8 * alpha_factor + 0x8000) >> 16;
  83. return (uint8_t)rgb;
  84. }
  85. uint8_t from_premul8(uint8_t rgb8, uint8_t a8)
  86. {
  87. uint32_t alpha_factor, rgb;
  88. if (a8 == 0) return rgb8;
  89. alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(a8));
  90. rgb = (((uint32_t)rgb8) << 16) / alpha_factor;
  91. if (rgb > 0xff) rgb = 0xff;
  92. return (uint8_t)rgb;
  93. }
  94. static
  95. void dif16to(void)
  96. {
  97. int32_t gpremul, gpremul1;
  98. int32_t max, max1, max2, a, g;
  99. printf("Premul TO diff\n");
  100. max = max1 = max2 = 0;
  101. for (a = 0; a < 65536; a += 255)
  102. for (g = 0; g < 65536; g++)
  103. {
  104. gpremul = to_premul16_float(g, a);
  105. gpremul1 = to_premul16(g, a);
  106. if (gpremul != gpremul1)
  107. {
  108. int32_t dif = abs(gpremul - gpremul1);
  109. if (dif > max)
  110. {
  111. max = dif;
  112. max1 = gpremul;
  113. max2 = gpremul1;
  114. }
  115. }
  116. }
  117. printf("Error max=%d on pre:%d pre1:%d\n", max, max1, max2);
  118. }
  119. static
  120. void dif16from(void)
  121. {
  122. int32_t gpremul, gpremul1;
  123. int32_t max, max1, max2, maxa, maxg, a, g;
  124. printf("Premul FROM diff\n");
  125. max = max1 = max2 = maxa = maxg = 0;
  126. for (a = 0; a < 65536; a += 255)
  127. for (g = 0; g < 65536; g++)
  128. {
  129. gpremul = from_premul16_float(g, a);
  130. gpremul1 = from_premul16(g, a);
  131. if (gpremul != gpremul1)
  132. {
  133. int32_t dif = abs(gpremul - gpremul1);
  134. if (dif > max)
  135. {
  136. max = dif;
  137. max1 = gpremul;
  138. max2 = gpremul1;
  139. maxa = a;
  140. maxg = g;
  141. }
  142. }
  143. }
  144. printf("Error max=%d on pre:%d pre1:%d (a:%d g:%d)\n", max, max1, max2, maxa, maxg);
  145. from_premul16_float(maxg, maxa);
  146. from_premul16(maxg, maxa);
  147. }
  148. static
  149. void dif8to(void)
  150. {
  151. int32_t gpremul, gpremul1;
  152. int32_t max, max1, max2, a, g;
  153. printf("Premul TO8 diff\n");
  154. max = max1 = max2 = 0;
  155. for (a = 0; a < 256; a++)
  156. for (g = 0; g < 256; g++)
  157. {
  158. gpremul = to_premul8_float(g, a);
  159. gpremul1 = to_premul8(g, a);
  160. if (gpremul != gpremul1)
  161. {
  162. int32_t dif = abs(gpremul - gpremul1);
  163. if (dif > max)
  164. {
  165. max = dif;
  166. max1 = gpremul;
  167. max2 = gpremul1;
  168. }
  169. }
  170. }
  171. printf("Error max=%d on pre:%d pre1:%d\n", max, max1, max2);
  172. }
  173. static
  174. void dif8from(void)
  175. {
  176. int32_t gpremul, gpremul1;
  177. int32_t max, max1, max2, maxa, maxg, a, g;
  178. printf("Premul FROM8 diff\n");
  179. max = max1 = max2 = maxa = maxg = 0;
  180. for (a = 0; a < 256; a++)
  181. for (g = 0; g < 256; g++)
  182. {
  183. gpremul = from_premul8_float(g, a);
  184. gpremul1 = from_premul8(g, a);
  185. if (gpremul != gpremul1)
  186. {
  187. int32_t dif = abs(gpremul - gpremul1);
  188. if (dif > max)
  189. {
  190. max = dif;
  191. max1 = gpremul;
  192. max2 = gpremul1;
  193. maxa = a;
  194. maxg = g;
  195. }
  196. }
  197. }
  198. printf("Error max=%d on pre:%d pre1:%d (a:%d g:%d)\n", max, max1, max2, maxa, maxg);
  199. from_premul8_float(maxg, maxa);
  200. from_premul8(maxg, maxa);
  201. }
  202. static
  203. void toFixedDomain(void)
  204. {
  205. int32_t g;
  206. for (g = 0; g < 65536; g++)
  207. {
  208. uint32_t a = _cmsToFixedDomain(g);
  209. uint32_t b = (uint32_t)round(((double)g / 65535.0) * 65536.0);
  210. if (a != b)
  211. printf("%d != %d\n", a, b);
  212. }
  213. }
  214. static
  215. void fromFixedDomain(void)
  216. {
  217. int32_t g;
  218. for (g = 0; g <= 65536; g++)
  219. {
  220. uint32_t a = _cmsFromFixedDomain(g);
  221. uint32_t b = (uint32_t)round(((double)g / 65536.0) * 65535.0);
  222. if (a != b)
  223. printf("%d != %d\n", a, b);
  224. }
  225. }
  226. // Check alpha
  227. int main()
  228. {
  229. toFixedDomain();
  230. fromFixedDomain();
  231. dif8from();
  232. dif8to();
  233. dif16from();
  234. dif16to();
  235. return 0;
  236. }