public int ImageToMCBitmapData(Dictionary <int, List <ColorMappingTarget> > ForceBitPattern, List <Formats.CharData> Chars, bool[,] ErrornousBlocks, int CharX, int CharY, int WidthChars, int HeightChars, out GR.Memory.ByteBuffer bitmapData, out GR.Memory.ByteBuffer screenChar, out GR.Memory.ByteBuffer screenColor) { int numErrors = 0; ColorMappingTarget[] bitPattern = new ColorMappingTarget[3] { ColorMappingTarget.BITS_01, ColorMappingTarget.BITS_10, ColorMappingTarget.BITS_11 }; var usedBitPattern = new GR.Collections.Set <ColorMappingTarget>(); Dictionary <int, GR.Collections.Set <ColorMappingTarget> > usedPatterns = new Dictionary <int, GR.Collections.Set <ColorMappingTarget> >(); screenChar = new GR.Memory.ByteBuffer((uint)(WidthChars * HeightChars)); screenColor = new GR.Memory.ByteBuffer((uint)(WidthChars * HeightChars)); bitmapData = new GR.Memory.ByteBuffer((uint)(8 * WidthChars * HeightChars)); GR.Collections.Map <byte, ColorMappingTarget> usedColors = new GR.Collections.Map <byte, ColorMappingTarget>(); for (int y = 0; y < HeightChars; ++y) { for (int x = 0; x < WidthChars; ++x) { // ein zeichen-block usedColors.Clear(); usedBitPattern.Clear(); if (ErrornousBlocks != null) { ErrornousBlocks[x, y] = false; } for (int charY = 0; charY < 8; ++charY) { for (int charX = 0; charX < 4; ++charX) { byte colorIndex = (byte)Image.GetPixel(x * 8 + charX * 2, y * 8 + charY); if (colorIndex >= 16) { if (Chars != null) { Chars[x + y * BlockWidth].Error = "Color index >= 16 (" + colorIndex + ") at " + (x * 8 + charX * 2).ToString() + ", " + (y * 8 + charY).ToString() + " (" + charX + "," + charY + ")"; } if (ErrornousBlocks != null) { ErrornousBlocks[x, y] = true; } ++numErrors; } if (colorIndex != Colors.BackgroundColor) { // remember used color usedColors.Add(colorIndex, 0); } } } // more than 3 colors? if (usedColors.Count > 3) { if (Chars != null) { Chars[x + y * BlockWidth].Error = "Too many colors used"; } if (ErrornousBlocks != null) { ErrornousBlocks[x, y] = true; } ++numErrors; } else { if (usedColors.Count > 0) { int colorTarget = 0; List <byte> keys = new List <byte>(usedColors.Keys); // check for overlaps - two colors are used that would map to the same target pattern? Dictionary <int, ColorMappingTarget> recommendedPattern = new Dictionary <int, ColorMappingTarget>(); numErrors += DetermineBestMapping(keys, x, y, ForceBitPattern, recommendedPattern, ErrornousBlocks); foreach (byte colorIndex in keys) { if (recommendedPattern.ContainsKey(colorIndex)) { usedColors[colorIndex] = recommendedPattern[colorIndex]; if (!usedPatterns.ContainsKey(colorIndex)) { usedPatterns.Add(colorIndex, new GR.Collections.Set <ColorMappingTarget>()); } usedPatterns[colorIndex].Add(recommendedPattern[colorIndex]); usedBitPattern.Add(recommendedPattern[colorIndex]); switch (recommendedPattern[colorIndex]) { case ColorMappingTarget.BITS_01: { // upper screen char nibble byte value = screenChar.ByteAt(x + y * WidthChars); value &= 0x0f; value |= (byte)(colorIndex << 4); screenChar.SetU8At(x + y * WidthChars, value); } break; case ColorMappingTarget.BITS_10: { // lower nibble in screen char byte value = screenChar.ByteAt(x + y * WidthChars); value &= 0xf0; value |= (byte)(colorIndex); screenChar.SetU8At(x + y * WidthChars, value); } break; case ColorMappingTarget.BITS_11: // color ram screenColor.SetU8At(x + y * WidthChars, colorIndex); break; } continue; } if (!usedPatterns.ContainsKey(colorIndex)) { usedPatterns.Add(colorIndex, new GR.Collections.Set <ColorMappingTarget>()); } usedPatterns[colorIndex].Add(bitPattern[colorTarget]); colorTarget = 0; while ((colorTarget < 3) && (usedBitPattern.ContainsValue(bitPattern[colorTarget]))) { ++colorTarget; } usedBitPattern.Add(bitPattern[colorTarget]); if (colorTarget == 0) { // upper screen char nibble byte value = screenChar.ByteAt(x + y * WidthChars); value &= 0x0f; value |= (byte)(colorIndex << 4); screenChar.SetU8At(x + y * WidthChars, value); usedColors[colorIndex] = ColorMappingTarget.BITS_01; } else if (colorTarget == 1) { // lower nibble in screen char byte value = screenChar.ByteAt(x + y * WidthChars); value &= 0xf0; value |= (byte)(colorIndex); screenChar.SetU8At(x + y * WidthChars, value); usedColors[colorIndex] = ColorMappingTarget.BITS_10; } else if (colorTarget == 2) { // color ram screenColor.SetU8At(x + y * WidthChars, colorIndex); usedColors[colorIndex] = ColorMappingTarget.BITS_11; } ++colorTarget; } } // write out bits /* * Debug.Log( "For Char " + x + "," + y ); * foreach ( var usedColor in usedColors ) * { * Debug.Log( " Color " + usedColor.Key + " = " + usedColor.Value ); * }*/ for (int charY = 0; charY < 8; ++charY) { for (int charX = 0; charX < 4; ++charX) { byte colorIndex = (byte)Image.GetPixel(x * 8 + charX * 2, y * 8 + charY); if (colorIndex != Colors.BackgroundColor) { // other color byte colorValue = 0; switch (usedColors[colorIndex]) { case ColorMappingTarget.BITS_01: colorValue = 0x01; break; case ColorMappingTarget.BITS_10: colorValue = 0x02; break; case ColorMappingTarget.BITS_11: colorValue = 0x03; break; } int bitmapIndex = x * 8 + y * 8 * WidthChars + charY; byte value = bitmapData.ByteAt(bitmapIndex); if (charX == 0) { value &= 0x3f; value |= (byte)(colorValue << 6); } else if (charX == 1) { value &= 0xcf; value |= (byte)(colorValue << 4); } else if (charX == 2) { value &= 0xf3; value |= (byte)(colorValue << 2); } else { value &= 0xfc; value |= colorValue; } bitmapData.SetU8At(bitmapIndex, value); } } } } } } /* * Debug.Log( "Used patterns:" ); * foreach ( var entry in usedPatterns ) * { * Debug.Log( "Index " + entry.Key ); * foreach ( var pattern in entry.Value ) * { * Debug.Log( " used " + pattern ); * } * }*/ return(numErrors); }
public bool ReadFromBuffer(GR.Memory.ByteBuffer ProjectFile) { ColorMapping.Clear(); for (int i = 0; i < 16; ++i) { ColorMapping.Add(i, new List <ColorMappingTarget> { ColorMappingTarget.ANY }); } Colors.Palettes.Clear(); GR.IO.MemoryReader memReader = new GR.IO.MemoryReader(ProjectFile); GR.IO.FileChunk chunk = new GR.IO.FileChunk(); while (chunk.ReadFromStream(memReader)) { GR.IO.MemoryReader chunkReader = chunk.MemoryReader(); switch (chunk.Type) { case FileChunkConstants.GRAPHIC_SCREEN_INFO: SelectedCheckType = (CheckType)chunkReader.ReadUInt32(); ScreenOffsetX = chunkReader.ReadInt32(); ScreenOffsetY = chunkReader.ReadInt32(); ScreenWidth = chunkReader.ReadInt32(); ScreenHeight = chunkReader.ReadInt32(); if ((ScreenWidth == 0) || (ScreenHeight == 0)) { ScreenWidth = 320; ScreenHeight = 200; } break; case FileChunkConstants.GRAPHIC_COLOR_MAPPING: { ColorMapping.Clear(); int numEntries = chunkReader.ReadInt32(); for (int i = 0; i < numEntries; ++i) { ColorMapping.Add(i, new List <ColorMappingTarget>()); int numMappings = chunkReader.ReadInt32(); for (int j = 0; j < numMappings; ++j) { ColorMappingTarget mappingTarget = (ColorMappingTarget)chunkReader.ReadUInt8(); ColorMapping[i].Add(mappingTarget); } } } break; case FileChunkConstants.GRAPHIC_DATA: { int width = chunkReader.ReadInt32(); int height = chunkReader.ReadInt32(); GR.Drawing.PixelFormat format = (GR.Drawing.PixelFormat)chunkReader.ReadInt32(); int paletteCount = chunkReader.ReadInt32(); Image.Create(width, height, format); for (int i = 0; i < paletteCount; ++i) { byte r = chunkReader.ReadUInt8(); byte g = chunkReader.ReadUInt8(); byte b = chunkReader.ReadUInt8(); Image.SetPaletteColor(i, r, g, b); } uint dataSize = chunkReader.ReadUInt32(); GR.Memory.ByteBuffer imageData = new GR.Memory.ByteBuffer(); chunkReader.ReadBlock(imageData, dataSize); Image.SetData(imageData); } break; case FileChunkConstants.MULTICOLOR_DATA: MultiColor = (chunkReader.ReadUInt8() == 1); Colors.BackgroundColor = chunkReader.ReadUInt8(); Colors.MultiColor1 = chunkReader.ReadUInt8(); Colors.MultiColor2 = chunkReader.ReadUInt8(); Colors.ActivePalette = chunkReader.ReadInt32(); if ((Colors.MultiColor1 < 0) || (Colors.MultiColor1 >= 16)) { Colors.MultiColor1 = 0; } if ((Colors.MultiColor2 < 0) || (Colors.MultiColor2 >= 16)) { Colors.MultiColor2 = 0; } break; case FileChunkConstants.PALETTE: Colors.Palettes.Add(Palette.Read(chunkReader)); break; } } memReader.Close(); if (Colors.Palettes.Count == 0) { Colors.Palettes.Add(PaletteManager.PaletteFromMachine(MachineType.C64)); } return(true); }