PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/pnm2ppa-1.04/make_hash_ink.c

#
C | 438 lines | 335 code | 56 blank | 47 comment | 82 complexity | f423678679008869929b9b3e998f5fd6 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*****************************************************************
  2. make_hash_ink.h -generate hashed version of palette.h data
  3. -----------------
  4. begin : Tue Jan 24 2000
  5. copyright : (C) 2000 by the pmn2ppa project
  6. author : Klamer Schutte
  7. email : Schutte@fel.tno.nl
  8. ******************************************************************/
  9. /***************************************************************************
  10. * *
  11. * This program is free software; you can redistribute it and/or modify *
  12. * it under the terms of the GNU General Public License as published by *
  13. * the Free Software Foundation; either version 2 of the License, or *
  14. * (at your option) any later version. *
  15. * *
  16. ***************************************************************************/
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <assert.h>
  20. #include "palette.h"
  21. #include "hash_ink.h"
  22. #define SHIFTED (1 << (shift))
  23. #define NOTSHIFTED (1 << (8 - shift))
  24. #define ENTRIES_ARR (NOTSHIFTED * NOTSHIFTED * NOTSHIFTED)
  25. int MaxPass;
  26. struct entry
  27. {
  28. int xyz;
  29. union {
  30. int entry_nr;
  31. struct hash_ink *hi;
  32. } u;
  33. struct entry *next; /* this list is sorted on xyz; lowest xyz first */
  34. };
  35. struct entry_list
  36. {
  37. struct entry *entries;
  38. int num_entries;
  39. struct entry_list *next; /* this list is sorted in num_entries; lowest
  40. numbers first */
  41. } *start_list = 0;
  42. inline int
  43. calc_xyz( struct hash_ink *hi )
  44. {
  45. /* if these assertions fail the result is not unique */
  46. assert(hi->x < (1 << 3));
  47. assert(hi->y < (1 << 3));
  48. return hi->x + (hi->y << 3) + (hi->z << 6);
  49. }
  50. int
  51. add_entry2( struct entry *e, int n, struct entry **ptr_to )
  52. {
  53. struct entry_list *cel, **prev_ptr, *new_el;
  54. struct entry *ce1, *ce2;
  55. static int this_entry = 0;
  56. int next_entry;
  57. assert(n > 0);
  58. prev_ptr = &start_list;
  59. for(cel = start_list; cel != 0; prev_ptr = &(cel->next), cel = cel->next)
  60. {
  61. if (cel->num_entries < n)
  62. continue;
  63. if (cel->num_entries > n)
  64. break;
  65. for(ce1 = cel->entries, ce2 = e; ce1 != 0;
  66. ce1 = ce1->next, ce2 = ce2->next)
  67. {
  68. assert(ce2 != 0);
  69. if (ce1->xyz != ce2->xyz)
  70. goto next_cel;
  71. }
  72. /* OK, we have found the correct entry. Delete set *e, and
  73. return the entry number */
  74. for(ce1 = e; ce1 != 0; ce1 = ce2)
  75. {
  76. ce2 = ce1->next;
  77. free(ce1);
  78. }
  79. if (ptr_to != 0)
  80. *ptr_to = cel->entries;
  81. return cel->entries->u.entry_nr;
  82. next_cel: ;
  83. }
  84. /* Hmmm. The set e is not found. Add the first item to the set,
  85. and recursively attempt it for its tail... */
  86. new_el = (struct entry_list *) malloc(sizeof(struct entry_list));
  87. /* printf(" New el %x assigned to %x\n", new_el, prev_ptr); */
  88. *prev_ptr = new_el;
  89. new_el->entries = e;
  90. new_el->num_entries = n;
  91. /* printf("new el next = %x\n", cel); */
  92. new_el->next = cel;
  93. if (e->next != 0)
  94. next_entry = add_entry2( e->next, n-1, &(e->next));
  95. else
  96. next_entry = -1;
  97. printf("\t/* %d */\t{ { %d, %d, %d}, %d, %d, %d, ", this_entry,
  98. e->u.hi->data[0], e->u.hi->data[1], e->u.hi->data[2],
  99. e->u.hi->x, e->u.hi->y, e->u.hi->z );
  100. if (next_entry == -1)
  101. printf("0 },\n");
  102. else
  103. printf("&entries%d[%d] },\n", MaxPass, next_entry);
  104. e->u.entry_nr = this_entry++;
  105. if (ptr_to != 0)
  106. *ptr_to = e;
  107. return e->u.entry_nr;
  108. }
  109. int
  110. add_entry( struct hash_ink *hi )
  111. {
  112. /* First, convert the hash_ink set to a entry set
  113. Second, check start_list if it is contained (done in add_entry2())
  114. If contained: return the entry number
  115. Else: add to start_list */
  116. struct entry *first = 0, *cur, *loop, **prev_ptr;
  117. struct hash_ink *chi;
  118. int res;
  119. int n = 0; /* n == number of entries in this set */
  120. for(chi = hi; chi != 0; chi = chi->next)
  121. {
  122. n++;
  123. cur = (struct entry *) malloc( sizeof(struct entry) );
  124. cur->xyz = calc_xyz( chi );
  125. cur->u.hi = chi;
  126. prev_ptr = &first;
  127. for(loop = first; loop != 0; loop = loop->next)
  128. {
  129. if (loop->xyz >= cur->xyz)
  130. {
  131. cur->next = loop;
  132. *prev_ptr = cur;
  133. break;
  134. }
  135. prev_ptr = &(loop->next);
  136. }
  137. if (loop == 0)
  138. {
  139. cur->next = 0;
  140. *prev_ptr = cur;
  141. }
  142. }
  143. res = add_entry2( first, n, 0 );
  144. for(chi = hi; chi != 0; )
  145. {
  146. struct hash_ink *nhi = chi->next;
  147. free(chi);
  148. chi = nhi;
  149. }
  150. return res;
  151. }
  152. int
  153. main(int argc, char *argv[] )
  154. {
  155. /* int MaxPass; */
  156. int x, y, z, r, g, b;
  157. int ra, ga, ba, rd, gd, bd;
  158. float dmin = -1, dmax = -1, d1;
  159. struct hash_ink /* **arr, */ *first, *prev, *cur;
  160. int i, n;
  161. int shift;
  162. int *entries_arr;
  163. if (argc != 3)
  164. fprintf(stderr, "Usage: %s MaxPass shift >> hash_ink.c\n", argv[0]);
  165. MaxPass = atoi(argv[1]);
  166. shift = atoi(argv[2]);
  167. /* arr = (struct hash_ink **) malloc( sizeof(struct hash_ink*) * ENTRIES_ARR );
  168. for(i = 0; i < ENTRIES_ARR; i++)
  169. arr[i] = 0; */
  170. entries_arr = (int *) malloc(sizeof(int) * ENTRIES_ARR);
  171. for(i = 0; i < ENTRIES_ARR; i++)
  172. entries_arr[i] = -1;
  173. printf("/* generated by %s %s %s */\n\n", argv[0], argv[1], argv[2] );
  174. printf("#include \"hash_ink.h\"\n\n");
  175. printf("int shift%d = %d;\n\n", MaxPass, shift);
  176. printf("static struct hash_ink entries%d[] = {\n", MaxPass);
  177. i = 0;
  178. for(r=0; r < 256; r += SHIFTED)
  179. for(g=0; g < 256; g += SHIFTED)
  180. for(b=0; b < 256; b += SHIFTED)
  181. {
  182. int rr = r >> shift;
  183. int gg = g >> shift;
  184. int bb = b >> shift;
  185. int h = (rr << (16 - shift * 2)) + (gg << (8-shift)) + bb;
  186. /* fprintf(stderr, "%d %d %d -> %d %d %d -> %d\n", r, g, b, rr, gg, bb, h );*/
  187. first = (struct hash_ink *) malloc( sizeof(struct hash_ink));
  188. /* arr[h]->x = i++; */
  189. cur = first;
  190. cur->next = 0;
  191. /* Now, calculate the dmin for hash entry h.
  192. Fill in *first with minimal values */
  193. dmin = -1;
  194. for(ra = 0; ra < SHIFTED; ra+=(SHIFTED-1))
  195. for(ga = 0; ga < SHIFTED; ga += (SHIFTED-1))
  196. for(ba = 0; ba < SHIFTED; ba += (SHIFTED -1))
  197. {
  198. int R = r + ra;
  199. int G = g + ga;
  200. int B = b + ba;
  201. int new_dmin = 0;
  202. for (z = 0; z < MaxPass + 1; z++)
  203. for (x = 0; x < MaxPass + 1; x++)
  204. for (y = 0; y < MaxPass + 1; y++)
  205. if (!
  206. (((x == 4) && (y > 2) && (z > 2)) ||
  207. ((y == 4) && (x > 2) && (z > 2)) ||
  208. ((z == 4) && (y > 2) && (x > 2))))
  209. {
  210. rd =
  211. (int) R - (int) hp_pal[4 - x][4 - y][4 -
  212. z]
  213. [0];
  214. gd =
  215. (int) G - (int) hp_pal[4 - x][4 - y][4 -
  216. z]
  217. [1];
  218. bd =
  219. (int) B - (int) hp_pal[4 - x][4 - y][4 -
  220. z]
  221. [2];
  222. d1 = /* 0.5 * */ rd * rd + gd * gd + bd * bd;
  223. if ((dmin < 0) || (d1 < dmin))
  224. {
  225. /* fprintf(stderr, "Found min %f, %d, %d, %d (%f, %d, %d %d)\n", d1, x, y, z, dmin, cur->x, cur->y, cur->z); */
  226. cur->data[0] = hp_pal[4 - x][4 - y][4 - z][0];
  227. cur->data[1] = hp_pal[4 - x][4 - y][4 - z][1];
  228. cur->data[2] = hp_pal[4 - x][4 - y][4 - z][2];
  229. cur->x = x;
  230. cur->y = y;
  231. cur->z = z;
  232. dmin = d1;
  233. new_dmin = 1;
  234. }
  235. }
  236. }
  237. /* Now, calculate the dmax for hash entry h.
  238. Fill in *first with minimal values */
  239. dmax = -1;
  240. for(ra = 0; ra < SHIFTED; ra+=(SHIFTED-1))
  241. for(ga = 0; ga < SHIFTED; ga += (SHIFTED-1))
  242. for(ba = 0; ba < SHIFTED; ba += (SHIFTED-1))
  243. {
  244. int R = r + ra;
  245. int G = g + ga;
  246. int B = b + ba;
  247. z = cur->z;
  248. y = cur->y;
  249. x = cur->x;
  250. {
  251. rd =
  252. (int) R - (int) hp_pal[4 - x][4 - y][4 -
  253. z]
  254. [0];
  255. gd =
  256. (int) G - (int) hp_pal[4 - x][4 - y][4 -
  257. z]
  258. [1];
  259. bd =
  260. (int) B - (int) hp_pal[4 - x][4 - y][4 -
  261. z]
  262. [2];
  263. d1 = /* 0.5 * */ rd * rd + gd * gd + bd * bd;
  264. if (d1 > dmax)
  265. {
  266. /* fprintf(stderr, "Found max %f, %d, %d, %d (%f, %f)\n", d1, x, y, z, dmax, dmin); */
  267. cur->data[0] = hp_pal[4 - x][4 - y][4 - z][0];
  268. cur->data[1] = hp_pal[4 - x][4 - y][4 - z][1];
  269. cur->data[2] = hp_pal[4 - x][4 - y][4 - z][2];
  270. cur->x = x;
  271. cur->y = y;
  272. cur->z = z;
  273. dmax = d1;
  274. }
  275. }
  276. }
  277. /* Now, for every {x,y,z} for which d1 is smaller then dmax add
  278. this entry to the *first (as a linked list!) */
  279. prev = cur;
  280. n = 0;
  281. for (z = 0; z < MaxPass + 1; z++)
  282. for (x = 0; x < MaxPass + 1; x++)
  283. for (y = 0; y < MaxPass + 1; y++)
  284. {
  285. if (!
  286. (((x == 4) && (y > 2) && (z > 2)) ||
  287. ((y == 4) && (x > 2) && (z > 2)) ||
  288. ((z == 4) && (y > 2) && (x > 2))))
  289. {
  290. for(ra = 0; ra < SHIFTED; ra+=(SHIFTED-1))
  291. for(ga = 0; ga < SHIFTED; ga += (SHIFTED-1))
  292. for(ba = 0; ba < SHIFTED; ba += (SHIFTED-1))
  293. {
  294. int R = r + ra;
  295. int G = g + ga;
  296. int B = b + ba;
  297. rd =
  298. (int) R - (int) hp_pal[4 - x][4 - y][4 -
  299. z]
  300. [0];
  301. gd =
  302. (int) G - (int) hp_pal[4 - x][4 - y][4 -
  303. z]
  304. [1];
  305. bd =
  306. (int) B - (int) hp_pal[4 - x][4 - y][4 -
  307. z]
  308. [2];
  309. d1 = /* 0.5 * */ rd * rd + gd * gd + bd * bd;
  310. if ((d1 < dmax) && (!((x == first->x) &&
  311. (y == first->y) &&
  312. (z == first->z))))
  313. {
  314. struct hash_ink *cur = (struct hash_ink *)
  315. malloc( sizeof(struct hash_ink) );
  316. prev->next = cur;
  317. cur->next = 0;
  318. prev = cur;
  319. /* fprintf(stderr, "Added min %f, %d, %d, %d (%f, %f, %d, %d %d)\n", d1, x, y, z, dmin, dmax, first->x, first->y, first->z); */
  320. cur->data[0] = hp_pal[4 - x][4 - y][4 - z][0];
  321. cur->data[1] = hp_pal[4 - x][4 - y][4 - z][1];
  322. cur->data[2] = hp_pal[4 - x][4 - y][4 - z][2];
  323. cur->x = x;
  324. cur->y = y;
  325. cur->z = z;
  326. n++;
  327. goto next_xyz; /* break out of ra gb ba loops */
  328. }
  329. }
  330. }
  331. next_xyz: ;
  332. }
  333. /* fprintf(stderr, "%d %d %d (%d): found %d %d %d (%d,%d,%d) (%f, %f) * %d\n",
  334. r, g, b, h, first->x, first->y, first->z,
  335. first->data[0], first->data[1], first->data[2],
  336. dmin, dmax, n ); */
  337. entries_arr[h] = add_entry(first);
  338. }
  339. #ifdef notdef
  340. printf("#include \"hash_ink.h\"\n\n");
  341. printf("int shift%d = %d;\n\n", MaxPass, shift);
  342. printf("static struct hash_ink entries%d[] = {\n", MaxPass);
  343. n = 0;
  344. for(i = 0; i < ENTRIES_ARR; i++)
  345. {
  346. printf("\t{ {%d, %d, %d}, %d, %d, %d, ",
  347. arr[i]->data[0], arr[i]->data[1], arr[i]->data[2],
  348. arr[i]->x, arr[i]->y, arr[i]->z );
  349. n++;
  350. cur = arr[i]->next;
  351. while( cur != 0 )
  352. {
  353. printf(" &entries%d[%d] },\n", MaxPass, n);
  354. printf("\t\t{ { %d, %d, %d} , %d, %d, %d, ",
  355. cur->data[0], cur->data[1], cur->data[2],
  356. cur->x, cur->y, cur->z );
  357. n++;
  358. cur = cur->next;
  359. }
  360. printf(" 0 },\n");
  361. }
  362. #endif
  363. printf("};\n\n");
  364. printf("struct hash_ink *arr_max%d[] = {", MaxPass);
  365. n = 0;
  366. for(i = 0; i < ENTRIES_ARR; i++)
  367. {
  368. printf("\t&entries%d[%d], \n", MaxPass, entries_arr[i]);
  369. #ifdef notdef
  370. n++;
  371. cur = arr[i]->next;
  372. while( cur != 0)
  373. {
  374. n++;
  375. cur = cur->next;
  376. }
  377. #endif
  378. }
  379. printf("};\n\n/* end of file generated by %s %s %s (%d entries) */\n\n",
  380. argv[0], argv[1], argv[2], n);
  381. return 0;
  382. }