public PaletteList(IConverterProfile profile) { convertProfile = profile; palettes = new List <Palette>(profile.NumPalettes); nextPaletteId = 0; AddNewPalette(); }
static void Main(string[] args) { if ( (args.Length < 3) || (!File.Exists(args[0])) ) { PrintUsageAndExit(); } string profile = args[2].ToLowerInvariant(); if (profile[0] == '"' || profile[0] == '\'') { profile = profile.Substring(1, profile.Length - 2); } if ((profile != "gm") && (profile != "gtmp")) { PrintErrorAndExit("Invalid profile {0}, must be GTMP or GM", args[2]); } IConverterProfile profileToUse = (profile == "gm") ? Profiles.GM : Profiles.GTMP; Bitmap bm = new Bitmap(args[0]); try { #if USE_32BIT_SOURCE using (Bitmap sourceFile = bm.Clone(new Rectangle(Point.Empty, bm.Size), System.Drawing.Imaging.PixelFormat.Format32bppRgb)) #else using (Bitmap sourceFile = bm.Clone(new Rectangle(Point.Empty, bm.Size), System.Drawing.Imaging.PixelFormat.Format16bppArgb1555)) #endif { bm.Dispose(); Size imgSize = sourceFile.Size; if ((imgSize.Width != PixelBuffer.CANVAS_WIDTH) || (imgSize.Height != PixelBuffer.CANVAS_HEIGHT)) { PrintErrorAndExit("File is sized {0}x{1} instead of {2}x{3}", imgSize.Width, imgSize.Height, PixelBuffer.CANVAS_WIDTH, PixelBuffer.CANVAS_HEIGHT); } Convert(profileToUse, sourceFile, args[1]); } Environment.ExitCode = 0; } catch (Exception e) { PrintErrorAndExit("Conversion failed due to error: {0}", e.Message); Environment.ExitCode = 2; } }
static void Convert(IConverterProfile profile, Bitmap source, string outFile) { const int totalPixels = PixelBuffer.CANVAS_WIDTH * PixelBuffer.CANVAS_HEIGHT; #if USE_32BIT_SOURCE int[] originalPixels = new int[totalPixels]; { Rectangle lockRect = new Rectangle(Point.Empty, source.Size); System.Drawing.Imaging.BitmapData sourceData = source.LockBits(lockRect, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb); Debug.Assert(sourceData.Stride == (sourceData.Width * 4)); System.Runtime.InteropServices.Marshal.Copy(sourceData.Scan0, originalPixels, 0, originalPixels.Length); source.UnlockBits(sourceData); } #else ushort[] originalPixels = new ushort[totalPixels]; { Rectangle lockRect = new Rectangle(Point.Empty, source.Size); System.Drawing.Imaging.BitmapData sourceData = source.LockBits(lockRect, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format16bppArgb1555); Debug.Assert(sourceData.Stride == (sourceData.Width * 2)); short[] tempPixels = new short[totalPixels]; System.Runtime.InteropServices.Marshal.Copy(sourceData.Scan0, tempPixels, 0, tempPixels.Length); source.UnlockBits(sourceData); Buffer.BlockCopy(tempPixels, 0, originalPixels, 0, tempPixels.Length * sizeof(ushort)); } #endif PaletteList palettes = new PaletteList(profile); List <PositionData> positions = new List <PositionData>(0x800); PixelBuffer convertedPixels = new PixelBuffer(profile.BitsPerPixel); ConvertAllTiles(originalPixels, convertedPixels, palettes, positions, profile); using (MemoryStream outputStream = new MemoryStream(50000)) { using (BinaryWriter bw = new BinaryWriter(outputStream)) { profile.WriteFile(bw, positions, palettes, convertedPixels); } File.WriteAllBytes(outFile, outputStream.ToArray()); } }
static void ConvertAllTiles(ushort[] pixels, PixelBuffer convertedPixels, PaletteList palettes, List <PositionData> positions, IConverterProfile profile) #endif { List <ImageSlice> convertedTiles = new List <ImageSlice>(); Dictionary <ImageSlice, TileInfo> uniqueTiles = new Dictionary <ImageSlice, TileInfo>(); int tiles = 0; for (int y = 0; y < PixelBuffer.CANVAS_HEIGHT; y += PixelBuffer.TILE_HEIGHT) { for (int x = 0; x < PixelBuffer.CANVAS_WIDTH; x += PixelBuffer.TILE_WIDTH) { #if USE_32BIT_SOURCE int[] tile = GetTileData(pixels, x, y); #else ushort[] tile = GetTileData(pixels, x, y); #endif int usedPalette; PositionData pd; ImageSlice slice = palettes.NaturalizeTile(tile, out usedPalette); if (slice != null) { ++tiles; int uniqueTileId; // see if this slice already exists if (uniqueTiles.ContainsKey(slice)) { TileInfo info = uniqueTiles[slice]; ImageSlice dup = convertedTiles[info.tileIndex]; Debug.Assert(AreArraysEqual(dup.rect, slice.rect), "In duplicate tile branch, but tiles aren't duplicates"); usedPalette = info.paletteId; uniqueTileId = info.tileIndex; } else { // it's a unique slice, add it uniqueTileId = convertedTiles.Count; TileInfo ti = new TileInfo(uniqueTileId, usedPalette); convertedTiles.Add(slice); uniqueTiles.Add(slice, ti); convertedPixels.WriteTile(slice); } //Debug.Assert(usedPalette < profile.NumPalettes); pd = new PositionData( (byte)(x / PixelBuffer.TILE_WIDTH), (byte)(y / PixelBuffer.TILE_HEIGHT), profile.MakeTileAndPaletteValue(uniqueTileId, usedPalette) ); positions.Add(pd); } else if (usedPalette != PaletteList.DISCARD_TILE) // these are all the same colour { #if USE_32BIT_SOURCE ushort singleColour = profile.SwizzleSolidColour(Palette.ConvertColourToRGB555(tile[0])); #else ushort singleColour = profile.SwizzleSolidColour(tile[0]); #endif pd = new PositionData( (byte)(x / PixelBuffer.TILE_WIDTH), (byte)(y / PixelBuffer.TILE_HEIGHT) ).SetSolidColour(singleColour); positions.Add(pd); #if DEBUG Console.WriteLine("Found solid colour tile at {0}x{1} of colour {2:x}", x, y, singleColour); #endif } // else this is a tile containing only black and/or transparent colours // and the converter profile said it shouldn't be included in the image file } } Console.WriteLine("Total tiles: {0}, unique tiles: {1}", tiles, convertedTiles.Count); }
static void ConvertAllTiles(int[] pixels, PixelBuffer convertedPixels, PaletteList palettes, List <PositionData> positions, IConverterProfile profile)