Exemple #1
0
        public void Generate()
        {
            if (InputFilePath == null)
            {
                throw new InvalidOperationException("Input file path is not specified.");
            }

            if (OutputDirPath == null)
            {
                throw new InvalidOperationException("Output directory path is not specified.");
            }

            if (ViewerCreation && BaseName == null)
            {
                throw new InvalidOperationException("Base name should be specified for viewer creation.");
            }

            var zoomLevels = new List <ZoomLevel>();

            ImageReader reader = null;

            try
            {
                reader = ImageReader.Create(InputFilePath);

                var d = 1f;

                ZoomLevel zoomLevel;

                do
                {
                    zoomLevel.ImageWidth  = (int)((float)reader.Width / d);
                    zoomLevel.ImageHeight = (int)((float)reader.Height / d);
                    zoomLevel.GridWidth   = (zoomLevel.ImageWidth + TileSize - 1) / TileSize;
                    zoomLevel.GridHeight  = (zoomLevel.ImageHeight + TileSize - 1) / TileSize;

                    zoomLevels.Add(zoomLevel);

                    tileTotal += zoomLevel.GridWidth * zoomLevel.GridHeight;

                    d *= 2;
                } while (zoomLevel.ImageWidth > TileSize || zoomLevel.ImageHeight > TileSize);

                zoomLevels.Reverse();


                if (ViewerCreation)
                {
                    var bd = AppDomain.CurrentDomain.BaseDirectory;

                    try
                    {
                        if (!Directory.Exists(OutputDirPath))
                        {
                            Directory.CreateDirectory(OutputDirPath);
                        }
                    }
                    catch (Exception e)
                    {
                        throw new IOException(String.Format("Can't create directory {0}.\r\n  {1}", OutputDirPath, e.Message));
                    }

                    File.Copy(Path.Combine(bd, ScriptFileName), Path.Combine(OutputDirPath, ScriptFileName), true);

                    var viewer = File.ReadAllText(Path.Combine(bd, ViewerFileName)).
                                 Replace("{viewerwidth}", ViewerWidth.ToString()).
                                 Replace("{viewerheight}", ViewerHeight.ToString()).
                                 Replace("{imagewidth}", reader.Width.ToString()).
                                 Replace("{imageheight}", reader.Height.ToString()).
                                 Replace("{basename}", BaseName).
                                 Replace("{structure}", FileStructure.Replace("{ext}", GetTileFileExt()));

                    if (TileSize != 256)
                    {
                        viewer = viewer.Replace("{tilesize}", TileSize.ToString());
                    }
                    else
                    {
                        var r = new Regex(@"^.*{tilesize}.*\r\n", RegexOptions.Multiline);
                        viewer = r.Replace(viewer, "");
                    }

                    File.WriteAllText(Path.Combine(OutputDirPath, BaseName + ".htm"), viewer);
                }
            }
            finally
            {
                if (reader != null)
                {
                    reader.Dispose();
                }
            }

            tileProcessedTotal = 0;

            //Application can't have more than 2048 file handlers.
            //We can reach the limit with >~100 MP images
            for (int minTileIndex = 1; minTileIndex <= tileTotal; minTileIndex += MaxOpenFileCount)
            {
                int maxTileIndex = Math.Min(minTileIndex + MaxOpenFileCount - 1, tileTotal);
                int tileIndex    = 0;

                //Store reference to all pipeline elements for further correct object disposing
                var pipelineElements = new List <PipelineElement>();

                try
                {
                    reader = ImageReader.Create(InputFilePath);

                    pipelineElements.Add(reader);

                    PipelineElement source;

                    //Create progress tracker
                    if (Progress != null)
                    {
                        var progress = new ProgressReporter();
                        progress.Progress += (s, e) =>
                        {
                            OnProgress(e);
                        };
                        pipelineElements.Add(progress);
                        reader.Receivers.Add(progress);

                        source = progress;
                    }
                    else
                    {
                        source = reader;
                    }

                    for (int zoom = 0; zoom < zoomLevels.Count; zoom++)
                    {
                        PipelineElement resize;

                        if (zoom == zoomLevels.Count)
                        {
                            resize = source;
                        }
                        else
                        {
                            resize = new Resize(zoomLevels[zoom].ImageWidth, zoomLevels[zoom].ImageHeight, ResizeInterpolationMode.Anisotropic9);
                            pipelineElements.Add(resize);
                            source.Receivers.Add(resize);
                        }


                        for (int tileX = 0; tileX < zoomLevels[zoom].GridWidth; tileX++)
                        {
                            for (int tileY = 0; tileY < zoomLevels[zoom].GridHeight; tileY++)
                            {
                                tileIndex++;

                                if (tileIndex < minTileIndex)
                                {
                                    continue;
                                }

                                int x      = tileX * TileSize;
                                int y      = tileY * TileSize;
                                int width  = Math.Min((tileX + 1) * TileSize, zoomLevels[zoom].ImageWidth) - x;
                                int height = Math.Min((tileY + 1) * TileSize, zoomLevels[zoom].ImageHeight) - y;

                                var crop = new Crop(x, y, width, height);
                                pipelineElements.Add(crop);
                                resize.Receivers.Add(crop);

                                var outputFilePath = Path.Combine(GetTileOutputDirPath(),
                                                                  String.Format(GetFileStructureFormat(), zoom, tileX, tileY, GetTileFileExt()));

                                var p = Path.GetDirectoryName(outputFilePath);

                                try
                                {
                                    if (!Directory.Exists(p))
                                    {
                                        Directory.CreateDirectory(p);
                                    }
                                }
                                catch (Exception e)
                                {
                                    throw new IOException(String.Format("Can't create directory {0}.\r\n  {1}", p, e.Message));
                                }

                                ImageWriter writer;

                                switch (TileImageFormat)
                                {
                                case TileImageFormat.PNG:
                                    writer = new PngWriter(outputFilePath);
                                    break;

                                default:
                                    writer = new JpegWriter(outputFilePath, TileJpegQuality);
                                    break;
                                }

                                pipelineElements.Add(writer);
                                crop.Receivers.Add(writer);

                                if (tileIndex == maxTileIndex)
                                {
                                    //Remove resize elements without crop receivers
                                    for (var l = source.Receivers.Count - 1; l >= 0; l--)
                                    {
                                        if (source.Receivers[l].Receivers.Count == 0)
                                        {
                                            source.Receivers.RemoveAt(l);
                                        }
                                    }

                                    Pipeline.Run(reader);

                                    tileProcessedTotal = maxTileIndex;

                                    goto LoopOut;
                                }
                            }
                        }
                    }

LoopOut:
                    ;
                }
                finally
                {
                    for (var i = 0; i < pipelineElements.Count; i++)
                    {
                        pipelineElements[i].Dispose();
                    }
                }
            }
        }
Exemple #2
0
 private string GetFileStructureFormat()
 {
     return(FileStructure.Replace("{z}", "{0}").Replace("{x}", "{1}").
            Replace("{y}", "{2}").Replace("{ext}", "{3}"));
 }