Beispiel #1
0
 private void SaveStitchedImageAeroFile(XmlSerializer xmlSerializer, StitchedImage stitchedImage, string path)
 {
     using (TextWriter tw = new StreamWriter(path + stitchedImage.FileName + ".aero"))
     {
         xmlSerializer.Serialize(tw, stitchedImage);
     }
 }
Beispiel #2
0
        public async Task GenerateAFSFilesAsync(AFS2GridSquare afs2GridSquare, string stitchedTilesDirectory, string afsGridSquareDirectory, IProgress <AFSFileGeneratorProgress> progress)
        {
            await Task.Run(() =>
            {
                var afsFileGeneratorProgress = new AFSFileGeneratorProgress();

                StitchedImage firstStitchedImageAeroFile = null;

                // The number of stiched tiles should always be pretty manageable so we can get a list of filenames

                if (Directory.Exists(stitchedTilesDirectory))
                {
                    string[] stitchedImagesAeroFiles = Directory.GetFiles(stitchedTilesDirectory, "*.aero");

                    int i = 0;

                    foreach (string aeroFilename in stitchedImagesAeroFiles)
                    {
                        try
                        {
                            StitchedImage stitchedImageAeroFile;

                            using (StreamReader reader = new StreamReader(aeroFilename))
                            {
                                stitchedImageAeroFile = (StitchedImage)xmlSerializer.Deserialize(reader);
                                reader.Close();
                            }

                            if (i == 0)
                            {
                                firstStitchedImageAeroFile = stitchedImageAeroFile;
                            }

                            double stepsPerPixelX = Math.Abs((stitchedImageAeroFile.WestLongitude - stitchedImageAeroFile.EastLongitude) / stitchedImageAeroFile.Width);
                            double stepsPerPixelY = -Math.Abs((stitchedImageAeroFile.NorthLatitude - stitchedImageAeroFile.SouthLatitude) / stitchedImageAeroFile.Height);

                            var aidFile = new AIDFile();

                            aidFile.ImageFile      = stitchedImageAeroFile.FileName + "." + stitchedImageAeroFile.ImageExtension;
                            aidFile.FlipVertical   = false;
                            aidFile.StepsPerPixelX = stepsPerPixelX;
                            aidFile.StepsPerPixelY = stepsPerPixelY;
                            aidFile.X = stitchedImageAeroFile.WestLongitude;
                            aidFile.Y = stitchedImageAeroFile.NorthLatitude;

                            var aidFileStr = aidFile.ToString();

                            string path = stitchedTilesDirectory + stitchedImageAeroFile.FileName + ".aid";

                            log.InfoFormat("Writing AID file {0}", path);
                            File.WriteAllText(path, aidFileStr);
                        }
                        catch (Exception ex)
                        {
                        }

                        i++;
                    }

                    if (firstStitchedImageAeroFile != null)
                    {
                        this.GenerateTMCFile(afs2GridSquare, stitchedTilesDirectory, afsGridSquareDirectory, firstStitchedImageAeroFile);
                    }
                    else
                    {
                        var messageBox = new CustomMessageBox("No stiched images found for this grid square and this image detail (zoom) level.\nRun the 'Download Image Tiles' and 'Stitch Image Tiles' actions first.",
                                                              "AeroScenery",
                                                              MessageBoxIcon.Error);

                        messageBox.ShowDialog();
                    }
                }
            });
        }
