segment.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #include <string.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  5. #define MAX(a,b) ((a) > (b) ? (a) : (b))
  6. typedef struct {
  7. int x0;
  8. int x1;
  9. int y0;
  10. int y1;
  11. double xmom;
  12. double ymom;
  13. int area;
  14. } seg;
  15. typedef struct {
  16. int x0;
  17. int x1;
  18. } run;
  19. void
  20. find_runs(run *result, const unsigned char *buf, unsigned char thresh, int xs)
  21. {
  22. int x;
  23. int j = 0;
  24. for (x = 0; x < xs;) {
  25. int x0, x1;
  26. for (x0 = x; x0 < xs; x0++)
  27. if (buf[x0] < thresh)
  28. break;
  29. if (x0 == xs)
  30. break;
  31. for (x1 = x0 + 1; x1 < xs; x1++)
  32. if (buf[x1] >= thresh)
  33. break;
  34. result[j].x0 = x0;
  35. result[j].x1 = x1;
  36. j++;
  37. x = x1 + 1;
  38. }
  39. result[j].x0 = 0;
  40. result[j].x1 = 0;
  41. }
  42. void
  43. print_rect(const seg *r)
  44. {
  45. printf("%d %d %d %d %g rect\n", r->x0, r->y0, r->x1, r->y1,
  46. r->area / (1.0 * (r->x1 - r->x0) * (r->y1 - r->y0)));
  47. printf("%g %g ci\n", r->xmom / r->area, r->ymom / r->area);
  48. }
  49. void
  50. merge_runs(seg *buf, const run *new_runs, int y)
  51. {
  52. int bi, ni;
  53. int bs;
  54. int bi0;
  55. int flag;
  56. for (bs = 0; buf[bs].x1; bs++);
  57. bi = 0;
  58. flag = 1;
  59. for (ni = 0; new_runs[ni].x1; ni++) {
  60. int run_len = new_runs[ni].x1 - new_runs[ni].x0;
  61. bi0 = bi;
  62. for (; bi < bs && buf[bi].x1 <= new_runs[ni].x0; bi++) {
  63. if (flag) {
  64. buf[bi].y1 = y;
  65. print_rect(&buf[bi]);
  66. } else {
  67. bi0 = bi + 1;
  68. flag = 1;
  69. }
  70. }
  71. if (bi > bi0) {
  72. memmove(&buf[bi0], &buf[bi], (bs - bi) * sizeof(seg));
  73. bs += bi0 - bi;
  74. }
  75. bi = bi0;
  76. if (bi < bs && buf[bi].x0 < new_runs[ni].x1) {
  77. double xmom = buf[bi].xmom;
  78. double ymom = buf[bi].ymom;
  79. int area = buf[bi].area;
  80. int y0 = buf[bi].y0;
  81. for (bi = bi + 1; bi < bs && buf[bi].x0 < new_runs[ni].x1; bi++) {
  82. y0 = MIN(y0, buf[bi].y0);
  83. xmom += buf[bi].xmom;
  84. ymom += buf[bi].ymom;
  85. area += buf[bi].area;
  86. }
  87. buf[bi0].x0 = MIN(buf[bi0].x0, new_runs[ni].x0);
  88. buf[bi0].x1 = MAX(buf[bi - 1].x1, new_runs[ni].x1);
  89. buf[bi0].y0 = y0;
  90. buf[bi0].xmom = xmom + run_len * .5 * (new_runs[ni].x0 + new_runs[ni].x1);
  91. buf[bi0].ymom = ymom + run_len * y;
  92. buf[bi0].area = area + run_len;
  93. if (bi > bi0 + 1) {
  94. memmove(&buf[bi0 + 1], &buf[bi], (bs - bi) * sizeof(seg));
  95. bs += bi0 + 1 - bi;
  96. }
  97. bi = bi0;
  98. flag = 0;
  99. } else {
  100. memmove(&buf[bi + 1], &buf[bi], (bs - bi) * sizeof(seg));
  101. bs++;
  102. buf[bi].x0 = new_runs[ni].x0;
  103. buf[bi].x1 = new_runs[ni].x1;
  104. buf[bi].y0 = y;
  105. buf[bi].xmom = run_len * .5 * (new_runs[ni].x0 + new_runs[ni].x1);
  106. buf[bi].ymom = run_len * y;
  107. buf[bi].area = run_len;
  108. bi++;
  109. flag = 1;
  110. }
  111. }
  112. bi0 = bi;
  113. for (; bi < bs; bi++) {
  114. if (flag) {
  115. buf[bi].y1 = y;
  116. print_rect(&buf[bi]);
  117. } else {
  118. bi0 = bi + 1;
  119. flag = 1;
  120. }
  121. }
  122. buf[bi0].x0 = 0;
  123. buf[bi0].x1 = 0;
  124. }
  125. static void
  126. die (char *why)
  127. {
  128. fprintf (stderr, "%s\n", why);
  129. exit (1);
  130. }
  131. #define MAX_SIZE 65536
  132. int
  133. main (int argc, char **argv)
  134. {
  135. FILE *fi = stdin;
  136. FILE *fo = stdout;
  137. char buf[256];
  138. int xs, ys;
  139. int depth;
  140. unsigned char *imgbuf;
  141. seg *segs;
  142. run *runs;
  143. int y;
  144. fgets (buf, sizeof(buf), fi);
  145. if (buf[0] != 'P' || buf[1] != '5')
  146. die ("Need pgmraw image on input");
  147. xs = ys = 0;
  148. do
  149. fgets (buf, sizeof(buf), fi);
  150. while (buf[0] == '#');
  151. sscanf (buf, "%d %d", &xs, &ys);
  152. if (xs <= 0 || ys <= 0 || xs > MAX_SIZE || ys > MAX_SIZE)
  153. die ("Input image size out of range");
  154. do
  155. fgets (buf, sizeof(buf), fi);
  156. while (buf[0] == '#');
  157. sscanf (buf, "%d", &depth);
  158. if (depth != 255)
  159. die ("Only works with depth=255 images");
  160. runs = (run *)malloc(((xs + 3) >> 1) * sizeof(run));
  161. segs = (seg *)malloc(((xs + 3) >> 1) * sizeof(seg));
  162. imgbuf = (unsigned char *)malloc (xs);
  163. segs[0].x0 = 0;
  164. segs[0].x1 = 0;
  165. for (y = 0; y < ys; y++) {
  166. fread (imgbuf, 1, xs, fi);
  167. find_runs(runs, imgbuf, 160, xs);
  168. merge_runs(segs, runs, y);
  169. }
  170. free(imgbuf);
  171. free(runs);
  172. free(segs);
  173. return 0;
  174. }