示例#1
0
        public static void Run( string source, PngLevel pngLevel, int checkId, bool tolerant )
        {
            PSD.File psd = QueryImage.Run( source );
            if ( !ImportImage.CheckPSD( psd ) ) return;

            MapInfo info = MapInfo.FromBitmap( psd.Layers[Boot.MapInfoLayerName].Image );

            // Extract the 3 buffers from the PSD
            int[] colorbuffer, idbuffer, borderbuffer;
            ImportImage.GetBuffers( psd, out colorbuffer, out idbuffer, out borderbuffer );

            // Get the convertor
            IIDConvertor convertor = ImportImage.GetConvertor( info );
            if ( convertor == null ) return;

            IIDConvertor tconvertor = null;
            if ( convertor is Inferis2IDConvertor && tolerant ) tconvertor = new InferisProxIDConvertor();

            if ( tconvertor != null )
                Console.WriteLine( "Using tolerant ID conversion." );

            // If needed, write out test PNGs of the extracted layers
            if ( pngLevel != PngLevel.None ) ImportImage.WriteTestPNGs( colorbuffer, idbuffer, borderbuffer, pngLevel, info );

            if ( info.LightmapZoom == 0 ) {
                Console.Write( "Checking ID map... " );
                // Use another buffer, since we need to remember the original for the image import later on.
                int[] cidbuffer = new int[idbuffer.Length];

                if ( checkId >= 0 && checkId <= Province.Count ) {
                    Point[] tagged = new Point[idbuffer.Length];
                    int t = 0;
                    for ( int i=0; i<idbuffer.Length; ++i ) {
                        cidbuffer[i] = convertor.ConvertRGB( idbuffer[i] );
                        if ( cidbuffer[i] == checkId ) {
                            tagged[t++] = new Point( i%info.Width, i/info.Width );
                        }
                    }

                    Console.WriteLine( "Done." );
                    Console.WriteLine();

                    Console.WriteLine( "ID {0} was found at the following locations in the file:", checkId );
                    for ( int i=0; i<t; ++i ) {
                        Console.WriteLine( "* {0},{1}", tagged[i].X, tagged[i].Y );
                    }
                }
                else {
                    ushort[] tagged = new ushort[Province.InternalCount];
                    int invalid = 0;
                    for ( int i=0; i<idbuffer.Length; ++i ) {
                        cidbuffer[i] = convertor.ConvertRGB( idbuffer[i] );
                        if ( cidbuffer[i] < 0 || cidbuffer[i] > Province.Count ) {
                            if ( tconvertor != null ) cidbuffer[i] = tconvertor.ConvertRGB( idbuffer[i] );
                            if ( cidbuffer[i] < 0 || cidbuffer[i] > Province.Count ) {
                                if ( invalid++ == 0 ) Console.WriteLine();
                                Console.WriteLine( "Error: Found invalid ID {2} at ({0},{1}). RGB value = {3:X6}", i % info.Width, (int)(i/info.Width), cidbuffer[i], (idbuffer[i] & 0xFFFFFF) );
                            }
                            else {
                                tagged[cidbuffer[i]]++;
                            }
                        }
                        else {
                            tagged[cidbuffer[i]]++;
                        }

                    }

                    if ( invalid > 0 ) {
                        Console.WriteLine( "Error: Invalid IDs encountered. Cannot import. Please fix." );
                        return;
                    }

                    Console.WriteLine( "Done." );
                    Console.WriteLine();

                    Console.WriteLine( "The IDs found in this file are:" );
                    bool first = true;
                    int avgtot = 0, avgcnt = 0;
                    for ( int i=0; i<tagged.Length; ++i ) {
                        if ( tagged[i] > 0 ) {
                            if ( !first ) Console.Write( ", " );
                            Console.Write( "{0} ({1})", i, tagged[i] );
                            first = false;
                            avgtot += tagged[i];
                            avgcnt++;
                        }
                    }
                    Console.WriteLine();
                    Console.WriteLine();
                    avgtot = (avgtot/avgcnt)/10;

                    Console.WriteLine( "Possible stray IDs (average = {0}):", avgtot*10 );
                    for ( int i=0; i<tagged.Length; ++i ) {
                        if ( tagged[i] > 0 && tagged[i] < avgtot ) {
                            Console.WriteLine( "* {0} ({1}x)", i, tagged[i] );
                        }
                    }
                    Console.WriteLine();
                }

            }
            else {
                Console.WriteLine( "This is not a lightmap1 exported file: no id check is necessary." );
            }

            Console.WriteLine( "The source file checked out okay. You should probably do a /SI run now before importing." );
        }
