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." ); }
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." ); } }