diff --git a/liblwgeom/liblwgeom.h b/liblwgeom/liblwgeom.h index afc5a4ce0..50acfc740 100644 --- a/liblwgeom/liblwgeom.h +++ b/liblwgeom/liblwgeom.h @@ -331,52 +331,6 @@ typedef struct } GBOX; -typedef struct chiptag -{ - int size; /* unused (for use by postgresql) */ - - int endian_hint; /* the number 1 in the endian of this datastruct */ - - BOX3D bvol; - int srid; - char future[4]; - float factor; /* Usually 1.0. - * Integer values are multiplied by this number - * to get the actual height value - * (for sub-meter accuracy height data). - */ - - int datatype; /* 1 = float32, - * 5 = 24bit integer, - * 6 = 16bit integer (short) - * 7 = 16bit ??? - * 8 = 8bit ??? - * 101 = float32 (NDR), - * 105 = 24bit integer (NDR), - * 106 = 16bit int (NDR) - * 107 = 16bit ??? (NDR) - * 108 = 8bit ??? (NDR) (this doesn't make sense) - */ - int height; - int width; - int compression; /* 0 = no compression, 1 = differencer - * 0x80 = new value - * 0x7F = nodata - */ - - /* - * this is provided for convenience, it should be set to - * sizeof(chip) bytes into the struct because the serialized form is: - *
- * NULL when serialized - */ - void *data; /* data[0] = bottm left, - * data[width] = 1st pixel, 2nd row (uncompressed) - */ - -} -CHIP; - /****************************************************************** * SPHEROID * diff --git a/postgis/Makefile.in b/postgis/Makefile.in index c61bc474d..640c854e0 100644 --- a/postgis/Makefile.in +++ b/postgis/Makefile.in @@ -36,7 +36,6 @@ PG_OBJS=lwgeom_pg.o \ lwgeom_box.o \ lwgeom_box3d.o \ lwgeom_box2dfloat4.o \ - lwgeom_chip.o \ lwgeom_geos.o \ lwgeom_geos_prepared.o \ lwgeom_geos_clean.o \ diff --git a/postgis/legacy_chip.sql.in.c b/postgis/legacy_chip.sql.in.c deleted file mode 100644 index 92375335c..000000000 --- a/postgis/legacy_chip.sql.in.c +++ /dev/null @@ -1,180 +0,0 @@ --- $Id$ --- Chip legacy functions -- -#include "sqldefines.h" -------------------------------------------------------------------- --- CHIP TYPE -------------------------------------------------------------------- - -CREATE OR REPLACE FUNCTION chip_in(cstring) - RETURNS chip - AS 'MODULE_PATHNAME','CHIP_in' - LANGUAGE 'C' IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION chip_out(chip) - RETURNS cstring - AS 'MODULE_PATHNAME','CHIP_out' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Deprecation in 1.5.0 -CREATE OR REPLACE FUNCTION ST_chip_in(cstring) - RETURNS chip - AS 'MODULE_PATHNAME','CHIP_in' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Deprecation in 1.5.0 -CREATE OR REPLACE FUNCTION ST_chip_out(chip) - RETURNS cstring - AS 'MODULE_PATHNAME','CHIP_out' - LANGUAGE 'C' IMMUTABLE STRICT; - -CREATE TYPE chip ( - alignment = double, - internallength = variable, - input = chip_in, - output = chip_out, - storage = extended -); ---- End CHIP TYPE -- -------------------------------------------- ---- Begin CHIP functions -------------------------------------------- ---- Deprecation in 1.5.0 -CREATE OR REPLACE FUNCTION st_geometry(chip) - RETURNS geometry - AS 'MODULE_PATHNAME','CHIP_to_LWGEOM' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Deprecation in 1.2.3 -CREATE OR REPLACE FUNCTION srid(chip) - RETURNS int4 - AS 'MODULE_PATHNAME','CHIP_getSRID' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Availability: 1.2.2 -CREATE OR REPLACE FUNCTION ST_srid(chip) - RETURNS int4 - AS 'MODULE_PATHNAME','CHIP_getSRID' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Deprecation in 1.2.3 -CREATE OR REPLACE FUNCTION height(chip) - RETURNS int4 - AS 'MODULE_PATHNAME','CHIP_getHeight' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Availability: 1.2.2 -CREATE OR REPLACE FUNCTION ST_height(chip) - RETURNS int4 - AS 'MODULE_PATHNAME','CHIP_getHeight' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Deprecation in 1.2.3 -CREATE OR REPLACE FUNCTION factor(chip) - RETURNS FLOAT4 - AS 'MODULE_PATHNAME','CHIP_getFactor' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Availability: 1.2.2 -CREATE OR REPLACE FUNCTION ST_factor(chip) - RETURNS FLOAT4 - AS 'MODULE_PATHNAME','CHIP_getFactor' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Deprecation in 1.2.3 -CREATE OR REPLACE FUNCTION width(chip) - RETURNS int4 - AS 'MODULE_PATHNAME','CHIP_getWidth' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Availability: 1.2.2 -CREATE OR REPLACE FUNCTION ST_width(chip) - RETURNS int4 - AS 'MODULE_PATHNAME','CHIP_getWidth' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Deprecation in 1.2.3 -CREATE OR REPLACE FUNCTION datatype(chip) - RETURNS int4 - AS 'MODULE_PATHNAME','CHIP_getDatatype' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Availability: 1.2.2 -CREATE OR REPLACE FUNCTION ST_datatype(chip) - RETURNS int4 - AS 'MODULE_PATHNAME','CHIP_getDatatype' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Deprecation in 1.2.3 -CREATE OR REPLACE FUNCTION compression(chip) - RETURNS int4 - AS 'MODULE_PATHNAME','CHIP_getCompression' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Availability: 1.2.2 -CREATE OR REPLACE FUNCTION ST_compression(chip) - RETURNS int4 - AS 'MODULE_PATHNAME','CHIP_getCompression' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Deprecation in 1.2.3 -CREATE OR REPLACE FUNCTION setSRID(chip,int4) - RETURNS chip - AS 'MODULE_PATHNAME','CHIP_setSRID' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Deprecation in 1.2.3 -CREATE OR REPLACE FUNCTION setFactor(chip,float4) - RETURNS chip - AS 'MODULE_PATHNAME','CHIP_setFactor' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Availability: 1.2.2 -CREATE OR REPLACE FUNCTION ST_setFactor(chip,float4) - RETURNS chip - AS 'MODULE_PATHNAME','CHIP_setFactor' - LANGUAGE 'C' IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION geometry(chip) - RETURNS geometry - AS 'MODULE_PATHNAME','CHIP_to_LWGEOM' - LANGUAGE 'C' IMMUTABLE STRICT; - -CREATE CAST (chip AS geometry) WITH FUNCTION geometry(chip) AS IMPLICIT; --- END CHIP -- - ------------------------------------------------- ---Begin 3D functions -- ------------------------------------------------- - --- Renamed in 2.0.0 to ST_3DLength -CREATE OR REPLACE FUNCTION ST_Length3D(geometry) - RETURNS FLOAT8 - AS 'MODULE_PATHNAME', 'LWGEOM_length_linestring' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Renamed in 2.0.0 to ST_3DLength_spheroid -CREATE OR REPLACE FUNCTION ST_Length_spheroid3D(geometry, spheroid) - RETURNS FLOAT8 - AS 'MODULE_PATHNAME','LWGEOM_length_ellipsoid_linestring' - LANGUAGE 'C' IMMUTABLE STRICT - COST 100; - --- Renamed in 2.0.0 to ST_3DPerimeter -CREATE OR REPLACE FUNCTION ST_Perimeter3D(geometry) - RETURNS FLOAT8 - AS 'MODULE_PATHNAME', 'LWGEOM_perimeter_poly' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Renamed in 2.0.0 to ST_3DMakeBox -CREATE OR REPLACE FUNCTION ST_MakeBox3D(geometry, geometry) - RETURNS box3d - AS 'MODULE_PATHNAME', 'BOX3D_construct' - LANGUAGE 'C' IMMUTABLE STRICT; - --- Renamed in 2.0.0 to ST_3DExtent -CREATE AGGREGATE ST_Extent3D( - sfunc = ST_combine_bbox, - basetype = geometry, - stype = box3d - ); ---END 3D functions-- diff --git a/postgis/lwgeom_chip.c b/postgis/lwgeom_chip.c deleted file mode 100644 index 94285238a..000000000 --- a/postgis/lwgeom_chip.c +++ /dev/null @@ -1,1364 +0,0 @@ -#include "postgres.h" -#include "access/gist.h" -#include "access/itup.h" -#include "fmgr.h" -#include "utils/elog.h" -#include "funcapi.h" - -#include "lwgeom_pg.h" -#include "liblwgeom.h" - -#include -#include -#include -#include -#include - -/* Define this to debug CHIP ops */ -/*#define DEBUG_CHIP 1*/ - -typedef unsigned short int UINT16; -typedef float FLOAT32; - -typedef struct PIXEL_T -{ - int type; /* 1=float32, 5=int24, 6=int16 */ - uchar val[4]; -} -PIXEL; - -typedef struct RGB_T -{ - uchar red; - uchar green; - uchar blue; -} -RGB; - - -/* Internal funcs */ -void swap_char(char *a,char *b); -void flip_endian_double(char *d); -void flip_endian_int32(char *i); -const char* pixelOpName(int op); -const char* pixelHEX(PIXEL* p); -UINT16 pixel_readUINT16(PIXEL *p); -void pixel_writeUINT16(PIXEL *p, UINT16 i); -PIXEL pixel_readval(char *buf); -void pixel_writeval(PIXEL *p, char *buf, size_t maxlen); -void pixel_add_float32(PIXEL *where, PIXEL *what); -void pixel_add_int24(PIXEL *where, PIXEL *what); -void pixel_add_int16(PIXEL *where, PIXEL *what); -void pixel_add(PIXEL *where, PIXEL *what); -size_t chip_xy_off(CHIP *c, size_t x, size_t y); -void chip_setPixel(CHIP *c, int x, int y, PIXEL *p); -PIXEL chip_getPixel(CHIP *c, int x, int y); -void chip_draw_pixel(CHIP *chip, int x, int y, PIXEL *pixel, int op); -void chip_draw_segment(CHIP *chip, int x1, int y1, int x2, int y2, PIXEL *pixel, int op); -void chip_fill(CHIP *chip, PIXEL *pixel, int op); -CHIP * pgchip_construct(BOX3D *bvol, int srid, int width, int height, int datatype, PIXEL *initvalue); -void chip_draw_ptarray(CHIP *chip, POINTARRAY *pa, PIXEL *pixel, int op); -void chip_draw_lwpoint(CHIP *chip, LWPOINT *lwpoint, PIXEL* pixel, int op); -void chip_draw_lwline(CHIP *chip, LWLINE *lwline, PIXEL* pixel, int op); -void chip_draw_lwgeom(CHIP *chip, LWGEOM *lwgeom, PIXEL *pixel, int op); -char * text_to_cstring(text *t); - - -/* Prototypes */ -Datum CHIP_in(PG_FUNCTION_ARGS); -Datum CHIP_out(PG_FUNCTION_ARGS); -Datum CHIP_to_LWGEOM(PG_FUNCTION_ARGS); -Datum CHIP_getSRID(PG_FUNCTION_ARGS); -Datum CHIP_getFactor(PG_FUNCTION_ARGS); -Datum CHIP_setFactor(PG_FUNCTION_ARGS); -Datum CHIP_getDatatype(PG_FUNCTION_ARGS); -Datum CHIP_getCompression(PG_FUNCTION_ARGS); -Datum CHIP_getHeight(PG_FUNCTION_ARGS); -Datum CHIP_getWidth(PG_FUNCTION_ARGS); -Datum CHIP_setSRID(PG_FUNCTION_ARGS); -Datum CHIP_send(PG_FUNCTION_ARGS); -Datum CHIP_dump(PG_FUNCTION_ARGS); -Datum CHIP_construct(PG_FUNCTION_ARGS); -Datum CHIP_getpixel(PG_FUNCTION_ARGS); -Datum CHIP_setpixel(PG_FUNCTION_ARGS); -Datum CHIP_draw(PG_FUNCTION_ARGS); -Datum CHIP_fill(PG_FUNCTION_ARGS); - - -/* - * Input is a string with hex chars in it. - * Convert to binary and put in the result - */ -PG_FUNCTION_INFO_V1(CHIP_in); -Datum CHIP_in(PG_FUNCTION_ARGS) -{ - char *str = PG_GETARG_CSTRING(0); - CHIP *result; - int size; - int t; - int input_str_len; - int datum_size; - - /*printf("chip_in called\n"); */ - - input_str_len = strlen(str); - - if ( ( ( (int)(input_str_len/2.0) ) *2.0) != input_str_len) - { - elog(ERROR,"CHIP_in parser - should be even number of characters!"); - PG_RETURN_NULL(); - } - - if (strspn(str,"0123456789ABCDEF") != strlen(str) ) - { - elog(ERROR,"CHIP_in parser - input contains bad characters. Should only have '0123456789ABCDEF'!"); - PG_RETURN_NULL(); - } - size = (input_str_len/2) ; - result = (CHIP *) palloc(size); - - for (t=0; tsize = size; - if (result->size < sizeof(CHIP)-sizeof(void*) ) - { - elog(ERROR,"CHIP_in parser - bad data (too small to be a CHIP)!"); - PG_RETURN_NULL(); - } - - if (result->endian_hint != 1) - { - /*need to do an endian flip */ - flip_endian_int32( (char *) &result->endian_hint); - - flip_endian_double((char *) &result->bvol.xmin); - flip_endian_double((char *) &result->bvol.ymin); - flip_endian_double((char *) &result->bvol.zmin); - - flip_endian_double((char *) &result->bvol.xmax); - flip_endian_double((char *) &result->bvol.ymax); - flip_endian_double((char *) &result->bvol.zmax); - - flip_endian_int32( (char *) & result->srid); - /*dont know what to do with future[8] ... */ - - flip_endian_int32( (char *) & result->height); - flip_endian_int32( (char *) & result->width); - flip_endian_int32( (char *) & result->compression); - flip_endian_int32( (char *) & result->factor); - flip_endian_int32( (char *) & result->datatype); - - } - if (result->endian_hint != 1 ) - { - elog(ERROR,"CHIP_in parser - bad data (endian flag != 1)!"); - PG_RETURN_NULL(); - } - datum_size = 4; - - if ( (result->datatype == 6) || (result->datatype == 7) || (result->datatype == 106) || (result->datatype == 107) ) - { - datum_size = 2; - } - if ( (result->datatype == 8) || (result->datatype == 108) ) - { - datum_size=1; - } - - if (result->compression ==0) /*only true for non-compressed data */ - { - if (result->size != (sizeof(CHIP) - sizeof(void*) + datum_size * result->width*result->height) ) - { - elog(ERROR,"CHIP_in parser - bad data (actual size [%d] != computed size [%ld])!", result->size, (long int)(sizeof(CHIP)-sizeof(void*) + datum_size * result->width*result->height) ); - PG_RETURN_NULL(); - } - } - - PG_RETURN_POINTER(result); -} - - -/*given a CHIP structure, convert it to Hex and put it in a string */ -PG_FUNCTION_INFO_V1(CHIP_out); -Datum CHIP_out(PG_FUNCTION_ARGS) -{ - CHIP *chip = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - char *result; - int size_result; - int t; - -#if DEBUG_CHIP - lwnotice("CHIP_out: %dx%d chip, %d in size", chip->width, chip->height, chip->size); -#endif - - size_result = (chip->size ) *2 +1; /* +1 for null char */ - result = palloc (size_result); - result[size_result-1] = 0; /*null terminate */ - - for (t=0; t< (chip->size); t++) - { - deparse_hex( ((uchar *) chip)[t], &result[t*2]); - } - PG_RETURN_CSTRING(result); -} - - -/*given a CHIP structure pipe it out as raw binary */ -PG_FUNCTION_INFO_V1(CHIP_send); -Datum CHIP_send(PG_FUNCTION_ARGS) -{ - CHIP *chip = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - bytea *result; - - - - result = (bytea *)palloc( chip->size ); - /*SET_VARSIZE(result, chip->size + VARHDRSZ);*/ - /*memcpy( VARDATA(result), chip, chip->size ); */ - memcpy( result, chip, chip->size ); - PG_RETURN_POINTER(result); - /*PG_RETURN_POINTER( (bytea *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)) );*/ -} - - -PG_FUNCTION_INFO_V1(CHIP_to_LWGEOM); -Datum CHIP_to_LWGEOM(PG_FUNCTION_ARGS) -{ - CHIP *chip = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - PG_LWGEOM *result; - POINT2D *pts = palloc(sizeof(POINT2D)*5); - POINTARRAY *pa[1]; - LWPOLY *poly; - uchar *ser; - int wantbbox = false; - - /* Assign coordinates to POINT2D array */ - pts[0].x = chip->bvol.xmin; - pts[0].y = chip->bvol.ymin; - pts[1].x = chip->bvol.xmin; - pts[1].y = chip->bvol.ymax; - pts[2].x = chip->bvol.xmax; - pts[2].y = chip->bvol.ymax; - pts[3].x = chip->bvol.xmax; - pts[3].y = chip->bvol.ymin; - pts[4].x = chip->bvol.xmin; - pts[4].y = chip->bvol.ymin; - - /* Construct point array */ - pa[0] = palloc(sizeof(POINTARRAY)); - pa[0]->serialized_pointlist = (uchar *)pts; - TYPE_SETZM(pa[0]->flags, 0, 0); - pa[0]->npoints = 5; - - /* Construct polygon */ - poly = lwpoly_construct(chip->srid, NULL, 1, pa); - - /* Serialize polygon */ - ser = lwpoly_serialize(poly); - - /* Construct PG_LWGEOM */ - result = PG_LWGEOM_construct(ser, chip->srid, wantbbox); - - PG_RETURN_POINTER(result); - -} - -PG_FUNCTION_INFO_V1(CHIP_getSRID); -Datum CHIP_getSRID(PG_FUNCTION_ARGS) -{ - CHIP *c = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - PG_RETURN_INT32(c->srid); -} - -PG_FUNCTION_INFO_V1(CHIP_getFactor); -Datum CHIP_getFactor(PG_FUNCTION_ARGS) -{ - CHIP *c = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - PG_RETURN_FLOAT4(c->factor); -} - -PG_FUNCTION_INFO_V1(CHIP_setFactor); -Datum CHIP_setFactor(PG_FUNCTION_ARGS) -{ - CHIP *c = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - float factor = PG_GETARG_FLOAT4(1); - CHIP *result; - - result = (CHIP *) palloc(c->size); - - memcpy(result,c,c->size); - result->factor = factor; - - PG_RETURN_POINTER(result); -} - - - -PG_FUNCTION_INFO_V1(CHIP_getDatatype); -Datum CHIP_getDatatype(PG_FUNCTION_ARGS) -{ - CHIP *c = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - PG_RETURN_INT32(c->datatype); -} - -PG_FUNCTION_INFO_V1(CHIP_getCompression); -Datum CHIP_getCompression(PG_FUNCTION_ARGS) -{ - CHIP *c = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - PG_RETURN_INT32(c->compression); -} - -PG_FUNCTION_INFO_V1(CHIP_getHeight); -Datum CHIP_getHeight(PG_FUNCTION_ARGS) -{ - CHIP *c = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - PG_RETURN_INT32(c->height); -} - -PG_FUNCTION_INFO_V1(CHIP_getWidth); -Datum CHIP_getWidth(PG_FUNCTION_ARGS) -{ - CHIP *c = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - PG_RETURN_INT32(c->width); -} - - -PG_FUNCTION_INFO_V1(CHIP_setSRID); -Datum CHIP_setSRID(PG_FUNCTION_ARGS) -{ - CHIP *c = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - int32 new_srid = PG_GETARG_INT32(1); - CHIP *result; - - result = (CHIP *) palloc(c->size); - - memcpy(result, c, c->size); - result->srid = new_srid; - - PG_RETURN_POINTER(result); -} - -void flip_endian_double(char *d) -{ - swap_char(d+7, d); - swap_char(d+6, d+1); - swap_char(d+5, d+2); - swap_char(d+4, d+3); -} - -void swap_char(char *a,char *b) -{ - char c; - - c = *a; - *a=*b; - *b=c; -} - -void flip_endian_int32(char *i) -{ - swap_char (i+3,i); - swap_char (i+2,i+1); -} - -/******************************************************************** - * - * NEW chip code - * - ********************************************************************/ - -#define CHIP_BOUNDS_CHECKS 1 - - -/* Macros to find size (in geographic units) of a CHIP cell (or pixel) */ -#define CHIP_CELL_WIDTH(x) ( ((x)->bvol.xmax-(x)->bvol.xmin)/(x)->width ) -#define CHIP_CELL_HEIGHT(x) ( ((x)->bvol.ymax-(x)->bvol.ymin)/(x)->height ) - -/* Return the size of values for pixel of the given datatype */ -size_t chip_pixel_value_size(int datatype); - -/******************************************************************** - * - * IO primitives - * - ********************************************************************/ - -#define PIXELOP_OVERWRITE 1 -#define PIXELOP_ADD 2 -#define PIXELOP_MULTIPLY 3 - -char *pixelop_name[] = -{ - "Unknown", - "Overwrite", - "Add", - "Multiply" -}; - -const char* -pixelOpName(int op) -{ - if ( op < 0 || op > 3 ) - { - return "Invalid"; - } - return pixelop_name[op]; -} - -const char* -pixelHEX(PIXEL* p) -{ - static char buf[256]; - size_t ps = chip_pixel_value_size(p->type); - int i,j; - static const char* hex = "0123456789ABCDEF"; - - for (i=0, j=0; ival[i]; - int upper = (val & 0xF0) >> 4; - int lower = val & 0x0F; - - buf[j++] = hex[ upper ]; - buf[j++] = hex[ lower ]; - } - buf[j]=0; - - return buf; -} - -UINT16 -pixel_readUINT16(PIXEL *p) -{ - UINT16 i=0; - memcpy(&i, &(p->val), 2); - //i = p->val[0] | (p->val[1] << 8); - return i; -} - -void -pixel_writeUINT16(PIXEL *p, UINT16 i) -{ - //memcpy(&(p->val), &i, 2); - p->val[0] = i&0xFF; - p->val[1] = i>>8; - p->val[2] = 0; - p->val[3] = 0; -} - -/* - * Write text representation of a PIXEL value into provided - * buffer. - */ -void -pixel_writeval(PIXEL *p, char *buf, size_t maxlen) -{ - FLOAT32 f32=0.0; - UINT16 i16=0; - - switch (p->type) - { - case 1: /* float32 */ - memcpy(&f32, p->val, 4); - sprintf(buf, "%g", f32); - break; - case 5: /* int24 (rgb) */ - buf[0] = '#'; - deparse_hex(p->val[0], &buf[1]); - deparse_hex(p->val[1], &buf[3]); - deparse_hex(p->val[2], &buf[5]); - buf[7]='\0'; - break; - case 6: /* int16 */ - i16=pixel_readUINT16(p); - snprintf(buf, maxlen, "%u", i16); - break; - default: - lwerror("Unsupported PIXEL value %d", p->type); - } -} - -PIXEL -pixel_readval(char *buf) -{ - FLOAT32 f32=0.0; - long int i16=0; - RGB rgb; - char *ptr; - PIXEL p; - - /* RGB */ - if ( buf[0] == '#' ) - { - if ( strlen(buf) < 7 ) lwerror("RGB value too short"); - p.type = 5; /* rgb */ - ptr=buf+1; - rgb.red = parse_hex(ptr); - ptr+=2; - rgb.green = parse_hex(ptr); - ptr+=2; - rgb.blue = parse_hex(ptr); - memcpy(p.val, &rgb, 3); - - return p; - } - - /* float32 */ - if ( strchr(buf, '.') ) - { - f32 = strtod(buf, &ptr); - if ( ptr != buf+strlen(buf) ) - lwerror("Malformed float value"); - p.type = 1; /* float32 */ - memcpy(p.val, &f32, 4); - - return p; - } - - /* int16 */ - i16 = strtol(buf, &ptr, 0); - if ( ptr != buf+strlen(buf) ) lwerror("Malformed integer value"); - if ( i16 > 65535 ) lwerror("Integer too high for an int16"); - p.type = 6; /* int16 */ - memcpy(p.val, &i16, 2); - p.val[2]=0; - p.val[3]=0; - return p; -} - -void -pixel_add_float32(PIXEL *where, PIXEL *what) -{ - FLOAT32 f1=0.0, f2=0.0; - memcpy(&f1, where->val, 4); - memcpy(&f2, what->val, 4); - f1 += f2; - memcpy(where->val, &f1, 4); -} - -void -pixel_add_int24(PIXEL *where, PIXEL *what) -{ - uint32 red, green, blue; - RGB rgb1, rgb2; - - memcpy(&rgb1, where->val, 3); - memcpy(&rgb2, what->val, 3); - red = rgb1.red + rgb2.red; - green = rgb1.green + rgb2.green; - blue = rgb1.blue + rgb2.blue; - if ( red > 255 ) - { - lwnotice("Red channel saturated by add operation"); - red = 255; - } - if ( green > 255 ) - { - lwnotice("Green channel saturated by add operation"); - green = 255; - } - if ( blue > 255 ) - { - lwnotice("Blue channel saturated by add operation"); - blue = 255; - } - rgb1.red = red; - rgb1.green = green; - rgb1.blue = blue; - memcpy(where->val, &rgb1, 3); -} - -void -pixel_add_int16(PIXEL *where, PIXEL *what) -{ - UINT16 i1, i2; - unsigned long int tmp; - - i1 = pixel_readUINT16(where); - i2 = pixel_readUINT16(what); - tmp = (unsigned long)i1 + i2; - if ( tmp > 65535 ) - { - lwnotice("UInt16 Pixel saturated by add operation (%u+%u=%u)", - i1, i2, tmp); - tmp = 65535; - } - i1 = tmp; - pixel_writeUINT16(where, i1); -} - -void -pixel_add(PIXEL *where, PIXEL *what) -{ - if ( where->type != what->type ) - lwerror("Can't add pixels of different types"); - - switch (where->type) - { - case 1: /*float32*/ - pixel_add_float32(where, what); - break; - - case 5: /*int24*/ - pixel_add_int24(where, what); - break; - - case 6: /*int16*/ - pixel_add_int16(where, what); - break; - - default: - lwerror("pixel_add: unkown pixel type %d", - where->type); - } - -} - -/* - * Return size of pixel values in bytes - */ -size_t -chip_pixel_value_size(int datatype) -{ - switch (datatype) - { - case 1: - case 101: - return 4; - case 5: - case 105: - return 3; - case 6: - case 7: - case 106: - case 107: - return 2; - case 8: - case 108: - return 1; - default: - lwerror("Unknown CHIP datatype: %d", datatype); - return 0; - } -} - -/* - * Returns offset of pixel at X,Y - */ -#define CHIP_XY_OFF(c, x, y) ((x)+((y)*(c)->width)) -size_t -chip_xy_off(CHIP *c, size_t x, size_t y) -{ -#ifdef CHIP_BOUNDS_CHECKS - if ( x < 0 || x >= c->width || y < 0 || y >= c->height ) - { - lwerror("Coordinates ouf of range"); - return 0; - } -#endif - return x+(y*c->width); -} - -/* - * Set pixel value. - * - * CHIP is assumed to be: - * - uncompressed - * - in machine's byte order - */ -void -chip_setPixel(CHIP *c, int x, int y, PIXEL *p) -{ - void *where; - size_t ps; - size_t off; - -#if DEBUG_CHIP - lwnotice("chip_setPixel([CHIP %p], %d, %d) called", c, x, y); -#endif - if ( c->datatype != p->type ) lwerror("Pixel datatype mismatch"); - - ps = chip_pixel_value_size(c->datatype); - off = chip_xy_off(c, x, y)*ps; - if ( off > c->size + sizeof(CHIP) ) - { - lwerror("Pixel offset out of CHIP size bounds"); - } - - where = ((char*)&(c->data))+off; - -#if DEBUG_CHIP - lwnotice("Writing %d bytes (%s) at offset %d (%p)", - ps, pixelHEX(p), off, where); -#endif - - memcpy(where, &(p->val), ps); -} - -/* - * Get pixel value. - * - * CHIP is assumed to be: - * - uncompressed - * - in machine's byte order - */ -PIXEL -chip_getPixel(CHIP *c, int x, int y) -{ - PIXEL p; - size_t ps = chip_pixel_value_size(c->datatype); - void *where = ((char*)&(c->data))+chip_xy_off(c, x, y)*ps; - p.type = c->datatype; - memset(p.val, '\0', 4); - memcpy(p.val, where, ps); - - return p; -} - -/******************************************************************** - * - * Drawing primitives - * - ********************************************************************/ - -/* - * Coordinates are in CHIP offset, so callers must - * appropriately translate. - */ -void -chip_draw_pixel(CHIP *chip, int x, int y, PIXEL *pixel, int op) -{ - -#if DEBUG_CHIP - lwnotice("chip_draw_pixel([CHIP %p], %d, %d, [PIXEL %p], %s) called", - (void*)chip, x, y, (void*)pixel, pixelOpName(op)); -#endif - - if ( x < 0 || x >= chip->width || y < 0 || y >= chip->height ) - { - /* should this be a warning ? */ - lwnotice("chip_draw_pixel called with out-of-range coordinates (%d,%d)", x, y); - return; - } - - /* - * Translate x and y values, which are in map units, to - * CHIP units - */ - - switch ( op ) - { - PIXEL p; - - case PIXELOP_OVERWRITE: - chip_setPixel(chip, x, y, pixel); - break; - - case PIXELOP_ADD: - p = chip_getPixel(chip, x, y); - pixel_add(&p, pixel); - chip_setPixel(chip, x, y, &p); - break; - - default: - lwerror("Unsupported PIXELOP: %d", op); - } - -} - -/* - * Bresenham Line Algorithm - * http://www.edepot.com/linebresenham.html - */ -void -chip_draw_segment(CHIP *chip, - int x1, int y1, int x2, int y2, - PIXEL *pixel, int op) -{ - int x, y; - int dx, dy; - int incx, incy; - int balance; - - - if (x2 >= x1) - { - dx = x2 - x1; - incx = 1; - } - else - { - dx = x1 - x2; - incx = -1; - } - - if (y2 >= y1) - { - dy = y2 - y1; - incy = 1; - } - else - { - dy = y1 - y2; - incy = -1; - } - - x = x1; - y = y1; - - if (dx >= dy) - { - dy <<= 1; - balance = dy - dx; - dx <<= 1; - - while (x != x2) - { - chip_draw_pixel(chip, x, y, pixel, op); - if (balance >= 0) - { - y += incy; - balance -= dx; - } - balance += dy; - x += incx; - } - chip_draw_pixel(chip, x, y, pixel, op); - } - else - { - dx <<= 1; - balance = dx - dy; - dy <<= 1; - - while (y != y2) - { - chip_draw_pixel(chip, x, y, pixel, op); - if (balance >= 0) - { - x += incx; - balance -= dy; - } - balance += dx; - y += incy; - } - chip_draw_pixel(chip, x, y, pixel, op); - } -} - -void -chip_fill(CHIP *chip, PIXEL *pixel, int op) -{ - int x, y; - -#if DEBUG_CHIP - lwnotice("chip_fill called"); -#endif - - for (x=0; xwidth; x++) - { - for (y=0; yheight; y++) - { - chip_draw_pixel(chip, x, y, pixel, op); - } - } -} - -/******************************************************************** - * - * CHIP constructors - * - ********************************************************************/ - -CHIP * -pgchip_construct(BOX3D *bvol, int srid, int width, int height, - int datatype, PIXEL *initvalue) -{ - size_t pixsize = chip_pixel_value_size(datatype); - size_t datasize = pixsize*width*height; - size_t size = sizeof(CHIP)-sizeof(void*)+datasize; - CHIP *chip = lwalloc(size); - -#if DEBUG_CHIP - lwnotice(" sizeof(CHIP):%d, pixelsize:%d, datasize:%d, total size:%d", sizeof(CHIP), pixsize, datasize, size); -#endif - - chip->size=size; - chip->endian_hint=1; - memcpy(&(chip->bvol), bvol, sizeof(BOX3D)); - chip->srid=srid; - memset(chip->future, '\0', 4); - chip->factor=1.0; - chip->datatype=datatype; - chip->height=height; - chip->width=width; - chip->compression=0; /* no compression */ - if ( ! initvalue ) - { - memset(&(chip->data), '\0', datasize); - } - else - { - chip_fill(chip, initvalue, PIXELOP_OVERWRITE); - } - return chip; -} - - -/******************************************************************** - * - * Drawing functions - * - ********************************************************************/ - - -/* - * Transform a POINT from geo coordinates to CHIP offsets. - * Can be optimized by caching CHIP info somewhere and using - * multiplications rather then divisions. - */ -static void -transform_point(CHIP* chip, POINT2D* p) -{ - /* geo size of full grid/chip */ - double geowidth = chip->bvol.xmax - chip->bvol.xmin; - double geoheight = chip->bvol.ymax - chip->bvol.ymin; - - /* geo size of a cell/pixel */ - double xscale = geowidth / chip->width; - double yscale = geoheight / chip->height; - - double xoff = ( chip->bvol.xmin + xscale ); - double yoff = ( chip->bvol.ymin + yscale ); - -#if 0 - double ox = p->x; - double oy = p->y; -#endif - - p->x = rint ( ( p->x - xoff ) / xscale ); - p->y = rint ( ( p->y - yoff ) / yscale ); - -#if 0 - lwnotice("Old x: %g, new x: %g", ox, p->x); -#endif - -} - -void -chip_draw_ptarray(CHIP *chip, POINTARRAY *pa, PIXEL *pixel, int op) -{ - POINT2D A, B; - int i; - int x1, x2, y1, y2; - - for (i=1; inpoints; i++) - { - getPoint2d_p(pa, i-1, &A); - getPoint2d_p(pa, i, &B); - - transform_point(chip, &A); - transform_point(chip, &B); - - x1 = A.x; - y1 = A.y; - x2 = B.x; - y2 = B.y; - - chip_draw_segment(chip, x1, y1, x2, y2, pixel, op); - } -} - -void -chip_draw_lwpoint(CHIP *chip, LWPOINT *lwpoint, PIXEL* pixel, int op) -{ - POINTARRAY *pa; - POINT2D point; - - pa = lwpoint->point; - getPoint2d_p(pa, 0, &point); - - /* translate to CHIP plane */ - transform_point(chip, &point); - - chip_draw_pixel(chip, point.x, point.y, pixel, op); -} - -void -chip_draw_lwline(CHIP *chip, LWLINE *lwline, PIXEL* pixel, int op) -{ - POINTARRAY *pa; - - pa = lwline->points; - chip_draw_ptarray(chip, pa, pixel, op); - return; -} - -void -chip_draw_lwgeom(CHIP *chip, LWGEOM *lwgeom, PIXEL *pixel, int op) -{ - int i; - LWCOLLECTION *coll; - - /* Check wheter we should completely skip this geometry */ - if ( lwgeom->bbox ) - { - if ( chip->bvol.xmax < lwgeom->bbox->xmin ) return; - if ( chip->bvol.xmin > lwgeom->bbox->xmax ) return; - if ( chip->bvol.ymax < lwgeom->bbox->ymin ) return; - if ( chip->bvol.ymin > lwgeom->bbox->ymax ) return; - } - - switch (lwgeom->type) - { - case POINTTYPE: - chip_draw_lwpoint(chip, (LWPOINT*)lwgeom, pixel, op); - return; - case LINETYPE: - chip_draw_lwline(chip, (LWLINE*)lwgeom, pixel, op); - return; - case POLYGONTYPE: - lwerror("%s geometry unsupported by draw operation", - lwtype_name(lwgeom->type)); - case MULTIPOINTTYPE: - case MULTILINETYPE: - case MULTIPOLYGONTYPE: - case COLLECTIONTYPE: - coll = (LWCOLLECTION *)lwgeom; - for (i=0; ingeoms; i++) - { - chip_draw_lwgeom(chip, coll->geoms[i], - pixel, op); - } - return; - default: - lwerror("Unknown geometry type: %d", lwgeom->type); - } -} - -/******************************************************************** - * - * PGsql interfaces - * - ********************************************************************/ - -typedef struct CHIPDUMPSTATE_T -{ - CHIP *chip; - int x; - int y; - char *values[3]; - char fmt[8]; -} -CHIPDUMPSTATE; - -/* - * Convert a TEXT to a C-String. - * Remember to lwfree the returned object. - */ -char * -text_to_cstring(text *t) -{ - char *s; - size_t len; - - len = VARSIZE(t)-VARHDRSZ; - s = lwalloc(len+1); - memcpy(s, VARDATA(t), len); - s[len] = '\0'; - - return s; -} - -PG_FUNCTION_INFO_V1(CHIP_dump); -Datum CHIP_dump(PG_FUNCTION_ARGS) -{ - CHIP *chip; - FuncCallContext *funcctx; - MemoryContext oldcontext, newcontext; - CHIPDUMPSTATE *state; - TupleDesc tupdesc; - AttInMetadata *attinmeta; - HeapTuple tuple; - TupleTableSlot *slot; - Datum result; - - if (SRF_IS_FIRSTCALL()) - { - funcctx = SRF_FIRSTCALL_INIT(); - newcontext = funcctx->multi_call_memory_ctx; - - oldcontext = MemoryContextSwitchTo(newcontext); - - chip = (CHIP *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)); - - /* Create function state */ - state = lwalloc(sizeof(CHIPDUMPSTATE)); - state->chip = chip; - state->x=0; - state->y=0; - state->values[0] = lwalloc(256); - state->values[1] = lwalloc(256); - state->values[2] = lwalloc(256); - - funcctx->user_fctx = state; - - /* - * Build a tuple description for an - * geometry_dump tuple - */ - tupdesc = RelationNameGetTupleDesc("chip_dump"); - - /* allocate a slot for a tuple with this tupdesc */ - slot = TupleDescGetSlot(tupdesc); - - /* allocate a slot for a tuple with this tupdesc */ - slot = TupleDescGetSlot(tupdesc); - - /* assign slot to function context */ - funcctx->slot = slot; - - /* - * generate attribute metadata needed later to produce - * tuples from raw C strings - */ - attinmeta = TupleDescGetAttInMetadata(tupdesc); - funcctx->attinmeta = attinmeta; - - MemoryContextSwitchTo(oldcontext); - } - - /* stuff done on every call of the function */ - funcctx = SRF_PERCALL_SETUP(); - newcontext = funcctx->multi_call_memory_ctx; - - /* get state */ - state = funcctx->user_fctx; - - /* Handled simple geometries */ - while ( state->y < state->chip->height && - state->x < state->chip->width ) - { - char buf[256]; - PIXEL p; - - if ( ! state->chip ) lwerror("state->chip corrupted"); - p = chip_getPixel(state->chip, state->x, state->y); - pixel_writeval(&p, buf, 255); - - sprintf(state->values[0], "%d", state->x); - sprintf(state->values[1], "%d", state->y); - sprintf(state->values[2], "%s", buf); - - tuple = BuildTupleFromCStrings(funcctx->attinmeta, - state->values); - result = TupleGetDatum(funcctx->slot, tuple); - - if ( state->x < state->chip->width-1 ) - { - state->x++; - } - else - { - state->x=0; - state->y++; - } - - SRF_RETURN_NEXT(funcctx, result); - - } - - SRF_RETURN_DONE(funcctx); -} - -PG_FUNCTION_INFO_V1(CHIP_construct); -Datum CHIP_construct(PG_FUNCTION_ARGS) -{ - CHIP *chip; - BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0); - int srid = PG_GETARG_INT32(1); - int width = PG_GETARG_INT32(2); - int height = PG_GETARG_INT32(3); - text *pixel_text = PG_GETARG_TEXT_P(4); - char *pixel = text_to_cstring(pixel_text); - PIXEL pix = pixel_readval(pixel); - -#if DEBUG_CHIP - lwnotice("CHIP_construct called"); -#endif - - if ( width <= 0 || height <= 0 ) - { - lwerror("Invalid values for width or height"); - PG_RETURN_NULL(); - } - - chip = pgchip_construct(box, srid, width, height, pix.type, &pix); - -#if DEBUG_CHIP - lwnotice("Created %dx%d chip type", chip->width, chip->height); -#endif - - PG_RETURN_POINTER(chip); -} - -PG_FUNCTION_INFO_V1(CHIP_getpixel); -Datum CHIP_getpixel(PG_FUNCTION_ARGS) -{ - CHIP *chip = (CHIP *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - int x = PG_GETARG_INT32(1); - int y = PG_GETARG_INT32(2); - char buf[256]; - size_t len; - text *ret; - PIXEL p; - - if ( x < 0 || x >= chip->width ) - { - lwerror("X out of range %d..%d", - 0, chip->width-1); - PG_RETURN_NULL(); - } - if ( y < 0 || y >= chip->height ) - { - lwerror("Y out of range %d..%d", - 0, chip->height-1); - PG_RETURN_NULL(); - } - - p = chip_getPixel(chip, x, y); - pixel_writeval(&p, buf, 255); - len = strlen(buf); - ret = lwalloc(len+VARHDRSZ); - SET_VARSIZE(ret, len+VARHDRSZ); - memcpy(VARDATA(ret), buf, len); - - PG_RETURN_POINTER(ret); -} - -PG_FUNCTION_INFO_V1(CHIP_setpixel); -Datum CHIP_setpixel(PG_FUNCTION_ARGS) -{ - CHIP *chip = (CHIP *) PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)); - int x = PG_GETARG_INT32(1); - int y = PG_GETARG_INT32(2); - text *init_val_text = PG_GETARG_TEXT_P(3); - char *init_val; - PIXEL pixel; - - /* Parse pixel */ - init_val = text_to_cstring(init_val_text); - pixel = pixel_readval(init_val); - - if ( chip->datatype != pixel.type ) - { - lwerror("Pixel datatype %d mismatches chip datatype %d", - pixel.type, chip->datatype); - } - - chip_setPixel(chip, x, y, &pixel); - - PG_RETURN_POINTER(chip); - -} - -PG_FUNCTION_INFO_V1(CHIP_draw); -Datum CHIP_draw(PG_FUNCTION_ARGS) -{ - CHIP *chip = (CHIP *) PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)); - PG_LWGEOM *geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - LWGEOM *lwgeom = pglwgeom_deserialize(geom); - text *pixel_text = PG_GETARG_TEXT_P(2); - char *pixel_str; - text *pixelop_text; - char *pixelop_str; - int pixelop = PIXELOP_OVERWRITE; - PIXEL pixel; - - /* Check SRID match */ - if ( chip->srid != lwgeom->srid ) - { - lwerror("Operation on mixed SRID objects"); - } - - if ( PG_NARGS() > 3 ) - { - pixelop_text = PG_GETARG_TEXT_P(3); - pixelop_str = text_to_cstring(pixelop_text); - if ( pixelop_str[0] == 'o' ) - { - pixelop = PIXELOP_OVERWRITE; - } - else if ( pixelop_str[0] == 'a' ) - { - pixelop = PIXELOP_ADD; - } - else - { - lwerror("Unsupported pixel operation %s", pixelop_str); - } - } - - /* Parse pixel */ - pixel_str = text_to_cstring(pixel_text); - pixel = pixel_readval(pixel_str); - lwfree(pixel_str); - - if ( pixel.type != chip->datatype ) - { - lwerror("Pixel/Chip datatype mismatch"); - } - - /* Perform drawing */ - chip_draw_lwgeom(chip, lwgeom, &pixel, pixelop); - - PG_RETURN_POINTER(chip); -} - -PG_FUNCTION_INFO_V1(CHIP_fill); -Datum CHIP_fill(PG_FUNCTION_ARGS) -{ - CHIP *chip = (CHIP *) PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)); - text *pixel_text = PG_GETARG_TEXT_P(1); - char *pixel_str; - text *pixelop_text; - char *pixelop_str; - int pixelop = PIXELOP_OVERWRITE; - PIXEL pixel; - - if ( PG_NARGS() > 2 ) - { - pixelop_text = PG_GETARG_TEXT_P(2); - pixelop_str = text_to_cstring(pixelop_text); - if ( pixelop_str[0] == 'o' ) - { - pixelop = PIXELOP_OVERWRITE; - } - else if ( pixelop_str[0] == 'a' ) - { - pixelop = PIXELOP_ADD; - } - else - { - lwerror("Unsupported pixel operation %s", pixelop_str); - } - } - - /* Parse pixel */ - pixel_str = text_to_cstring(pixel_text); - pixel = pixel_readval(pixel_str); - lwfree(pixel_str); - - if ( pixel.type != chip->datatype ) - { - lwerror("Pixel/Chip datatype mismatch"); - } - - /* Perform fill */ - chip_fill(chip, &pixel, pixelop); - - PG_RETURN_POINTER(chip); -}