示例#2
0
        private void MapImageParsedArguments_ProcessOption(ParsedArguments sender, ProcessArgumentEventArgs e)
        {
            switch ( e.Value.ToLower() ) {
                case "i": case "import":
                    action = Action.ImportImage;
                    simulate = false;
                    break;
                case "e": case "export":
                    action = Action.ExportImage;
                    break;
                case "q": case "query":
                    action = Action.QueryImage;
                    break;
                case "si": case "simulateimport":
                    action = Action.ImportImage;
                    simulate = true;
                    break;
                case "c": case "check":
                    action = Action.CheckImage;
                    break;
                case "o":
                    overwrite = true;
                    break;
                case "1": case "2": case "3":
                    useLightmap = int.Parse( e.Value );
                    break;
                case "p": case "png":
                    if (e.Data.Length > 0) {
                        foreach(string s in e.Data.Split(new char[] { ',' })) {
                            switch (s.ToLower()) {
                                case "shading":
                                case "s":
                                case "shades":
                                case "shade":
                                    pngLevel |= PngLevel.Shading;
                                    break;

                                case "ids":
                                case "i":
                                case "id":
                                case "idmap":
                                    pngLevel |= PngLevel.IDs;
                                    break;

                                case "borders":
                                case "b":
                                case "border":
                                    pngLevel |= PngLevel.Borders;
                                    break;
                            }
                        }
                    }
                    else {
                        pngLevel = PngLevel.All;
                    }
                    break;
                case "d": case "direct":
                    direct = true;
                    break;
                case "g":
                    if ( e.Data.Length > 0 ) {
                        try {
                            regen = int.Parse( e.Data );
                        }
                        catch ( FormatException ) {
                            // Do nothing
                        }
                    }
                    else {
                        regen = 1;
                    }
                    break;
                case "r":
                    if ( e.Data.Length > 0 ) {
                        if ( e.Data.ToLower() == "full" ) {
                            region = new Rectangle( -1, -1, -1, -1 );
                            mode = RegionMode.Full;
                        }
                        else {
                            int size = -1;
                            try {
                                size = int.Parse( e.Data );
                            }
                            catch ( FormatException ) {
                                size = -1;
                            }

                            if ( size <= 0 ) {
                                string[] spec= e.Data.Split( new char[] {','}, 4 );

                                if ( spec.Length >= 4 ) {
                                    Rectangle newRegion = region;
                                    try {
                                        newRegion = new Rectangle( int.Parse( spec[0] ), int.Parse( spec[1] ), int.Parse( spec[2] ), int.Parse( spec[3] ) );
                                    }
                                    catch ( FormatException ) {
                                        // Do nothing
                                    }
                                    region = newRegion;
                                }
                                mode = RegionMode.Normal;
                            }
                            else {
                                region = new Rectangle( 0, 0, size, size );
                                mode = RegionMode.All;
                            }
                        }
                    }
                    break;
                case "relocate":
                    if ( e.Data.Length > 0 ) {
                        string[] spec= e.Data.Split( new char[] {','}, 2 );

                        if ( spec.Length >= 2 ) {
                            Point newReloc = reloc;
                            try {
                                newReloc = new Point( int.Parse( spec[0] ), int.Parse( spec[1] ) );
                            }
                            catch ( FormatException ) {
                                // Do nothing
                            }
                            reloc = newReloc;
                        }
                    }
                    break;
                case "id":
                    try {
                        id = int.Parse( e.Data );
                    }
                    catch ( FormatException ) {
                        id = -1;
                    }
                    break;
                case "pedantic":
                    tolerant = false;
                    break;
                case "checkidgrid":
                    checkidgrid = true;
                    break;
            }
        }
