public JavaMap(byte[] colors) : base(colors) { if (colors.Length != MAP_WIDTH * MAP_HEIGHT) { throw new ArgumentException($"Invalid image dimensions: {colors.Length} is not {MAP_WIDTH}*{MAP_HEIGHT}"); } Image = new LockBitmap(MAP_WIDTH, MAP_HEIGHT); Image.LockBits(); for (int y = 0; y < MAP_HEIGHT; y++) { for (int x = 0; x < MAP_WIDTH; x++) { byte color = colors[(MAP_WIDTH * y) + x]; if (ByteToColor.TryGetValue(color, out Color col)) { Image.SetPixel(x, y, col); } else { Image.SetPixel(x, y, Color.Transparent); } } } Image.UnlockBits(); Original = Image.GetImage(); }
public static IEnumerable <BedrockMap> FromSettings(MapCreationSettings settings) { Bitmap original = ResizeImg(settings.Original, MAP_WIDTH * settings.SplitW, MAP_HEIGHT * settings.SplitH, settings.InterpMode); LockBitmap final = new LockBitmap((Bitmap)original.Clone()); final.LockBits(); // first index = which map this is var colors = new byte[settings.SplitW * settings.SplitH][]; for (int i = 0; i < colors.Length; i++) { colors[i] = new byte[MAP_WIDTH * MAP_HEIGHT * 4]; } #region bedrock map algorithm for (int y = 0; y < final.Height; y++) { for (int x = 0; x < final.Width; x++) { Color realpixel = final.GetPixel(x, y); Color nearest = Color.FromArgb(realpixel.A < 128 ? 0 : 255, realpixel.R, realpixel.G, realpixel.B); final.SetPixel(x, y, nearest); int currentmap = y / MAP_HEIGHT * settings.SplitW + x / MAP_WIDTH; int byteindex = MAP_WIDTH * 4 * (y % MAP_HEIGHT) + 4 * (x % MAP_WIDTH); colors[currentmap][byteindex] = nearest.R; colors[currentmap][byteindex + 1] = nearest.G; colors[currentmap][byteindex + 2] = nearest.B; // saving the alpha works just fine, but bedrock renders each pixel fully solid or transparent // it rounds (<128: invisible, >=128: solid) colors[currentmap][byteindex + 3] = nearest.A; } } #endregion final.UnlockBits(); var maps = new List <BedrockMap>(); for (int y = 0; y < settings.SplitH; y++) { for (int x = 0; x < settings.SplitW; x++) { Rectangle crop = new Rectangle( x * original.Width / settings.SplitW, y * original.Height / settings.SplitH, original.Width / settings.SplitW, original.Height / settings.SplitH); maps.Add(new BedrockMap( CropImage(original, crop), CropImage(final.GetImage(), crop), colors[settings.SplitW * y + x])); } } return(maps); }
public BedrockMap(byte[] colors) : base(colors) { if (colors.Length != MAP_WIDTH * MAP_HEIGHT * 4) { throw new ArgumentException($"Invalid image dimensions: {colors.Length} is not {MAP_WIDTH}*{MAP_HEIGHT}*4"); } Image = new LockBitmap(MAP_WIDTH, MAP_HEIGHT); Image.LockBits(); for (int y = 0; y < MAP_HEIGHT; y++) { for (int x = 0; x < MAP_WIDTH; x++) { int byteindex = (MAP_WIDTH * 4 * y) + (4 * x); Image.SetPixel(x, y, Color.FromArgb(colors[byteindex + 3], colors[byteindex], colors[byteindex + 1], colors[byteindex + 2])); } } Image.UnlockBits(); Original = Image.GetImage(); }
public static IEnumerable <JavaMap> FromSettings(MapCreationSettings settings) { Bitmap original = ResizeImg(settings.Original, MAP_WIDTH * settings.SplitW, MAP_HEIGHT * settings.SplitH, settings.InterpMode); LockBitmap final = new LockBitmap((Bitmap)original.Clone()); final.LockBits(); // first index = which map this is var colors = new byte[settings.SplitW * settings.SplitH][]; for (int i = 0; i < colors.Length; i++) { colors[i] = new byte[MAP_WIDTH * MAP_HEIGHT]; } #region java map algorithm for (int y = 0; y < final.Height; y++) { for (int x = 0; x < final.Width; x++) { Color oldpixel = final.GetPixel(x, y); Color newpixel = Color.Empty; // partial transparency is not allowed if (oldpixel.A < 128) { newpixel = Color.FromArgb(0, 0, 0, 0); } else { if (!NearestColorCache.TryGetValue(oldpixel, out newpixel)) { double mindist = Double.PositiveInfinity; // find the color in the palette that is closest to this one foreach (Color mapcolor in ColorToByte.Keys.Where(o => o.A == 255)) { double distance = ColorDistance(oldpixel, mapcolor); if (mindist > distance) { mindist = distance; newpixel = mapcolor; } } NearestColorCache[oldpixel] = newpixel; } } final.SetPixel(x, y, newpixel); if (settings.Dither) { // floyd-steinberg int error_a = oldpixel.A - newpixel.A; int error_r = oldpixel.R - newpixel.R; int error_g = oldpixel.G - newpixel.G; int error_b = oldpixel.B - newpixel.B; GiveError(final, x + 1, y, error_a, error_r, error_g, error_b, 7); GiveError(final, x - 1, y + 1, error_a, error_r, error_g, error_b, 3); GiveError(final, x, y + 1, error_a, error_r, error_g, error_b, 5); GiveError(final, x + 1, y + 1, error_a, error_r, error_g, error_b, 1); } int currentmap = y / MAP_HEIGHT * settings.SplitW + x / MAP_WIDTH; int currentpixel = MAP_WIDTH * (y % MAP_HEIGHT) + (x % MAP_WIDTH); if (newpixel == Color.FromArgb(0, 0, 0, 0)) { colors[currentmap][currentpixel] = 0x00; } else { colors[currentmap][currentpixel] = ColorToByte[newpixel]; } } } #endregion final.UnlockBits(); var maps = new List <JavaMap>(); for (int y = 0; y < settings.SplitH; y++) { for (int x = 0; x < settings.SplitW; x++) { Rectangle crop = new Rectangle( x * original.Width / settings.SplitW, y * original.Height / settings.SplitH, original.Width / settings.SplitW, original.Height / settings.SplitH); maps.Add(new JavaMap( CropImage(original, crop), CropImage(final.GetImage(), crop), colors[settings.SplitW * y + x])); } } return(maps); }