pam.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /* pam.h - pam (portable alpha map) utility library
  2. **
  3. ** Colormap routines.
  4. **
  5. ** Copyright (C) 1989, 1991 by Jef Poskanzer.
  6. ** Copyright (C) 1997 by Greg Roelofs.
  7. **
  8. ** Permission to use, copy, modify, and distribute this software and its
  9. ** documentation for any purpose and without fee is hereby granted, provided
  10. ** that the above copyright notice appear in all copies and that both that
  11. ** copyright notice and this permission notice appear in supporting
  12. ** documentation. This software is provided "as is" without express or
  13. ** implied warranty.
  14. */
  15. #ifndef PAM_H
  16. #define PAM_H
  17. float liqpowf(float x, float y);
  18. // accidental debug assertions make color search much slower,
  19. // so force assertions off if there's no explicit setting
  20. #if !defined(NDEBUG) && !defined(DEBUG)
  21. #define NDEBUG
  22. #endif
  23. #include <math.h>
  24. #include <assert.h>
  25. #include <stdlib.h>
  26. #include <stdbool.h>
  27. #ifndef MAX
  28. # define MAX(a,b) ((a) > (b)? (a) : (b))
  29. # define MIN(a,b) ((a) < (b)? (a) : (b))
  30. #endif
  31. #define MAX_DIFF 1e20
  32. #ifndef USE_SSE
  33. # if defined(__SSE__) && (defined(__amd64__) || defined(__X86_64__) || defined(_WIN64) || defined(WIN32) || defined(__WIN32__))
  34. # define USE_SSE 1
  35. # else
  36. # define USE_SSE 0
  37. # endif
  38. #endif
  39. #if USE_SSE
  40. # include <xmmintrin.h>
  41. # ifdef _MSC_VER
  42. # include <intrin.h>
  43. # define SSE_ALIGN
  44. # else
  45. # define SSE_ALIGN __attribute__ ((aligned (16)))
  46. # if defined(__i386__) && defined(__PIC__)
  47. # define cpuid(func,ax,bx,cx,dx)\
  48. __asm__ __volatile__ ( \
  49. "push %%ebx\n" \
  50. "cpuid\n" \
  51. "mov %%ebx, %1\n" \
  52. "pop %%ebx\n" \
  53. : "=a" (ax), "=r" (bx), "=c" (cx), "=d" (dx) \
  54. : "a" (func));
  55. # else
  56. # define cpuid(func,ax,bx,cx,dx)\
  57. __asm__ __volatile__ ("cpuid":\
  58. "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func));
  59. # endif
  60. #endif
  61. #else
  62. # define SSE_ALIGN
  63. #endif
  64. #ifndef _MSC_VER
  65. #define LIQ_ARRAY(type, var, count) type var[count]
  66. #else
  67. #define LIQ_ARRAY(type, var, count) type* var = (type*)_alloca(sizeof(type)*(count))
  68. #endif
  69. #if defined(__GNUC__) || defined (__llvm__)
  70. #define ALWAYS_INLINE __attribute__((always_inline)) inline
  71. #define NEVER_INLINE __attribute__ ((noinline))
  72. #elif defined(_MSC_VER)
  73. #define inline __inline
  74. #define restrict __restrict
  75. #define ALWAYS_INLINE __forceinline
  76. #define NEVER_INLINE __declspec(noinline)
  77. #else
  78. #define ALWAYS_INLINE inline
  79. #define NEVER_INLINE
  80. #endif
  81. /* from pam.h */
  82. typedef struct {
  83. unsigned char r, g, b, a;
  84. } rgba_pixel;
  85. typedef struct {
  86. float a, r, g, b;
  87. } SSE_ALIGN f_pixel;
  88. static const float internal_gamma = 0.5499f;
  89. LIQ_PRIVATE void to_f_set_gamma(float gamma_lut[], const double gamma);
  90. /**
  91. Converts 8-bit color to internal gamma and premultiplied alpha.
  92. (premultiplied color space is much better for blending of semitransparent colors)
  93. */
  94. ALWAYS_INLINE static f_pixel rgba_to_f(const float gamma_lut[], const rgba_pixel px);
  95. inline static f_pixel rgba_to_f(const float gamma_lut[], const rgba_pixel px)
  96. {
  97. float a = px.a/255.f;
  98. return (f_pixel) {
  99. .a = a,
  100. .r = gamma_lut[px.r]*a,
  101. .g = gamma_lut[px.g]*a,
  102. .b = gamma_lut[px.b]*a,
  103. };
  104. }
  105. inline static rgba_pixel f_to_rgb(const float gamma, const f_pixel px)
  106. {
  107. if (px.a < 1.f/256.f) {
  108. return (rgba_pixel){0,0,0,0};
  109. }
  110. float r = px.r / px.a,
  111. g = px.g / px.a,
  112. b = px.b / px.a,
  113. a = px.a;
  114. r = liqpowf((float)r, (float)(gamma/internal_gamma));
  115. g = liqpowf((float)g, (float)(gamma/internal_gamma));
  116. b = liqpowf((float)b, (float)(gamma/internal_gamma));
  117. // 256, because numbers are in range 1..255.9999… rounded down
  118. r *= 256.f;
  119. g *= 256.f;
  120. b *= 256.f;
  121. a *= 256.f;
  122. return (rgba_pixel){
  123. .r = r>=255.f ? 255 : r,
  124. .g = g>=255.f ? 255 : g,
  125. .b = b>=255.f ? 255 : b,
  126. .a = a>=255.f ? 255 : a,
  127. };
  128. }
  129. ALWAYS_INLINE static double colordifference_ch(const double x, const double y, const double alphas);
  130. inline static double colordifference_ch(const double x, const double y, const double alphas)
  131. {
  132. // maximum of channel blended on white, and blended on black
  133. // premultiplied alpha and backgrounds 0/1 shorten the formula
  134. const double black = x-y, white = black+alphas;
  135. return MAX(black*black, white*white);
  136. }
  137. ALWAYS_INLINE static float colordifference_stdc(const f_pixel px, const f_pixel py);
  138. inline static float colordifference_stdc(const f_pixel px, const f_pixel py)
  139. {
  140. // px_b.rgb = px.rgb + 0*(1-px.a) // blend px on black
  141. // px_b.a = px.a + 1*(1-px.a)
  142. // px_w.rgb = px.rgb + 1*(1-px.a) // blend px on white
  143. // px_w.a = px.a + 1*(1-px.a)
  144. // px_b.rgb = px.rgb // difference same as in opaque RGB
  145. // px_b.a = 1
  146. // px_w.rgb = px.rgb - px.a // difference simplifies to formula below
  147. // px_w.a = 1
  148. // (px.rgb - px.a) - (py.rgb - py.a)
  149. // (px.rgb - py.rgb) + (py.a - px.a)
  150. const double alphas = py.a-px.a;
  151. return colordifference_ch(px.r, py.r, alphas) +
  152. colordifference_ch(px.g, py.g, alphas) +
  153. colordifference_ch(px.b, py.b, alphas);
  154. }
  155. ALWAYS_INLINE static float colordifference(f_pixel px, f_pixel py);
  156. inline static float colordifference(f_pixel px, f_pixel py)
  157. {
  158. #if USE_SSE
  159. const __m128 vpx = _mm_load_ps((const float*)&px);
  160. const __m128 vpy = _mm_load_ps((const float*)&py);
  161. // y.a - x.a
  162. __m128 alphas = _mm_sub_ss(vpy, vpx);
  163. alphas = _mm_shuffle_ps(alphas,alphas,0); // copy first to all four
  164. __m128 onblack = _mm_sub_ps(vpx, vpy); // x - y
  165. __m128 onwhite = _mm_add_ps(onblack, alphas); // x - y + (y.a - x.a)
  166. onblack = _mm_mul_ps(onblack, onblack);
  167. onwhite = _mm_mul_ps(onwhite, onwhite);
  168. const __m128 max = _mm_max_ps(onwhite, onblack);
  169. // add rgb, not a
  170. const __m128 maxhl = _mm_movehl_ps(max, max);
  171. const __m128 tmp = _mm_add_ps(max, maxhl);
  172. const __m128 sum = _mm_add_ss(maxhl, _mm_shuffle_ps(tmp, tmp, 1));
  173. const float res = _mm_cvtss_f32(sum);
  174. assert(fabs(res - colordifference_stdc(px,py)) < 0.001);
  175. return res;
  176. #else
  177. return colordifference_stdc(px,py);
  178. #endif
  179. }
  180. /* from pamcmap.h */
  181. union rgba_as_int {
  182. rgba_pixel rgba;
  183. unsigned int l;
  184. };
  185. typedef struct {
  186. f_pixel acolor;
  187. float adjusted_weight, // perceptual weight changed to tweak how mediancut selects colors
  188. perceptual_weight; // number of pixels weighted by importance of different areas of the picture
  189. float color_weight; // these two change every time histogram subset is sorted
  190. union {
  191. unsigned int sort_value;
  192. unsigned char likely_colormap_index;
  193. } tmp;
  194. } hist_item;
  195. typedef struct {
  196. hist_item *achv;
  197. void (*free)(void*);
  198. double total_perceptual_weight;
  199. unsigned int size;
  200. unsigned int ignorebits;
  201. } histogram;
  202. typedef struct {
  203. f_pixel acolor;
  204. float popularity;
  205. bool fixed; // if true it's user-supplied and must not be changed (e.g in K-Means iteration)
  206. } colormap_item;
  207. typedef struct colormap {
  208. unsigned int colors;
  209. void* (*malloc)(size_t);
  210. void (*free)(void*);
  211. colormap_item palette[];
  212. } colormap;
  213. struct acolorhist_arr_item {
  214. union rgba_as_int color;
  215. unsigned int perceptual_weight;
  216. };
  217. struct acolorhist_arr_head {
  218. struct acolorhist_arr_item inline1, inline2;
  219. unsigned int used, capacity;
  220. struct acolorhist_arr_item *other_items;
  221. };
  222. struct acolorhash_table {
  223. struct mempool *mempool;
  224. unsigned int ignorebits, maxcolors, colors, cols, rows;
  225. unsigned int hash_size;
  226. unsigned int freestackp;
  227. struct acolorhist_arr_item *freestack[512];
  228. struct acolorhist_arr_head buckets[];
  229. };
  230. LIQ_PRIVATE void pam_freeacolorhash(struct acolorhash_table *acht);
  231. LIQ_PRIVATE struct acolorhash_table *pam_allocacolorhash(unsigned int maxcolors, unsigned int surface, unsigned int ignorebits, void* (*malloc)(size_t), void (*free)(void*));
  232. LIQ_PRIVATE histogram *pam_acolorhashtoacolorhist(const struct acolorhash_table *acht, const double gamma, void* (*malloc)(size_t), void (*free)(void*));
  233. LIQ_PRIVATE bool pam_computeacolorhash(struct acolorhash_table *acht, const rgba_pixel *const pixels[], unsigned int cols, unsigned int rows, const unsigned char *importance_map);
  234. LIQ_PRIVATE bool pam_add_to_hash(struct acolorhash_table *acht, unsigned int hash, unsigned int boost, union rgba_as_int px, unsigned int row, unsigned int rows);
  235. LIQ_PRIVATE void pam_freeacolorhist(histogram *h);
  236. LIQ_PRIVATE colormap *pam_colormap(unsigned int colors, void* (*malloc)(size_t), void (*free)(void*));
  237. LIQ_PRIVATE colormap *pam_duplicate_colormap(colormap *map);
  238. LIQ_PRIVATE void pam_freecolormap(colormap *c);
  239. #endif