123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #define MIN(a,b) ((a) < (b) ? (a) : (b))
- #define MAX(a,b) ((a) > (b) ? (a) : (b))
- typedef struct {
- int x0;
- int x1;
- int y0;
- int y1;
- double xmom;
- double ymom;
- int area;
- } seg;
- typedef struct {
- int x0;
- int x1;
- } run;
- void
- find_runs(run *result, const unsigned char *buf, unsigned char thresh, int xs)
- {
- int x;
- int j = 0;
- for (x = 0; x < xs;) {
- int x0, x1;
- for (x0 = x; x0 < xs; x0++)
- if (buf[x0] < thresh)
- break;
- if (x0 == xs)
- break;
- for (x1 = x0 + 1; x1 < xs; x1++)
- if (buf[x1] >= thresh)
- break;
- result[j].x0 = x0;
- result[j].x1 = x1;
- j++;
- x = x1 + 1;
- }
- result[j].x0 = 0;
- result[j].x1 = 0;
- }
- void
- print_rect(const seg *r)
- {
- printf("%d %d %d %d %g rect\n", r->x0, r->y0, r->x1, r->y1,
- r->area / (1.0 * (r->x1 - r->x0) * (r->y1 - r->y0)));
- printf("%g %g ci\n", r->xmom / r->area, r->ymom / r->area);
- }
- void
- merge_runs(seg *buf, const run *new_runs, int y)
- {
- int bi, ni;
- int bs;
- int bi0;
- int flag;
- for (bs = 0; buf[bs].x1; bs++);
- bi = 0;
- flag = 1;
- for (ni = 0; new_runs[ni].x1; ni++) {
- int run_len = new_runs[ni].x1 - new_runs[ni].x0;
- bi0 = bi;
- for (; bi < bs && buf[bi].x1 <= new_runs[ni].x0; bi++) {
- if (flag) {
- buf[bi].y1 = y;
- print_rect(&buf[bi]);
- } else {
- bi0 = bi + 1;
- flag = 1;
- }
- }
- if (bi > bi0) {
- memmove(&buf[bi0], &buf[bi], (bs - bi) * sizeof(seg));
- bs += bi0 - bi;
- }
- bi = bi0;
- if (bi < bs && buf[bi].x0 < new_runs[ni].x1) {
- double xmom = buf[bi].xmom;
- double ymom = buf[bi].ymom;
- int area = buf[bi].area;
- int y0 = buf[bi].y0;
- for (bi = bi + 1; bi < bs && buf[bi].x0 < new_runs[ni].x1; bi++) {
- y0 = MIN(y0, buf[bi].y0);
- xmom += buf[bi].xmom;
- ymom += buf[bi].ymom;
- area += buf[bi].area;
- }
- buf[bi0].x0 = MIN(buf[bi0].x0, new_runs[ni].x0);
- buf[bi0].x1 = MAX(buf[bi - 1].x1, new_runs[ni].x1);
- buf[bi0].y0 = y0;
- buf[bi0].xmom = xmom + run_len * .5 * (new_runs[ni].x0 + new_runs[ni].x1);
- buf[bi0].ymom = ymom + run_len * y;
- buf[bi0].area = area + run_len;
- if (bi > bi0 + 1) {
- memmove(&buf[bi0 + 1], &buf[bi], (bs - bi) * sizeof(seg));
- bs += bi0 + 1 - bi;
- }
- bi = bi0;
- flag = 0;
- } else {
- memmove(&buf[bi + 1], &buf[bi], (bs - bi) * sizeof(seg));
- bs++;
- buf[bi].x0 = new_runs[ni].x0;
- buf[bi].x1 = new_runs[ni].x1;
- buf[bi].y0 = y;
- buf[bi].xmom = run_len * .5 * (new_runs[ni].x0 + new_runs[ni].x1);
- buf[bi].ymom = run_len * y;
- buf[bi].area = run_len;
- bi++;
- flag = 1;
- }
- }
- bi0 = bi;
- for (; bi < bs; bi++) {
- if (flag) {
- buf[bi].y1 = y;
- print_rect(&buf[bi]);
- } else {
- bi0 = bi + 1;
- flag = 1;
- }
- }
- buf[bi0].x0 = 0;
- buf[bi0].x1 = 0;
- }
- static void
- die (char *why)
- {
- fprintf (stderr, "%s\n", why);
- exit (1);
- }
- #define MAX_SIZE 65536
- int
- main (int argc, char **argv)
- {
- FILE *fi = stdin;
- FILE *fo = stdout;
- char buf[256];
- int xs, ys;
- int depth;
- unsigned char *imgbuf;
- seg *segs;
- run *runs;
- int y;
- fgets (buf, sizeof(buf), fi);
- if (buf[0] != 'P' || buf[1] != '5')
- die ("Need pgmraw image on input");
- xs = ys = 0;
- do
- fgets (buf, sizeof(buf), fi);
- while (buf[0] == '#');
- sscanf (buf, "%d %d", &xs, &ys);
- if (xs <= 0 || ys <= 0 || xs > MAX_SIZE || ys > MAX_SIZE)
- die ("Input image size out of range");
- do
- fgets (buf, sizeof(buf), fi);
- while (buf[0] == '#');
- sscanf (buf, "%d", &depth);
- if (depth != 255)
- die ("Only works with depth=255 images");
- runs = (run *)malloc(((xs + 3) >> 1) * sizeof(run));
- segs = (seg *)malloc(((xs + 3) >> 1) * sizeof(seg));
- imgbuf = (unsigned char *)malloc (xs);
- segs[0].x0 = 0;
- segs[0].x1 = 0;
- for (y = 0; y < ys; y++) {
- fread (imgbuf, 1, xs, fi);
- find_runs(runs, imgbuf, 160, xs);
- merge_runs(segs, runs, y);
- }
- free(imgbuf);
- free(runs);
- free(segs);
- return 0;
- }
|