Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

351 lines (284 sloc) 7.527 kb
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "imager.h"
/*
2d bitmask with test and set operations
*/
struct i_bitmap*
btm_new(i_img_dim xsize,i_img_dim ysize) {
i_img_dim i;
size_t bytes;
struct i_bitmap *btm;
btm=(struct i_bitmap*)mymalloc(sizeof(struct i_bitmap)); /* checked 4jul05 tonyc */
bytes = (xsize*ysize+8)/8;
if (bytes * 8 / ysize < xsize-1) { /* this is kind of rough */
fprintf(stderr, "Integer overflow allocating bitmap (" i_DFp ")",
i_DFcp(xsize, ysize));
exit(3);
}
btm->data=(char*)mymalloc(bytes); /* checked 4jul05 tonyc */
btm->xsize=xsize;
btm->ysize=ysize;
memset(btm->data, 0, bytes);
return btm;
}
void
btm_destroy(struct i_bitmap *btm) {
myfree(btm->data);
myfree(btm);
}
int
btm_test(struct i_bitmap *btm,i_img_dim x,i_img_dim y) {
i_img_dim btno;
if (x<0 || x>btm->xsize-1 || y<0 || y>btm->ysize-1) return 0;
btno=btm->xsize*y+x;
return (1<<(btno%8))&(btm->data[btno/8]);
}
void
btm_set(struct i_bitmap *btm,i_img_dim x,i_img_dim y) {
i_img_dim btno;
if (x<0 || x>btm->xsize-1 || y<0 || y>btm->ysize-1) abort();
btno=btm->xsize*y+x;
btm->data[btno/8]|=1<<(btno%8);
}
/*
Bucketed linked list - stack type
*/
static struct llink *
llink_new(struct llink* p,size_t size);
static int
llist_llink_push(struct llist *lst, struct llink *lnk,const void *data);
static void
llink_destroy(struct llink* l);
/*
=item llist_new()
=synopsis struct llist *l = llist_new(100, sizeof(foo);
Create a new stack structure. Implemented as a linked list of pools.
Parameters:
=over
=item *
multip - number of entries in each pool
=item *
ssize - size of the objects being pushed/popped
=back
=cut
*/
struct llist *
llist_new(int multip, size_t ssize) {
struct llist *l;
l = mymalloc(sizeof(struct llist)); /* checked 4jul05 tonyc */
l->h = NULL;
l->t = NULL;
l->multip = multip;
l->ssize = ssize;
l->count = 0;
return l;
}
/*
=item llist_push()
=synopsis llist_push(l, &foo);
Push an item on the stack.
=cut
*/
void
llist_push(struct llist *l,const void *data) {
size_t ssize = l->ssize;
int multip = l->multip;
/* fprintf(stderr,"llist_push: data=0x%08X\n",data);
fprintf(stderr,"Chain size: %d\n", l->count); */
if (l->t == NULL) {
l->t = l->h = llink_new(NULL,ssize*multip); /* Tail is empty - list is empty */
/* fprintf(stderr,"Chain empty - extended\n"); */
}
else { /* Check for overflow in current tail */
if (l->t->fill >= l->multip) {
struct llink* nt = llink_new(l->t, ssize*multip);
l->t->n=nt;
l->t=nt;
/* fprintf(stderr,"Chain extended\n"); */
}
}
/* fprintf(stderr,"0x%08X\n",l->t); */
if (llist_llink_push(l,l->t,data)) {
i_fatal(3, "out of memory\n");
}
}
/*
=item llist_pop()
Pop an item off the list, storing it at C<data> which must have enough room for an object of the size supplied to llist_new().
returns 0 if the list is empty
=cut
*/
int
llist_pop(struct llist *l,void *data) {
/* int ssize=l->ssize;
int multip=l->multip;*/
if (l->t == NULL) return 0;
l->t->fill--;
l->count--;
memcpy(data,(char*)(l->t->data)+l->ssize*l->t->fill,l->ssize);
if (!l->t->fill) { /* This link empty */
if (l->t->p == NULL) { /* and it's the only link */
llink_destroy(l->t);
l->h = l->t = NULL;
}
else {
l->t=l->t->p;
llink_destroy(l->t->n);
}
}
return 1;
}
void
llist_dump(struct llist *l) {
int j;
int i=0;
struct llink *lnk;
lnk=l->h;
while(lnk != NULL) {
for(j=0;j<lnk->fill;j++) {
/* memcpy(&k,(char*)(lnk->data)+l->ssize*j,sizeof(void*));*/
/*memcpy(&k,(char*)(lnk->data)+l->ssize*j,sizeof(void*));*/
printf("%d - %p\n",i,*(void **)((char *)(lnk->data)+l->ssize*j));
i++;
}
lnk=lnk->n;
}
}
/*
=item llist_destroy()
Destroy a linked-list based stack.
=cut
*/
void
llist_destroy(struct llist *l) {
struct llink *t,*lnk = l->h;
while( lnk != NULL ) {
t=lnk;
lnk=lnk->n;
myfree(t);
}
myfree(l);
}
/* Links */
static struct llink *
llink_new(struct llink* p,size_t size) {
struct llink *l;
l = mymalloc(sizeof(struct llink)); /* checked 4jul05 tonyc */
l->n = NULL;
l->p = p;
l->fill = 0;
l->data = mymalloc(size); /* checked 4jul05 tonyc - depends on caller to llist_push */
return l;
}
/* free's the data pointer, itself, and sets the previous' next pointer to null */
static void
llink_destroy(struct llink* l) {
if (l->p != NULL) { l->p->n=NULL; }
myfree(l->data);
myfree(l);
}
/* if it returns true there wasn't room for the
item on the link */
static int
llist_llink_push(struct llist *lst, struct llink *lnk, const void *data) {
int multip;
multip = lst->multip;
/* fprintf(stderr,"llist_llink_push: data=0x%08X -> 0x%08X\n",data,*(int*)data);
fprintf(stderr,"ssize = %d, multip = %d, fill = %d\n",lst->ssize,lst->multip,lnk->fill); */
if (lnk->fill == lst->multip) return 1;
/* memcpy((char*)(lnk->data)+lnk->fill*lst->ssize,data,lst->ssize); */
memcpy((char*)(lnk->data)+lnk->fill*lst->ssize,data,lst->ssize);
/* printf("data=%X res=%X\n",*(int*)data,*(int*)(lnk->data));*/
lnk->fill++;
lst->count++;
return 0;
}
/*
Oct-tree implementation
*/
struct octt *
octt_new() {
int i;
struct octt *t;
t=(struct octt*)mymalloc(sizeof(struct octt)); /* checked 4jul05 tonyc */
for(i=0;i<8;i++) t->t[i]=NULL;
t->cnt=0;
return t;
}
/* returns 1 if the colors wasn't in the octtree already */
int
octt_add(struct octt *ct,unsigned char r,unsigned char g,unsigned char b) {
struct octt *c;
int i,cm;
int ci;
int rc;
rc=0;
c=ct;
/* printf("[r,g,b]=[%d,%d,%d]\n",r,g,b); */
for(i=7;i>-1;i--) {
cm=1<<i;
ci=((!!(r&cm))<<2)+((!!(g&cm))<<1)+!!(b&cm);
/* printf("idx[%d]=%d\n",i,ci); */
if (c->t[ci] == NULL) {
c->t[ci]=octt_new();
rc=1;
}
c=c->t[ci];
}
c->cnt++; /* New. The only thing really needed (I think) */
return rc;
}
void
octt_delete(struct octt *ct) {
int i;
for(i=0;i<8;i++) if (ct->t[i] != NULL) octt_delete(ct->t[i]); /* do not free instance here because it will free itself */
myfree(ct);
}
void
octt_dump(struct octt *ct) {
int i;
/* printf("node [0x%08X] -> (%d)\n",ct,ct->cnt); */
for(i=0;i<8;i++)
if (ct->t[i] != NULL)
printf("[ %d ] -> %p\n", i, (void *)ct->t[i]);
for(i=0;i<8;i++)
if (ct->t[i] != NULL)
octt_dump(ct->t[i]);
}
/* note that all calls of octt_count are operating on the same overflow
variable so all calls will know at the same time if an overflow
has occured and stops there. */
void
octt_count(struct octt *ct,int *tot,int max,int *overflow) {
int i,c;
c=0;
if (!(*overflow)) return;
for(i=0;i<8;i++) if (ct->t[i]!=NULL) {
octt_count(ct->t[i],tot,max,overflow);
c++;
}
if (!c) (*tot)++;
if ( (*tot) > (*overflow) ) *overflow=0;
}
/* This whole function is new */
/* walk through the tree and for each colour, store its seen count in the
space pointed by *col_usage_it_adr */
void
octt_histo(struct octt *ct, unsigned int **col_usage_it_adr) {
int i,c;
c = 0;
for(i = 0; i < 8; i++)
if (ct->t[i] != NULL) {
octt_histo(ct->t[i], col_usage_it_adr);
c++;
}
if (!c) {
*(*col_usage_it_adr)++ = ct->cnt;
}
}
i_img_dim
i_abs(i_img_dim x) {
return x < 0 ? -x : x;
}
Jump to Line
Something went wrong with that request. Please try again.