public byte[] MatImgToPng(MaterialImage img)
 {
     using (Bitmap bmp = new Bitmap(img.Width, img.Height))
     {
         BitmapData bdat   = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
         int        stride = bdat.Stride;
         // Surely there's a better way to do this!
         unsafe
         {
             byte *ptr = (byte *)bdat.Scan0;
             for (int x = 0; x < img.Width; x++)
             {
                 for (int y = 0; y < img.Height; y++)
                 {
                     FastColor tcol = img.GetAt(x, y);
                     ptr[(x * 4) + y * stride + 0] = tcol.B;
                     ptr[(x * 4) + y * stride + 1] = tcol.G;
                     ptr[(x * 4) + y * stride + 2] = tcol.R;
                     ptr[(x * 4) + y * stride + 3] = tcol.A;
                 }
             }
         }
         using (DataStream ds = new DataStream())
         {
             bmp.Save(ds, ImageFormat.Png);
             return(ds.ToArray());
         }
     }
 }
        public byte[] GetChunkRenderLD(WorldSystem.Region tregion, int tx, int ty, int tz)
        {
            int           wid   = Constants.CHUNK_WIDTH;
            int           divvy = GetDividerForZ(tz) * Constants.CHUNK_WIDTH;
            MaterialImage bmp   = GenerateSeedImageBmp(tregion, tx * divvy, ty * divvy, (tx + 1) * divvy, (ty + 1) * divvy, wid);
            KeyValuePair <byte[], byte[]> bitters = tregion.ChunkManager.GetTopsHigher(tx, ty, tz);

            byte[] bits       = bitters.Key;
            byte[] bits_trans = bitters.Value;
            if (bits == null || bits_trans == null)
            {
                return(MatImgToPng(bmp));
            }
            for (int x = 0; x < Constants.CHUNK_WIDTH; x++)
            {
                for (int y = 0; y < Constants.CHUNK_WIDTH; y++)
                {
                    int       ind = tregion.TopsHigherBlockIndex(x, y);
                    ushort    mat = Utilities.BytesToUshort(Utilities.BytesPartial(bits, ind * 2, 2));
                    FastColor fc;
                    if (mat == 0)
                    {
                        fc = new FastColor()
                        {
                            A = 0
                        };
                    }
                    else
                    {
                        MaterialImage imag = MaterialImages[mat];
                        fc = imag.GetAt(0, 0);
                    }
                    for (int i = 3; i >= 0; i--)
                    {
                        mat = Utilities.BytesToUshort(Utilities.BytesPartial(bits_trans, ind * 2 * 4, 2));
                        if (mat != 0)
                        {
                            MaterialImage simag = MaterialImages[mat];
                            FastColor     fc2   = simag.Colors[0];
                            fc = Blend(fc2, fc);
                        }
                    }
                    fc = Blend(fc, bmp.GetAt(x, y));
                    bmp.SetAt(x, y, fc);
                }
            }
            // TODO: Add entity icons? (Trees in particular!)
            return(MatImgToPng(bmp));
        }
        public byte[] GetChunkRenderHD(WorldSystem.Region tregion, int tx, int ty, bool fullzoom)
        {
            const int     wid = TexWidth * Constants.CHUNK_WIDTH;
            MaterialImage bmp = new MaterialImage()
            {
                Colors = new FastColor[wid * wid], Width = wid, Height = wid
            };
            KeyValuePair <byte[], byte[]> bitters = tregion.ChunkManager.GetTops(tx, ty);

            byte[] xp = null;
            byte[] xm = null;
            byte[] yp = null;
            byte[] ym = null;
            if (!fullzoom)
            {
                xp = tregion.ChunkManager.GetTops(tx + 1, ty).Key;
                xm = tregion.ChunkManager.GetTops(tx - 1, ty).Key;
                yp = tregion.ChunkManager.GetTops(tx, ty + 1).Key;
                ym = tregion.ChunkManager.GetTops(tx, ty - 1).Key;
            }
            byte[] bits       = bitters.Key;
            byte[] bits_trans = bitters.Value;
            if (bits == null || bits_trans == null)
            {
                return(null);
            }
            for (int x = 0; x < Constants.CHUNK_WIDTH; x++)
            {
                for (int y = 0; y < Constants.CHUNK_WIDTH; y++)
                {
                    int           ind  = tregion.TopsHigherBlockIndex(x, y);
                    ushort        mat  = Utilities.BytesToUshort(Utilities.BytesPartial(bits, ind * 2, 2));
                    MaterialImage imag = MaterialImages[mat];
                    if (fullzoom)
                    {
                        for (int sx = 0; sx < TexWidth; sx++)
                        {
                            for (int sy = 0; sy < TexWidth; sy++)
                            {
                                FastColor fc = imag.GetAt(sx, sy);
                                fc.A = 255;
                                for (int i = 3; i >= 0; i--)
                                {
                                    ushort smat = Utilities.BytesToUshort(Utilities.BytesPartial(bits_trans, (ind * 4 + i) * 2, 2));
                                    if (smat != 0)
                                    {
                                        MaterialImage simag = MaterialImages[smat];
                                        FastColor     fc2   = simag.GetAt(sx, sy);
                                        fc = Blend(fc2, fc);
                                    }
                                }
                                bmp.SetAt(x * TexWidth + sx, y * TexWidth + sy, fc);
                            }
                        }
                    }
                    else
                    {
                        int       height = Utilities.BytesToInt(Utilities.BytesPartial(bits, CWCW2 + ind * 4, 4));
                        FastColor fc     = imag.GetAt(0, 0);
                        fc.A = 255;
                        for (int i = 3; i >= 0; i--)
                        {
                            ushort smat = Utilities.BytesToUshort(Utilities.BytesPartial(bits_trans, ind * 2 * 4, 2));
                            if (smat != 0)
                            {
                                MaterialImage simag = MaterialImages[smat];
                                FastColor     fc2   = simag.Colors[0];
                                fc = Blend(fc2, fc);
                            }
                        }
                        FastColor lightened = fc;
                        lightened.R = (byte)Math.Min(lightened.R + 20, 255);
                        lightened.G = (byte)Math.Min(lightened.G + 20, 255);
                        lightened.B = (byte)Math.Min(lightened.B + 20, 255);
                        FastColor darkened = fc;
                        darkened.R = (byte)Math.Max(darkened.R - 20, 0);
                        darkened.G = (byte)Math.Max(darkened.G - 20, 0);
                        darkened.B = (byte)Math.Max(darkened.B - 20, 0);
                        FastColor doublelightened = fc;
                        doublelightened.R = (byte)Math.Min(doublelightened.R + 40, 255);
                        doublelightened.G = (byte)Math.Min(doublelightened.G + 40, 255);
                        doublelightened.B = (byte)Math.Min(doublelightened.B + 40, 255);
                        FastColor doubledarkened = fc;
                        doubledarkened.R = (byte)Math.Max(doubledarkened.R - 40, 0);
                        doubledarkened.G = (byte)Math.Max(doubledarkened.G - 40, 0);
                        doubledarkened.B = (byte)Math.Max(doubledarkened.B - 40, 0);
                        int relxp = x + 1 < Constants.CHUNK_WIDTH ? Utilities.BytesToInt(Utilities.BytesPartial(bits, CWCW2 + tregion.TopsHigherBlockIndex(x + 1, y) * 4, 4))
                            : (xp == null ? height : Utilities.BytesToInt(Utilities.BytesPartial(xp, CWCW2 + tregion.TopsHigherBlockIndex(0, y) * 4, 4)));
                        int relyp = y + 1 < Constants.CHUNK_WIDTH ? Utilities.BytesToInt(Utilities.BytesPartial(bits, CWCW2 + tregion.TopsHigherBlockIndex(x, y + 1) * 4, 4))
                            : (yp == null ? height : Utilities.BytesToInt(Utilities.BytesPartial(yp, CWCW2 + tregion.TopsHigherBlockIndex(x, 0) * 4, 4)));
                        int relxm = x - 1 >= 0 ? Utilities.BytesToInt(Utilities.BytesPartial(bits, CWCW2 + tregion.TopsHigherBlockIndex(x - 1, y) * 4, 4))
                            : (xm == null ? height : Utilities.BytesToInt(Utilities.BytesPartial(xm, CWCW2 + tregion.TopsHigherBlockIndex(Constants.CHUNK_WIDTH - 1, y) * 4, 4)));
                        int relym = y - 1 >= 0 ? Utilities.BytesToInt(Utilities.BytesPartial(bits, CWCW2 + tregion.TopsHigherBlockIndex(x, y - 1) * 4, 4))
                            : (ym == null ? height : Utilities.BytesToInt(Utilities.BytesPartial(ym, CWCW2 + tregion.TopsHigherBlockIndex(x, Constants.CHUNK_WIDTH - 1) * 4, 4)));
                        bmp.SetAt(x * 4 + 0, y * 4 + 0, ((relym < height) ? ((relxm < height) ? doublelightened : (relxm > height ? fc : lightened)) :
                                                         ((relym > height) ? ((relxm < height) ? fc : ((relxm > height) ? doubledarkened : darkened)) : ((relxm < height) ? lightened : ((relxm > height) ? darkened : fc)))));
                        bmp.SetAt(x * 4 + 1, y * 4 + 0, (relym < height) ? lightened : ((relym > height) ? darkened : fc));
                        bmp.SetAt(x * 4 + 2, y * 4 + 0, (relym < height) ? lightened : ((relym > height) ? darkened : fc));
                        bmp.SetAt(x * 4 + 3, y * 4 + 0, (relym < height) ? ((relxp < height) ? doublelightened : ((relxp > height) ? fc : lightened)) :
                                  ((relym > height) ? ((relxp < height) ? fc : ((relxp > height) ? doubledarkened : darkened)) : ((relxp < height) ? lightened : ((relxp > height) ? darkened : fc))));
                        bmp.SetAt(x * 4 + 0, y * 4 + 1, (relxm < height) ? lightened : ((relxm > height) ? darkened : fc));
                        bmp.SetAt(x * 4 + 1, y * 4 + 1, fc);
                        bmp.SetAt(x * 4 + 2, y * 4 + 1, fc);
                        bmp.SetAt(x * 4 + 3, y * 4 + 1, (relxp < height) ? lightened : ((relxp > height) ? darkened : fc));
                        bmp.SetAt(x * 4 + 0, y * 4 + 2, (relxm < height) ? lightened : ((relxm > height) ? darkened : fc));
                        bmp.SetAt(x * 4 + 1, y * 4 + 2, fc);
                        bmp.SetAt(x * 4 + 2, y * 4 + 2, fc);
                        bmp.SetAt(x * 4 + 3, y * 4 + 2, (relxp < height) ? lightened : ((relxp > height) ? darkened : fc));
                        bmp.SetAt(x * 4 + 0, y * 4 + 3, (relxm < height) ? ((relyp < height) ? doublelightened : ((relyp > height) ? fc : lightened)) :
                                  ((relxm > height) ? ((relyp < height) ? lightened : ((relyp > height) ? doubledarkened : darkened)) : ((relyp < height) ? lightened : ((relyp > height) ? darkened : fc))));
                        bmp.SetAt(x * 4 + 1, y * 4 + 3, (relyp < height) ? lightened : ((relyp > height) ? darkened : fc));
                        bmp.SetAt(x * 4 + 2, y * 4 + 3, (relyp < height) ? lightened : ((relyp > height) ? darkened : fc));
                        bmp.SetAt(x * 4 + 3, y * 4 + 3, (relxp < height) ? ((relyp < height) ? doublelightened : ((relyp > height) ? fc : lightened))
                            : ((relxp > height) ? ((relyp < height) ? fc : ((relyp > height) ? doubledarkened : darkened)) : ((relyp < height) ? lightened : ((relyp > height) ? darkened : fc))));
                    }
                }
            }
            // TODO: Add entity icons? (Trees in particular!)
            return(MatImgToPng(bmp));
        }