Skip to content

Commit

Permalink
Abstract all System.Drawing stuff in ImageUtils.cs, in preparation for
Browse files Browse the repository at this point in the history
  • Loading branch information
UnknownShadow200 committed Aug 15, 2022
1 parent 36ba055 commit 1344711
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 171 deletions.
20 changes: 3 additions & 17 deletions MCGalaxy/Commands/building/CmdImageprint.cs
Expand Up @@ -16,15 +16,14 @@
permissions and limitations under the Licenses.
*/
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Threading;
using MCGalaxy.Drawing;
using MCGalaxy.Drawing.Ops;
using MCGalaxy.Generator;
using MCGalaxy.Maths;
using MCGalaxy.Network;
using MCGalaxy.Util;
using BlockID = System.UInt16;

namespace MCGalaxy.Commands.Building {
Expand Down Expand Up @@ -106,7 +105,7 @@ public sealed class CmdImageprint : Command2 {
}

void DoDrawImageCore(Player p, Vec3S32[] marks, DrawArgs dArgs) {
Bitmap bmp = HeightmapGen.DecodeImage(dArgs.Data, p);
IBitmap2D bmp = HeightmapGen.DecodeImage(dArgs.Data, p);
if (bmp == null) return;

ImagePrintDrawOp op = new ImagePrintDrawOp();
Expand All @@ -118,7 +117,7 @@ public sealed class CmdImageprint : Command2 {
Clamp(p, marks, op, ref width, ref height);

if (width < bmp.Width || height < bmp.Height) {
bmp = Resize(bmp, width, height);
bmp.Resize(width, height, true);
}

op.Source = bmp; op.Palette = dArgs.Pal;
Expand All @@ -144,19 +143,6 @@ public sealed class CmdImageprint : Command2 {
width = resizedWidth; height = resizedHeight;
}

static Bitmap Resize(Bitmap bmp, int width, int height) {
Bitmap resized = new Bitmap(width, height);
using (Graphics g = Graphics.FromImage(resized)) {
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawImage(bmp, 0, 0, width, height);
}

bmp.Dispose();
return resized;
}

static int LargestDelta(Level lvl, Vec3S32 point) {
Vec3S32 clamped = lvl.ClampPos(point);
int dx = Math.Abs(point.X - clamped.X);
Expand Down
18 changes: 10 additions & 8 deletions MCGalaxy/Drawing/Image/ImagePrintDrawOp.cs
Expand Up @@ -18,8 +18,8 @@
using System;
using MCGalaxy.Drawing.Brushes;
using MCGalaxy.Maths;
using MCGalaxy.Util;
using BlockID = System.UInt16;
using Draw = System.Drawing;

namespace MCGalaxy.Drawing.Ops
{
Expand All @@ -31,7 +31,7 @@ public class ImagePrintDrawOp : DrawOp
return Source.Width * Source.Height;
}

internal Draw.Bitmap Source;
internal IBitmap2D Source;
internal bool DualLayer, LayerMode;
public ImagePalette Palette;

Expand All @@ -42,9 +42,11 @@ public class ImagePrintDrawOp : DrawOp
selector = new RgbPaletteMatcher();
CalcLayerColors();

using (PixelGetter getter = new PixelGetter(Source)) {
getter.Init();
OutputPixels(getter, output);
try {
Source.LockBits();
OutputPixels(output);
} finally {
Source.UnlockBits();
}
selector = null;

Expand Down Expand Up @@ -101,14 +103,14 @@ public class ImagePrintDrawOp : DrawOp
return entry;
}

void OutputPixels(PixelGetter pixels, DrawOpOutput output) {
int width = pixels.Width, height = pixels.Height;
void OutputPixels(DrawOpOutput output) {
int width = Source.Width, height = Source.Height;
int srcY = height - 1; // need to flip coords in bitmap vertically

for (int yy = 0; yy < height; yy++, srcY--)
for (int xx = 0; xx < width; xx++)
{
Pixel P = pixels.Get(xx, srcY);
Pixel P = Source.Get(xx, srcY);
ushort x = (ushort)(Origin.X + dx.X * xx + dy.X * yy);
ushort y = (ushort)(Origin.Y + dx.Y * xx + dy.Y * yy);
ushort z = (ushort)(Origin.Z + dx.Z * xx + dy.Z * yy);
Expand Down
91 changes: 35 additions & 56 deletions MCGalaxy/Generator/HeightmapGen.cs
Expand Up @@ -16,30 +16,25 @@
permissions and limitations under the Licenses.
*/
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using MCGalaxy.Network;
using MCGalaxy.Drawing;
using MCGalaxy.Util;

namespace MCGalaxy.Generator
{
public static class HeightmapGen
{
static void OnDecodeError(Player p, Bitmap bmp) {
static void OnDecodeError(Player p, IBitmap2D bmp) {
if (bmp != null) bmp.Dispose();
// TODO failed to decode the image. make sure you are using the URL of the image directly, not just the webpage it is hosted on
p.Message("&WThere was an error reading the downloaded image.");
p.Message("&WThe url may need to end with its extension (such as .jpg).");
}

public static Bitmap DecodeImage(byte[] data, Player p) {
Bitmap bmp = null;
public static IBitmap2D DecodeImage(byte[] data, Player p) {
IBitmap2D bmp = null;
try {
bmp = new Bitmap(new MemoryStream(data));
int width = bmp.Width;
// sometimes Mono will return an invalid bitmap instance that throws ArgumentNullException,
// so we make sure to check for that here rather than later.
bmp = IBitmap2D.Create();
bmp.Decode(data);
return bmp;
} catch (ArgumentException ex) {
// GDI+ throws ArgumentException when data is not an image
Expand All @@ -61,65 +56,49 @@ public static class HeightmapGen

byte[] data = HttpUtil.DownloadImage(url, p);
if (data == null) return false;
Bitmap bmp = DecodeImage(data, p);
IBitmap2D bmp = DecodeImage(data, p);
if (bmp == null) return false;

int index = 0, oneY = lvl.Width * lvl.Length;
try {
using (bmp) {
if (lvl.Width != bmp.Width || lvl.Length != bmp.Height) {
p.Message("&cHeightmap size ({0}x{1}) does not match Width x Length ({2}x{3}) of the level",
bmp.Width, bmp.Height, lvl.Width, lvl.Length);
p.Message("&cAs such, the map may not look accurate.");
bmp = Resize(bmp, lvl.Width, lvl.Length);
bmp.Resize(lvl.Width, lvl.Height, false);
}

using (PixelGetter pixels = new PixelGetter(bmp)) {
pixels.Init();
for (int z = 0; z < pixels.Height; z++)
for (int x = 0; x < pixels.Width; x++)
bmp.LockBits();

for (int z = 0; z < bmp.Height; z++)
for (int x = 0; x < bmp.Width; x++)
{
int height = bmp.Get(x, z).R;
byte layer = Block.Dirt, top = Block.Grass;

if (
IsCliff(height, bmp, x - 1, z) ||
IsCliff(height, bmp, x + 1, z) ||
IsCliff(height, bmp, x, z - 1) ||
IsCliff(height, bmp, x, z + 1))
{
int height = pixels.Get(x, z).R;
byte layer = Block.Dirt, top = Block.Grass;

if (
IsCliff(height, pixels, x - 1, z) ||
IsCliff(height, pixels, x + 1, z) ||
IsCliff(height, pixels, x, z - 1) ||
IsCliff(height, pixels, x, z + 1))
{
layer = Block.Stone; top = Block.Stone;
}

// remap from 0..255 to 0..lvl.Height
height = height * lvl.Height / 255;
for (int y = 0; y < height - 1; y++)
lvl.blocks[index + oneY * y] = layer;
if (height > 0)
lvl.blocks[index + oneY * (height - 1)] = top;
index++;
layer = Block.Stone; top = Block.Stone;
}

// remap from 0..255 to 0..lvl.Height
height = height * lvl.Height / 255;
for (int y = 0; y < height - 1; y++)
lvl.blocks[index + oneY * y] = layer;
if (height > 0)
lvl.blocks[index + oneY * (height - 1)] = top;
index++;
}
// Cannot use using { } here because bmp may be reassigned
} finally { bmp.Dispose(); }
return true;
}

static Bitmap Resize(Bitmap bmp, int width, int height) {
Bitmap resized = new Bitmap(width, height);
using (Graphics g = Graphics.FromImage(resized)) {
g.InterpolationMode = InterpolationMode.NearestNeighbor;
g.SmoothingMode = SmoothingMode.None;
g.PixelOffsetMode = PixelOffsetMode.None;
g.DrawImage(bmp, 0, 0, width, height);
}

bmp.Dispose();
return resized;
return true;
}

static bool IsCliff(int height, PixelGetter pixels, int x, int z) {
if (x >= pixels.Width || x < 0 || z >= pixels.Height || z < 0) return false;
int neighbourHeight = pixels.Get(x, z).R;
static bool IsCliff(int height, IBitmap2D bmp, int x, int z) {
if (x >= bmp.Width || x < 0 || z >= bmp.Height || z < 0) return false;
int neighbourHeight = bmp.Get(x, z).R;
return height >= neighbourHeight + 2;
}
}
Expand Down
6 changes: 3 additions & 3 deletions MCGalaxy/MCGalaxy_.csproj
Expand Up @@ -443,7 +443,6 @@
<Compile Include="Drawing\Image\ImagePalette.cs" />
<Compile Include="Drawing\Image\ImagePrintDrawOp.cs" />
<Compile Include="Drawing\Image\IPaletteMatcher.cs" />
<Compile Include="Drawing\Image\PixelGetter.cs" />
<Compile Include="Drawing\TransformFactories\RotateTransform.cs" />
<Compile Include="Drawing\TransformFactories\SimpleTransforms.cs" />
<Compile Include="Drawing\TransformFactories\TransformFactory.cs" />
Expand Down Expand Up @@ -653,7 +652,8 @@
<Compile Include="Server\Maintenance\Updater.cs" />
<Compile Include="Server\Maintenance\ZipReader.cs" />
<Compile Include="Server\Maintenance\ZipWriter.cs" />
<Compile Include="Server\OperatingSystem.cs" />
<Compile Include="util\ImageUtils.cs" />
<Compile Include="util\OperatingSystem.cs" />
<Compile Include="Server\Server.cs" />
<Compile Include="Server\Server.DB.cs" />
<Compile Include="Server\Server.Fields.cs" />
Expand All @@ -672,7 +672,7 @@
<Compile Include="util\Formatting\Matcher.cs" />
<Compile Include="util\Formatting\MultiPageOutput.cs" />
<Compile Include="util\IO\FileIO.cs" />
<Compile Include="util\IO\Paths.cs" />
<Compile Include="Server\Paths.cs" />
<Compile Include="util\IO\TextFile.cs" />
<Compile Include="util\Math\AABB.cs" />
<Compile Include="util\Math\DirUtils.cs" />
Expand Down
File renamed without changes.

0 comments on commit 1344711

Please sign in to comment.