示例#3
0
        public static void Run( string source, string target, int regen, Point relocate, bool nowrite, PngLevel pngLevel, bool tolerant, bool checkIdgrid )
        {
            if (pngLevel != PngLevel.All && pngLevel != PngLevel.None) {
                Console.WriteLine("Can't use PNG specifier with import. Use /p instead of /p:<spec>.");
                return;
            }

            if ( nowrite ) Console.WriteLine( "*** Simulation ***\n" );

            // Open the PSD, and check if it's valid.
            PSD.File psd = QueryImage.Run( source );
            if ( !CheckPSD( psd ) ) return;
            Console.WriteLine( );

            // Get the mapinfo from the PSD
            MapInfo info = MapInfo.FromBitmap( psd.Layers[Boot.MapInfoLayerName].Image );
            if ( !relocate.IsEmpty ) {
                relocate = new Point( Lightmap.FitToGrid( relocate.X ), Lightmap.FitToGrid( relocate.Y ) );
                Console.WriteLine( "Image will be relocated from {0},{1} to {2},{3}...", info.X, info.Y, relocate.X, relocate.Y );
                info.Location = relocate;
            }

            // Extract the 3 buffers from the PSD
            int[] colorbuffer, idbuffer, borderbuffer;
            ImportImage.GetBuffers( psd, out colorbuffer, out idbuffer, out borderbuffer );

            // Remove ref to PSD so it can get garbagecollected
            psd = null;

            // Get the convertor
            IIDConvertor convertor = GetConvertor( info );
            if ( convertor == null ) return;

            IIDConvertor tconvertor = null;
            if ( convertor is Inferis2IDConvertor && tolerant ) tconvertor = new InferisProxIDConvertor();

            if ( tconvertor != null )
                Console.WriteLine( "Using tolerant ID conversion." );

            // Now, open the map file
            Console.WriteLine( "Opening target file \"{0}\"...", Path.GetFileName( target ) );
            EU2.Edit.File file = new EU2.Edit.File();
            file.ReadFrom( target );

            int[] cidbuffer = null;
            if ( info.LightmapZoom == 0 ) {
                Console.Write( "Checking ID map... " );
                // Use another buffer, since we need to remember the original for the image import later on.
                cidbuffer = new int[idbuffer.Length];
                int invalid = 0;
                for ( int i=0; i<idbuffer.Length; ++i ) {
                    cidbuffer[i] = convertor.ConvertRGB( idbuffer[i] );
                    if ( cidbuffer[i] < 0 || cidbuffer[i] > Province.Count ) {
                        if ( tconvertor != null ) cidbuffer[i] = tconvertor.ConvertRGB( idbuffer[i] );
                        if ( cidbuffer[i] < 0 || cidbuffer[i] > Province.Count ) {
                            Console.WriteLine( "Error: Found invalid ID {2} at ({0},{1}). RGB value = {3:X6}", i % info.Width, (int)(i/info.Width), cidbuffer[i], (idbuffer[i] & 0xFFFFFF) );
                            if ( invalid++ > 10 ) {
                                Console.WriteLine( "Error: Too many invalid IDs found... Stopping." );
                                break;
                            }
                        }
                    }

                    if ( cidbuffer[i] == Province.TerraIncognitaID ) cidbuffer[i] = Province.MaxValue;
                }

                if ( invalid > 0 ) {
                    Console.WriteLine( "Error: Invalid IDs encountered. Cannot import. Please fix." );
                    return;
                }
            }

            // If needed, write out test PNGs of the extracted layers
            if (pngLevel != PngLevel.None)
                WriteTestPNGs(colorbuffer, idbuffer, borderbuffer, pngLevel, info);

            // and get the correct Lightmap
            Lightmap map = null;
            switch ( info.LightmapZoom ) {
                case 0:
                    map = file.Lightmap1; break;
                case 1:
                    map = file.Lightmap2; break;
                case 2:
                    map = file.Lightmap3; break;
            }

            if ( map == null ) {
                Console.WriteLine( "Error: The source image was exported from lightmap{0}, but it no longer exists in the target file." );
                return;
            }

            if ( map.Zoom == 0 ) {
                // Then check if the bitmap differs...
                ushort[] checkbuffer = file.IDMap.ExportBitmapBuffer( info.Bounds );
                bool mismatch = false;
                System.Diagnostics.Debug.Assert( checkbuffer.Length == cidbuffer.Length, "ID buffers have non-matching size" );
                for ( int i=0; !mismatch && i<cidbuffer.Length; ++i ) {
                    if ( cidbuffer[i] != checkbuffer[i] ) mismatch = true;
                }

                if ( mismatch ) {
                    if ( map.Zoom > 0 ) {
                        Console.WriteLine( "Changes to ID map only supported for lightmap 1." );
                        return;
                    }
                    Console.WriteLine( "Mismatch found, updating the ID map." );
                    file.IDMap.ImportBitmapBuffer( info.Bounds, cidbuffer );
                }
                else
                    Console.WriteLine( " No update needed to the ID map." );

                ushort[] affectedIDs = null;
                bool doBoundboxes = false;
                if ( regen > 0 ) {
                    // regenerate certain files first...
                    if ( regen > 2 ) {
                        Console.WriteLine( "Regenerating adjacenties (complete)..." );
                        file.AdjacencyTable = file.IDMap.BuildAdjacencyTable( file.Provinces );

                        // This marks all ids as affected.
                        affectedIDs = new ushort[Province.Count];
                        for ( ushort i=0; i<Province.Count; ++i ) affectedIDs[i] = i;

                        // Force regen of boundboxes
                        doBoundboxes = true;
                    }
                    else if ( mismatch || regen > 1 ) {
                        Console.Write( "Regenerating adjacenties (quick) " );
                        if ( regen > 1 ) Console.Write( "(forced)" );
                        Console.WriteLine( "... " );

                        // Rebuild part and note the affected Ids.
                        affectedIDs = file.IDMap.BuildAdjacencyTable( file.AdjacencyTable, info.Bounds, file.Provinces );

                        // Force regen of boundboxes
                        doBoundboxes = true;
                    }
                }

                // reattach
                map.Attach( file.Provinces, file.AdjacencyTable, file.IDMap );

                if ( doBoundboxes ) {
                    Console.WriteLine( "Regenerating boundboxes..." );
                    file.BoundBoxes = new BoundBoxes( file.IDMap.CalculateBoundBoxes() );
                }

                if ( affectedIDs != null && affectedIDs.Length > 0 ) {
                    Rectangle[] boxes = file.BoundBoxes.GetBoxes( affectedIDs );
                    int[] indexes = map.GetBlockIndexes( boxes );
                    int[] indexes2 = map.GetBlockIndexes( info.Bounds );

                    int total = indexes.Length;
                    for ( int i=0; i<indexes.Length; ++i ) {
                        for ( int e=0; e<indexes2.Length; ++e ) {
                            if ( indexes[i] == indexes2[e] ) {
                                indexes[i] = -1;
                                total--;
                                break;
                            }
                        }
                    }

                    Console.WriteLine( "Decompressing blocks of affected provinces outside of modified area." );
                    Console.Write( "{0} provinces affected, {1} blocks to recompress... ", affectedIDs.Length, total );
                    if ( total > 0 ) {
                        indexes2 = new int[total];
                        total = 0;
                        for ( int i=0; i<indexes.Length; ++i ) {
                            if ( indexes[i] > 0 ) indexes2[total++] = indexes[i];
                        }
                        map.Recompress( indexes2 );
                    }

                    if ( nowrite && checkIdgrid ) {
                        Console.Write( "Checking for IDGrid complexity..." );
                        Rectangle errorArea;
                        if ( IDGrid.CheckAreaForOverflow( file.IDMap, info.Bounds, out errorArea ) ) {
                            Console.WriteLine(" ok!" );
                        }
                        else {
                            Console.WriteLine( " too complex (error in region {0},{1}-{2},{3}).", errorArea.Left, errorArea.Top, errorArea.Right, errorArea.Bottom);
                        }
                    }
                    Console.WriteLine( "Done." );
                }
            }
            else {
                Console.Write( "Scaling down ID map (file changes will not be applied at this zoom level)..." );
                ushort[] tmpbuffer = MapToolsLib.Utils.ScaleIDBuffer( file.IDMap.ExportBitmapGrid( map.CoordMap.ZoomedToActual( info.Bounds ) ), map.Zoom );
                idbuffer = new int[tmpbuffer.Length];
                for ( int i=0; i<idbuffer.Length; ++i ) {
                    if ( tmpbuffer[i] >= Province.Count ) tmpbuffer[i] = Province.TerraIncognitaID;
                    idbuffer[i] = (tconvertor == null ? convertor : tconvertor).ConvertID( tmpbuffer[i] );
                }
                Console.WriteLine( " Done." );
            }

            Console.WriteLine( "Importing image..." );
            RawImage rawimg = new IOShader( tconvertor == null ? convertor : tconvertor ).Unshade32( map.Zoom, info.Bounds, colorbuffer, idbuffer, borderbuffer );
            map.EncodeImage( rawimg );

            if ( !nowrite ) {
                file.WriteTo( target );
                Console.Write( "Import successful." );
            }
            else {
                try {
                    file.WriteTo( System.IO.FileStream.Null );
                }
                catch ( Exception e ) {
                    Console.Write( "There's an error when saving the target file." );
                    throw e;
                }
                Console.Write( "The import process was tested successfully. You can safely do a real import with the same source and target." );
            }
        }
