summaryrefslogtreecommitdiffstats
path: root/gis/qmapshack/qmt_map2jnx.patch
diff options
context:
space:
mode:
Diffstat (limited to 'gis/qmapshack/qmt_map2jnx.patch')
-rw-r--r--gis/qmapshack/qmt_map2jnx.patch1199
1 files changed, 0 insertions, 1199 deletions
diff --git a/gis/qmapshack/qmt_map2jnx.patch b/gis/qmapshack/qmt_map2jnx.patch
deleted file mode 100644
index 50d5a26666..0000000000
--- a/gis/qmapshack/qmt_map2jnx.patch
+++ /dev/null
@@ -1,1199 +0,0 @@
-From 79a266943a40bee8fa5e71776c6a76c4d46bfbf8 Mon Sep 17 00:00:00 2001
-From: Oliver Eichler <oliver.eichler@dspsolutions.de>
-Date: Thu, 12 Sep 2019 20:31:26 +0200
-Subject: [PATCH] [QMS-3] Add qmt_map2jnx from former sub-repo
-
----
- src/qmt_map2jnx/CMakeLists.txt | 59 ++
- src/qmt_map2jnx/argv.cpp | 45 ++
- src/qmt_map2jnx/argv.h | 16 +
- src/qmt_map2jnx/main.cpp | 1039 ++++++++++++++++++++++++++++++++
- 4 files changed, 1159 insertions(+)
- create mode 100644 src/qmt_map2jnx/CMakeLists.txt
- create mode 100644 src/qmt_map2jnx/argv.cpp
- create mode 100644 src/qmt_map2jnx/argv.h
- create mode 100644 src/qmt_map2jnx/main.cpp
-
-diff --git a/src/qmt_map2jnx/CMakeLists.txt b/src/qmt_map2jnx/CMakeLists.txt
-new file mode 100644
-index 00000000..12b29d94
---- /dev/null
-+++ b/src/qmt_map2jnx/CMakeLists.txt
-@@ -0,0 +1,59 @@
-+
-+
-+set(APPLICATION_NAME qmt_map2jnx)
-+set(MAP2JNX_VERSION_MAJOR 1)
-+set(MAP2JNX_VERSION_MINOR 0)
-+set(MAP2JNX_VERSION_PATCH 0)
-+
-+add_definitions(
-+ -DVER_MAJOR=${MAP2JNX_VERSION_MAJOR}
-+ -DVER_MINOR=${MAP2JNX_VERSION_MINOR}
-+ -DVER_STEP=${MAP2JNX_VERSION_PATCH}
-+ -DVER_TWEAK=${VERSION_SUFFIX}
-+ -DAPPLICATION_NAME=${APPLICATION_NAME}
-+)
-+
-+
-+#if you don't want the full compiler output, remove the following line
-+SET(CMAKE_VERBOSE_MAKEFILE ON)
-+SET(SRCS main.cpp argv.cpp)
-+SET(HDRS argv.h)
-+
-+
-+include_directories(
-+ ${CMAKE_BINARY_DIR}
-+ ${CMAKE_CURRENT_BINARY_DIR}
-+ ${GDAL_INCLUDE_DIRS}
-+ ${PROJ4_INCLUDE_DIRS}
-+ ${JPEG_INCLUDE_DIRS}
-+)
-+
-+if(APPLE)
-+ INCLUDE_DIRECTORIES(/System/Library/Frameworks/Foundation.framework)
-+ INCLUDE_DIRECTORIES(/System/Library/Frameworks/DiskArbitration.framework)
-+endif(APPLE)
-+
-+if(WIN32)
-+ include_directories(
-+ ${CMAKE_SOURCE_DIR}/Win32/
-+ )
-+endif(WIN32)
-+
-+#list all source files here
-+ADD_EXECUTABLE( ${APPLICATION_NAME} ${SRCS} ${HDRS})
-+
-+#add definitions, compiler switches, etc.
-+IF(UNIX)
-+ ADD_DEFINITIONS(-Wall)
-+ENDIF(UNIX)
-+
-+IF(WIN32)
-+ ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)
-+ENDIF(WIN32)
-+
-+TARGET_LINK_LIBRARIES(${APPLICATION_NAME} ${GDAL_LIBRARIES} ${PROJ4_LIBRARIES} ${JPEG_LIBRARIES})
-+
-+install(
-+ TARGETS ${APPLICATION_NAME} DESTINATION ${BIN_INSTALL_DIR}
-+)
-+
-diff --git a/src/qmt_map2jnx/argv.cpp b/src/qmt_map2jnx/argv.cpp
-new file mode 100644
-index 00000000..a7f7939c
---- /dev/null
-+++ b/src/qmt_map2jnx/argv.cpp
-@@ -0,0 +1,45 @@
-+/**********************************************************************************************
-+ This program is free software: you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation, either version 3 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program. If not, see <http://www.gnu.org/licenses/>.
-+
-+**********************************************************************************************/
-+#include <stdlib.h>
-+#include <string.h>
-+
-+#ifdef WIN32
-+#include <windows.h>
-+#endif
-+
-+char* get_argv(const int index, char** argv)
-+{
-+ char* result = NULL;
-+ int len;
-+
-+#ifdef WIN32
-+ int numargs;
-+ wchar_t** argw = CommandLineToArgvW(GetCommandLineW(), &numargs);
-+
-+ // determine the buffer length first (including the trailing null)
-+ len = WideCharToMultiByte(CP_UTF8, 0, argw[index], -1, NULL, 0, NULL, NULL);
-+ result = (char*)calloc(len, 1);
-+ WideCharToMultiByte(CP_UTF8, 0, argw[index], -1, result, len, NULL, NULL);
-+
-+ GlobalFree(argw);
-+#else
-+ len = strlen(argv[index]) + 1;
-+ result = (char*)calloc(len, 1);
-+ strcpy(result, argv[index]);
-+#endif
-+
-+ return result;
-+}
-diff --git a/src/qmt_map2jnx/argv.h b/src/qmt_map2jnx/argv.h
-new file mode 100644
-index 00000000..0967d0b7
---- /dev/null
-+++ b/src/qmt_map2jnx/argv.h
-@@ -0,0 +1,16 @@
-+/**********************************************************************************************
-+ This program is free software: you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation, either version 3 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program. If not, see <http://www.gnu.org/licenses/>.
-+
-+**********************************************************************************************/
-+char* get_argv(const int index, char** argv);
-diff --git a/src/qmt_map2jnx/main.cpp b/src/qmt_map2jnx/main.cpp
-new file mode 100644
-index 00000000..bef9cc43
---- /dev/null
-+++ b/src/qmt_map2jnx/main.cpp
-@@ -0,0 +1,1039 @@
-+/**********************************************************************************************
-+ This program is free software: you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation, either version 3 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program. If not, see <http://www.gnu.org/licenses/>.
-+
-+**********************************************************************************************/
-+
-+#include "config.h"
-+
-+#ifdef _MSC_VER
-+#define fseeko _fseeki64
-+#define ftello _ftelli64
-+#else
-+#define _FILE_OFFSET_BITS 64
-+#endif //
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <stdint.h>
-+#include <math.h>
-+#include <wctype.h>
-+
-+
-+#include <list>
-+#include <string>
-+#include <vector>
-+
-+#include <gdal_priv.h>
-+#include <proj_api.h>
-+#include <ogr_spatialref.h>
-+
-+extern "C"
-+{
-+#include <jpeglib.h>
-+}
-+
-+#include "argv.h"
-+
-+
-+#ifndef _MKSTR_1
-+#define _MKSTR_1(x) #x
-+#define _MKSTR(x) _MKSTR_1(x)
-+#endif
-+
-+#define VER_STR _MKSTR(VER_MAJOR) "." _MKSTR(VER_MINOR) "." _MKSTR(VER_STEP)
-+#define WHAT_STR "qmt_map2jnx, Version " VER_STR
-+
-+#define JNX_MAX_TILES 50000 //6250
-+#define JNX_MAX_TILE_SIZE 1024
-+
-+#define JPG_BLOCK_SIZE (JNX_MAX_TILE_SIZE * JNX_MAX_TILE_SIZE)
-+
-+#define HEADER_BLOCK_SIZE 1024
-+
-+#pragma pack(1)
-+
-+struct jnx_hdr_t
-+{
-+ jnx_hdr_t(): version(0x00000004), devid(0), expire(0), productId(0), crc(0), signature(0), signature_offset(0), zorder(25){}
-+ uint32_t version; // byte 00000000..00000003
-+ uint32_t devid; // byte 00000004..00000007
-+ int32_t top; // byte 00000014..00000017
-+ int32_t right; // byte 00000010..00000013
-+ int32_t bottom; // byte 0000000C..0000000F
-+ int32_t left; // byte 00000008..0000000B
-+ uint32_t details; // byte 00000018..0000001B
-+ uint32_t expire; // byte 0000001C..0000001F
-+ uint32_t productId; // byte 00000020..00000023
-+ uint32_t crc; // byte 00000024..00000027
-+ uint32_t signature; // byte 00000028..0000002B
-+ uint32_t signature_offset; // byte 0000002C..0000002F
-+ uint32_t zorder; // byte 00000030..00000033
-+};
-+
-+
-+struct jnx_level_t
-+{
-+ jnx_level_t(): nTiles(0), offset(0), scale(0), dummy(2){}
-+
-+ uint32_t nTiles;
-+ uint32_t offset;
-+ uint32_t scale;
-+ uint32_t dummy;
-+};
-+
-+struct jnx_tile_t
-+{
-+ jnx_tile_t() : top(0), right(0), bottom(0), left(0), width(0), height(0), size(0), offset(0){}
-+ int32_t top;
-+ int32_t right;
-+ int32_t bottom;
-+ int32_t left;
-+ uint16_t width;
-+ uint16_t height;
-+ uint32_t size;
-+ uint32_t offset;
-+};
-+
-+
-+#ifdef WIN32
-+#pragma pack()
-+#else
-+#pragma pack(0)
-+#endif
-+
-+struct file_t
-+{
-+ file_t(): dataset(0), pj(0){memset(colortable,0, sizeof(colortable));}
-+ ~file_t()
-+ {
-+ //if(dataset) delete dataset;
-+ if(pj) pj_free(pj);
-+ }
-+
-+ bool operator<(const file_t& other) const
-+ {
-+ return (xscale > other.xscale);
-+ }
-+
-+ std::string filename;
-+ std::string projection;
-+ GDALDataset * dataset;
-+ projPJ pj;
-+ uint32_t width;
-+ uint32_t height;
-+ double xscale;
-+ double yscale;
-+ double scale;
-+ double xref1;
-+ double yref1;
-+ double xref2;
-+ double yref2;
-+
-+ double lon1;
-+ double lat1;
-+ double lon2;
-+ double lat2;
-+
-+ uint32_t colortable[256];
-+
-+};
-+
-+struct level_t : public jnx_level_t
-+{
-+ std::list<file_t *> files;
-+ uint32_t tileSize;
-+};
-+
-+struct scale_t
-+{
-+ double scale;
-+ uint32_t jnxScale;
-+};
-+
-+/// number of used levels
-+static int32_t nLevels;
-+/// up to five levels. nLevels gives the actual count
-+static level_t levels[5];
-+/// information about all files
-+static std::list<file_t> files;
-+/// the target lon/lat WGS84 projection
-+static projPJ wgs84;
-+/// the JNX file header to be copied to the outfile
-+static jnx_hdr_t jnx_hdr;
-+/// the tile information table for all 5 levels
-+static jnx_tile_t tileTable[JNX_MAX_TILES * 5];
-+/// tile buffer for 8 bit palette tiles, private to readTile
-+static uint8_t tileBuf8Bit[JNX_MAX_TILE_SIZE * JNX_MAX_TILE_SIZE] = {0};
-+/// tile buffer for 24 bit raw RGB tiles, private to writeTile
-+static uint8_t tileBuf24Bit[JNX_MAX_TILE_SIZE * JNX_MAX_TILE_SIZE * 3] = {0};
-+/// tile buffer for 32 bit raw RGBA tiles
-+static uint32_t tileBuf32Bit[JNX_MAX_TILE_SIZE * JNX_MAX_TILE_SIZE] = {0};
-+/// internal jpeg buffer used by write tile.
-+static std::vector<JOCTET> jpgbuf;
-+
-+static void prinfFileinfo(const file_t& file)
-+{
-+ printf("\n\n----------------------");
-+ printf("\n%s:", file.filename.c_str());
-+ printf("\nprojection: %s", file.projection.c_str());
-+ printf("\nwidth: %i pixel height: %i pixel", file.width, file.height);
-+
-+ if(pj_is_latlong(file.pj))
-+ {
-+ printf("\narea (top/left, bottom/right): %f %f, %f %f", file.lat1, file.lon1, file.lat2, file.lon2);
-+ printf("\nxscale: %f °/px, yscale: %f °/px", file.xscale, file.yscale);
-+ }
-+ else
-+ {
-+ printf("\narea (top/left, bottom/right): %f %f, %f %f", file.lat1, file.lon1, file.lat2, file.lon2);
-+ printf("\nxscale: %f m/px, yscale: %f m/px", file.xscale, file.yscale);
-+ }
-+ printf("\nreal scale: %f m/px", file.scale);
-+}
-+
-+bool readTile(uint32_t xoff, uint32_t yoff, uint32_t xsize, uint32_t ysize, file_t& file, uint32_t * output)
-+{
-+ GDALDataset * dataset = file.dataset;
-+ int32_t rasterBandCount = dataset->GetRasterCount();
-+
-+ memset(output,-1, sizeof(uint32_t) * xsize * ysize);
-+
-+ if(rasterBandCount == 1)
-+ {
-+ GDALRasterBand * pBand;
-+ pBand = dataset->GetRasterBand(1);
-+ if(pBand->RasterIO(GF_Read,(int)xoff,(int)yoff, xsize, ysize, tileBuf8Bit,xsize,ysize,GDT_Byte,0,0) == CE_Failure)
-+ {
-+ return false;
-+ }
-+
-+ for(unsigned int i = 0; i < (xsize * ysize); i++)
-+ {
-+ output[i] = file.colortable[tileBuf8Bit[i]];
-+ }
-+ }
-+ else
-+ {
-+ for(int b = 1; b <= rasterBandCount; ++b)
-+ {
-+ GDALRasterBand * pBand;
-+ pBand = dataset->GetRasterBand(b);
-+
-+ uint32_t mask = ~(0x000000FF << (8*(b-1)));
-+
-+ if(pBand->RasterIO(GF_Read,(int)xoff,(int)yoff, xsize, ysize, tileBuf8Bit,xsize,ysize,GDT_Byte,0,0) == CE_Failure)
-+ {
-+ return false;
-+ }
-+
-+ for(unsigned int i = 0; i < (xsize * ysize); i++)
-+ {
-+ uint32_t pixel = output[i];
-+
-+ pixel &= mask;
-+ pixel |= tileBuf8Bit[i] << (8*(b-1));
-+ output[i] = pixel;
-+ }
-+ }
-+ }
-+
-+ return true;
-+}
-+
-+
-+
-+static void init_destination (j_compress_ptr cinfo)
-+{
-+ jpgbuf.resize(JPG_BLOCK_SIZE);
-+ cinfo->dest->next_output_byte = &jpgbuf[0];
-+ cinfo->dest->free_in_buffer = jpgbuf.size();
-+}
-+
-+static boolean empty_output_buffer (j_compress_ptr cinfo)
-+{
-+ size_t oldsize = jpgbuf.size();
-+ jpgbuf.resize(oldsize + JPG_BLOCK_SIZE);
-+ cinfo->dest->next_output_byte = &jpgbuf[oldsize];
-+ cinfo->dest->free_in_buffer = jpgbuf.size() - oldsize;
-+ return true;
-+}
-+
-+static void term_destination (j_compress_ptr cinfo)
-+{
-+ jpgbuf.resize(jpgbuf.size() - cinfo->dest->free_in_buffer);
-+}
-+
-+
-+static uint32_t writeTile(uint32_t xsize, uint32_t ysize, uint32_t * raw_image, FILE * fid, int quality, int subsampling)
-+{
-+ uint32_t size = 0;
-+ struct jpeg_compress_struct cinfo;
-+ struct jpeg_error_mgr jerr;
-+ JSAMPROW row_pointer[1];
-+
-+ jpeg_destination_mgr destmgr = {0};
-+ destmgr.init_destination = init_destination;
-+ destmgr.empty_output_buffer = empty_output_buffer;
-+ destmgr.term_destination = term_destination;
-+
-+ // convert from RGBA to RGB
-+ for(uint32_t r = 0; r < ysize; r++)
-+ {
-+ for(uint32_t c = 0; c < xsize; c++)
-+ {
-+ uint32_t pixel = raw_image[r * xsize + c];
-+ tileBuf24Bit[r * xsize * 3 + c * 3] = pixel & 0x0FF;
-+ tileBuf24Bit[r * xsize * 3 + c * 3 + 1] = (pixel >> 8) & 0x0FF;
-+ tileBuf24Bit[r * xsize * 3 + c * 3 + 2] = (pixel >> 16) & 0x0FF;
-+ }
-+ }
-+
-+ cinfo.err = jpeg_std_error( &jerr );
-+ jpeg_create_compress(&cinfo);
-+
-+ cinfo.dest = &destmgr;
-+ cinfo.image_width = xsize;
-+ cinfo.image_height = ysize;
-+ cinfo.input_components = 3;
-+ cinfo.in_color_space = JCS_RGB;
-+
-+ jpeg_set_defaults( &cinfo );
-+
-+ if (subsampling != -1)
-+ {
-+ switch (subsampling)
-+ {
-+ case 422: // 2x1, 1x1, 1x1 (4:2:2) : Medium
-+ {
-+ cinfo.comp_info[0].h_samp_factor = 2;
-+ cinfo.comp_info[0].v_samp_factor = 1;
-+ cinfo.comp_info[1].h_samp_factor = 1;
-+ cinfo.comp_info[1].v_samp_factor = 1;
-+ cinfo.comp_info[2].h_samp_factor = 1;
-+ cinfo.comp_info[2].v_samp_factor = 1;
-+ break;
-+ }
-+ case 411: // 2x2, 1x1, 1x1 (4:1:1) : High
-+ {
-+ cinfo.comp_info[0].h_samp_factor = 2;
-+ cinfo.comp_info[0].v_samp_factor = 2;
-+ cinfo.comp_info[1].h_samp_factor = 1;
-+ cinfo.comp_info[1].v_samp_factor = 1;
-+ cinfo.comp_info[2].h_samp_factor = 1;
-+ cinfo.comp_info[2].v_samp_factor = 1;
-+ break;
-+ }
-+ case 444: // 1x1 1x1 1x1 (4:4:4) : None
-+ {
-+ cinfo.comp_info[0].h_samp_factor = 1;
-+ cinfo.comp_info[0].v_samp_factor = 1;
-+ cinfo.comp_info[1].h_samp_factor = 1;
-+ cinfo.comp_info[1].v_samp_factor = 1;
-+ cinfo.comp_info[2].h_samp_factor = 1;
-+ cinfo.comp_info[2].v_samp_factor = 1;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (quality != -1)
-+ {
-+ jpeg_set_quality( &cinfo, quality, TRUE );
-+ }
-+
-+ jpeg_start_compress( &cinfo, TRUE );
-+
-+ while( cinfo.next_scanline < cinfo.image_height )
-+ {
-+ row_pointer[0] = (JSAMPLE*)&tileBuf24Bit[ cinfo.next_scanline * cinfo.image_width * cinfo.input_components];
-+ jpeg_write_scanlines( &cinfo, row_pointer, 1 );
-+ }
-+ /* similar to read file, clean up after we're done compressing */
-+ jpeg_finish_compress( &cinfo );
-+ jpeg_destroy_compress( &cinfo );
-+
-+ // write data to output file
-+ size = jpgbuf.size() - 2;
-+ fwrite(&jpgbuf[2], size, 1, fid);
-+
-+ return size;
-+}
-+
-+static double distance(const double u1, const double v1, const double u2, const double v2)
-+{
-+ double dU = u2 - u1; // lambda
-+ double dV = v2 - v1; // roh
-+
-+ double d = 2*asin(sqrt(sin(dV/2) * sin(dV/2) + cos(v1) * cos(v2) * sin(dU/2) * sin(dU/2)));
-+
-+ return 6371010 * d;
-+}
-+
-+static uint32_t scale2jnx(double scale)
-+{
-+ /*
-+ Ok, I've made some calculations, and got the following formula to
-+ calculate the JNX scale (S) depending on the map's meters/pixel
-+ ratio (R):
-+
-+ S(R) =
-+ qRound(
-+ 76437 *
-+ exp(
-+ ln(2.000032708011) *
-+ qRound(
-+ ln(R * 130.2084 / 76437) /
-+ ln(2.000032708011)
-+ )
-+ )
-+ )
-+
-+
-+ where
-+ qRound - is a function which returns the closest integer from
-+ floating point value, [unfortunately its defined in C99 but not standard C++]
-+ exp - exponent,
-+ ln - natural logarithm.
-+
-+ Magic number 130.2084 - is an average value for
-+ (JNX scale) / (maps meters per pixel)
-+ ratio among all zoom levels in metric system.
-+
-+ Magic number 2.000032708011 is a ratio on which our standard scale
-+ table is built. It is (76437 / 4777) ^ (1/4).
-+ */
-+
-+ return (uint32_t)floor(0.5 + 76437 * exp(log(2.000032708011) * floor(0.5 + log(scale * 10 * 130.2084 / 76437) / log(2.000032708011) ) ) );
-+}
-+
-+static char randChar()
-+{
-+ char buf[2];
-+#if defined(HAVE_ARC4RANDOM)
-+ int r = (int)((arc4random() * 16.0) / UINT_MAX);
-+#else
-+ int r = (int)((rand() * 16.0) / RAND_MAX);
-+#endif
-+ sprintf(buf,"%X", r & 0x0F);
-+ return buf[0];
-+}
-+
-+static void createGUID(char * guid)
-+{
-+#if !defined(HAVE_ARC4RANDOM)
-+ srand((unsigned int)time(0));
-+#endif
-+
-+ guid[0] = randChar();
-+ guid[1] = randChar();
-+ guid[2] = randChar();
-+ guid[3] = randChar();
-+ guid[4] = randChar();
-+ guid[5] = randChar();
-+ guid[6] = randChar();
-+ guid[7] = randChar();
-+ guid[8] = '-';
-+ guid[9] = randChar();
-+ guid[10] = randChar();
-+ guid[11] = randChar();
-+ guid[12] = randChar();
-+ guid[13] = '-';
-+ guid[14] = randChar();
-+ guid[15] = randChar();
-+ guid[16] = randChar();
-+ guid[17] = randChar();
-+ guid[18] = '-';
-+ guid[19] = randChar();
-+ guid[20] = randChar();
-+ guid[21] = randChar();
-+ guid[22] = randChar();
-+ guid[23] = '-';
-+ guid[24] = randChar();
-+ guid[25] = randChar();
-+ guid[26] = randChar();
-+ guid[27] = randChar();
-+ guid[28] = randChar();
-+ guid[29] = randChar();
-+ guid[30] = randChar();
-+ guid[31] = randChar();
-+ guid[32] = randChar();
-+ guid[33] = randChar();
-+ guid[34] = randChar();
-+ guid[35] = randChar();
-+ guid[36] = 0;
-+
-+}
-+
-+/// this code is from the GDAL project
-+static void printProgress(int current, int total)
-+{
-+ double dfComplete = double(current)/double(total);
-+
-+ static int nLastTick = -1;
-+ int nThisTick = (int) (dfComplete * 40.0);
-+
-+ nThisTick = MIN(40,MAX(0,nThisTick));
-+
-+ // Have we started a new progress run?
-+ if( nThisTick < nLastTick && nLastTick >= 39 )
-+ {
-+ nLastTick = -1;
-+ }
-+
-+ if( nThisTick <= nLastTick )
-+ {
-+ return;
-+ }
-+
-+ while( nThisTick > nLastTick )
-+ {
-+ nLastTick++;
-+ if( nLastTick % 4 == 0 )
-+ {
-+ fprintf( stdout, "%d", (nLastTick / 4) * 10 );
-+ }
-+ else
-+ {
-+ fprintf( stdout, "." );
-+ }
-+ }
-+
-+ if( nThisTick == 40 )
-+ {
-+ fprintf( stdout, " - done.\n" );
-+ }
-+ else
-+ {
-+ fflush( stdout );
-+ }
-+
-+}
-+
-+
-+int main(int argc, char ** argv)
-+{
-+ uint16_t tmp16;
-+ const uint8_t dummy = 0;
-+ uint32_t tileTableStart = 0;
-+ uint32_t tileCnt = 0;
-+ uint32_t tilesTotal = 0;
-+ char projstr[1024];
-+ OGRSpatialReference oSRS;
-+ int quality = -1;
-+ int subsampling = -1;
-+
-+ const char *copyright = "Unknown";
-+ const char *subscname = "BirdsEye";
-+ const char *mapname = "Unknown";
-+
-+ char *copyright_buf = NULL;
-+ char *subscname_buf = NULL;
-+ char *mapname_buf = NULL;
-+
-+ std::vector<int> forced_scale_values;
-+
-+ printf("\n****** %s ******\n", WHAT_STR);
-+
-+ if(argc < 2)
-+ {
-+ fprintf(stderr,"\nusage: qmt_map2jnx -q <1..100> -s <411|422|444> -p <0..> -c \"copyright notice\" -m \"BirdsEye\" -n \"Unknown\" -x file1_scale,file2_scale,...,fileN_scale <file1> <file2> ... <fileN> <outputfile>\n");
-+ fprintf(stderr,"\n");
-+ fprintf(stderr," -q The JPEG quality from 1 to 100. Default is 75 \n");
-+ fprintf(stderr," -s The chroma subsampling. Default is 411 \n");
-+ fprintf(stderr," -p The product ID. Default is 0 \n");
-+ fprintf(stderr," -c The copyright notice. Default is \"Unknown\" \n");
-+ fprintf(stderr," -m The subscription product name. Default is \"BirdsEye\" \n");
-+ fprintf(stderr," -n The map name. Default is \"Unknown\" \n");
-+ fprintf(stderr," -z The z order (drawing order). Default is 25\n");
-+ fprintf(stderr," -x Override levels scale. Default: autodetect\n");
-+ fprintf(stderr,"\n");
-+ fprintf(stderr,"\nThe projection of the input files must have the same latitude along");
-+ fprintf(stderr,"\na pixel row. Mecator and Longitude/Latitude projections match this");
-+ fprintf(stderr,"\nthis property. Transversal Merkator or Lambert projections do not.");
-+ fprintf(stderr,"\n");
-+ fprintf(stderr,"\nTo rectify a geotiff map, you can use the gdalwarp command, e.g.");
-+ fprintf(stderr,"\ngdalwarp -t_srs \"EPSG:4326\" <inputfile> <outputfile>");
-+ fprintf(stderr,"\n");
-+ fprintf(stderr,"Scale levels must be pass in same order as level files pointed.\n");
-+ fprintf(stderr,"Empty and zero values equal to autodetect. We can point only needed\n");
-+ fprintf(stderr,"levels, like:\n");
-+ fprintf(stderr," -x 45356,,,75; -x ,,,,75\n");
-+ fprintf(stderr,"Calculated levels table can be found:\n");
-+ fprintf(stderr," English: http://whiter.brinkster.net/en/JNX.shtml\n");
-+ fprintf(stderr," Russian: http://whiter.brinkster.net/JNX.shtml\n");
-+ fprintf(stderr,"Most common values for different map scales:\n");
-+ fprintf(stderr," JNX scale Map scale\n");
-+ fprintf(stderr," ------------- ---------\n");
-+ fprintf(stderr," 78125-31250 1:1 000 000\n");
-+ fprintf(stderr," 20834-7813 1:500 000\n");
-+ fprintf(stderr," 7813-3125 1:200 000\n");
-+ fprintf(stderr," 3125-2084 1:100 000\n");
-+ fprintf(stderr," 2084-782 1:50 000\n");
-+ fprintf(stderr," 782-32 1:25 000\n");
-+ fprintf(stderr," 32-21 1:10 000\n");
-+ fprintf(stderr," 21-14 1:5000, 1:2000\n");
-+ fprintf(stderr,"\n");
-+ fprintf(stderr,"\n");
-+ exit(-1);
-+ }
-+
-+ GDALAllRegister();
-+ wgs84 = pj_init_plus("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs");
-+
-+ // read geo information from input files
-+ //files.resize(argc - 2);
-+ int skip_next_arg = 0;
-+ int files_count = 0;
-+
-+ for(int i = 1; i < (argc - 1); i++)
-+ {
-+ if (skip_next_arg)
-+ {
-+ skip_next_arg = 0;
-+ continue;
-+ }
-+
-+ if (argv[i][0] == '-')
-+ {
-+ if (towupper(argv[i][1]) == 'Q')
-+ {
-+ quality = atol(argv[i+1]);
-+ skip_next_arg = 1;
-+ continue;
-+ }
-+ else if (towupper(argv[i][1]) == 'S')
-+ {
-+ subsampling = atol(argv[i+1]);
-+ skip_next_arg = 1;
-+ continue;
-+ }
-+ else if (towupper(argv[i][1]) == 'P')
-+ {
-+ jnx_hdr.productId = atol(argv[i+1]);
-+ skip_next_arg = 1;
-+ continue;
-+ }
-+ else if (towupper(argv[i][1]) == 'C')
-+ {
-+ copyright = copyright_buf = get_argv(i + 1, argv);
-+ skip_next_arg = 1;
-+ continue;
-+ }
-+ else if (towupper(argv[i][1]) == 'M')
-+ {
-+ subscname = subscname_buf = get_argv(i + 1, argv);
-+ skip_next_arg = 1;
-+ continue;
-+ }
-+ else if (towupper(argv[i][1]) == 'N')
-+ {
-+ mapname = mapname_buf = get_argv(i + 1, argv);
-+ skip_next_arg = 1;
-+ continue;
-+ }
-+ else if (towupper(argv[i][1]) == 'Z')
-+ {
-+ jnx_hdr.zorder = atol(argv[i+1]);
-+ skip_next_arg = 1;
-+ continue;
-+ }
-+ else if (towupper(argv[i][1]) == 'X')
-+ {
-+ skip_next_arg = 1;
-+
-+ std::string scales_buf(get_argv(i + 1, argv));
-+ size_t pos = 0;
-+ size_t last_pos = 0;
-+
-+ pos = scales_buf.find_first_of(',');
-+ std::string val;
-+ while (pos != std::string::npos)
-+ {
-+ val = scales_buf.substr(last_pos, pos - last_pos);
-+ last_pos = pos + 1;
-+ pos = scales_buf.find_first_of(',', pos + 1);
-+
-+ //printf("val: %s : %d\n", val.c_str(), pos);
-+ forced_scale_values.push_back(atol(val.c_str()));
-+ }
-+ val = scales_buf.substr(last_pos, pos);
-+ //printf("val: %s : %d\n", val.c_str(), pos);
-+ forced_scale_values.push_back(atol(val.c_str()));
-+
-+ continue;
-+ }
-+
-+ }
-+
-+ files_count++;
-+ files.resize(files_count);
-+
-+ double dist;
-+
-+ GDALDataset * dataset = (GDALDataset*)GDALOpen(argv[i],GA_ReadOnly);
-+ if(dataset == 0)
-+ {
-+ fprintf(stderr,"\nFailed to open %s\n", argv[i]);
-+ exit(-1);
-+ }
-+
-+ projPJ pj;
-+ char * ptr = projstr;
-+
-+ if(dataset->GetProjectionRef())
-+ {
-+ strncpy(projstr,dataset->GetProjectionRef(),sizeof(projstr));
-+ }
-+ oSRS.importFromWkt(&ptr);
-+ oSRS.exportToProj4(&ptr);
-+
-+ pj = pj_init_plus(ptr);
-+ if(pj == 0)
-+ {
-+ fprintf(stderr,"\nUnknown projection in file %s\n", argv[i]);
-+ exit(-1);
-+ }
-+
-+ double adfGeoTransform[6];
-+ dataset->GetGeoTransform( adfGeoTransform );
-+
-+ std::list<file_t>::iterator f = files.begin();
-+ std::advance(f, files_count - 1);
-+
-+ file_t& file = *f;
-+ file.filename = argv[i];
-+ file.projection = ptr;
-+ file.dataset = dataset;
-+ file.pj = pj;
-+ file.width = dataset->GetRasterXSize();
-+ file.height = dataset->GetRasterYSize();
-+ file.xscale = adfGeoTransform[1];
-+ file.yscale = adfGeoTransform[5];
-+ file.xref1 = adfGeoTransform[0];
-+ file.yref1 = adfGeoTransform[3];
-+ file.xref2 = file.xref1 + file.width * file.xscale;
-+ file.yref2 = file.yref1 + file.height * file.yscale;
-+
-+ if(pj_is_latlong(file.pj))
-+ {
-+ file.lon1 = file.xref1;
-+ file.lat1 = file.yref1;
-+ file.lon2 = file.xref2;
-+ file.lat2 = file.yref2;
-+ }
-+ else
-+ {
-+ file.lon1 = file.xref1;
-+ file.lat1 = file.yref1;
-+ file.lon2 = file.xref2;
-+ file.lat2 = file.yref2;
-+
-+ pj_transform(pj,wgs84,1,0,&file.lon1,&file.lat1,0);
-+ pj_transform(pj,wgs84,1,0,&file.lon2,&file.lat2,0);
-+
-+ file.lon1 *= RAD_TO_DEG;
-+ file.lat1 *= RAD_TO_DEG;
-+ file.lon2 *= RAD_TO_DEG;
-+ file.lat2 *= RAD_TO_DEG;
-+ }
-+
-+ dist = distance(file.lon1 * DEG_TO_RAD, file.lat1 * DEG_TO_RAD, file.lon2 * DEG_TO_RAD, file.lat1 * DEG_TO_RAD);
-+ file.scale = dist/file.width;
-+
-+ // fill color table if necessary
-+ GDALRasterBand * pBand;
-+ pBand = dataset->GetRasterBand(1);
-+
-+ if(pBand->GetColorInterpretation() == GCI_PaletteIndex)
-+ {
-+ GDALColorTable * pct = pBand->GetColorTable();
-+ for(int c=0; c < pct->GetColorEntryCount(); ++c)
-+ {
-+ const GDALColorEntry& e = *pct->GetColorEntry(c);
-+ file.colortable[c] = e.c1 | (e.c2 << 8) | (e.c3 << 16) | (e.c4 << 24);
-+ }
-+ }
-+ else if(pBand->GetColorInterpretation() == GCI_GrayIndex )
-+ {
-+ for(int c=0; c < 256; ++c)
-+ {
-+ file.colortable[c] = c | (c << 8) | (c << 16) | 0xFF000000;
-+ }
-+ }
-+
-+ int success = 0;
-+ int idx = (int)pBand->GetNoDataValue(&success);
-+
-+ if(success)
-+ {
-+ file.colortable[idx] &= 0x00FFFFFF;
-+ }
-+ }
-+
-+ // apply sorted files to levels and extract file header data
-+ double right = -180.0;
-+ double top = -90.0;
-+ double left = 180.0;
-+ double bottom = 90.0;
-+
-+ double scale = 0.0;
-+ files.sort();
-+ std::list<file_t>::iterator f;
-+ for(f = files.begin(); f != files.end(); f++)
-+ {
-+ file_t& file = *f;
-+ prinfFileinfo(file);
-+
-+ if(file.lon1 < left) left = file.lon1;
-+ if(file.lat1 > top) top = file.lat1;
-+ if(file.lat2 < bottom) bottom = file.lat2;
-+ if(file.lon2 > right) right = file.lon2;
-+
-+ if(scale != 0.0 && ((fabs(scale - file.xscale)) / scale) > 0.02)
-+ {
-+ nLevels++;
-+ if(nLevels > 4)
-+ {
-+ fprintf(stderr,"\nToo many different detail levels.\n");
-+ exit(-1);
-+ }
-+ }
-+ scale = file.xscale;
-+
-+ levels[nLevels].files.push_back(&file);
-+ }
-+ nLevels++;
-+
-+ FILE * fid = fopen(argv[argc-1],"wb");
-+ if(fid == 0)
-+ {
-+ fprintf(stderr,"\nFailed to create file %s\n", argv[argc-1]);
-+ exit(-1);
-+ }
-+
-+ jnx_hdr.left = (int32_t)((left * 0x7FFFFFFF) / 180);
-+ jnx_hdr.top = (int32_t)((top * 0x7FFFFFFF) / 180);
-+ jnx_hdr.right = (int32_t)((right * 0x7FFFFFFF) / 180);
-+ jnx_hdr.bottom = (int32_t)((bottom * 0x7FFFFFFF) / 180);
-+
-+ jnx_hdr.details = nLevels;
-+
-+ printf("\n\n======== map header ========");
-+ printf("\nmap area (top/left, bottom/right): %f %f, %f %f", left, top, right, bottom);
-+ printf("\n %08X %08X, %08X %08X", jnx_hdr.left, jnx_hdr.top, jnx_hdr.right, jnx_hdr.bottom);
-+ printf("\nnumber of detail levels: %i", jnx_hdr.details);
-+ printf("\nz-order: %i\n", jnx_hdr.zorder);
-+
-+
-+ for(int i=0; i<HEADER_BLOCK_SIZE; i++)
-+ {
-+ fwrite(&dummy, sizeof(dummy), 1, fid);
-+ }
-+ fseeko(fid,0,SEEK_SET);
-+ fwrite(&jnx_hdr, sizeof(jnx_hdr), 1, fid);
-+
-+ // --------------------------------------------------------------
-+ // get all information to write the table of detail levels and the dummy tile table
-+ for(int i = 0; i < nLevels; i++)
-+ {
-+ uint32_t size = 256;
-+ level_t& level = levels[i];
-+ std::list<file_t *>::iterator f;
-+ double scale = 0.0;
-+
-+ while(size <= JNX_MAX_TILE_SIZE)
-+ {
-+ level.nTiles = 0;
-+ level.tileSize = size;
-+ for(f = level.files.begin(); f != level.files.end(); f++)
-+ {
-+ file_t& file = *(*f);
-+ double xTiles = file.width / double(size);
-+ double yTiles = file.height / double(size);
-+ level.nTiles += int(ceil(xTiles)) * int(ceil(yTiles));
-+
-+ scale = file.scale;
-+ }
-+
-+ if(level.nTiles < JNX_MAX_TILES)
-+ {
-+ break;
-+ }
-+ size <<= 1;
-+ }
-+
-+
-+ level.offset = tilesTotal * sizeof(jnx_tile_t) + HEADER_BLOCK_SIZE; // still has to be offset by complete header
-+ if (forced_scale_values.size() == 0 || (unsigned)i >= forced_scale_values.size() || forced_scale_values[i] == 0)
-+ {
-+ level.scale = scale2jnx(scale);
-+ }
-+ else
-+ {
-+ level.scale = forced_scale_values[i];
-+ }
-+ tilesTotal += level.nTiles;
-+
-+ fwrite(&level.nTiles, sizeof(level.nTiles), 1, fid);
-+ fwrite(&level.offset, sizeof(level.offset), 1, fid);
-+ fwrite(&level.scale, sizeof(level.scale), 1, fid);
-+ fwrite(&level.dummy, sizeof(level.dummy), 1, fid);
-+ fwrite(copyright, strlen(copyright) + 1, 1, fid);
-+
-+
-+ printf("\n Level %i: % 5i tiles, offset %08X, scale: %i, %ix%i", i, level.nTiles, level.offset, level.scale, level.tileSize, level.tileSize);
-+
-+ }
-+
-+ // --------------------------------------------------------------
-+ // write map loader info block
-+ uint32_t blockVersion = 0x00000009;
-+ char GUID[40];
-+ createGUID(GUID);
-+
-+ tmp16 = jnx_hdr.productId;
-+
-+ fwrite(&blockVersion, sizeof(blockVersion), 1, fid);
-+ fwrite(GUID, 37, 1, fid);
-+ fwrite(subscname, strlen(subscname) + 1, 1, fid);
-+ fwrite(&dummy, sizeof(dummy), 1, fid);
-+ fwrite(&tmp16, sizeof(tmp16), 1, fid);
-+ fwrite(mapname, strlen(mapname) + 1, 1, fid);
-+ fwrite(&nLevels , sizeof(nLevels), 1, fid);
-+ for(int i = 1; i <= nLevels; i++)
-+ {
-+ char str[40];
-+ sprintf(str,"Level %i", i);
-+ fwrite(str, strlen(str) + 1, 1, fid);
-+ fwrite(str, strlen(str) + 1, 1, fid);
-+ fwrite(copyright, strlen(copyright) + 1, 1, fid);
-+ fwrite(&i,sizeof(i), 1, fid);
-+ }
-+
-+ // --------------------------------------------------------------
-+ // write dummy tile table
-+ tileTableStart = HEADER_BLOCK_SIZE;
-+ fseeko(fid, tileTableStart, SEEK_SET);
-+ fwrite(tileTable, sizeof(jnx_tile_t), tilesTotal, fid);
-+
-+ // --------------------------------------------------------------
-+ // read tiles from input files and write jpeg coded tiles to output file
-+ printf("\n\nStart conversion:\n");
-+ for(int l = 0; l < nLevels; l++)
-+ {
-+ level_t& level = levels[l];
-+
-+ std::list<file_t *>::iterator f;
-+ for(f = level.files.begin(); f != level.files.end(); f++)
-+ {
-+ file_t& file = *(*f);
-+
-+ uint32_t xoff = 0;
-+ uint32_t yoff = 0;
-+
-+ uint32_t xsize = level.tileSize;
-+ uint32_t ysize = level.tileSize;
-+
-+ while(yoff < file.height)
-+ {
-+ if(ysize > (file.height - yoff))
-+ {
-+ ysize = file.height - yoff;
-+ }
-+
-+ xsize = level.tileSize;
-+ xoff = 0;
-+
-+ while(xoff < file.width)
-+ {
-+ if(xsize > (file.width - xoff))
-+ {
-+ xsize = (file.width - xoff);
-+ }
-+
-+ // //
-+ if(!readTile(xoff, yoff, xsize, ysize, file, tileBuf32Bit))
-+ {
-+ fprintf(stderr,"\nError reading tiles from map file\n");
-+ exit(-1);
-+ }
-+
-+ jnx_tile_t& tile = tileTable[tileCnt++];
-+ if(pj_is_latlong(file.pj))
-+ {
-+
-+ double u1 = file.lon1 + xoff * file.xscale;
-+ double v1 = file.lat1 + yoff * file.yscale;
-+ double u2 = file.lon1 + (xoff + xsize) * file.xscale;
-+ double v2 = file.lat1 + (yoff + ysize) * file.yscale;
-+
-+
-+ tile.left = (int32_t)(u1 * 0x7FFFFFFF / 180);
-+ tile.top = (int32_t)(v1 * 0x7FFFFFFF / 180);
-+ tile.right = (int32_t)(u2 * 0x7FFFFFFF / 180);
-+ tile.bottom = (int32_t)(v2 * 0x7FFFFFFF / 180);
-+
-+ }
-+ else
-+ {
-+ double u1 = file.xref1 + xoff * file.xscale;
-+ double v1 = file.yref1 + yoff * file.yscale;
-+ double u2 = file.xref1 + (xoff + xsize) * file.xscale;
-+ double v2 = file.yref1 + (yoff + ysize) * file.yscale;
-+
-+ pj_transform(file.pj,wgs84,1,0,&u1,&v1,0);
-+ pj_transform(file.pj,wgs84,1,0,&u2,&v2,0);
-+
-+ tile.left = (int32_t)((u1 * RAD_TO_DEG) * 0x7FFFFFFF / 180);
-+ tile.top = (int32_t)((v1 * RAD_TO_DEG) * 0x7FFFFFFF / 180);
-+ tile.right = (int32_t)((u2 * RAD_TO_DEG) * 0x7FFFFFFF / 180);
-+ tile.bottom = (int32_t)((v2 * RAD_TO_DEG) * 0x7FFFFFFF / 180);
-+ }
-+
-+ tile.width = xsize;
-+ tile.height = ysize;
-+ tile.offset = (uint32_t)(ftello(fid) & 0x0FFFFFFFF);
-+ tile.size = writeTile(xsize, ysize, tileBuf32Bit, fid, quality, subsampling);
-+
-+ printProgress(tileCnt, tilesTotal);
-+ // //
-+ xoff += xsize;
-+ }
-+
-+ yoff += ysize;
-+ }
-+ }
-+ }
-+
-+ // terminate output file
-+ fwrite("BirdsEye", 8, 1, fid);
-+
-+ // write final tile table
-+ fseeko(fid, tileTableStart, SEEK_SET);
-+ fwrite(tileTable, sizeof(jnx_tile_t), tilesTotal, fid);
-+ // done
-+ fclose(fid);
-+
-+ // clean up
-+ pj_free(wgs84);
-+ GDALDestroyDriverManager();
-+ if (copyright_buf)
-+ free(copyright_buf);
-+ if (subscname_buf)
-+ free(subscname_buf);
-+ if (mapname_buf)
-+ free(mapname_buf);
-+ printf("\n\n");
-+ return 0;
-+}