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}"); } var canvas = new LockBitmap(MAP_WIDTH, MAP_HEIGHT); canvas.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)) { canvas.SetPixel(x, y, col); } else { canvas.SetPixel(x, y, Color.Transparent); } } } canvas.UnlockBits(); Image = canvas.GetImage(); Original = Image; }
public static IEnumerable <BedrockMap> FromSettings(MapCreationSettings settings) { Bitmap original = ResizeImg(settings.Original, MAP_WIDTH * settings.SplitW, MAP_HEIGHT * settings.SplitH, settings.InterpMode, !settings.Stretch); LockBitmap final = new LockBitmap((Bitmap)original.Clone()); final.LockBits(); // first index = which map this is var colors = new byte[settings.NumberOfMaps][]; 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); var map_image = CropImage(final.GetImage(), crop); //if (!IsEmpty(map_image)) maps.Add(new BedrockMap( CropImage(original, crop), map_image, colors[settings.SplitW * y + x])); } } return(maps); }
private static void GiveError(LockBitmap img, int x, int y, int alpha, int red, int green, int blue, int proportion) { if (x >= 0 && y >= 0 && x < img.Width && y < img.Height) { Color old = img.GetPixel(x, y); img.SetPixel(x, y, Color.FromArgb( ByteClamp(old.A, (alpha * proportion) >> 4), ByteClamp(old.R, (red * proportion) >> 4), ByteClamp(old.G, (green * proportion) >> 4), ByteClamp(old.B, (blue * proportion) >> 4) )); } }
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"); } var canvas = new LockBitmap(MAP_WIDTH, MAP_HEIGHT); canvas.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); canvas.SetPixel(x, y, Color.FromArgb(colors[byteindex + 3], colors[byteindex], colors[byteindex + 1], colors[byteindex + 2])); } } canvas.UnlockBits(); Image = canvas.GetImage(); Original = Image; }
public static IEnumerable <JavaMap> FromSettings(MapCreationSettings settings) { Bitmap original = ResizeImg(settings.Original, MAP_WIDTH * settings.SplitW, MAP_HEIGHT * settings.SplitH, settings.InterpMode, !settings.Stretch); LockBitmap final = new LockBitmap((Bitmap)original.Clone()); final.LockBits(); // first index = which map this is var colors = new byte[settings.NumberOfMaps][]; 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.Set(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); var map_image = CropImage(final.GetImage(), crop); // if (!IsEmpty(map_image)) // currently commented out because the user can pretty easily check if there are going to be empty maps // also it breaks the temporary loading maps that assume exactly width*height outputs maps.Add(new JavaMap( CropImage(original, crop), map_image, colors[settings.SplitW * y + x])); } } return(maps); }
public static IEnumerable <JavaMap> FromSettings(MapCreationSettings settings, IJavaVersion mapping, IProgress <MapCreationProgress> progress) { Bitmap original = ResizeImg(settings.Original, MAP_WIDTH * settings.SplitW, MAP_HEIGHT * settings.SplitH, settings.InterpMode, !settings.Stretch); LockBitmap final = new LockBitmap((Bitmap)original.Clone()); final.LockBits(); // first index = which map this is var colors = new byte[settings.NumberOfMaps][]; for (int i = 0; i < colors.Length; i++) { colors[i] = new byte[MAP_WIDTH * MAP_HEIGHT]; } var report = new MapCreationProgress(); #region java map algorithm for (int y = 0; y < final.Height; y++) { report.PercentageComplete = ((decimal)y) / final.Height; progress.Report(report); for (int x = 0; x < final.Width; x++) { Color oldpixel = final.GetPixel(x, y); var newpixel = GetBestPixel(oldpixel, settings.Algorithm, mapping); 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] = mapping.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); var map_image = CropImage(final.GetImage(), crop); maps.Add(new JavaMap( CropImage(original, crop), map_image, colors[settings.SplitW * y + x])); } } return(maps); }