示例#4
0
 public static void WriteTestPNGs( int[] colorbuffer, int[] idbuffer, int[] borderbuffer, PngLevel pngLevel, MapInfo info )
 {
     Console.Write( "Writing buffer check PNGs...");
     if ((pngLevel & PngLevel.Shading)>0) {
         Console.Write("Colorbuffer... ");
         Visualiser.CreateImage32(colorbuffer, info.Size).Save("test-Shading.png", ImageFormat.Png);
     }
     if ((pngLevel & PngLevel.IDs)>0) {
         Console.Write("IDbuffer... ");
         Visualiser.CreateImage32(idbuffer, info.Size).Save("test-IDs.png", ImageFormat.Png);
     }
     if ((pngLevel & PngLevel.Borders)>0) {
         Console.Write("Borderbuffer... ");
         Visualiser.CreateImage32(borderbuffer, info.Size).Save("test-Borders.png", ImageFormat.Png);
     }
     Console.WriteLine( "Done!" );
 }
示例#5
0
        private static void DoExport( Lightmap map, Rectangle region, PngLevel pngLevel, IDMap idmap, string sourcefile, string target )
        {
            Console.WriteLine( "Decoding image..." );
            RawImage rawimg = map.DecodeImage( region );
            int[] shadebuffer, idbuffer, borderbuffer;
            new IOShader( Boot.DefaultConvertor ).MultiShade32( rawimg, out shadebuffer, out idbuffer, out borderbuffer );

            // We don't use the lightmap version as a source: this can lead to errors.
            // Use the idmap as source. For lightmap2 and lightmap3, this needs to be scaled down.
            // -- NOTE: if this is changed, don't forget to turn on the id converting in the IOShader.Multishade above!
            ushort[] tmpbuffer = null;

            if ( map.Zoom == 0 ) {
                tmpbuffer = idmap.ExportBitmapBuffer( rawimg.Bounds );
            }
            else {
                Console.WriteLine( "Scaling idmap..." );
                tmpbuffer = MapToolsLib.Utils.ScaleIDBuffer( idmap.ExportBitmapGrid( map.CoordMap.ZoomedToActual( rawimg.Bounds ) ), map.Zoom );
            }

            // Convert it to the map format
            for ( int i=0; i<idbuffer.Length; ++i ) {
                if ( tmpbuffer[i] >= Province.Count ) tmpbuffer[i] = Province.TerraIncognitaID;
                idbuffer[i] = Boot.DefaultConvertor.ConvertID( tmpbuffer[i] );
            }

            if ( pngLevel != PngLevel.None ) {
                string basetarget = Path.ChangeExtension( Path.GetFileNameWithoutExtension( target ) + "-###", Path.GetExtension( target ) );

                if ((pngLevel & PngLevel.Shading) > 0) {
                    target = basetarget.Replace("###", Boot.ShadingLayerName);
                    Console.WriteLine("Exporting to \"{0}\"...", Path.GetFileName(target));
                    Visualiser.CreateImage32(shadebuffer, rawimg.Size).Save(target, ImageFormat.Png);
                }

                if ((pngLevel & PngLevel.IDs) > 0) {
                    target = basetarget.Replace("###", Boot.IDLayerName);
                    Console.WriteLine("Exporting to \"{0}\"...", Path.GetFileName(target));
                    Visualiser.CreateImage32(idbuffer, rawimg.Size).Save(target, ImageFormat.Png);
                }

                if ((pngLevel & PngLevel.Borders) > 0) {
                    target = basetarget.Replace("###", Boot.BorderLayerName);
                    Console.WriteLine("Exporting to \"{0}\"...", Path.GetFileName(target));
                    Visualiser.CreateImage32(borderbuffer, rawimg.Size).Save(target, ImageFormat.Png);
                }
            }
            else {
                Console.WriteLine( "Exporting to \"{0}\"...", Path.GetFileName( target ) );

                PSD.File psd = new PSD.File( rawimg.Size );

                Bitmap img = new MapInfo( map.Zoom, rawimg.Location, rawimg.Size, sourcefile, Path.GetFileName( target ), Boot.DefaultConvertor ).AsBitmap();
                PSD.Layer l = psd.Layers.Add( new PSD.Layer( Boot.MapInfoLayerName, 0, 0, img ) );
                l.Opacity = 255;
                l.Visible = false;
                l.ProtectTransparancy = true;

                img = Visualiser.CreateImage32( shadebuffer, rawimg.Size );
                l = psd.Layers.Add( new PSD.Layer( Boot.ShadingLayerName, 0, 0, img ) );
                l.Opacity = 254;
                l.Visible = true;
                l.ProtectTransparancy = false;

                img = Visualiser.CreateImage32( idbuffer, rawimg.Size );

                l = psd.Layers.Add( new PSD.Layer( Boot.IDLayerName, 0, 0, img ) );
                l.Opacity = 254;
                l.Mode = PSD.LayerMode.Overlay;
                l.Visible = true;
                l.ProtectTransparancy = false;

                img = Visualiser.CreateImage32( borderbuffer, rawimg.Size, true );
                l = psd.Layers.Add( new PSD.Layer( Boot.BorderLayerName, 0, 0, img ) );
                l.Opacity = 254;
                l.Visible = true;
                l.ProtectTransparancy = false;

                // -- Write the psd
                FileStream stream = null;
                try {
                    stream = new FileStream( target, FileMode.Create, FileAccess.Write, FileShare.None );
                    psd.WriteTo( new BinaryWriter( stream ) );
                }
                finally {
                    if ( stream != null ) stream.Close();
                }
            }
        }
