[postgis-commits] svn - r2697 - in
branches/gSoC2007_raster/pgraster: . win32/build
postgis-commits at postgis.refractions.net
postgis-commits at postgis.refractions.net
Sun Aug 19 18:57:54 PDT 2007
Author: xingkth
Date: 2007-08-19 18:57:53 -0700 (Sun, 19 Aug 2007)
New Revision: 2697
Added:
branches/gSoC2007_raster/pgraster/win32/build/pgraster2geotiff.exe
Modified:
branches/gSoC2007_raster/pgraster/geotiff2pgraster.c
branches/gSoC2007_raster/pgraster/pgraster2geotiff.c
branches/gSoC2007_raster/pgraster/pgraster_utils.c
branches/gSoC2007_raster/pgraster/pgraster_utils.h
Log:
Xing. GoogleSoC2007 Code Upload(20070819)
Modified: branches/gSoC2007_raster/pgraster/geotiff2pgraster.c
===================================================================
--- branches/gSoC2007_raster/pgraster/geotiff2pgraster.c 2007-08-17 22:46:15 UTC (rev 2696)
+++ branches/gSoC2007_raster/pgraster/geotiff2pgraster.c 2007-08-20 01:57:53 UTC (rev 2697)
@@ -156,6 +156,8 @@
FILE *debug;
#endif
+int getopt();
+
/* Prototypes */
char * getTableOID(char *schema, char *table);
void usage(char* me, int status, FILE* out);
@@ -249,7 +251,7 @@
Cleanup();
/* Step 6. Function Successfully Return and Send Message To Terminal or Log */
- PrintResultMessage();
+ PrintResultMessage(1);
return 0;
}
@@ -400,7 +402,7 @@
int c, curindex;
char buf[QUERY_BUF_LENGTH];
- memset(buf,QUERY_BUF_LENGTH, '\0');
+ memset(buf,'\0', QUERY_BUF_LENGTH);
/* Parse command line */
while ((c = getopt(ARGC, ARGV, "h:d:U:p:P:rk:vq")) != EOF){
@@ -1069,7 +1071,7 @@
else if(bps == 32)
datatype = DT_32BIT_S;
else
- {
+ {// Read spatial extent information from PGRASTER_METADATA
if(outmode != MODE_QUIET)
fprintf(stderr , "**Error**: Unsupported TIFF sample format.\n");
exit_nicely(conn,1);
@@ -1087,7 +1089,7 @@
else
{
if(outmode != MODE_QUIET)
- fprintf(stderr , "**Error**: Unsupported TIFF sample format.\n");
+ fprintf(stderr, "**Error**: Unsupported TIFF sample format.\n");
exit_nicely(conn,1);
}
break;
@@ -1313,7 +1315,7 @@
* this programe will exit abnormally.
* Using SQL functions.
*/
- memset(query, QUERY_BUF_LENGTH, '\0');
+ memset(query,'\0', QUERY_BUF_LENGTH);
sprintf(query,"SELECT AddRasterTableFull('%s','%s',%f,%f,%d,%d,%d,%d,%d,%d,%d,%d,%d);",
schema,
table,
@@ -1345,11 +1347,11 @@
fldLen = PQgetlength(res,0,0);
pszValue = PQgetvalue(res,0,0);
metadata.name = malloc(fldLen * sizeof(char)+1);
- memset(metadata.name,sizeof(char)*fldLen+1,'\0');
+ memset(metadata.name,'\0',sizeof(char)*fldLen+1);
memcpy(metadata.name,(char*)pszValue,fldLen*sizeof(char));
PQclear(res);
- memset(query, QUERY_BUF_LENGTH, '\0');
+ memset(query, '\0', QUERY_BUF_LENGTH);
sprintf(query,"SELECT rasterObjectID FROM pgraster_metadata WHERE name='%s'",
metadata.name);
@@ -1390,7 +1392,7 @@
paramValues[0] = (char*)(metadata.spatialExtent);
paramLengths[0] = G_GetSize(metadata.spatialExtent);
paramFormats[0] = 1; //Binary
- memset(query, QUERY_BUF_LENGTH, '\0');
+ memset(query, '\0' , QUERY_BUF_LENGTH);
sprintf(query,"UPDATE \"%s\".\"pgraster_metadata\" SET spatialextent=GeomFromWKB($1,%d) WHERE rasterObjectID=%Ld",
schema,
@@ -1421,12 +1423,12 @@
{
// Create Prepared Insert Statement for Raster Data Insertion
insertStmt = (char*)malloc(strlen(schema) + strlen(table) + 1);
- memset(insertStmt, strlen(schema) + strlen(table) + 1, '\0');
+ memset(insertStmt, '\0' , strlen(schema) + strlen(table) + 1);
memcpy(insertStmt, schema, strlen(schema));
memcpy(insertStmt+strlen(schema), table, strlen(table));
- memset(query, QUERY_BUF_LENGTH, '\0');
+ memset(query, '\0' , QUERY_BUF_LENGTH);
sprintf(query,"INSERT INTO \"%s\".\"%s\"(rasterobjectid,pyramidlevel,bandblocknumber,rowblocknumber,columnblocknumber,blockbandsize,blockrowsize,blockcolumnsize,blockmbr,datablock) Values($1,$2,$3,$4,$5,$6,$7,$8,GeomFromWKB($9),$10)",
schema,
table);
@@ -1459,7 +1461,7 @@
void _CleanUpDemo()
{
char query[QUERY_BUF_LENGTH];
- memset(query, QUERY_BUF_LENGTH, '\0');
+ memset(query, '\0' , QUERY_BUF_LENGTH);
printf("Executing CleanUpDemo()!!!!\n");
@@ -2289,7 +2291,7 @@
void CreateIndex()
{
char query[QUERY_BUF_LENGTH];
- memset(query, QUERY_BUF_LENGTH, '\0');
+ memset(query, '\0', QUERY_BUF_LENGTH);
if(outmode == MODE_VERBOSE)
fprintf(stdout, "Start building GiST on block mbr.\n");
sprintf(query,"CREATE INDEX \"index_%s_%s\" ON \"%s\".\"%s\" using GIST ( blockMBR GIST_GEOMETRY_OPS)",
@@ -2321,7 +2323,7 @@
double adfCoeff[6], x, y;
char query[QUERY_BUF_LENGTH];
- memset(query,QUERY_BUF_LENGTH,'\0');
+ memset(query,'\0',QUERY_BUF_LENGTH);
if(outmode == MODE_VERBOSE)
fprintf(stdout, "Start loading SRS information.\n");
@@ -2354,7 +2356,7 @@
// A(0), B(1), C(2), D(3), E(4), F(5)
// Xgeo = E + Xpixel * A + Ypixel * C
// Ygeo = F + Ypixel * D + Xpixel * B
- sprintf(query, "UPDATE \"%s\".\"pgraster_srs\" SET rowdenominator='{%lf,%lf,%lf}', columndenominator='{%lf,%lf,%lf}' WHERE rasterObjectID=%Ld",schema, adfCoeff[5], adfCoeff[3],adfCoeff[1],adfCoeff[4], adfCoeff[2],adfCoeff[0],metadata.rasterObjectID);
+ sprintf(query, "UPDATE \"%s\".\"pgraster_srs\" SET rowdenominator='{%lf,%lf,%lf}', columndenominator='{%lf,%lf,%lf}' WHERE rasterObjectID=%Ld",schema, adfCoeff[5], adfCoeff[3],adfCoeff[1],adfCoeff[4], adfCoeff[0],adfCoeff[2],metadata.rasterObjectID);
res = PQexec(conn,query);
@@ -2377,7 +2379,7 @@
{
// Some metadata need to be updated after the data loading.
char query[QUERY_BUF_LENGTH];
- memset(query, QUERY_BUF_LENGTH, '\0');
+ memset(query, '\0' , QUERY_BUF_LENGTH);
if(outmode == MODE_VERBOSE)
fprintf(stdout, "Start updating metadata second time.\n");
sprintf(query,"UPDATE \"%s\".\"pgraster_metadata\" SET rasterpyramiddepth=%d WHERE rasterObjectID=%Ld", schema, (int)nPyramidDepth, metadata.rasterObjectID);
@@ -2427,12 +2429,12 @@
if(sucessful == 1)
{
//sucessful
- fprintf(stdout, "GeoTIFF file '%s' importing failed.\n", geotiff_file);
+ fprintf(stdout, "GeoTIFF file '%s' succesfully imported.\n", geotiff_file);
}
else
{
//fail
- fprintf(stdout, "GeoTIFF file '%s' succesfully imported.\n", geotiff_file);
+ fprintf(stdout, "GeoTIFF file '%s' importing failed.\n", geotiff_file);
}
}
Modified: branches/gSoC2007_raster/pgraster/pgraster2geotiff.c
===================================================================
--- branches/gSoC2007_raster/pgraster/pgraster2geotiff.c 2007-08-17 22:46:15 UTC (rev 2696)
+++ branches/gSoC2007_raster/pgraster/pgraster2geotiff.c 2007-08-20 01:57:53 UTC (rev 2697)
@@ -32,6 +32,7 @@
static char rcsid[] =
"$Id: pgraster2geotiff.c 2007-07-22 Xing.Lin $";
+#include "../config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -41,57 +42,1513 @@
/* Solaris9 does not provide stdint.h */
/* #include <stdint.h> */
#include <inttypes.h>
+
+//GeoTIFF & TIFF library headers
+#include "geotiff.h"
+#include "xtiffio.h"
+#include "geotiffio.h"
+#include "geo_tiffp.h"
+#include "geo_normalize.h"
+#include "geovalues.h"
+
+//Libpq & PGRaster headers
#include "libpq-fe.h"
#include "getopt.h"
#include "pgraster_const.h"
#include "pgraster_types.h"
#include "pgraster_utils.h"
+#include "pgraster_version.h"
+#include "wkb.h"
#include "compat.h"
/* Used to help create tempate tables names */
#include <sys/types.h> // for getpid()
#include <unistd.h> // for getpid()
+#ifdef HAVE_ICONV_H
+#include <iconv.h>
+#endif
+
#ifdef __CYGWIN__
#include <sys/param.h>
#endif
+#define TIFFOpen XTIFFOpen
+#define TIFFClose XTIFFClose
+#define streq(a,b) (strcmp(a,b) == 0)
+#define strneq(a,b,n) (strncmp(a,b,n) == 0)
+
/* Debug Control Flag */
#define DEBUG 1
-/*
- * Verbosity:
- * set to 1 to see record fetching progress
- * set to 2 to see also shapefile creation progress
- * set to 3 for debugging
- */
-#define VERBOSE 1
+/* Buffer length for SQL statement */
+#define QUERY_BUF_LENGTH 1024
/* Global data */
+PGconn *conn;
+PGresult *res;
+TIFF *tif=(TIFF*)0; /* TIFF-level descriptor */
+GTIF *gtif=(GTIF*)0; /* GeoKey-level descriptor */
+int rowbuflen;
+char *table, *geotiff_file, *schema, *geotiff_filename;
+int keep_fieldname_case = 0;
+int big_endian = 0;
+int pgis_major_version;
+#define MODE_QUIET 0
+#define MODE_NORMAL 1
+#define MODE_VERBOSE 2
+int outmode = 1; // 0=quiet mode; 1=normal mode, 2=verbose mode.
+bool beginTransaction = FALSE;
+char *PG_VERSION = "8.2.4\0";
+PGRasterMetadata metadata;
+/* TIFF Writer/Reader Global Data */
+byte *pDataBuffer = NULL;
+short scanlineMode = 0;
+int nTIFFBytePerPixel = 0;
+int nTIFFBitsPerPixel = 0;
+int nRealBytePerPixel = 0;
+int nRealBitsPerPixel = 0;
+uint32 stripMax, stripCount;
+tsize_t stripSize;
+uint32 rowsperstrip = 20;
+uint32 bufferSize;
+unsigned long imageOffset;
+uint16 bps = 1;
+uint16 spp = 1;
+uint16 mode = PHOTOMETRIC_MINISBLACK;
+uint16 format = SAMPLEFORMAT_UINT;
+uint16 planar = PLANARCONFIG_CONTIG;
+uint16 compression = COMPRESSION_NONE;
+uint16 predictor = (uint16)-1;
+int jpegcolormode = JPEGCOLORMODE_RGB;
+uint32 defg3opts = (uint32) -1;
+uint16 defcompression = (uint16) -1;
+uint16 defpredictor = (uint16) -1;
+uint16 preMultiplied = 0;
+uint16 fillorder = FILLORDER_MSB2LSB ;
+byte tiff_bigendian = 0; // whether TIFF file uses big endian byte order.
+byte badIndians = 0; // whether TIFFBigEndian != big_endian
+byte hasAlpha = 0; // hasAlpha channel???
+uint32 rows = 0; // number of TIFF image rows
+uint32 cols = 0; // number of TIFF image column
+uint32 bands = 0; // number of raster bands (image channel)
+uint32 nPyramidDepth = 0; // pyramide depth.
+byte nPyramidEnabled = 0;
+/* GeoTIFF Paramaters */
+short dimensions = 0;
+_int64 objectid = 0;
+char *captureDate = NULL;
+short Model = -1;
+short RasterModel = -1; // Area or Point
+int SRID = -1;
+double xGeoResolution = 0.0;
+double yGeoResolution = 0.0;
+double zGeoResolution = 0.0;
+PGRasterDataType datatype = DT_UNKNOWN;
+PGRasterBandType bandtype = BT_UNKNOWN;
+PGRasterValueType valuetype = VT_IMAGE;
+char* pgraster_name = NULL;
+WKBGeometry* spatialExtent = NULL;
+double columnDominator[3];
+double rowDominator[3];
+uint32 blocksizeBands=0, blocksizeRows=0, blocksizeColumns = 0;
+uint32 padding = 0;
+uint32 georeferenced = 0;
+uint32 blockBandInterleaving = 0;
+uint32 blockCompression = CT_NONE;
+uint32 blockQuality = 0;
+double dblNodataValue = -1.0f;
+
+#ifdef USE_ICONV
+char *encoding=NULL;
+#endif
+
+
+#ifdef DEBUG
+ FILE *debug;
+#endif
+
+/* External function declaration*/
+int getopt();
+
/* Prototypes */
+char * getTableOID(char *schema, char *table);
+void usage(char* me, int status, FILE* out);
+int parse_commandline(int ARGC, char **ARGV);
+static void parse_table(char *spec);
+static void parse_geotiffname(char *spec);
+static void exit_nicely(PGconn *conn, int code);
+int get_pgraster_version(void);
+int get_postgis_version(void);
+int processCompressOptions(char* opt);
+void processG3Options(char* cp);
+void CheckAndCorrectColormap(TIFF* tif, int n, uint16* r, uint16* g, uint16* b);
-
+/*******************************************************/
+/* Function for data exporting from PGRaster to GeoTIFF*/
+/*******************************************************/
+
+/* Step 0. Parse Paramaters and Create Connection*/
+void ParseAndCreateConnection(int ARGC, char **ARGV);
+
+/* Step 1. Initialization*/
+void Initialization();
+
+void _ReadPGRasterMetadata();
+
+void _CreateGeoTIFF();
+
+void _SetUpTIFFDirectory(TIFF *tif);
+
+void _SetUpGeoKeys(GTIF* gtif);
+
+void _WriteGeoTIFFHeader();
+
+void _CleanUpDemo();
+
+/* Step 2. Read GeoTIFF Data & Insert into PGRaster via PreparedStatement */
+void WriteTIFFData();
+
+/* Step 3. Cleanup & Close Connection*/
+void Cleanup();
+
+/* Step 4. Function Successfully Return and Send Message To Terminal or Log */
+void PrintResultMessage();
+
+#ifdef USE_ICONV
+char *utf8(const char *fromcode, char *inputbuf);
+#endif
+void *safe_malloc(size_t size)
+{
+ void *ret = malloc(size);
+ if ( ! ret ) {
+ if(outmode != MODE_QUIET)
+ fprintf(stderr, "**Error**: Out of virtual memory\n");
+ exit_nicely(conn, 1);
+ }
+ return ret;
+}
+#define malloc(x) safe_malloc(x)
+
/* Main Programe */
int main(int ARGC, char **ARGV)
{
/* Definition for local variables */
- /* Read User Input */
+ /* Step 0. Parse Paramaters and Create Connection */
+ ParseAndCreateConnection(ARGC, ARGV);
+
+ /* Step 1. Initialization & Read Metadata of PGRaster dataset for Data Export*/
+ Initialization();
- /* Initialization & Create PreparedStatement for Data Insert */
+ /* Step 2. Write TIFF Data Into TIFF files */
+ WriteTIFFData();
- /* Read Metadata from PGRaster & Write into GeoTIFF header via libgeotiff*/
+ /* Step 3. Cleanup & Close Connection*/
+ Cleanup();
- /* Read Data from PGRaster & Write into GeoTIFF via libgeotiff functions*/
+ /* Step 4. Function Successfully Return and Send Message To Terminal or Log */
+ PrintResultMessage(1);
- /* Close Files, PGConn and Clear PGresult*/
+ return 0;
+}
- /* Function Successfully Return and Send Message To Terminal or Log */
+/******** Implementation of Functions ********/
+/*
+ * Return allocate memory. Free after use.
+ */
+char * getTableOID(char *schema, char *table)
+{
+ PGresult *res3;
+ char *query;
+ char *ret;
+ size_t size;
- return -1;
+ size = strlen(table)+256;
+ if ( schema ) size += strlen(schema)+1;
+
+ query = (char *)malloc(size);
+
+ if ( schema )
+ {
+ sprintf(query, "SELECT oid FROM pg_class c, pg_namespace n WHERE c.relnamespace n.oid AND n.nspname = '%s' AND c.relname = '%s'", schema, table);
+ }
+ else
+ {
+ sprintf(query, "SELECT oid FROM pg_class WHERE relname = '%s'", table);
+ }
+
+ res3 = PQexec(conn, query);
+ free(query);
+ if ( ! res3 || PQresultStatus(res3) != PGRES_TUPLES_OK ) {
+ if(outmode != MODE_QUIET)
+ fprintf(stderr, "**Error** when getting TableOID: %s", PQerrorMessage(conn));
+ exit_nicely(conn, 1);
+ }
+ if(PQntuples(res3) == 1 ){
+ ret = strdup(PQgetvalue(res3, 0, 0));
+ }else if(PQntuples(res3) == 0 ){
+ if(outmode != MODE_QUIET)
+ fprintf(stdout, "Cannot find relation OID (does table exist?).\n");
+ PQclear(res3);
+ return NULL;
+ }else{
+ ret = strdup(PQgetvalue(res3, 0, 0));
+ if(outmode != MODE_QUIET)
+ printf( "Warning: Multiple relations detected, the program will only dump the first relation.\n");
+ }
+ PQclear(res3);
+ return ret;
}
-/******** Implementation of Functions ********/
+/*
+ * Print the usage information to standard output destination (terminal, file or so on).
+ */
+void usage(char* me, int status, FILE* out)
+{
+ fprintf(out,"PostgreSQL Version: %s \\ PostGIS Version: %s\n", PG_VERSION, POSTGIS_VERSION);
+ fprintf(out,"RCSID: %s RELEASE: %s\n", rcsid, PGRASTER_VERSION);
+ fprintf(out,"USAGE: %s [<options>] [<schema>.]table [geotiff-file] \n", me);
+
+ fprintf(out,"\n");
+
+ fprintf(out,"OPTIONS:\n");
+
+ fprintf(out," -h <host>\n");
+ fprintf(out," The database host to connect to. If ignored, the default address\n");
+ fprintf(out," of host will be \"localhost/127.0.0.1\". If no database running on\n");
+ fprintf(out," this host, the program will exit immediately with a error msg.\n");
+
+ fprintf(out," -p <port>\n");
+ fprintf(out," The port to connect to on the database host. If ignored, the\n");
+ fprintf(out," standard port number of 5432 will be used.If no database running\n");
+ fprintf(out," on this port, the program will exit immediately with a error msg.\n");
+
+ fprintf(out," -d <database>\n");
+ fprintf(out," The database to use when connecting. If ignored, the current OS\n");
+ fprintf(out," username will be used the name of database to login into. If this\n");
+ fprintf(out," database is refused to login, the program will exit immediately\n");
+ fprintf(out," with a error message.\n");
+
+ fprintf(out," -P <password>\n");
+ fprintf(out," The password to use when connecting to the database. This option\n");
+ fprintf(out," can't be ignored. If this password is refused to login, the pro-\n");
+ fprintf(out," gram will exit immediately with a error message.\n");
+
+ fprintf(out," -U <user>\n");
+ fprintf(out," The username to use when connecting to the database. If ignored,\n");
+ fprintf(out," the current OS username will be used to login into the database.\n");
+ fprintf(out," If this username is refused to login, the program will exit\n");
+ fprintf(out," immediately with a error message.\n");
+
+ fprintf(out,"[<schema>.]table [geotiff_file]\n");
+ fprintf(out," Export the specified pgraster table (e.x. public.usatm1990) into\n");
+ fprintf(out," GeoTIFF file. The <schema> and <geotiff_file> paramater is optional.\n");
+ fprintf(out," If ignored, the \'public\' as schema and <table> as geotiff_file will.\n");
+ fprintf(out," be adopted.\n");
+
+ fprintf(out," -k Keep postgresql identifiers case.\n");
+ fprintf(out," -?/--help Display this help screen.\n");
+
+ fprintf(out," -q Load data in quiet mode.\n");
+
+ fprintf(out," -v Load data in verbose mode.\n");
+
+ fprintf(out,"\n");
+
+ fprintf(out,"(Note that -a, -c, -d and -p are mutually exclusive.)\n");
+
+ fprintf(out,"####################### (NOT SUPPORTED YET) #########################\n");
+
+ fprintf(out,"(Note that -a, -c, -d and -p are mutually exclusive.)\n");
+
+ fprintf(out," -d Drops the database table before creating a new table with the\n");
+ fprintf(out," data in the geotiff file.\n");
+
+ fprintf(out," -a Appends data from the geotiff file into the existing database\n");
+ fprintf(out," table. Although it is not recommended to store raw data of sever-\n");
+ fprintf(out," ral raster dataset into one raster data table (sharing). But if\n");
+ fprintf(out," you insist, you can do it by this option\n");
+
+ fprintf(out," -c Creates a new table and populates it from the geotiff file. This\n");
+ fprintf(out," is the default mode.\n");
+
+
+ fprintf(out," -p Only produces the table creation SQL code, without adding any\n");
+ fprintf(out," actual data. This can be used if you need to completely seperate\n");
+ fprintf(out," the table creation and data loading steps.\n");
+ fprintf(out," (NOT SUPPORTED YET)\n");
+
+ fprintf(out," -D Use the PostgreSQL \"dump\" format for the output data. This can\n");
+ fprintf(out," be combined with -a, -c and -d. It is much faster to load than\n");
+ fprintf(out," the default \"insert\" SQL format. Use this for very large data\n");
+ fprintf(out," sets. If this option is set, then the following options could be\n");
+ fprintf(out," ignored.\n");
+ fprintf(out," (NOT SUPPORTED YET)\n");
+
+ fprintf(out,"####################### (NOT SUPPORTED YET) #########################\n");
+
+ fprintf(out,"\n");
+
+ exit (status);
+}
+
+/* Parse command line parameters */
+int parse_commandline(int ARGC, char **ARGV)
+{
+ if ( ARGC == 1 ) {
+ usage(ARGV[0], 0, stdout);
+ }
+
+ int c, curindex;
+ char buf[QUERY_BUF_LENGTH];
+
+ memset(buf,'\0', QUERY_BUF_LENGTH);
+
+ /* Parse command line */
+ while ((c = getopt(ARGC, ARGV, "h:d:U:p:P:rk:vq")) != EOF){
+ switch (c) {
+ case 'h':
+ /*setenv("PGHOST", optarg, 1); */
+ snprintf(buf, 255, "PGHOST=%s", optarg);
+ putenv(strdup(buf));
+ break;
+ case 'd':
+ /*setenv("PGHOST", optarg, 1); */
+ snprintf(buf, 255, "PGDATABASE=%s", optarg);
+ putenv(strdup(buf));
+ break;
+ case 'U':
+ /*setenv("PGUSER", optarg, 1); */
+ snprintf(buf, 255, "PGUSER=%s", optarg);
+ putenv(strdup(buf));
+ break;
+ case 'p':
+ /*setenv("PGPORT", optarg, 1); */
+ snprintf(buf, 255, "PGPORT=%s", optarg);
+ putenv(strdup(buf));
+ break;
+ case 'P':
+ /*setenv("PGPASSWORD", optarg, 1); */
+ snprintf(buf, 255, "PGPASSWORD=%s", optarg);
+ putenv(strdup(buf));
+ break;
+ case 'v': // verbose mode
+ outmode = MODE_VERBOSE;
+ break;
+ case 'q': // quiet mode
+ outmode = MODE_QUIET;
+ break;
+ case 'k':
+ keep_fieldname_case = 1;
+ break;
+ case '?':
+ usage(ARGV[0], 0, stdout);
+ default:
+ return 0;
+ }
+ }
+
+ curindex=0;
+ for (; optind<ARGC; optind++){
+ if (curindex == 0) {
+ schema = "public\0";
+ parse_table(ARGV[optind]);
+ geotiff_filename = table;
+ geotiff_file = malloc(strlen(table) + 4);
+ memcpy(geotiff_file, table, strlen(table));
+ memcpy(geotiff_file,".tif", 4);
+ }else if(curindex == 1){
+ geotiff_file = ARGV[optind];
+ parse_geotiffname(geotiff_file);
+ }
+ curindex++;
+ }
+
+ /*
+ * Transform table name to lower case unless asked
+ * to keep original case (we'll quote it later on)
+ */
+ if (keep_fieldname_case == 1)
+ {
+ LowerCase(table);
+ if ( schema ) LowerCase(schema);
+ }
+
+ // could only have on operant of geotiff_file
+ if (curindex < 1)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Get a table (and optionally a schema) if there is any.
+ * The table option could be ommited if user choose to use
+ * the same table name as the input geotiff filename.
+ */
+static void parse_table(char *spec)
+{
+ char *ptr;
+
+ table = spec;
+ if ( (ptr=strchr(table, '.')) )
+ {
+ *ptr = '\0';
+ schema = table;
+ table = ptr+1;
+ }
+}
+
+/*
+ * Parse the filename from geotiff_file path. Typical geotiff_file looks like:
+ * 1) /home/pgraster/data/usa_tm1990.tif
+ * 2) usa_tm1990.tif
+ * XXX: "Windows \" vs "Linux/Unix /"
+ */
+static void parse_geotiffname(char *spec)
+{
+ char *ptr;
+ char *strTemp;
+ int nlen;
+ int nlen2;
+
+
+ if(spec == NULL)
+ return;
+
+ nlen = strlen(spec);
+
+ strTemp = (char*)malloc(sizeof(char)*nlen+1);
+ strTemp = strcpy(strTemp, spec);
+ strTemp[nlen-1]='\0';
+
+ if ( (ptr=strrchr(strTemp, '.')) )
+ {
+ *ptr = '\0';
+ if( (ptr=strrchr(strTemp,92)) || (ptr=strrchr(strTemp,'/')) )
+ //XXX: how to deal with '/' and '\' different OS.
+ {
+ ptr = ptr+1;
+ nlen2 = strlen(ptr);
+ geotiff_filename = (char*)malloc(sizeof(char)*nlen2+1);
+ geotiff_filename = strcpy(geotiff_filename, ptr);
+ }
+ else
+ {
+ ptr = strTemp;
+ nlen2 = strlen(ptr);
+ geotiff_filename=(char*)malloc(sizeof(char)*nlen2+1);
+ geotiff_filename = strcpy(geotiff_filename, ptr);
+ }
+ }
+ else
+ {
+ if(outmode != MODE_QUIET)
+ fprintf(stderr, "**Error**: Fail to parse GeoTIFF dataset name from file %s\n", geotiff_file);
+ }
+}
+
+/*
+ * Exit Nicely for PostgreSQL Client that uses libpq-fe.
+ */
+static void exit_nicely(PGconn *conn, int code)
+{
+ if(beginTransaction == TRUE)
+ {
+ res = PQexec(conn, "ROLLBACK");
+ PQclear(res);
+ }
+
+ /* Close GeoTIFF File */
+ if (gtif) GTIFFree(gtif);
+ if (tif) XTIFFClose(tif);
+
+ /* Close PGConnection*/
+ PQfinish(conn);
+ exit(code);
+}
+
+/*
+ * Get PostGIS Major Version.
+ */
+int get_postgis_major_version(void)
+{
+ PGresult *res;
+ char *version;
+ int ver;
+ char *query = "SELECT postgis_version()";
+ res = PQexec(conn, query);
+
+ if ( ! res || PQresultStatus(res) != PGRES_TUPLES_OK )
+ {
+ if(outmode != MODE_QUIET)
+ {
+ fprintf(stderr, "**Error**: Can't detect postgis version:\n");
+ fprintf(stderr, "**Error**: PostgisVersionQuery: %s", PQerrorMessage(conn));
+ }
+ exit(1);
+ }
+
+ version = PQgetvalue(res, 0, 0);
+ ver = atoi(version);
+ PQclear(res);
+ return ver;
+}
+
+int processCompressOptions(char* opt)
+{
+ if (streq(opt, "none"))
+ compression = COMPRESSION_NONE;
+ else if (streq(opt, "packbits"))
+ compression = COMPRESSION_PACKBITS;
+ else if (strneq(opt, "jpeg", 4)) {
+ char* cp = strchr(opt, ':');
+ if (cp && isdigit(cp[1]))
+ blockQuality = atoi(cp+1);
+ if (cp && strchr(cp, 'r'))
+ jpegcolormode = JPEGCOLORMODE_RAW;
+ compression = COMPRESSION_JPEG;
+ } else if (strneq(opt, "g3", 2)) {
+ processG3Options(opt);
+ compression = COMPRESSION_CCITTFAX3;
+ } else if (streq(opt, "g4"))
+ compression = COMPRESSION_CCITTFAX4;
+ else if (strneq(opt, "lzw", 3)) {
+ char* cp = strchr(opt, ':');
+ if (cp)
+ defpredictor = atoi(cp+1);
+ compression = COMPRESSION_LZW;
+ } else if (strneq(opt, "zip", 3)) {
+ char* cp = strchr(opt, ':');
+ if (cp)
+ defpredictor = atoi(cp+1);
+ compression = COMPRESSION_DEFLATE;
+ } else
+ return (0);
+ return (1);
+}
+
+void processG3Options(char* cp)
+{
+ if( (cp = strchr(cp, ':')) != NULL ) {
+ if (defg3opts == (uint32) -1)
+ defg3opts = 0;
+ do {
+ cp++;
+ if (strneq(cp, "1d", 2))
+ defg3opts &= ~GROUP3OPT_2DENCODING;
+ else if (strneq(cp, "2d", 2))
+ defg3opts |= GROUP3OPT_2DENCODING;
+ else if (strneq(cp, "fill", 4))
+ defg3opts |= GROUP3OPT_FILLBITS;
+ else
+ usage("pgraster2geotiff", 2, stderr);;
+ } while( (cp = strchr(cp, ':')) != NULL );
+ }
+}
+
+/*
+ * Get PGRaster Major Version
+ */
+int get_pgraster_version(void)
+{
+ PGresult *res;
+ char *version;
+ int ver;
+ char query[] = "SELECT pgraster_version()";
+ res = PQexec(conn, query);
+
+ if ( ! res || PQresultStatus(res) != PGRES_TUPLES_OK )
+ {
+ if(outmode != MODE_QUIET)
+ {
+ fprintf(stderr, "**Error**: Can't detect PGRaster version:\n");
+ fprintf(stderr, "**Error**: PGRaster Version Query: %s", PQerrorMessage(conn));
+ }
+ exit(1);
+ }
+
+ version = PQgetvalue(res, 0, 0);
+ ver = atoi(version);
+ PQclear(res);
+ return ver;
+}
+
+/* make_good_string from shp_loader*/
+char * make_good_string(char *str)
+{
+ /*
+ * find all the tabs and make them \<tab>s
+ *
+ * 1. find # of tabs
+ * 2. make new string
+ *
+ * we dont escape already escaped tabs
+ */
+
+ char *result;
+ char *ptr, *optr;
+ int toescape = 0;
+ size_t size;
+#ifdef USE_ICONV
+ char *utf8str=NULL;
+
+ if ( encoding )
+ {
+ utf8str=utf8(encoding, str);
+ if ( ! utf8str ) exit(1);
+ str = utf8str;
+ }
+#endif
+
+ ptr = str;
+
+ while (*ptr) {
+ if ( *ptr == '\t' || *ptr == '\\' ) toescape++;
+ ptr++;
+ }
+
+ if (toescape == 0) return str;
+
+ size = ptr-str+toescape+1;
+
+ result = calloc(1, size);
+
+ optr=result;
+ ptr=str;
+ while (*ptr) {
+ if ( *ptr == '\t' || *ptr == '\\' ) *optr++='\\';
+ *optr++=*ptr++;
+ }
+ *optr='\0';
+
+#ifdef USE_ICONV
+ if ( encoding ) free(str);
+#endif
+
+ return result;
+
+}
+
+void CheckAndCorrectColormap(TIFF* tif, int n, uint16* r, uint16* g, uint16* b)
+{
+ int i;
+
+ for (i = 0; i < n; i++)
+ if (r[i] >= 256 || g[i] >= 256 || b[i] >= 256)
+ return;
+ TIFFWarning(TIFFFileName(tif), "Scaling 8-bit colormap");
+#define CVT(x) (((x) * ((1L<<16)-1)) / 255)
+ for (i = 0; i < n; i++) {
+ r[i] = CVT(r[i]);
+ g[i] = CVT(g[i]);
+ b[i] = CVT(b[i]);
+ }
+#undef CVT
+}
+
+/* protect_quotes_string from shp_loader*/
+char * protect_quotes_string(char *str)
+{
+ /*
+ * find all quotes and make them \quotes
+ * find all '\' and make them '\\'
+ *
+ * 1. find # of characters
+ * 2. make new string
+ */
+
+ char *result;
+ char *ptr, *optr;
+ int toescape = 0;
+ size_t size;
+#ifdef USE_ICONV
+ char *utf8str=NULL;
+
+ if ( encoding )
+ {
+ utf8str=utf8(encoding, str);
+ if ( ! utf8str ) exit(1);
+ str = utf8str;
+ }
+#endif
+
+ ptr = str;
+
+ while (*ptr) {
+ if ( *ptr == '\'' || *ptr == '\\' ) toescape++;
+ ptr++;
+ }
+
+ if (toescape == 0) return str;
+
+ size = ptr-str+toescape+1;
+
+ result = calloc(1, size);
+
+ optr=result;
+ ptr=str;
+ while (*ptr) {
+ if ( *ptr == '\'' || *ptr == '\\' ) *optr++='\\';
+ *optr++=*ptr++;
+ }
+ *optr='\0';
+
+#ifdef USE_ICONV
+ if ( encoding ) free(str);
+#endif
+
+ return result;
+}
+
+
+/********************************************************************/
+/******************** Functions for Data Loading ********************/
+/********************************************************************/
+void ParseAndCreateConnection(int ARGC, char **ARGV)
+{
+ /* Definition and Initialization for local/global variables */
+ big_endian = is_bigendian();
+
+ geotiff_file = NULL;
+ table = NULL;
+ schema = NULL;
+ geotiff_filename = NULL;
+ rowbuflen=100;
+ keep_fieldname_case = 0;
+ conn = NULL;
+ res = NULL;
+
+ if ( getenv("ROWBUFLEN") ) rowbuflen=atoi(getenv("ROWBUFLEN"));
+ /*
+ * Make sure dates are returned in ISO
+ * style (YYYY-MM-DD).
+ * This is to allow goodDBFValue() function
+ * to successfully extract YYYYMMDD format
+ * expected in shapefile's dbf file.
+ */
+ putenv("PGDATESTYLE=ISO");
+
+ if ( ! parse_commandline(ARGC, ARGV) )
+ {
+ if(outmode != MODE_QUIET)
+ { fprintf(stderr, "**ERROR** invalid option or command parameters.\n");
+ usage(ARGV[0], 2, stderr);
+ }
+
+ exit_nicely(conn,1);
+ }
+
+#ifdef DEBUG
+ if( getenv("PGHOST") != NULL && getenv("PGUSER") != NULL &&
+ getenv("PGPORT") != NULL && getenv("PGDATABASE") != NULL &&
+ getenv("PGPASSWORD") != NULL
+ )
+ fprintf(stdout, "PGHOST=%s PGPORT=%s PGDATABASE=%s PGUSER=%s PGPASSWORD=%s\n",
+ getenv("PGHOST"), getenv("PGPORT"), getenv("PGDATABASE"),
+ getenv("PGUSER"), getenv("PGPASSWORD"));
+ fprintf(stdout, "SCHEMA=%s TABLE=%s geotiff_file=%s geotiff_filename=%s\n",schema,table,geotiff_file,geotiff_filename);
+#endif
+
+ if(outmode != MODE_QUIET)
+ {
+ fprintf(stdout, "****************************************************************\n");
+ fprintf(stdout, "****************** PGRaster2GeoTIFF Converter ******************\n");
+ fprintf(stdout, "****************************************************************\n");
+ fprintf(stdout, "From PostgreSQL:\n\t host=%s PGPORT=%s database=%s user=%s password=%s schema=%s table=%s \n",
+ getenv("PGHOST"), getenv("PGPORT"), getenv("PGDATABASE"),
+ getenv("PGUSER"), getenv("PGPASSWORD"),schema,table);
+
+ fprintf(stdout, "To GeoTIFF:\n\tgeotiff_file=%s geotiff_filename=%s\n", geotiff_file,geotiff_filename);
+ }
+}
+
+/* Step 1. Initialization*/
+void Initialization()
+{
+ /* Declare local variable */
+ char query[QUERY_BUF_LENGTH];
+ bool bResult = FALSE;
+
+ if(outmode == MODE_VERBOSE)
+ {
+ fprintf(stdout, "Start initializing data export from PGRaster to GeoTIFF......\n");
+ }
+
+ /* Make a connection to the specified database, and exit on failure */
+ // All the necessary information is stored in OS Env-Variables
+ conn = PQconnectdb("");
+ if (PQstatus(conn) != CONNECTION_OK)
+ {
+ if(outmode != MODE_QUIET)
+ fprintf(stderr, "**Error**: when making connection to PostgreSQL: %s", PQerrorMessage(conn));
+ exit_nicely(conn, 1);
+ }
+
+#ifdef DEBUG
+ fprintf(stdout,"Connection OK!!!");
+#endif /* DEBUG */
+
+#ifdef DEBUG
+ debug = fopen("geotiff2pgraster.log", "wt");
+ PQtrace(conn, debug);
+#endif /* DEBUG */
+
+#ifdef DEBUG
+ _CleanUpDemo();
+#endif
+
+ /*
+ * Check Input Schema & Table Valid for Insert???
+ */
+ sprintf(query, "SELECT CheckRasterValidity('%s','%s')", schema, table);
+
+#ifdef DEBUG
+ printf("Query=%s\n", query);
+#endif
+
+
+ res = PQexecParams(conn,
+ query,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 1); /* ask for binary results */
+
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ {
+ if(outmode != MODE_QUIET)
+ fprintf(stderr, "**Error** when check raster name validity: %s", PQerrorMessage(conn));
+ PQclear(res);
+ exit_nicely(conn,1);
+ }
+ else
+ {
+ bResult = ((byte*)PQgetvalue(res,0,0))[0];
+ PQclear(res);
+ }
+
+ if(bResult == TRUE)
+ {
+ if(outmode != MODE_QUIET)
+ fprintf(stdout, "Current schema & table name does NOT exist. Please try again using a different pair.");
+ exit_nicely(conn, 1);
+ }
+ else
+ {
+ if(outmode != MODE_QUIET)
+ fprintf(stdout, "Current schema & table name exist.\n");
+ }
+
+ /*
+ * Read metadata from PGRaster into local variable
+ */
+ _ReadPGRasterMetadata();
+
+
+ /*
+ * Create GeoTIFF file and prepare for data and metadata writing.
+ */
+ _CreateGeoTIFF();
+
+ /*
+ * Write GeoTIFF metadata into header.
+ */
+ _WriteGeoTIFFHeader();
+
+ if(outmode == MODE_VERBOSE)
+ {
+ fprintf(stdout, "Finish data loader initializaiton.\n");
+ }
+}
+
+/* Clean files in last demo */
+void _CleanUpDemo()
+{
+ FILE *f_old = fopen(protect_quotes_string(geotiff_file),"r");
+ if(f_old != NULL)
+ {
+ fclose(f_old);
+ remove(protect_quotes_string(geotiff_file));
+ }
+}
+
+void _ReadPGRasterMetadata()
+{
+ /*
+ * Open the file, read the GeoTIFF information
+ */
+ char query[QUERY_BUF_LENGTH];
+
+ if(outmode == MODE_VERBOSE)
+ {
+ fprintf(stdout, "Start reading PGRaster metadata......\n");
+ }
+
+ // Read information from PGRASTER_META
+ memset(query, '\0' , QUERY_BUF_LENGTH);
+
+ sprintf(query, "SELECT rasterObjectID, name, capturedate,rasterdimensions,rasterbandtype,rasterdatatype,rastervaluetype,rasterbandcount,rasterrowcount,rastercolumncount,rastercelldepth,rasterpyramidenabled, rasterpyramiddepth,blocksizebands,blocksizerows,blocksizecolumns,blockpadding,blockbandinterleaving,blockcompression,blockquality,nodatavalue,srid, georeferenced FROM \"%s\".\"pgraster_metadata\" WHERE rasterSchema='%s' AND rasterDataTable='%s'",
+ schema,schema,table);
+
+ res = PQexec(conn,query);
+#ifdef DEBUG
+ printf("Query 1: %s\n",query);
+#endif
+
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ {
+ if(outmode != MODE_QUIET)
+ fprintf(stderr, "**Error** when fecthing metadata information from PostgreSQL: %s\n.", PQerrorMessage(conn));
+
+ PQclear(res);
+
+ exit_nicely(conn,1);
+ }
+ else
+ {
+ //rasterObjectID
+ objectid = atoi(PQgetvalue(res,0,0));
+
+ //Name
+ pgraster_name = malloc(PQgetlength(res,0,1));
+ memcpy(pgraster_name, (char*)(PQgetvalue(res,0,1)),PQgetlength(res,0,1));
+
+ //Capture Date
+ captureDate = malloc(PQgetlength(res,0,2));
+ memcpy(captureDate, (char*)(PQgetvalue(res,0,2)),PQgetlength(res,0,2));
+
+ //Dimensions
+ dimensions = atoi(PQgetvalue(res,0,3));
+
+ //rasterbandtype
+ bandtype = atoi(PQgetvalue(res,0,4));
+
+ //rasterdatatype
+ datatype = atoi(PQgetvalue(res,0,5));
+
+ //rastervaluetype,
+ valuetype = atoi(PQgetvalue(res,0,6));
+
+ //rasterbandcount
+ bands = atoi(PQgetvalue(res,0,7));
+
+ //rasterrowcount
+ rows = atoi(PQgetvalue(res,0,8));
+
+ //rastercolumncount
+ cols = atoi(PQgetvalue(res,0,9));
+
+ //rastercelldepth
+ nRealBitsPerPixel = atoi(PQgetvalue(res,0,10));
+
+ //rasterpyramidenabled
+ nPyramidEnabled = atoi(PQgetvalue(res,0,11));
+
+ //rasterpyramiddepth
+ nPyramidDepth = atoi(PQgetvalue(res,0,12));
+
+ //blocksizebands
+ blocksizeBands = atoi(PQgetvalue(res,0,13));
+
+ //blocksizerows
+ blocksizeRows = atoi(PQgetvalue(res,0,14));
+
+ //blockcolumns
+ blocksizeColumns = atoi(PQgetvalue(res,0,15));
+
+ //blockpadding
+ padding = atoi(PQgetvalue(res,0,16));
+
+ //blockbandinterleaving
+ blockBandInterleaving = atoi(PQgetvalue(res,0,17));
+
+ //blockcompression
+ blockCompression = atoi(PQgetvalue(res,0,18));
+
+ //blockquality,
+ blockQuality = atoi(PQgetvalue(res,0,18));
+
+ //nodatavalue
+ dblNodataValue = atof(PQgetvalue(res,0,19));
+
+ //srid
+ SRID = atoi(PQgetvalue(res,0,20));
+
+ //georeferenced
+ georeferenced = atoi(PQgetvalue(res,0,21));
+
+#ifdef DEBUG
+ printf("SRID: %d\n", SRID);
+#endif
+
+ PQclear(res);
+ }
+
+ // Read spatial extent information from PGRASTER_METADATA
+ memset(query, '\0' , QUERY_BUF_LENGTH);
+ sprintf(query, "SELECT AsBinary(spatialextent) FROM \"%s\".\"pgraster_metadata\" WHERE rasterSchema='%s' AND rasterDataTable='%s'", schema,schema,table);
+ res = PQexecParams(conn,
+ query,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 1); // Binary Format
+
+#ifdef DEBUG
+ printf("Query 1: %s\n",query);
+#endif
+
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ {
+ if(outmode != MODE_QUIET)
+ fprintf(stderr, "**Error** when fecthing SRS information from PostgreSQL:%s\n.", PQerrorMessage(conn));
+
+ PQclear(res);
+
+ exit_nicely(conn,1);
+ }
+ else
+ {
+ //AsBinary(spatialextent)
+ spatialExtent = (WKBGeometry*)malloc(sizeof(char)*PQgetlength(res,0,0));
+ memcpy((byte*)spatialExtent, (byte*)PQgetvalue(res,0,0), PQgetlength(res,0,0));
+
+#ifdef DEBUG
+ printf("WKB Size: %d, WKT: \n", PQgetlength(res,0,0));
+#endif
+ }
+
+ // Read spatial metadata information from PGRASTER_SRS
+ memset(query, '\0' , QUERY_BUF_LENGTH);
+ sprintf(query, "SELECT srid::integer,spatialresolutionx::double precision,spatialresolutiony::double precision,spatialresolutionz::double precision,rowdenominator[1]::double precision,rowdenominator[2]::double precision,rowdenominator[3]::double precision, columndenominator[1]::double precision,columndenominator[2]::double precision,columndenominator[3]::double precision FROM \"%s\".\"pgraster_srs\" WHERE rasterObjectID=%Ld", schema, objectid);
+ res = PQexecParams(conn,
+ query,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 1); // Binary Format
+
+#ifdef DEBUG
+ printf("Query 1: %s\n",query);
+#endif
+
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ {
+ if(outmode != MODE_QUIET)
+ fprintf(stderr, "**Error** when fecthing SRS information from PostgreSQL:%s\n.", PQerrorMessage(conn));
+
+ PQclear(res);
+
+ exit_nicely(conn,1);
+ }
+ else
+ {
+
+ //SRID
+ SRID = _ntohl(((int*)PQgetvalue(res,0,0))[0]);
+
+ //spatialresolutionx
+ xGeoResolution = _ntohd(((double*)PQgetvalue(res,0,1))[0]);
+
+ //spatialresolutiony
+ yGeoResolution = _ntohd(((double*)PQgetvalue(res,0,2))[0]);
+
+ //spatialresolutionz
+ zGeoResolution = _ntohd(((double*)PQgetvalue(res,0,3))[0]);
+
+#ifdef DEBUG
+ printf("SRID: %d, xGeoResolution: %f, yGeoResolution: %f,zGeoResolution: %f\n", SRID, xGeoResolution,yGeoResolution,zGeoResolution);
+#endif
+
+ //rowdenominator
+ rowDominator[0] = _ntohd(((double*)PQgetvalue(res,0,4))[0]);
+ rowDominator[1] = _ntohd(((double*)PQgetvalue(res,0,5))[0]);
+ rowDominator[2] = _ntohd(((double*)PQgetvalue(res,0,6))[0]);
+
+ //columndenominator
+ columnDominator[0] = _ntohd(((double*)PQgetvalue(res,0,7))[0]);
+ columnDominator[1] = _ntohd(((double*)PQgetvalue(res,0,8))[0]);
+ columnDominator[2] = _ntohd(((double*)PQgetvalue(res,0,9))[0]);
+
+#ifdef DEBUG
+ printf("rowDominator: %f, %f, %f\n ", rowDominator[0],rowDominator[1],rowDominator[2]);
+#endif
+
+ PQclear(res);
+ }
+
+ // XXX: Not finished.
+ // Read information from PGRASTER_PALETTE (Skip this part.)
+
+ // Pop Information into mode,sampleperpixel, bitspersample, sampleformat
+ if(bandtype == BT_RGB && datatype == DT_24BIT_RGB)
+ {
+ spp = bands * 3;
+ mode = PHOTOMETRIC_RGB;
+ bps = nTIFFBitsPerPixel / spp;
+ format = SAMPLEFORMAT_UINT;
+ }
+ else if(bandtype == BT_RGBA && datatype == DT_32BIT_RGBA)
+ {
+ spp = bands * 4;
+ mode = PHOTOMETRIC_RGB;
+ bps = nTIFFBitsPerPixel / spp;
+ format = SAMPLEFORMAT_UINT;
+ }
+ else
+ {
+ spp = bands;
+ mode = PHOTOMETRIC_MINISBLACK;
+ bps = nRealBitsPerPixel/spp;
+
+ switch(datatype)
+ {
+ case DT_1BIT:
+ case DT_2BIT:
+ case DT_4BIT:
+ case DT_8BIT_U:
+ case DT_16BIT_U:
+ case DT_32BIT_U:
+ //case DT_64BIT_U:
+ format = SAMPLEFORMAT_UINT;
+ break;
+
+ case DT_8BIT_S:
+ case DT_16BIT_S:
+ case DT_32BIT_S:
+ //case DT_64BIT_S:
+ format = SAMPLEFORMAT_INT;
+ break;
+
+ case DT_32BIT_REAL:
+ format = SAMPLEFORMAT_IEEEFP;
+ break;
+
+ default:
+ format = SAMPLEFORMAT_VOID;
+ break;
+ }
+ }
+
+ if(outmode == MODE_VERBOSE)
+ {
+ fprintf(stdout, "Finish reading PGRaster metadata.\n");
+ }
+}
+
+void _CreateGeoTIFF()
+{
+ //Set BigEndian as default output byte order
+ uint16 tif_magic;
+ FILE* ftifftemp = fopen(geotiff_file, "w");
+
+ if(ftifftemp == NULL)
+ {
+ if(outmode != MODE_QUIET)
+ fprintf(stderr, "**Error** when open another instance of TIFF file\n");
+ exit_nicely(conn, 1);
+ }
+ fseek(ftifftemp,0,SEEK_SET);
+ if(big_endian)
+ tif_magic = TIFF_BIGENDIAN;
+ else
+ tif_magic = TIFF_LITTLEENDIAN;
+ fwrite(&tif_magic,sizeof(tif_magic),1, ftifftemp);
+ fclose(ftifftemp);
+ ftifftemp = NULL;
+
+ tif=XTIFFOpen(geotiff_file,"w");
+ if (!tif)
+ {
+ if(outmode != MODE_QUIET)
+ fprintf(stderr, "**Error** when creating TIFF file.\n");
+ exit_nicely(conn,1);
+ }
+
+ gtif = GTIFNew(tif);
+ if (!gtif)
+ {
+ if(outmode != MODE_QUIET)
+ fprintf(stderr, "**Error** when creating GeoTIFF file.\n");
+ exit_nicely(conn,1);
+ }
+
+ _SetUpTIFFDirectory(tif);
+
+ _SetUpGeoKeys(gtif);
+}
+
+void _SetUpTIFFDirectory(TIFF *tif)
+{
+ double pixscale[3]={xGeoResolution,yGeoResolution,zGeoResolution};
+
+ TIFFSetField(tif,TIFFTAG_IMAGEWIDTH, cols);
+ TIFFSetField(tif,TIFFTAG_IMAGELENGTH, rows);
+ TIFFSetField(tif,TIFFTAG_COMPRESSION, compression);
+ TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT, format);
+ TIFFSetField(tif,TIFFTAG_PLANARCONFIG, planar);
+ TIFFSetField(tif,TIFFTAG_BITSPERSAMPLE, bps);
+ TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, mode);
+ TIFFSetField(tif,TIFFTAG_ROWSPERSTRIP, rowsperstrip);
+ TIFFSetField(tif,TIFFTAG_FILLORDER, fillorder);
+ TIFFSetField(tif,TIFFTAG_GEOPIXELSCALE, 3,pixscale);
+}
+
+//XXX: NOT FINISHED
+void _SetUpGeoKeys(GTIF *gtif)
+{
+ // Should we read information from spatial_ref_sys
+ // and parase them from the text???
+ GTIFKeySet(gtif, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelGeographic);
+ GTIFKeySet(gtif, GTRasterTypeGeoKey, TYPE_SHORT, 1, RasterPixelIsArea);
+ GTIFKeySet(gtif, GTCitationGeoKey, TYPE_ASCII, 0, "Unknown GTCitationGeoKey");
+ GTIFKeySet(gtif, GeographicTypeGeoKey, TYPE_SHORT, 1, KvUserDefined);
+ GTIFKeySet(gtif, GeogCitationGeoKey, TYPE_ASCII, 0, "Unknow GeogCitationGeoKey");
+ GTIFKeySet(gtif, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, Angular_Degree);
+ GTIFKeySet(gtif, GeogLinearUnitsGeoKey, TYPE_SHORT, 1, Linear_Meter);
+ GTIFKeySet(gtif, GeogGeodeticDatumGeoKey, TYPE_SHORT, 1, KvUserDefined);
+ GTIFKeySet(gtif, GeogEllipsoidGeoKey, TYPE_SHORT, 1, Ellipse_Everest_1830_1967_Definition);
+ GTIFKeySet(gtif, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1, (double)6377298.556);
+ GTIFKeySet(gtif, GeogInvFlatteningGeoKey, TYPE_DOUBLE, 1, (double)300.8017);
+
+ //
+
+}
+
+void _WriteGeoTIFFHeader()
+{
+ /* Write SRS Information*/
+
+ /* Write tiepoints through spatial extent or TFW information*/
+ {
+ double pixsize[3], xoff, yoff, tiepoint[6], x_rot, y_rot;
+
+ pixsize[0] = columnDominator[1];
+ y_rot = rowDominator[2];
+ x_rot = columnDominator[2];
+ pixsize[1] = rowDominator[1];
+ xoff = columnDominator[0];
+ yoff = rowDominator[0];
+
+#ifdef DEBUG
+ printf("%f\n,%f\n,%f\n,%f\n,%f\n,%f\n", pixsize[0],y_rot,x_rot,pixsize[1],xoff,yoff);
+#endif
+ /*
+ * Write out pixel scale, and tiepoint information.
+ */
+ if( x_rot == 0.0 && y_rot == 0.0 )
+ {
+ pixsize[1] = ABS(pixsize[1]);
+ pixsize[2] = 0.0;
+ TIFFSetField(tif, GTIFF_PIXELSCALE, 3, pixsize);
+
+ tiepoint[0] = 0.5;
+ tiepoint[1] = 0.5;
+ tiepoint[2] = 0.0;
+ tiepoint[3] = xoff;
+ tiepoint[4] = yoff;
+ tiepoint[5] = 0.0;
+ TIFFSetField(tif, GTIFF_TIEPOINTS, 6, tiepoint);
+ }
+ else
+ {
+ double adfMatrix[16];
+
+ memset(adfMatrix,0,sizeof(double) * 16);
+
+ adfMatrix[0] = pixsize[0];
+ adfMatrix[1] = x_rot;
+ adfMatrix[3] = xoff - (pixsize[0]+x_rot) * 0.5;
+ adfMatrix[4] = y_rot;
+ adfMatrix[5] = pixsize[1];
+ adfMatrix[7] = yoff - (pixsize[1]+y_rot) * 0.5;
+ adfMatrix[15] = 1.0;
+
+ TIFFSetField( tif, TIFFTAG_GEOTRANSMATRIX, 16, adfMatrix );
+ }
+ }
+}
+
+void WriteTIFFData()
+{
+
+/*
+ * int i;
+ char buffer[WIDTH];
+
+ memset(buffer,0,(size_t)WIDTH);
+ for (i=0;i<HEIGHT;i++)
+ if (!TIFFWriteScanline(tif, buffer, i, 0))
+ TIFFError("WriteImage","failure in WriteScanline\n");
+ */
+ char *exptStmt = malloc(strlen(schema)+1+strlen(table));
+ char query[QUERY_BUF_LENGTH];
+ const char *paramValues[2];
+ int paramLengths[2];
+ int paramFormats[2];
+ char *buffer = NULL;
+ int i=0,j=0,k=0,n=0;
+ _uint32 curBlockRow,curBlockBand;
+ _uint32 rowsReturned = 0;
+ _uint32 rowsToRead = 0;
+ rowsperstrip = blocksizeRows;
+ nTIFFBytePerPixel = (bps/8) * spp;
+ _uint32 stripsize = cols * rowsperstrip * bps * spp;
+
+ if(stripsize % 8 == 0 )
+ stripsize =stripsize / 8;
+ else
+ stripsize = stripsize / 8 + 1;
+
+ if(rows % rowsperstrip == 0)
+ stripMax = rows / rowsperstrip;
+ else
+ stripMax = rows / rowsperstrip + 1;
+
+#ifdef DEBUG
+ printf("nTIFFBytePerPixel:%d, rowsperstrip: %d, stripMax: %d, stripsize: %d\n",
+ nTIFFBytePerPixel, rowsperstrip,stripMax, stripsize);
+#endif
+
+ memcpy(exptStmt, schema, strlen(schema));
+ exptStmt[strlen(schema)] = '_';
+ memcpy(exptStmt+strlen(schema)+1, table, strlen(table));
+
+
+ memset(query,'\0',QUERY_BUF_LENGTH);
+ sprintf(query, "SELECT * FROM \"%s\".\"%s\" WHERE rasterObjectID=%d AND pyramidlevel=1 AND rowblocknumber=$1 AND bandblocknumber=$2 ORDER BY columnblocknumber",schema,table,(int)objectid);
+
+ res = PQprepare( conn,
+ exptStmt,
+ query,
+ 2,
+ NULL);
+ if ( PQresultStatus(res) != PGRES_COMMAND_OK )
+ {
+ if(outmode != MODE_QUIET)
+ fprintf(stderr, "**Error** when trying to create prepared statement for data exporting at server side: %s\n.",PQerrorMessage(conn));
+ exit_nicely(conn, 1);
+ }
+ PQclear(res);
+
+
+ buffer = malloc(stripsize);
+ for(i = 0 ; i < stripMax; i++)
+ {
+ memset(buffer,0, stripsize);
+
+ if(i != (stripMax-1))
+ rowsToRead = rowsperstrip;
+ else
+ rowsToRead = rows - (stripMax - 1) * rowsperstrip;
+
+ curBlockRow = _htonl((_uint32)i+1);
+ paramValues[0] = (char*)(&(curBlockRow));
+ paramLengths[0] = sizeof(curBlockRow);
+ paramFormats[0] = 1;
+
+#ifdef DEBUG
+ printf("rowsToRead: %d\n", rowsToRead);
+#endif
+
+ for(j = 0; j < bands; j++)
+ {
+ curBlockBand = _htonl((_uint32)j+1);
+ paramValues[1] = (char*)(&(curBlockBand));
+ paramLengths[1] = sizeof(curBlockBand);
+ paramFormats[1] = 1;
+
+ // Execute Prepared Statement
+ res = PQexecPrepared( conn,
+ exptStmt,
+ 2,
+ paramValues,
+ paramLengths,
+ paramFormats,
+ 1
+ );
+
+ if ( res == NULL || PQresultStatus(res) != PGRES_TUPLES_OK )
+ {
+ if(outmode != MODE_QUIET)
+ fprintf(stderr, "**Error** when trying to read raster data at server side: %s\n.",PQerrorMessage(conn));
+ exit_nicely(conn, 1);
+ }
+
+ //read data buffer
+ rowsReturned = (_uint32)PQntuples(res);
+
+#ifdef DEBUG
+ printf("rowsReturned: %d\n", rowsReturned);
+#endif
+
+ for(k = 0; k < rowsReturned; k++)
+ {
+ _uint32 realBlockColumnNumber = _ntohl(*((_uint32*)PQgetvalue(res,k,4)));
+ _uint32 realBlockBandSize = _ntohl(*((_uint32*)PQgetvalue(res,k,5)));
+ _uint32 realBlockRowSize = _ntohl(*((_uint32*)PQgetvalue(res,k,6)));
+ _uint32 realBlockColumnSize = _ntohl(*((_uint32*)PQgetvalue(res,k,7)));
+ byte* pQData = PQgetvalue(res,k,9);
+#ifdef DEBUG
+ printf("realBlockColumnNumber: %d ", realBlockColumnNumber);
+ printf("realBlockBandSize: %d ", realBlockBandSize);
+ printf("realBlockRowSize: %d \n", realBlockRowSize);
+#endif
+ for(n=0; n < realBlockRowSize; n++)
+ {
+ //fill data buffer
+ memcpy(buffer+(cols*n+(realBlockColumnNumber-1)*blocksizeColumns)*nTIFFBytePerPixel, pQData+(realBlockColumnSize*n)*nTIFFBytePerPixel,nTIFFBytePerPixel*realBlockColumnSize);
+ }
+ }
+
+ PQclear(res);
+ }
+
+ // flush data buffer to TIFF scanline
+ if( TIFFWriteEncodedStrip( tif, i, buffer,
+ nTIFFBytePerPixel * rowsToRead * cols ) == -1 )
+ {
+ // Write Failed.
+ if(outmode != MODE_QUIET)
+ fprintf(stderr, "**Error** when trying to write raster data to GeoTIFF file.");
+ exit_nicely(conn, 1);
+ }
+ }
+
+}
+
+void Cleanup()
+{
+
+ GTIFWriteKeys(gtif);
+ GTIFFree(gtif);
+ XTIFFClose(tif);
+
+ /* Close Connection*/
+ PQfinish(conn);
+}
+
+void PrintResultMessage(int sucessful)
+{
+ if(sucessful == 1)
+ {
+ //sucessful
+ fprintf(stdout, "GeoTIFF file '%s' succesfully exported.\n", geotiff_file);
+ }
+ else
+ {
+ //fail
+ fprintf(stdout, "GeoTIFF file '%s' exporting failed.\n", geotiff_file);
+ }
+}
Modified: branches/gSoC2007_raster/pgraster/pgraster_utils.c
===================================================================
--- branches/gSoC2007_raster/pgraster/pgraster_utils.c 2007-08-17 22:46:15 UTC (rev 2696)
+++ branches/gSoC2007_raster/pgraster/pgraster_utils.c 2007-08-20 01:57:53 UTC (rev 2697)
@@ -36,6 +36,8 @@
#include "pgraster_const.h"
#include "math.h"
+#pragma pack(1)
+
/* Some byte data reading/seeking tools */
void skipbyte(byte **c) {
*c+=1;
@@ -411,49 +413,62 @@
{
//return ((n & 0xFF) << 56) | ((n & 0xFF00) << 8) | ((n & 0xFF0000) >> 8) | ((n & 0xFF000000) >> 24);
return ((_uint64)(_ntohl((_uint32)((n << 32) >> 32))) << 32) | (_uint32)_ntohl(((int)(n >> 32)));
-
}
_uint64 _ntohll(_uint64 n)
{
- return _htonll(n);
+ return _htonll(n);
}
double _htond(double f)
{
- union
+ union
{
double f;
_uint32 h[2];
}swap;
-
+
swap.f = f;
- swap.h[0] = _htonl(swap.h[0]);
- swap.h[1] = _htonl(swap.h[1]);
+ swap.h[0] = _ntohl(swap.h[0]);
+ swap.h[1] = _ntohl(swap.h[1]);
- return swap.f;
+ if (!is_bigendian()) // little endian
+ {
+ _uint32 temp = swap.h[0];
+ swap.h[0] = swap.h[1];
+ swap.h[1] = temp;
+ }
+
+ return swap.f;
}
double _ntohd(double f)
{
- union
+ union
{
double f;
_uint32 h[2];
}swap;
-
+
swap.f = f;
- swap.h[0] = _htonl(swap.h[0]);
- swap.h[1] = _htonl(swap.h[1]);
+ swap.h[0] = _ntohl(swap.h[0]);
+ swap.h[1] = _ntohl(swap.h[1]);
- return swap.f;
+ if (!is_bigendian()) // little endian
+ {
+ _uint32 temp = swap.h[0];
+ swap.h[0] = swap.h[1];
+ swap.h[1] = temp;
+ }
+
+ return swap.f;
}
float _htonf(float f)
{
union
{
- double f;
+ float f;
_uint32 i;
}swap;
@@ -467,7 +482,7 @@
{
union
{
- double f;
+ float f;
_uint32 i;
}swap;
@@ -476,5 +491,4 @@
return swap.f;
}
-
-
+#pragma pack()
Modified: branches/gSoC2007_raster/pgraster/pgraster_utils.h
===================================================================
--- branches/gSoC2007_raster/pgraster/pgraster_utils.h 2007-08-17 22:46:15 UTC (rev 2696)
+++ branches/gSoC2007_raster/pgraster/pgraster_utils.h 2007-08-20 01:57:53 UTC (rev 2697)
@@ -119,7 +119,6 @@
_uint16 _htons(_uint16 n);
-
_uint16 _ntohs(_uint16 n);
_uint32 _htonl(_uint32 n);
@@ -130,35 +129,12 @@
_uint64 _ntohll(_uint64 n);
-uint32_t _htonf_(float f);
+float _ntohf(float f);
-float _ntohf_(uint32_t p);
+float _htonf(float f);
-/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
-* National Laboratory.
-* Copyright (c) 2002 The Regents of the University of California, as
-* Operator of Los Alamos National Laboratory.
-* EPICS BASE Versions 3.13.7
-* and higher are distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
-\*************************************************************************/
+double _ntohd(double d);
-/*
- * mitfp.c - routines to convert between VAX float and big endian
- * IEEE float
- *
- * Author: Jeffrey O. Hill
- *
- *
- */
+double _htond(double d);
-float _ntohf(float ieee);
-
-float _htonf(float mit);
-
-double _ntohlf(double ieee);
-
-double _htonlf(double mit);
-
#endif
Added: branches/gSoC2007_raster/pgraster/win32/build/pgraster2geotiff.exe
===================================================================
(Binary files differ)
Property changes on: branches/gSoC2007_raster/pgraster/win32/build/pgraster2geotiff.exe
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
More information about the postgis-commits
mailing list