#include #include #include #include #include #include #include #include #include #include #include static pf_class_t *bitgrid_class; pf_class_t *pf_class_bitgrid(void) { return bitgrid_class; } /* bitgrids are stored little endian, with LSB = left for each byte. */ /* todo: unify images, ca's all kinds of things to bitgrids aa bit grid is nothing more than the description of the layout of the bits. like: bitgrid/16/320/240/3 this is basicly just changing the subheader (in place) and change the way the data should be interpreted. there's only this small problem with matrix perm data.. probably best to kick that out and create a different object. most headers could be unified for this: first word = encoding. determines basic data type (bit dimension) then follow all other dimensions, inner to outer. */ #define CHECK(type) { if (!a) return 0; if (a->t != type) return 0; } static pf_symbol_t *bitgrid_desc(pf_bitgrid_t *b){ char s[100]; strcpy(s, "bitgrid"); int i; for (i = 0; i < b->dims; i++){ char d[10]; sprintf(d, "/%d", (int)b->dim[i]); strcat(s, d); } return pf_symbol(s); } static pf_packet_t pf_bitgrid_factory(pf_list_t *l){ pf_atom_t *a = l->first->next; pf_bitgrid_t b; b.dims = 0; int bitsize = 1; while (a && (b.dims < PF_BITGRID_MAXDIM)){ int i; CHECK(a_int); i = b.dim[b.dims] = a->w.w_int; if (i < 0) return 0; b.dims++; bitsize *= i; a = a->next; } int datasize = (bitsize-1)/8+1; // pf_post("bitgrid size %p words", datasize/4); pf_bitgrid_t *bitgrid = (pf_bitgrid_t *)pf_packet_create(sizeof(pf_bitgrid_t), datasize); if (!bitgrid) return 0; bitgrid->super.type = bitgrid_class; bitgrid->dims = b.dims; memcpy(bitgrid->dim, b.dim, PF_BITGRID_MAXDIM * sizeof(u32)); return (pf_packet_t)bitgrid; } /* debug shortcut */ static PF_FUNCTION(bitgrid_random){ CHECKN(1); pf_symbol_t *type = SYMBOL(ARG0); pf_packet_t p = PUSH_NEW("%s",type->s_name); pf_header_t *h = pf_packet_header(p); if (pf_packet_class(h) != pf_class_bitgrid()) ABORT(e_type); unsigned char *data = DATA(h); int size = SIZE(h); while (size--) *data++ = random(); NIP1; EXIT; } // convert image to bitgrid. static PF_FUNCTION(image_bitgrid){ CHECKN(3); pf_image_t *image = IMAGE(ARG2); int threshold = INT(ARG1); int bits = INT(ARG0); int w = image->width; int h = image->height; switch(bits){ case 1: { if (w & 0x1F) { THROW(e_inval, "image width (%d) needs to be a multiple of 32", w); } if (16 != PF_IMAGE_ENCODING_BITDEPTH(image->encoding)) { THROW(e_inval, "only image/s16 is supported", w); } pf_packet_t p = pf_factory_newpacket( pf_symbolf("bitgrid/1/%d/%d", w, h)); PUSH_PACKET(p); unsigned long *out = pf_packet_data(p); short int *in = DATA(image); int words; for (words = 0; words < ((w * h) >> 5); words++){ // FILL BITGRID int bits = 32; unsigned long accu = 0; do { accu >>= 1; accu |= (*in++ >= threshold) ? 0x80000000 : 0; } while (--bits); *out++ = accu; } break; } default: THROW(e_inval, "bitgrid bit depth %d not supported", bits); } NIP3; EXIT; } // convert to bitmask /* This is the central point where the meaning of a bit pattern as an image is determined. Looking at the inner shift loop, you can see the LSB is the leftmost pixel, and the MSB is the rightmost one. */ static PF_FUNCTION(bitgrid_image){ CHECK1(a_packet); pf_bitgrid_t *bin = BITGRID(ARG0); if (bin->dim[0] != 1) ABORT(e_type); // damn these converters. int wout, hout; if (bin->dims == 3){ wout = bin->dim[1]; hout = bin->dim[2]; } else if (bin->dims == 2){ // hack to display 1D ca wout = bin->dim[1] / 16; hout = 16; } else { ABORT(e_type); } pf_packet_t pout = pf_factory_newpacket( pf_symbolf("image/s16/%d/%d/1", wout, hout)); if (!pout) ABORT (e_inval); int *src = (int *)DATA(bin); int words = SIZE(bin) / sizeof (int); short int *dst = pf_packet_data(pout); while (words--){ int i = sizeof(int) * 8; int x = *src++; while (i--){ *dst++ = (x & 1) ? 0x7fff : 0; x >>= 1; } } DROP1; PUSH_PACKET(pout); EXIT; } // 1D load/store - these treat packet as mutable // modulo addresssing static PF_FUNCTION(bitgrid_store){ CHECKN(3); unsigned int address = INT(ARG1); int value = INT(ARG2); pf_bitgrid_t *b = BITGRID(ARG0); switch(b->dim[0]){ case 32: { long *data = DATA(b); unsigned int size = SIZE(b) / 4; data[address % size] = value; break; } case 16: { short *data = DATA(b); unsigned int size = SIZE(b) / 2; data[address % size] = value; break; } case 8: { char *data = DATA(b); unsigned int size = SIZE(b); data[address % size] = value; break; } case 1: { char *data = DATA(b); unsigned int size = SIZE(b); int hi = address >> 3; int lo = address & 7; char ormask = 1 << lo; char andmask = ormask ^ -1; data[hi % size] &= andmask; data[hi % size] |= ormask; break; } default: ABORT(e_bug); } DROP1; DROP1; DROP1; EXIT; } static PF_FUNCTION(bitgrid_load){ CHECKN(2); unsigned int address = INT(ARG1); int value = 0; pf_bitgrid_t *b = BITGRID(ARG0); switch(b->dim[0]){ case 32: { long *data = DATA(b); unsigned int size = SIZE(b) / 4; value = data[address % size]; break; } case 16: { short *data = DATA(b); unsigned int size = SIZE(b) / 2; value = data[address % size]; break; } case 8: { char *data = DATA(b); unsigned int size = SIZE(b); value = data[address % size]; break; } case 1: { char *data = DATA(b); unsigned int size = SIZE(b); int hi = address >> 3; int lo = address & 7; value = data[hi % size]; value >>= lo; value &= 1; break; } default: ABORT(e_bug); } DROP1; DROP1; PUSH_INT(value); EXIT; } PF_FUNCTION(pf_forth_bitgrid_setup){ bitgrid_class = pf_class_new(pf_symbol("bitgrid"), pf_bitgrid_factory); pf_class_set_desc(bitgrid_class, (pf_method_to_desc_t)bitgrid_desc); PF_REGISTER_FUNCTION(bitgrid_image, "bitgrid:image", "( bitgrid -- image )\tConvert bitgrid to image packet."); PF_REGISTER_FUNCTION(image_bitgrid, "image:bitgrid", "( image threshold bits -- bitgrid )\tConvert first image plane to bitgrid using threshold."); PF_REGISTER_FUNCTION(bitgrid_random, "bitgrid:random", "( type -- bitgrid )\tRandom bitgrid."); PF_REGISTER_FUNCTION(bitgrid_store, "bitgrid:!", "( value address bitgrid -- )\t1D muting store value."); PF_REGISTER_FUNCTION(bitgrid_load, "bitgrid:@", "( address bitgrid -- value )\t1D load value."); EXIT; }