/// <summary> /// This function is used to generate the base level plate files. /// </summary> /// <param name="serializer"> /// Image tile serializer to retrieve the tile. /// </param> private void CreateBaseLevelPlateFiles(IImageTileSerializer serializer) { int maxPlate = (int)Math.Pow(2, this.plateFileDetails.MinOverlappedLevel); Parallel.For( 0, maxPlate, yPlate => { for (int xPlate = 0; xPlate < maxPlate; xPlate++) { // Get plate file name base don the X and Y coordinates of the plate file. string plateFilePath = System.IO.Path.Combine(this.platesFolderPath, this.plateFileDetails.MinOverlappedLevel.ToString(CultureInfo.InvariantCulture), string.Format(CultureInfo.InvariantCulture, Constants.BaseLevelPlateFormat, this.plateFileDetails.MinOverlappedLevel, xPlate, yPlate)); // Create the plate file instance. PlateFile currentPlate = new PlateFile(plateFilePath, this.plateFileDetails.LevelsPerPlate); currentPlate.Create(); for (int level = this.plateFileDetails.LevelsPerPlate - 1; level >= 0; level--) { // Get the number of tiles for the given level index. int numberOftiles = (int)Math.Pow(2, level); // Calculate the start and end index of X axis. int xStart = xPlate * numberOftiles; // Calculate the start and end index of Y axis. int yStart = yPlate * numberOftiles; // Add each tile to the plate file. for (int yIndex = 0; yIndex < numberOftiles; yIndex++) { for (int xIndex = 0; xIndex < numberOftiles; xIndex++) { TilesProcessed++; if (serializer != null) { Bitmap tile = serializer.Deserialize((this.maxLevels - (this.plateFileDetails.LevelsPerPlate - 1) + level), xStart + xIndex, yStart + yIndex); if (tile != null) { using (MemoryStream ms = new MemoryStream()) { ms.Seek(0, SeekOrigin.Begin); tile.Save(ms, format); currentPlate.AddStream(ms, level, xIndex, yIndex); } tile.Dispose(); } } } } } // Update the header and close the file stream. currentPlate.UpdateHeaderAndClose(); } }); }
/// <summary> /// This function is used to retrieve the tile from the multiple plates. /// </summary> /// <param name="level">Level of the image.</param> /// <param name="x">X axis image.</param> /// <param name="y">Y axis image.</param> /// <param name="platesFolder">Multiple plates folder.</param> /// <param name="topLevelPlateFilename">Top level plate file name.</param> /// <param name="plateFilenameFormat">Format for plate file name.</param> /// <returns>Tile image for the specified image.</returns> private static Stream GetTileFromMultiplePlates(int level, int x, int y, DirectoryInfo platesFolder, string topLevelPlateFilename, string plateFilenameFormat) { Stream outputStream = null; int maxLevel = GetMaxLevel(platesFolder); // TODO: Need to check on how to get the details on how many levels are there in a plate. int levelsPerPlate = 8; // Get the levels break up from Plates folder structure. List <int> plateLevels = GetPlateLevels(platesFolder); // Sort the plate levels. This is make sure that we can do binary search. plateLevels.Sort(); // Get the index of level of the plate files (folder name) where the plate file which contains the tile for level, x and y could be found. // BinarySearch = The zero-based index of item in the sorted List<T>, if item is found; otherwise, a negative number that is the bitwise // complement of the index of the next element that is larger than item or, if there is no larger element, the bitwise complement of Count. int plateLevelIndex = plateLevels.BinarySearch(level); plateLevelIndex = plateLevelIndex < 0 ? ~plateLevelIndex - 1 : plateLevelIndex; if (plateLevelIndex <= 0) { // This means that we need to get data from top level plate file. PlateFile plateFileInstance = new PlateFile(Path.Combine(platesFolder.FullName, topLevelPlateFilename), levelsPerPlate); outputStream = plateFileInstance.GetFileStream(level, x, y); } else if (level <= maxLevel) { // Get the minimum level number (which will be the Folder name) from the plate level index. int minLevel = plateLevels[plateLevelIndex]; // Level in the local plate file. int plateLevel = level - minLevel; int powLevDiff = (int)Math.Pow(2, plateLevel); int plateIndexX = x / powLevDiff; int plateIndexY = y / powLevDiff; string filename = string.Format(CultureInfo.InvariantCulture, plateFilenameFormat, minLevel, plateIndexX, plateIndexY); int tileIndexX = x % powLevDiff; int tileIndexY = y % powLevDiff; PlateFile plateFileInstance = new PlateFile(Path.Combine(platesFolder.FullName, minLevel.ToString(CultureInfo.InvariantCulture), filename), levelsPerPlate); outputStream = plateFileInstance.GetFileStream(plateLevel, tileIndexX, tileIndexY); } return(outputStream); }
/// <summary> /// This function is used to generate the top level plate file. /// </summary> /// <param name="serializer"> /// Image tile serializer to retrieve the tile. /// </param> private void CreateTopLevelDemPlateFile(IDemTileSerializer serializer) { string plateFilePath = System.IO.Path.Combine(this.platesFolderPath, Constants.DEMTopLevelPlate); PlateFile currentPlate = new PlateFile(plateFilePath, this.maxLevels); currentPlate.Create(); for (int level = 0; level <= this.plateFileDetails.MaxOverlappedLevel; level++) { // Number of tiles in each direction at this level int n = (int)Math.Pow(2, level); // Add each tile to the plate file. for (int indexY = 0; indexY < n; indexY++) { for (int indexX = 0; indexX < n; indexX++) { TilesProcessed++; if (serializer != null) { short[] data = serializer.Deserialize(level, indexX, indexY); if (data != null) { using (MemoryStream ms = new MemoryStream()) { ms.Seek(0, SeekOrigin.Begin); BinaryWriter bw = new BinaryWriter(ms); foreach (short value in data) { bw.Write(value); } currentPlate.AddStream(ms, level, indexX, indexY); } data = null; } } } } } // Update the header and close the file stream. currentPlate.UpdateHeaderAndClose(); }
/// <summary> /// This function is used to create the plate file from already generated DEM pyramid. /// </summary> /// <param name="serializer"> /// DEM tile serializer to retrieve the tile. /// </param> public void CreateFromDemTile(IDemTileSerializer serializer) { PlateFile currentPlate = new PlateFile(this.PlateFilePath, this.Levels); currentPlate.Create(); for (int level = 0; level <= Levels; level++) { // Number of tiles in each direction at this level int n = (int)Math.Pow(2, level); // Add each tile to the plate file. for (int indexY = 0; indexY < n; indexY++) { for (int indexX = 0; indexX < n; indexX++) { if (serializer != null) { short[] data = serializer.Deserialize(level, indexX, indexY); if (data != null) { using (MemoryStream ms = new MemoryStream()) { ms.Seek(0, SeekOrigin.Begin); BinaryWriter bw = new BinaryWriter(ms); foreach (short value in data) { bw.Write(value); } currentPlate.AddStream(ms, level, indexX, indexY); } data = null; } } } } } // Update the header and close the file stream. currentPlate.UpdateHeaderAndClose(); }
/// <summary> /// This function is used to create the plate file from already generated pyramids. /// </summary> /// <param name="serializer"> /// Image tile serializer to retrieve the tile. /// </param> public void CreateFromImageTile(IImageTileSerializer serializer) { TilesProcessed = 0; PlateFile currentPlate = new PlateFile(this.PlateFilePath, this.Levels); currentPlate.Create(); for (int level = 0; level <= Levels; level++) { // Number of tiles in each direction at this level int n = (int)Math.Pow(2, level); // Add each tile to the plate file. for (int indexY = 0; indexY < n; indexY++) { for (int indexX = 0; indexX < n; indexX++) { TilesProcessed++; if (serializer != null) { Bitmap tile = serializer.Deserialize(level, indexX, indexY); if (tile != null) { using (MemoryStream ms = new MemoryStream()) { ms.Seek(0, SeekOrigin.Begin); tile.Save(ms, ImageFormat.Png); currentPlate.AddStream(ms, level, indexX, indexY); } tile.Dispose(); } } } } } // Update the header and close the file stream. currentPlate.UpdateHeaderAndClose(); }
/// <summary> /// This function is used to generate the top level plate file. /// </summary> /// <param name="serializer"> /// Image tile serializer to retrieve the tile. /// </param> private void CreateTopLevelPlateFile(IImageTileSerializer serializer) { string plateFilePath = System.IO.Path.Combine(this.platesFolderPath, Constants.TopLevelPlate); PlateFile currentPlate = new PlateFile(plateFilePath, this.maxLevels); currentPlate.Create(); for (int level = 0; level <= this.plateFileDetails.MaxOverlappedLevel; level++) { // Number of tiles in each direction at this level int n = (int)Math.Pow(2, level); // Add each tile to the plate file. for (int indexY = 0; indexY < n; indexY++) { for (int indexX = 0; indexX < n; indexX++) { TilesProcessed++; if (serializer != null) { Bitmap tile = serializer.Deserialize(level, indexX, indexY); if (tile != null) { using (MemoryStream ms = new MemoryStream()) { ms.Seek(0, SeekOrigin.Begin); tile.Save(ms, format); currentPlate.AddStream(ms, level, indexX, indexY); } tile.Dispose(); } } } } } // Update the header and close the file stream. currentPlate.UpdateHeaderAndClose(); }
/// <summary> /// This function is used to retrieve the tile from the multiple plates. /// </summary> /// <param name="level">Level of the image.</param> /// <param name="x">X axis image.</param> /// <param name="y">Y axis image.</param> /// <param name="platesFolder">Multiple plates folder.</param> /// <param name="topLevelPlateFilename">Top level plate file name.</param> /// <param name="plateFilenameFormat">Format for plate file name.</param> /// <returns>Tile image for the specified image.</returns> private static Stream GetTileFromMultiplePlates(int level, int x, int y, DirectoryInfo platesFolder, string topLevelPlateFilename, string plateFilenameFormat) { Stream outputStream = null; int maxLevel = GetMaxLevel(platesFolder); // TODO: Need to check on how to get the details on how many levels are there in a plate. int levelsPerPlate = 8; // Get the levels break up from Plates folder structure. List<int> plateLevels = GetPlateLevels(platesFolder); // Sort the plate levels. This is make sure that we can do binary search. plateLevels.Sort(); // Get the index of level of the plate files (folder name) where the plate file which contains the tile for level, x and y could be found. // BinarySearch = The zero-based index of item in the sorted List<T>, if item is found; otherwise, a negative number that is the bitwise // complement of the index of the next element that is larger than item or, if there is no larger element, the bitwise complement of Count. int plateLevelIndex = plateLevels.BinarySearch(level); plateLevelIndex = plateLevelIndex < 0 ? ~plateLevelIndex - 1 : plateLevelIndex; if (plateLevelIndex <= 0) { // This means that we need to get data from top level plate file. PlateFile plateFileInstance = new PlateFile(Path.Combine(platesFolder.FullName, topLevelPlateFilename), levelsPerPlate); outputStream = plateFileInstance.GetFileStream(level, x, y); } else if (level <= maxLevel) { // Get the minimum level number (which will be the Folder name) from the plate level index. int minLevel = plateLevels[plateLevelIndex]; // Level in the local plate file. int plateLevel = level - minLevel; int powLevDiff = (int)Math.Pow(2, plateLevel); int plateIndexX = x / powLevDiff; int plateIndexY = y / powLevDiff; string filename = string.Format(CultureInfo.InvariantCulture, plateFilenameFormat, minLevel, plateIndexX, plateIndexY); int tileIndexX = x % powLevDiff; int tileIndexY = y % powLevDiff; PlateFile plateFileInstance = new PlateFile(Path.Combine(platesFolder.FullName, minLevel.ToString(CultureInfo.InvariantCulture), filename), levelsPerPlate); outputStream = plateFileInstance.GetFileStream(plateLevel, tileIndexX, tileIndexY); } return outputStream; }
/// <summary> /// Gets tile image. /// </summary> /// <param name="id">ID for specified Pyramid.</param> /// <param name="level">Level for the image.</param> /// <param name="x">X axis of the image.</param> /// <param name="y">Y axis of the image.</param> /// <returns>Stream for the tile image for the specified level, x and y axis.</returns> public Stream GetTile(string id, int level, int x, int y) { Stream outputStream = null; try { string pyramidFolderPath = Path.Combine(this.CommunityLocation, id, Constants.PyramidFolder); string platesFolderPath = Path.Combine(this.CommunityLocation, id, Constants.PlatesFolder); DirectoryInfo pyramidFolder = new DirectoryInfo(pyramidFolderPath); DirectoryInfo platesFolder = new DirectoryInfo(platesFolderPath); if (pyramidFolder.Exists) { string pyramidPath = Path.Combine(this.CommunityLocation, id, Constants.TileImagePath); string filename = string.Format(CultureInfo.InvariantCulture, pyramidPath, level, x, y, ImageFormat.Png.ToString()); if (File.Exists(filename)) { using (Bitmap bmp = new Bitmap(filename, false)) { if (bmp != null) { outputStream = new MemoryStream(); bmp.Save(outputStream, ImageFormat.Png); outputStream.Seek(0, SeekOrigin.Begin); } } } } else if (platesFolder.Exists) { outputStream = PlateFileHelper.GetTileFromMultiplePlates(level, x, y, platesFolder.FullName); } else { // If Pyramid folder is not available, then try to read from plate file. FileInfo plateFile = pyramidFolder.Parent.GetFiles(Constants.PlateFileSearchPattern).FirstOrDefault(); if (plateFile != null && plateFile.Exists) { PlateFile plateFileInstance = new PlateFile(plateFile.FullName, level); outputStream = plateFileInstance.GetFileStream(level, x, y); } } } catch (ArgumentException ex) { ErrorHandler.LogException(ex); throw new FaultException(ex.Message); } catch (IOException ex) { ErrorHandler.LogException(ex); throw new FaultException(ex.Message); } catch (ObjectDisposedException ex) { ErrorHandler.LogException(ex); throw new FaultException(ex.Message); } return outputStream; }
/// <summary> /// Gets Dem for the specified tile id. /// </summary> /// <param name="id">Tile details id.</param> /// <param name="level">Level of the image.</param> /// <param name="x">X axis image.</param> /// <param name="y">Y axis image.</param> /// <returns>Dem for the specified image.</returns> public Stream GetDem(string id, int level, int x, int y) { Stream outputStream = null; try { string pyramidFolderPath = Path.Combine(this.CommunityLocation, id, Constants.PyramidFolder); string demPlatesFolderPath = Path.Combine(this.CommunityLocation, id, Constants.DEMPlatesFolder); DirectoryInfo pyramidFolder = new DirectoryInfo(pyramidFolderPath); DirectoryInfo platesFolder = new DirectoryInfo(demPlatesFolderPath); if (pyramidFolder.Exists) { string pyramidPath = Path.Combine(this.CommunityLocation, id, Constants.DemTilePath); string filename = string.Format(CultureInfo.InvariantCulture, pyramidPath, level, x, y, Constants.DemExtension); if (File.Exists(filename)) { byte[] data = null; using (Stream s = File.OpenRead(filename)) { int length = (int)s.Length; data = new byte[length]; s.Read(data, 0, length); outputStream = new MemoryStream(data); } } } else if (platesFolder.Exists) { // Get from multiple plates outputStream = PlateFileHelper.GetDEMTileFromMultiplePlates(level, x, y, platesFolder.FullName); } else { // If Pyramid folder is not available, then try to read from plate file. FileInfo plateFile = pyramidFolder.Parent.GetFiles(Constants.PlateFileSearchPattern).FirstOrDefault(); if (plateFile != null && plateFile.Exists) { PlateFile plateFileInstance = new PlateFile(plateFile.FullName, level); outputStream = plateFileInstance.GetFileStream(level, x, y); } } } catch (ArgumentException ex) { ErrorHandler.LogException(ex); throw new FaultException(ex.Message); } catch (IOException ex) { ErrorHandler.LogException(ex); throw new FaultException(ex.Message); } catch (ObjectDisposedException ex) { ErrorHandler.LogException(ex); throw new FaultException(ex.Message); } return outputStream; }