Beispiel #3
0
        private void GenerateTMCFile(AFS2GridSquare afs2GridSquare, string stitchedTilesDirectory, string afsGridSquareDirectory, StitchedImage firstStitchedImageAeroFile)
        {
            // Create directories for Geoconvert output if they do not exist.
            // Better to do this here in case anyone wants to run Geoconvert manually
            var geoConvertRawDirectory = String.Format("{0}-geoconvert-raw\\", firstStitchedImageAeroFile.ZoomLevel);
            var geoConvertTTCDirectory = String.Format("{0}-geoconvert-ttc\\", firstStitchedImageAeroFile.ZoomLevel);
            var geoConvertRawPath      = afsGridSquareDirectory + geoConvertRawDirectory;
            var geoConvertTTCPath      = afsGridSquareDirectory + geoConvertTTCDirectory;

            if (!Directory.Exists(geoConvertRawPath))
            {
                Directory.CreateDirectory(geoConvertRawPath);
            }

            if (!Directory.Exists(geoConvertTTCPath))
            {
                Directory.CreateDirectory(geoConvertTTCPath);
            }

            var tmcFile = new TMCFile();

            tmcFile.AlwaysOverwrite      = true;
            tmcFile.DoHeightmaps         = false;
            tmcFile.FolderDestinationRaw = geoConvertRawPath;
            tmcFile.FolderDestinationTTC = geoConvertTTCPath;
            tmcFile.FolderSourceFiles    = stitchedTilesDirectory;
            tmcFile.WriteImagesWithMask  = AeroSceneryManager.Instance.Settings.GeoConvertWriteImagesWithMask.Value;
            tmcFile.WriteRawFiles        = AeroSceneryManager.Instance.Settings.GeoConvertWriteRawFiles.Value;
            tmcFile.WriteTTCFiles        = true;

            // All TMC regions will have the same lat / lon max and min
            // Create a template Region here to base other regions off
            TMCRegion tmcRegionTemplate = new TMCRegion();

            // Really NW Corner
            tmcRegionTemplate.LatMin = afs2GridSquare.NorthLatitude;
            tmcRegionTemplate.LonMin = afs2GridSquare.WestLongitude;

            // Realy SE Corner
            tmcRegionTemplate.LatMax = afs2GridSquare.SouthLatitude;
            tmcRegionTemplate.LonMax = afs2GridSquare.EastLongitude;

            tmcFile.Regions = this.GenerateTMCFileRegions(tmcRegionTemplate);

            var tmcFileStr = tmcFile.ToString();

            var filenameParts = firstStitchedImageAeroFile.FileName.Split('_');
            var tmcFilename   = String.Format("{0}_{1}_{2}", filenameParts[0], filenameParts[1], filenameParts[2]);

            string path = String.Format("{0}{1}.tmc", stitchedTilesDirectory, tmcFilename);

            File.WriteAllText(path, tmcFileStr);
        }
