}
}
-ibbox_t*get_bitmap_bboxes_simple(unsigned char*alpha, int width, int height)
+ibbox_t*get_bitmap_bboxes_simple(unsigned char*alpha, int width, int height, int rowsize)
{
int ymin = -1;
int ymax = -1;
int x,y;
for(y=0;y<height;y++) {
- unsigned char*a = &alpha[y*width];
+ unsigned char*a = &alpha[y*rowsize];
for(x=0;x<width;x++) {
if(a[x]) break;
}
typedef struct _context {
void**group;
unsigned char*alpha;
+ int rowsize;
int width;
int height;
head_t*heads;
assert(!h->prev);
context->heads = h->next;
}
+ free(h);
}
#define POINTS_TO_HEAD(ptr) (((head_t*)(ptr))->magic==HEAD_MAGIC)
}
}
+ibbox_t ibbox_clip(ibbox_t* outer, ibbox_t* inner)
+{
+ ibbox_t i = {inner->xmin, inner->ymin, inner->xmax, inner->ymax, 0};
+ if(i.xmax > outer->xmax) i.xmax = outer->xmax;
+ if(i.ymax > outer->ymax) i.ymax = outer->ymax;
+ if(i.xmax < outer->xmin) i.xmax = outer->xmin;
+ if(i.ymax < outer->ymin) i.ymax = outer->ymin;
+
+ if(i.xmin > outer->xmax) i.xmin = outer->xmax;
+ if(i.ymin > outer->ymax) i.ymin = outer->ymax;
+ if(i.xmin < outer->xmin) i.xmin = outer->xmin;
+ if(i.ymin < outer->ymin) i.ymin = outer->ymin;
+ return i;
+}
+
static void** annotate(context_t*context)
{
unsigned char*alpha = context->alpha;
}
}
int pos = 0;
+ int apos = 0;
for(y=1;y<height;y++) {
pos += width;
- if(alpha[pos]) {
+ apos += context->rowsize;
+ if(alpha[apos]) {
if(group[pos-width])
link_to(context,pos,pos-width);
else
/* once this code is stable we should copy&paste it
out of the loop, change the loop end to width-1 and
add the pos-width+1 case */
- if(alpha[pos+x]) {
+ if(alpha[apos+x]) {
if(group[pos+x-width]) {
link_to(context,pos+x,pos+x-width);
if(group[pos+x-1])
} while(changed);
}
+typedef struct _circle_coord {
+ S16 x,y;
+} circle_coord_t;
+
+static int compare_circle_coord(const void *_v1, const void *_v2)
+{
+ circle_coord_t*v1=(circle_coord_t*)_v1;
+ circle_coord_t*v2=(circle_coord_t*)_v2;
+ return (v1->x*v1->x + v1->y*v1->y) - (v2->x*v2->x + v2->y*v2->y);
+}
+
static head_t* search_vicinity(context_t*context, head_t*h, int max_radius, double*cos, double*sin)
{
+ static circle_coord_t*circle_order = 0;
+ static int circle_order_size = 0;
+
+ if(!circle_order) {
+ circle_order_size = (max_radius*(max_radius+1))/2;
+ circle_order = malloc(sizeof(circle_coord_t)*circle_order_size);
+ int x,y;
+ int i = 0;
+ for(y=0;y<max_radius;y++) {
+ for(x=0;x<=y;x++) {
+ circle_order[i].x=x;
+ circle_order[i].y=y;
+ i++;
+ }
+ }
+ assert(i==circle_order_size);
+ qsort(circle_order, circle_order_size, sizeof(circle_coord_t), compare_circle_coord);
+ }
+
int t;
void**data = context->group;
- /* FIXME: this function isn't very efficient. We need a better way to iterate
- through all points, sorted by distance, in the neighborhood of a coordinate */
- for(t=3;t<max_radius*2;t++) {
+ int signx[4] = {-1,1,-1,1};
+ int signy[4] = {-1,-1,1,1};
+ for(t=1;t<circle_order_size;t++) {
+ int xx = circle_order[t].x;
+ int yy = circle_order[t].y;
int s;
- for(s=0;s<256;s++) {
- int x=h->x+cos[s]*t/4.0+0.5;
- int y=h->y+sin[s]*t/4.0+0.5;
+ for(s=0;s<4;s++) {
+ int x=h->x+xx*signx[s];
+ int y=h->y+yy*signy[s];
if(x>=0 && y>=0 && x<context->width && y<context->height) {
int pos = y*context->width+x;
if(data[pos]) {
while(h) {
head_t*next = h->next;
if(!h->seen) {
- if(h->bbox.xmax - h->bbox.ymin < 16
- && h->bbox.ymax - h->bbox.ymin < 16) {
+ if(h->bbox.xmax - h->bbox.xmin < 32
+ || h->bbox.ymax - h->bbox.ymin < 32) {
head_t*other = search_vicinity(context, h, 64, costab, sintab);
if(other) {
merge(context, h->pos, other->pos);
changed = 1;
break;
} else {
+ //printf("nothing in the vicinity of %d,%d,%d,%d\n", h->bbox);
h->seen = 1;
}
- }
+ } /*else {
+ printf("area %d,%d,%d,%d is large enough (%dx%d)\n",
+ h->bbox.xmin,
+ h->bbox.ymin,
+ h->bbox.xmax,
+ h->bbox.ymax,
+ h->bbox.xmax - h->bbox.xmin,
+ h->bbox.ymax - h->bbox.ymin);
+ } */
}
h = next;
}
}
}
-ibbox_t*get_bitmap_bboxes(unsigned char*alpha, int width, int height)
+ibbox_t*get_bitmap_bboxes(unsigned char*alpha, int width, int height, int rowsize)
{
int size = width*height;
if(width<=1 || height<=1)
- return get_bitmap_bboxes_simple(alpha, width, height);
+ return get_bitmap_bboxes_simple(alpha, width, height, rowsize);
context_t context;
context.alpha = alpha;
+ context.rowsize = rowsize;
context.width = width;
context.height = height;
context.heads = 0;
void**group = annotate(&context);
fix_small_boxes(&context);
overlap_bboxes(&context);
+#ifdef MAIN
+ display(&context);
+#endif
ibbox_t*bboxes = 0;
"\1\0\0\0\0\0\1\0"
"\1\1\1\0\0\0\0\0";
- get_bitmap_bboxes(alpha, 8,8);
+ get_bitmap_bboxes(alpha, 8,8, 8);
}
#endif