示例#6
0
        public static void Run( string source, string target, Rectangle region, RegionMode mode, int zoom, PngLevel pngLevel, bool direct )
        {
            if ( (mode == RegionMode.Normal && region.IsEmpty) || (mode == RegionMode.All && region.Width <= 0 ) ) {
                Console.WriteLine( "No region was specified. Use \"/r:<x,y,width,height>\", \"/r:full\" or \"/r:<size>\" to specify the region to export." );
                return;
            }

            Console.WriteLine( "Opening source file \"{0}\"...", Path.GetFileName( source ) );

            region.Width -= 1;
            region.Height -= 1;

            IFile file;
            if ( direct ) {
                file = new EU2.Edit.EU2Proxy();
                file.ReadFrom( source ); // source is EU2 dir
            }
            else {
                file = new EU2.Edit.File();
                file.ReadFrom( source );
            }

            Lightmap map = null;
            switch ( zoom ) {
                case 1:
                    map = file.Lightmap1; break;
                case 2:
                    map = file.Lightmap2; break;
                case 3:
                    map = file.Lightmap3; break;
            }

            if ( map == null ) {
                Console.WriteLine( "The source file does not contain lightmap{0}.", zoom );
                return;
            }

            map.VolatileDecompression = true;

            if ( mode == RegionMode.All ) {
                int size = ((region.Width+Lightmap.BlockSize-1) >> Lightmap.BlockFactor) << Lightmap.BlockFactor;
                Console.WriteLine( "Exporting full map as separate files of size {0}x{0}.", size );
                for ( int y=0; y<map.Size.Height; y+=size ) {
                    for ( int x=0; x<map.Size.Width; x+=size ) {
                        region = new Rectangle( x, y, size, size );
                        string parttarget = Path.Combine( Path.GetDirectoryName( target ),
                            Path.GetFileNameWithoutExtension( target ) +
                            String.Format( "-[{0},{1}-{2},{3}]", region.Left, region.Top, region.Right, region.Bottom ) +
                            Path.GetExtension( target ) );
                        DoExport( map, region, pngLevel, file.IDMap, Path.GetFileName( source ), parttarget );
                    }
                }
            }
            else if ( mode == RegionMode.Full ) {
                Console.WriteLine( "Exporting full map as one file." );
                region = new Rectangle( new Point( 0, 0 ), map.Size );
                DoExport( map, region, pngLevel, file.IDMap, Path.GetFileName( source ), target );
            }
            else {
                Console.WriteLine( "Exporting map region: ({0},{1})-({2},{3}) (width={4}, height={5}).", region.Left, region.Top, region.Right, region.Bottom, region.Width, region.Height );
                DoExport(map, region, pngLevel, file.IDMap, Path.GetFileName(source), target);
            }

            Console.Write( "Export successful." );
        }