/*--------------------------------------------------------------------------*/ void map_container::zoom_level_set(double factor) { double zoom_delta = DBL_MAX; logstream_write("requested zoom, %f\n", factor); for (int i = 0; i < ZOOMS_SUPPORTED; i++) { double delta = zoom_table[i].zoom - factor; if ( delta < 0 ) delta = -delta; if ( delta < zoom_delta) { logstream_write("selecting %f\n", zoom_table[i].zoom); zoom_current = i; zoom_delta = delta; } } map_info_update(); }
/*--------------------------------------------------------------------------*/ long map_container::map_width() { double width = 0; width = image_ops.scale_dx(image, zoom_table[zoom_current].source); width *= zoom_table[zoom_current].factor; logstream_write("returning map width, %d\n", (long)mcround(width)); return (long)mcround(width); }
/*--------------------------------------------------------------------------*/ long map_container::map_height() { double height = 0; height = image_ops.scale_dy(image, zoom_table[zoom_current].source); height *= zoom_table[zoom_current].factor; logstream_write("returning map height, %d\n", (long)mcround(height)); return (long)mcround(height); }
/*--------------------------------------------------------------------------*/ void map_container::zoom_in() { if (zoom_current < ZOOMS_SUPPORTED - 1) { zoom_current++; logstream_write("requested zoom, %d\n", (long)(zoom_table[zoom_current].zoom * 100)); map_info_update(); } }
/*--------------------------------------------------------------------------*/ void map_container::zoom_out() { if (zoom_current) { zoom_current--; logstream_write("requested zoom, %d\n", (long)(zoom_table[zoom_current].zoom * 100)); map_info_update(); } }
/*--------------------------------------------------------------------------*/ void map_container::ll_to_xy_onmap(double latitude, double longitude, long *x, long *y) { double dbl_x, dbl_y; projection->ll_to_xy(&dbl_x, &dbl_y, longitude, latitude); *x = (long)mcround(dbl_x); *y = (long)mcround(dbl_y); logstream_write("converting ll to map xy, lat = %f, lon = %f, x = %d, y = %d\n", latitude, longitude, *x, *y); }
/*--------------------------------------------------------------------------*/ long map_container::xy_onmap_to_ll(long x, long y, double* latitude, double* longitude) { long r = projection->xy_to_ll(latitude, longitude, (double)x, (double)y); logstream_write("converting map xy to ll , x = %d, y = %d, lat = %f, lon = %f\n", x, y, *latitude, *longitude); return r; }
/*--------------------------------------------------------------------------*/ void map_container::ll_to_xy_on_tile(double latitude, double longitude, long *x, long *y) { long map_x, map_y; long c, r; ll_to_xy_onmap(latitude, longitude, &map_x, &map_y); ll_to_cr(latitude, longitude, &c, &r); *x = map_x - c * (64 * zoom_table[zoom_current].factor); *y = map_y - r * (64 * zoom_table[zoom_current].factor); logstream_write("converting ll to tile xy, lat = %f, lon = %f, x = %d, y = %d\n", latitude, longitude, *x, *y); }
/*--------------------------------------------------------------------------*/ void map_container::ll_to_cr(double latitude, double longitude, long *c, long *r) { long x, y; ll_to_xy_onmap(latitude, longitude, &x, &y); long tile_x = (abs)((long)mcround(x))/(64 * zoom_table[zoom_current].factor); long tile_y = (abs)((long)mcround(y))/(64 * zoom_table[zoom_current].factor); logstream_write("converting ll to cr, lat = %f, lon = %f, c = %d, r = %d\n", latitude, longitude, tile_x, tile_y); *c = tile_x; *r = tile_y; }
/*--------------------------------------------------------------------------*/ ozf_stream* ozf_open(char* path) { ozf_stream* s = NULL; FILE* f = fopen(path, "rb"); logstream_write("ozf: opening %s\n", path); if (f) { logstream_write("ozf: %s opened\n", path); s = (ozf_stream*)malloc(sizeof(ozf_stream)); memset(s, 0, sizeof(ozf_stream)); s->file = f; s->type = OZF_STREAM_DEFAULT; fseek(f, 0, SEEK_END); s->size = ftell(f); logstream_write("ozf: stream size: %d bytes\n", s->size); // need to find more convenient way if (strstr(path, ".ozfx3")) { logstream_write("ozf: %s is an encrypted stream\n", path); s->type = OZF_STREAM_ENCRYPTED; s->key = ozf_calculate_key(s->file); logstream_write("ozf: stream key = %08x\n", s->key); ozf_init_encrypted_stream(s); } else if (strstr(path, ".ozf2")) { logstream_write("ozf: %s is raw stream\n", path); ozf_init_raw_stream(s); } } else { logstream_write("ozf: %s open fails\n", path); } return s; }
/*----------------------------------------------------------------------------*/ void wpt_container::load(const char* file) { numpoints = 0; free(points); char *cur_locale=strdup(setlocale(LC_NUMERIC,NULL)); setlocale(LC_NUMERIC,"C"); points = (waypoint*)malloc(WAYPOINTS_MAX*sizeof(waypoint)); memset(points, 0, WAYPOINTS_MAX*sizeof(waypoint)); unsaved = 0; char szDatum[256]; char szTemp[STRING_MAX]; FILE *fp = fopen(file, "rt"); if (!fp) { logstream_write("failed to open waypoint file\n"); return; } fgets(szTemp, STRING_MAX, fp); szTemp[strlen(szTemp)-1] = 0; if ( !strncmp(szTemp, "OziExplorer Waypoint File", strlen("OziExplorer Waypoint File")) ) { waypoint wpt; fgets(szTemp, STRING_MAX, fp); szTemp[strlen(szTemp)-1] = 0; strcpy(szDatum, szTemp); fgets(szTemp, STRING_MAX, fp); // skipping fgets(szTemp, STRING_MAX, fp); // skipping while ( 1 ) { if(!fgets(szTemp, STRING_MAX, fp)) break; memset(&wpt, 0, sizeof(waypoint)); szTemp[strlen(szTemp)-1] = 0; // printf("i: %d\n", numpoints); char* pszThis; char* pszThat; // skipping number - for Lowrance/Eagles and Silva GPS receivers pszThis = szTemp; pszThat = strchr(pszThis, ','); // printf("1\n"); // reading Name - the waypoint name pszThis = pszThat + 1; pszThat = strchr(pszThis, ','); *pszThat = 0; strcpy(wpt.name, pszThis); int k = strlen(wpt.name)-1; while(wpt.name[k] == 0x20 && k) { wpt.name[k] = 0; k--; } // printf("wpt name: '%s'\n", wpt.name); // printf("2\n"); // reading latitude pszThis = pszThat + 1; pszThat = strchr(pszThis, ','); *pszThat = 0; wpt.lat = atof(pszThis); // printf("3\n"); // reading longitude pszThis = pszThat + 1; pszThat = strchr(pszThis, ','); *pszThat = 0; wpt.lon = atof(pszThis); // printf("4\n"); // reading time pszThis = pszThat + 1; pszThat = strchr(pszThis, ','); *pszThat = 0; // printf("5\n"); double pascalDateTime = atof(pszThis); time_t unixDateTime = (pascalDateTime - ((70*365L)+17 + 2)) * (24L*60*60); wpt.time = unixDateTime; // skipping 10 fields // printf("6\n"); #if 0 pszThis = pszThat + 1; for ( long i = 0; i < 9; i++ ) { pszThat = strchr(pszThis, ','); pszThis = pszThat + 1; } pszThat = strchr(pszThis, ','); *pszThat = 0; wpt.alt = atol(pszThis); double height; // printf("wpt: %s: %f, %f\n", wpt.name, wpt.lat, wpt.lon); #endif if(numpoints >= WAYPOINTS_MAX - 1) break; memcpy(&points[numpoints], &wpt, sizeof(waypoint)); points[numpoints].deleted = 0; points[numpoints].added = 0; numpoints++; } } setlocale(LC_NUMERIC,cur_locale); free(cur_locale); fclose(fp); }
/*--------------------------------------------------------------------------*/ map_container::map_container(char* file) { filename = (char*)malloc(strlen(file) + 1); strcpy(filename, file); zoom_current = 0; projection = NULL; calibration = maploader_openmap(filename); char imagefile[UL_NAME_MAX]; logstream_write("map container: %s\n", calibration->image_path); logstream_write("map container: %s\n", calibration->image_file); strcpy(imagefile, calibration->image_path); strcat(imagefile, calibration->image_file); image_ops.open = img_open; image_ops.get_tile = img_get_tile; image_ops.num_scales = img_num_scales; image_ops.num_tiles_per_x = img_num_tiles_per_x; image_ops.num_tiles_per_y = img_num_tiles_per_y; image_ops.scale_dx = img_scale_dx; image_ops.scale_dy = img_scale_dy; image_ops.close = img_close; char* ext = imagefile + strlen(imagefile); do { ext--; if (*ext == '.') break; } while (ext > imagefile); logstream_write("img: %s\n", imagefile); logstream_write("ext: %s\n", ext); if (!strcmp(ext, ".ozf") || !strcmp(ext, ".ozf2") || !strcmp(ext, ".ozfx3")) { image_ops.open = ozf_open; image_ops.get_tile = ozf_get_tile; image_ops.num_scales = ozf_num_scales; image_ops.num_tiles_per_x = ozf_num_tiles_per_x; image_ops.num_tiles_per_y = ozf_num_tiles_per_y; image_ops.scale_dx = ozf_scale_dx; image_ops.scale_dy = ozf_scale_dy; image_ops.close = ozf_close; } image = image_ops.open(imagefile); build_zoom_table(); zoom_level_set(1.0); map_info_update(); }
/*--------------------------------------------------------------------------*/ void map_container::build_zoom_table() { zoom_table = (map_scale*)malloc(ZOOMS_SUPPORTED * sizeof(map_scale)); memset(zoom_table, 0, ZOOMS_SUPPORTED * sizeof(map_scale)); int scales = image_ops.num_scales(image); logstream_write("mapinfo: %d %d\n", calibration->width, calibration->height); logstream_write("building scales table\n"); for (int i = 0; i < ZOOMS_SUPPORTED; i++) { int k = 0; double delta = DBL_MAX; double ozf_zoom; for (int j = 0; j < scales; j++) { int dx, dy; dx = image_ops.scale_dx(image, j); dy = image_ops.scale_dy(image, j); double a = dy; double b = calibration->height; double percents = (a / b) * 100; //percents = mcround(percents); double zoom = percents / 100; // if current zoom is < 100% - we need to select // nearest upper native zoom // otherwize we need to select // any nearest zoom if (zoom_levels_supported[i] < 1.0) if (zoom_levels_supported[i] > zoom) continue; double d = zoom - zoom_levels_supported[i]; d = d < 0 ? -d : d; if (d < delta) { delta = d; k = j; ozf_zoom = zoom; } } zoom_table[i].zoom = zoom_levels_supported[i]; zoom_table[i].source = k; zoom_table[i].factor = zoom_levels_supported[i] / ozf_zoom; logstream_write("scale: %f, selected source scale: %f (%d), factor: %f\n", zoom_table[i].zoom, ozf_zoom, k, zoom_table[i].zoom/ozf_zoom); } }
/*--------------------------------------------------------------------------*/ void ozf_get_tile(ozf_stream* stream, int scale, int x, int y, unsigned char* data) { ozf_stream* s = stream; long j; if (scale > s->scales - 1) return; if (x > s->images[scale].header.xtiles - 1) return; if (y > s->images[scale].header.ytiles - 1) return; if (x < 0) return; if (y < 0) return; long i = y * s->images[scale].header.xtiles + x; unsigned long tilesize = s->images[scale].tiles_table[i+1] - s->images[scale].tiles_table[i]; unsigned char* tile = (unsigned char*)alloca(tilesize); fseek(s->file, s->images[scale].tiles_table[i], SEEK_SET); fread(tile, tilesize, 1, s->file); if (s->type == OZF_STREAM_ENCRYPTED) { if (s->images[scale].encryption_depth == -1) ozf_decode1(tile, tilesize, s->key); else ozf_decode1(tile, s->images[scale].encryption_depth, s->key); } if (!(tile[0] == 0x78 && tile[1] == 0xda)) // zlib signature { logstream_write("ozf: zlib signature verification failed\n"); return; } unsigned long decompressed_size = OZF_TILE_WIDTH * OZF_TILE_HEIGHT; unsigned char* decompressed = (unsigned char*)alloca(decompressed_size); long n = ozf_decompress_tile((Bytef*)decompressed, (uLongf*)&decompressed_size, (const Bytef*)tile, (uLong)tilesize); unsigned char* foo = data; unsigned char* palette = (unsigned char*)s->images[scale].header.palette; for(j = 0; j < OZF_TILE_WIDTH * OZF_TILE_HEIGHT; j++) { unsigned char c = decompressed[j]; // flipping image vertical int tile_y = (OZF_TILE_WIDTH - 1) - (j / OZF_TILE_WIDTH); int tile_x = j % OZF_TILE_WIDTH; int tile_z = tile_y * OZF_TILE_WIDTH + tile_x; unsigned char r = palette[c*4 + 2]; unsigned char g = palette[c*4 + 1]; unsigned char b = palette[c*4 + 0]; unsigned char a = 255; // applying bgr -> rgba data[tile_z * 4 + 0] = r; // r data[tile_z * 4 + 1] = g; // g data[tile_z * 4 + 2] = b; // b data[tile_z * 4 + 3] = a; // a } }
/*--------------------------------------------------------------------------*/ void ozf_init_raw_stream(ozf_stream* stream) { ozf_stream* s = stream; unsigned long offset; unsigned long scales_table_offset; int i, j; logstream_write("ozf: processing raw stream\n"); offset = 0; s->ozf2 = (ozf2_header*)malloc(sizeof(ozf2_header)); fseek(s->file, offset, SEEK_SET); fread(&s->ozf2->magic, sizeof(short), 1, s->file); fread(&s->ozf2->dummy1, sizeof(long), 1, s->file); fread(&s->ozf2->dummy2, sizeof(long), 1, s->file); fread(&s->ozf2->dummy3, sizeof(long), 1, s->file); fread(&s->ozf2->dummy4, sizeof(long), 1, s->file); fread(&s->ozf2->width, sizeof(long), 1, s->file); fread(&s->ozf2->height, sizeof(long), 1, s->file); fread(&s->ozf2->depth, sizeof(short), 1, s->file); fread(&s->ozf2->bpp, sizeof(short), 1, s->file); fread(&s->ozf2->dummy5, sizeof(long), 1, s->file); fread(&s->ozf2->memsiz, sizeof(long), 1, s->file); fread(&s->ozf2->dummy6, sizeof(long), 1, s->file); fread(&s->ozf2->dummy7, sizeof(long), 1, s->file); fread(&s->ozf2->dummy8, sizeof(long), 1, s->file); fread(&s->ozf2->version, sizeof(long), 1, s->file); logstream_write("ozf: decoded ozf2 header: \n"); logstream_write("\twidth:\t%d\n", s->ozf2->width); logstream_write("\theight:\t%d\n", s->ozf2->height); logstream_write("\tdepth:\t%d\n", s->ozf2->depth); logstream_write("\tbpp:\t%d\n", s->ozf2->bpp); offset = s->size - sizeof(long); fseek(s->file, offset, SEEK_SET); fread(&scales_table_offset, sizeof(long), 1, s->file); logstream_write("ozf: scales table starts at: %d\n", scales_table_offset); s->scales = (s->size - scales_table_offset - sizeof(long)) / sizeof(long); logstream_write("ozf: scales total: %d\n", s->scales); s->scales_table = (unsigned long*)malloc(s->scales * sizeof(unsigned long)); s->images = (ozf_image*)malloc(s->scales * sizeof(ozf_image)); fseek(s->file, scales_table_offset, SEEK_SET); fread(s->scales_table, s->scales * sizeof(long), 1, s->file); for (i = 0; i < s->scales; i++) { unsigned char* tile; logstream_write("ozf: scale %d header starts at: %d\n", i, s->scales_table[i]); fseek(s->file, s->scales_table[i], SEEK_SET); fread(&s->images[i].header.width, sizeof(long), 1, s->file); fread(&s->images[i].header.height, sizeof(long), 1, s->file); fread(&s->images[i].header.xtiles, sizeof(short), 1, s->file); fread(&s->images[i].header.ytiles, sizeof(short), 1, s->file); fread(s->images[i].header.palette, sizeof(long)*256, 1, s->file); logstream_write("ozf: \twidth:\t%d\n", s->images[i].header.width); logstream_write("ozf: \theight:\t%d\n", s->images[i].header.height); logstream_write("ozf: \ttiles per x:\t%d\n", s->images[i].header.xtiles); logstream_write("ozf: \ttiles per y:\t%d\n", s->images[i].header.ytiles); s->images[i].tiles = s->images[i].header.xtiles * s->images[i].header.ytiles + 1; s->images[i].tiles_table = (unsigned long*)malloc(s->images[i].tiles * sizeof(long)); fread(s->images[i].tiles_table, s->images[i].tiles * sizeof(long), 1, s->file); } }
/*--------------------------------------------------------------------------*/ void ozf_init_encrypted_stream(ozf_stream* stream) { ozf_stream* s = stream; unsigned char bytes_per_infoblock; unsigned long offset; unsigned long scales_table_offset; int i, j; logstream_write("ozf: processing encrypted stream\n"); fseek(s->file, OZFX3_MAGIC_OFFSET_0, SEEK_SET); fread(&bytes_per_infoblock, 1, 1, s->file); logstream_write("ozf: bytes per info block: %d\n", bytes_per_infoblock); offset = OZFX3_MAGIC_OFFSET_1 + bytes_per_infoblock - OZFX3_MAGIC_BLOCKLENGTH_0 + sizeof(long); s->ozf3 = (ozf3_header*)malloc(sizeof(ozf3_header)); fseek(s->file, offset, SEEK_SET); fread(&s->ozf3->size, sizeof(long), 1, s->file); fread(&s->ozf3->width, sizeof(long), 1, s->file); fread(&s->ozf3->height, sizeof(long), 1, s->file); fread(&s->ozf3->depth, sizeof(short), 1, s->file); fread(&s->ozf3->bpp, sizeof(short), 1, s->file); ozf_decode1((unsigned char*)s->ozf3, sizeof(ozf3_header), s->key); logstream_write("ozf: decoded ozf3 header: \n"); logstream_write("\tsize:\t%d\n", s->ozf3->size); logstream_write("\twidth:\t%d\n", s->ozf3->width); logstream_write("\theight:\t%d\n", s->ozf3->height); logstream_write("\tdepth:\t%d\n", s->ozf3->depth); logstream_write("\tbpp:\t%d\n", s->ozf3->bpp); offset = s->size - sizeof(long); fseek(s->file, offset, SEEK_SET); fread(&scales_table_offset, sizeof(long), 1, s->file); ozf_decode1((unsigned char*)&scales_table_offset, sizeof(long), s->key); logstream_write("ozf: scales table starts at: %d\n", scales_table_offset); s->scales = (s->size - scales_table_offset - sizeof(long)) / sizeof(long); logstream_write("ozf: scales total: %d\n", s->scales); s->scales_table = (unsigned long*)malloc(s->scales * sizeof(unsigned long)); s->images = (ozf_image*)malloc(s->scales * sizeof(ozf_image)); fseek(s->file, scales_table_offset, SEEK_SET); fread(s->scales_table, s->scales * sizeof(long), 1, s->file); for (i = 0; i < s->scales; i++) { unsigned char* tile; ozf_decode1((unsigned char*)&s->scales_table[i], sizeof(long), s->key); logstream_write("ozf: scale %d header starts at: %d\n", i, s->scales_table[i]); fseek(s->file, s->scales_table[i], SEEK_SET); fread(&s->images[i].header.width, sizeof(long), 1, s->file); fread(&s->images[i].header.height, sizeof(long), 1, s->file); fread(&s->images[i].header.xtiles, sizeof(short), 1, s->file); fread(&s->images[i].header.ytiles, sizeof(short), 1, s->file); fread(s->images[i].header.palette, sizeof(long)*256, 1, s->file); ozf_decode1((unsigned char*)&s->images[i].header.width, sizeof(long), s->key); ozf_decode1((unsigned char*)&s->images[i].header.height, sizeof(long), s->key); ozf_decode1((unsigned char*)&s->images[i].header.xtiles, sizeof(short), s->key); ozf_decode1((unsigned char*)&s->images[i].header.ytiles, sizeof(short), s->key); logstream_write("ozf: \twidth:\t%d\n", s->images[i].header.width); logstream_write("ozf: \theight:\t%d\n", s->images[i].header.height); logstream_write("ozf: \ttiles per x:\t%d\n", s->images[i].header.xtiles); logstream_write("ozf: \ttiles per y:\t%d\n", s->images[i].header.ytiles); ozf_decode1((unsigned char*)s->images[i].header.palette, 1024, s->key); s->images[i].tiles = s->images[i].header.xtiles * s->images[i].header.ytiles + 1; s->images[i].tiles_table = (unsigned long*)malloc(s->images[i].tiles * sizeof(long)); fread(s->images[i].tiles_table, s->images[i].tiles * sizeof(long), 1, s->file); for (j = 0; j < s->images[i].tiles; j++) { unsigned long* p = &s->images[i].tiles_table[j]; ozf_decode1((unsigned char*)p, sizeof(long), s->key); } unsigned long tilesize = s->images[i].tiles_table[1] - s->images[i].tiles_table[0]; tile = (unsigned char*)malloc(tilesize); fseek(s->file, s->images[i].tiles_table[0], SEEK_SET); fread(tile, tilesize, 1, s->file); s->images[i].encryption_depth = ozf_get_encyption_depth(tile, tilesize, s->key); free(tile); logstream_write("ozf: \tencryption depth:\t%d\n", s->images[i].encryption_depth); } }