Beispiel #4
0
        public async Task StitchImageTilesAsync(string tileDownloadDirectory, string stitchedTilesDirectory, bool deleteOriginals, IProgress <TileStitcherProgress> progress)
        {
            await Task.Run(() =>
            {
                var tileStitcherProgress = new TileStitcherProgress();

                this.xmlSerializer = new XmlSerializer(typeof(ImageTile));
                this.stitchedImageXmlSerializer = new XmlSerializer(typeof(StitchedImage));

                int startTileX;
                int startTileY;
                int endTileX;
                int endTileY;

                // Get the top left tile X & Y and the bottom right tile X & Y
                // We can work everything else out from this
                this.GetStartingAndEndTileXY(tileDownloadDirectory, out startTileX, out startTileY, out endTileX, out endTileY);

                //Debug.WriteLine("startTileX " + startTileX);
                //Debug.WriteLine("startTileY " + startTileY);
                //Debug.WriteLine("endTileX " + endTileX);
                //Debug.WriteLine("endTileY " + endTileY);

                int numberOfTilesX = (endTileX - startTileX) + 1;
                int numberOfTilesY = (endTileY - startTileY) + 1;

                //Debug.WriteLine("Tiles X " + numberOfTilesX);
                //Debug.WriteLine("Tiles Y " + numberOfTilesY);
                //Debug.WriteLine("Filename prefix " + filenamePrefix);

                var firstImageTile = this.LoadImageTile(tileDownloadDirectory, startTileX, startTileY);

                // Get some info from the first tile. We can assume all tiles have these
                // properties or something is very wrong
                var imageSource = firstImageTile.Source;
                var zoomLevel   = firstImageTile.ZoomLevel;
                var tileWidth   = firstImageTile.Width;
                var tileHeight  = firstImageTile.Height;

                int maxTilesPerStitchedImageX = AeroSceneryManager.Instance.Settings.MaximumStitchedImageSize.Value;
                int maxTilesPerStitchedImageY = AeroSceneryManager.Instance.Settings.MaximumStitchedImageSize.Value;

                // Calculate the size of our stitched images in each direction
                var imageSizeX = maxTilesPerStitchedImageX * tileWidth;
                var imageSizeY = maxTilesPerStitchedImageY * tileHeight;

                // Calculate how many images we need
                var requiredStitchedImagesX = (int)Math.Ceiling((float)numberOfTilesX / (float)maxTilesPerStitchedImageX);
                var requiredStitchedImagesY = (int)Math.Ceiling((float)numberOfTilesY / (float)maxTilesPerStitchedImageY);
                var requiredStichedImages   = requiredStitchedImagesX * requiredStitchedImagesY;

                int imageTileOffsetX = 0;
                int imagetileOffsetY = 0;

                tileStitcherProgress.TotalStitchedImages = requiredStichedImages;

                // Loop through each stitched image that we will need
                for (int stitchedImagesYIx = 0; stitchedImagesYIx < requiredStitchedImagesY; stitchedImagesYIx++)
                {
                    for (int stitchedImagesXIx = 0; stitchedImagesXIx < requiredStitchedImagesX; stitchedImagesXIx++)
                    {
                        imageTileOffsetX = stitchedImagesXIx * maxTilesPerStitchedImageX;
                        imagetileOffsetY = stitchedImagesYIx * maxTilesPerStitchedImageY;

                        // This might not be right, but it's a reasonable estimate. We wont know until we read each file
                        tileStitcherProgress.TotalImageTilesForCurrentStitchedImage = maxTilesPerStitchedImageX * maxTilesPerStitchedImageY;

                        int columnsUsed = 0;
                        int rowsUsed    = 0;

                        // By giving these incorrect values, we can be sure they will we overwritten without having
                        // to make them nullable and do null checks
                        double northLatitude = -500;
                        double westLongitude = 500;
                        double southLatitude = 500;
                        double eastLongitude = -500;

                        using (Bitmap bitmap = new System.Drawing.Bitmap(imageSizeX, imageSizeY))
                        {
                            bitmap.MakeTransparent();

                            using (Graphics g = Graphics.FromImage(bitmap))
                            {
                                tileStitcherProgress.CurrentTilesRenderedForCurrentStitchedImage = 0;

                                // Work left to right, top to bottom
                                // Loop through rows
                                for (int yIx = 0; yIx < maxTilesPerStitchedImageY; yIx++)
                                {
                                    bool rowHasImages = false;

                                    // Loop through columns
                                    for (int xIx = 0; xIx < maxTilesPerStitchedImageX; xIx++)
                                    {
                                        int currentTileX = xIx + imageTileOffsetX + startTileX;
                                        int currentTileY = yIx + imagetileOffsetY + startTileY;

                                        var imageTileData = this.LoadImageTile(tileDownloadDirectory, currentTileX, currentTileY);

                                        if (imageTileData != null)
                                        {
                                            // Even if all the images in this row are invalid, the aero files are present
                                            // so an attempt was made to download something
                                            rowHasImages = true;

                                            // Update our overall stitched image lat and long maxima and minima
                                            // We want the highest NorthLatitude value of any image tile for this stitched image
                                            if (imageTileData.NorthLatitude > northLatitude)
                                            {
                                                northLatitude = imageTileData.NorthLatitude;
                                            }

                                            // We want the lowest SouthLatitude value of any image tile for this stitched image
                                            if (imageTileData.SouthLatitude < southLatitude)
                                            {
                                                southLatitude = imageTileData.SouthLatitude;
                                            }

                                            // We want the lowest WestLongitude value of any image tile for this stitched image
                                            if (imageTileData.WestLongitude < westLongitude)
                                            {
                                                westLongitude = imageTileData.WestLongitude;
                                            }

                                            // We want the highest EastLongitude value of any image tile for this stitched image
                                            if (imageTileData.EastLongitude > eastLongitude)
                                            {
                                                eastLongitude = imageTileData.EastLongitude;
                                            }

                                            var imageTileFilename = tileDownloadDirectory + imageTileData.FileName + "." + imageTileData.ImageExtension;

                                            Image tile = null;

                                            try
                                            {
                                                tile = Image.FromFile(imageTileFilename);

                                                if (tile != null)
                                                {
                                                    var imagePointX = (xIx * imageTileData.Width);
                                                    var imagePointY = (yIx * imageTileData.Width);

                                                    g.DrawImage(tile, new PointF(imagePointX, imagePointY));
                                                    tileStitcherProgress.CurrentTilesRenderedForCurrentStitchedImage++;
                                                    progress.Report(tileStitcherProgress);
                                                }

                                                tile.Dispose();
                                            }
                                            catch (Exception)
                                            {
                                                // The image file was probably invalid, but there's not a lot we can do
                                                // Leave it transparent
                                            }
                                            finally
                                            {
                                                // Even if the image was invalid, we still had an aero file for it
                                                // so it counts as a used column
                                                var colsUsedInThisRow = xIx + 1;

                                                if (columnsUsed < colsUsedInThisRow)
                                                {
                                                    columnsUsed = colsUsedInThisRow;
                                                }

                                                if (tile != null)
                                                {
                                                    tile.Dispose();
                                                }
                                            }
                                        }
                                    }

                                    if (rowHasImages)
                                    {
                                        rowsUsed++;
                                    }
                                }
                            }

                            var stitchFilename = String.Format("{0}_{1}_stitch_{2}_{3}.png", imageSource, zoomLevel, stitchedImagesXIx + 1, stitchedImagesYIx + 1);
                            var stitchedImage  = new StitchedImage();

                            stitchedImage.ImageExtension   = "png";
                            stitchedImage.NorthLatitude    = northLatitude;
                            stitchedImage.WestLongitude    = westLongitude;
                            stitchedImage.SouthLatitude    = southLatitude;
                            stitchedImage.EastLongitude    = eastLongitude;
                            stitchedImage.Width            = columnsUsed * tileWidth;
                            stitchedImage.Height           = rowsUsed * tileHeight;
                            stitchedImage.Source           = imageSource;
                            stitchedImage.ZoomLevel        = zoomLevel;
                            stitchedImage.StichedImageSetX = stitchedImagesXIx + 1;
                            stitchedImage.StichedImageSetY = stitchedImagesYIx + 1;

                            //Debug.WriteLine("Rows Used " + rowsUsed);
                            //Debug.WriteLine("Columns Used " + columnsUsed);


                            // Have we drawn an image to the maximum number of rows and columns for this image?
                            if (columnsUsed == maxTilesPerStitchedImageX && rowsUsed == maxTilesPerStitchedImageY)
                            {
                                // Save the bitmap as it is
                                log.InfoFormat("Saving stitched image {0}", stitchFilename);
                                bitmap.Save(stitchedTilesDirectory + stitchFilename, ImageFormat.Png);
                                tileStitcherProgress.CurrentStitchedImage++;
                            }
                            else
                            {
                                // Resize the bitmap down to the used number of rows and columns
                                log.InfoFormat("Cropping stitched image {0}", stitchFilename);
                                CropBitmap(bitmap, new Rectangle(0, 0, columnsUsed *tileWidth, rowsUsed *tileHeight), stitchedTilesDirectory, stitchFilename);
                                tileStitcherProgress.CurrentStitchedImage++;
                            }

                            this.SaveStitchedImageAeroFile(this.stitchedImageXmlSerializer, stitchedImage, stitchedTilesDirectory);
                        }
                    }
                }

                if (deleteOriginals)
                {
                }
            });
        }