Tiled map editor

I’ve been using this for some while now so thought I’d post the link, so those of you that haven’t already taken advantage of it can do so. It’s a standalone tile map editor that is stupidly easy to use and thanks to Nick Gravelyn’s excellent TiledLib library, stupidly easy to incorporate into your XNA projects.

Whilst it’s nice to develop your own range of development tools, I’m a big believer in making life easy for yourself where you can! Sure I could write my own tile engine in XNA or Winforms, but I couldn’t do it this well and it would take me an age…time that could be better spent on other areas of my projects.

Anyway check out Tiled and Nick’s superb library, they’re both really rather good! 🙂

Selecting a region within an Image

The following code snippet shows you how to draw a selection rectangle over the top of an image and crop it accordingly.

You’ll need to add a Button and a PictureBox to a Form.

Click and drag over the PictureBox to select an area and when you’re ready, click the button and it will perform the crop and save the cropped selection as a new image. This follows on from my last post, have a play around with these methods and explore further!



using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private Point startPoint = new Point();  //the point(x,y) we start drawing our rectange
        private Rectangle myRectangle = new Rectangle();  //a rectangle

        public Form1()
        {
            InitializeComponent();
        }

        private void pictureBox1_MouseEnter(object sender, EventArgs e)
        {
            this.Cursor = Cursors.Cross;
        }

        private void pictureBox1_MouseLeave(object sender, EventArgs e)
        {
            this.Cursor = Cursors.Default;
        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            startPoint.X = e.X;  //start point gets mouse coords
            startPoint.Y = e.Y;
        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)  //are we holding the left mouse button?
            {
                Point endPoint = new Point();  //the end point (x,y) of our rectangle
                Pen p = new Pen(Brushes.Red);  //a red pen
                Graphics g = pictureBox1.CreateGraphics();

                endPoint.X = e.X;  //end point gets mouse coords
                endPoint.Y = e.Y;

                pictureBox1.Refresh();  //stop flicker and actually display rectangle

                Size myRectSize = new Size(endPoint.X - startPoint.X, endPoint.Y - startPoint.Y);  //calculate the size of our rectangle
                myRectangle = new Rectangle(startPoint, myRectSize);  //assign new rectangle object
                g.DrawRectangle(p, myRectangle);  //and draw it!
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Image myImage = CropImage(pictureBox1.Image, myRectangle);  //crop the image
            myImage.Save("C:\\testPic.png", ImageFormat.Png);  //save it
        }

        private static Image CropImage(Image imageToCrop, Rectangle rect)
        {
            Bitmap b = new Bitmap(imageToCrop);  //new bmp
            Image croppedImage = b.Clone(rect, b.PixelFormat);  //copy a section of the original

            return croppedImage;
        }
    }
}

Image resizing and cropping

A couple of methods to demonstrate the resizing and cropping of images.


private static Image ResizeImage(Image imageToResize, Size newSize)
{
    Bitmap b = new Bitmap(newSize.Width, newSize.Height);  //new bitmap
    Graphics g = Graphics.FromImage((Image)b);  //new graphics object 

    g.InterpolationMode = InterpolationMode.HighQualityBicubic;  //change this depending expanding/shrinking etc..
    g.DrawImage(imageToResize, 0, 0, newSize.Width, newSize.Height);  //draw the new image
    g.Dispose();  //done now thanks.

    return (Image)b;
}

You can of course use GetThumbnail in some instances and avoid all of this convolution, however using the interpolation method above will maintain far better image quality.


private static Image CropImage(Image imageToCrop, Rectangle rect)
{
    Bitmap b = new Bitmap(imageToCrop);  //new bmp
    Image croppedImage = b.Clone(rect, b.PixelFormat);  //copy a section of the original

    return croppedImage;
}

Scrolling a picturebox

Can’t be bothered extending the picturebox control to allow scrolling?…me either! Dump a panel on a form and set it’s ‘AutoScroll’ property to true, now place a picturebox on this panel and set it’s SizeMode to ‘AutoSize’. And there you have it, a scrollable picturebox without writing a single line of code!…just the way I like it! 🙂

ISO 6346 – Shipping Container Codes

The following link explains how to perform check digit calculations for the validation of shipping container codes.

Below is some code based on the calculation steps shown in the above wikipedia page, it validates the check digit, so the complete container number (including check digit) should be entered in the textbox.

Just drop a button and textbox on a form and wire up the event handlers:

public Dictionary<char, int> AlphabetCodes = new Dictionary<char, int>();
public List<int> PowerOfMultipliers = new List<int>();

private void Form1_Load(object sender, EventArgs e)
{
    int step = 10;

    //populate dictionary...
    //...create a dictionary entry for all letters of the alphabet using their Ascii value to identify them.
    //if you subtract their ascii value by the value of the first alpha ascii character (in this case 65 for
    //uppercase 'A'), it will give you it's position in the alphabet, Add 10 to this and skip over all multiples
    //of 11 to give you ISO Owner Code numbers for each letter.
    for (int i = 65; i < 91; i++)
    {
        char c = (char)i;
        int pos = i - 65 + step;

        if (c == 'A' || c == 'K' || c == 'U')  //omit multiples of 11.
            step += 1;

        AlphabetCodes.Add(c, pos);  //add to dictionary
    }

    //populate list...
    //create a list of 10, 2^x numbers for calculation.  List should contain 1, 2, 4, 8, 16, 32, 64 etc..
    for (int i = 0; i < 10; i++)
    {
        int result = (int)Math.Pow(2, i);  //power of 2 calculation.
        PowerOfMultipliers.Add(result);  //add to list.
    }
}

private void button1_Click(object sender, EventArgs e)
{
    int total = 0;

    if (textBox1.Text.Length == 11)  //container numbers must be 11 characters long.
    {
        for (int i = 0; i < 10; i++)  //loop through the first 10 characters (the 11th is the check digit!).
        {
            if (AlphabetCodes.ContainsKey(textBox1.Text[i]))  //if the current character is in the dictionary.
                total += (AlphabetCodes[textBox1.Text[i]] * PowerOfMultipliers[i]);  //add it's value to the total.
            else
            {
                int serialNumber = (int)textBox1.Text[i] - 48;  //it must be a number, so get the number from the char ascii value.
                total += (serialNumber * PowerOfMultipliers[i]);  //and add it to the total.
            }
        }

        int checkDigit = (int)total % 11;  //this should give you the check digit

        //The check digit shouldn't equal 10 according to ISO best practice - BUT there are containers out there that do, so we'll
        //double check and set the check digit to 0...again according to ISO best practice.
        if (checkDigit == 10)
            checkDigit = 0;

        if (checkDigit != (int)textBox1.Text[10] - 48)  //check digit should equal the last character in the textbox.
            MessageBox.Show("Container Number NOT Valid");
        else
            MessageBox.Show("Container Number Valid");
    }
    else
    {
        MessageBox.Show("Container Number must be 11 characters in length");
    }
}

Pocket PC – Actually closing a form

You would be forgiven for thinking that clicking on the ‘X’ in the top right of your form would close it, as per all standard Windows applications…but be warned this is NOT the case with Pocket PC applications! I’m not sure what the wisdom is behind this decision, I guess it doesn’t really matter, I just wish it were more obvious!

Anyway, clicking the cross does nothing more than minimise your form, in order to fully close it, you must set it’s ‘MinimizeBox’ property to false. This will in turn display an ‘ok’ button instead of a ‘X’ at the top of your form, and it is clicking this ‘ok’ button that fires the form closing events!…obvious when you think about it!…hmmmmm.

So there’s an hour of my life I’ll never get back! Thanks Microsoft.

Sending raw data to a printer

An awesome printer helper class for sending raw data to a printer. I have found this very useful for sending control codes to our Datamax label printers at work for barcode printing etc.

I added an additional method to the helper class (bodged together from the existing ones!) that accepts a memory stream instead of a file or string.

public static bool SendStreamToPrinter(string szPrinterName, MemoryStream ms, string DocName)
{
    // Open the file.
    //FileStream fs = new FileStream(szFileName, FileMode.Open);
    // Create a BinaryReader on the file.
    BinaryReader br = new BinaryReader(ms);
    // Dim an array of bytes big enough to hold the file's contents.
    Byte[] bytes = new Byte[ms.Length];
    bool bSuccess = false;
    // Your unmanaged pointer.
    IntPtr pUnmanagedBytes = new IntPtr(0);
    int nLength;

    nLength = Convert.ToInt32(ms.Length);
    // Read the contents of the file into the array.
    bytes = br.ReadBytes(nLength);
    // Allocate some unmanaged memory for those bytes.
    pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
    // Copy the managed byte array into the unmanaged array.
    Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
    // Send the unmanaged bytes to the printer.
    bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength, DocName);
    // Free the unmanaged memory that you allocated earlier.
    Marshal.FreeCoTaskMem(pUnmanagedBytes);
    return bSuccess;
}

SharpZipLib compression in C#

I have recently been playing around with SharpZipLib, an open source compression library for C#.

Below is some code demonstrating how to recursively zip folders and subfolders. If an exception is thrown (i.e if a file is open when you try and zip it), it copies the file to a temp directory and zips it from there.

public static void ZipFolder(string Root, string CurrentFolder, ZipOutputStream ZipStream)
{
    string[] SubFolders = Directory.GetDirectories(CurrentFolder);

    foreach (string Folder in SubFolders)
    {
        ZipFolder(Root, Folder, ZipStream);
    }

    string path = CurrentFolder.Substring(Root.Length) + "/";

    if (path.Length > 1)
    {
        ZipEntry zEntry;
        zEntry = new ZipEntry(path);
        zEntry.DateTime = DateTime.Now;
    }

    foreach (string file in Directory.GetFiles(CurrentFolder))
    {
        ZipFile(ZipStream, path, file);
    }
}

private static void ZipFile(ZipOutputStream ZipStream, string path, string file)
{
    try
    {
        byte[] buffer = new byte[4096];
        string filePath = (path.Length > 1 ? path : string.Empty) + Path.GetFileName(file);
        ZipEntry zEntry = new ZipEntry(filePath);

        zEntry.DateTime = DateTime.Now;

        ZipStream.PutNextEntry(zEntry);

        using (FileStream fs = File.OpenRead(file))
        {
            int sourceBytes;
            do
            {
                sourceBytes = fs.Read(buffer, 0, buffer.Length);
                ZipStream.Write(buffer, 0, sourceBytes);
            }
            while (sourceBytes > 0);
        }
    }
    catch (Exception)
    {
        if (File.Exists(file))
        {
            File.Copy(file, @"C:\TEMP\" + Path.GetFileName(file), true);
            ZipFile(ZipStream, path, @"C:\TEMP\" + Path.GetFileName(file));
        }
    }
}

Create a thumbnail image from a ByteArray

So you have an image saved to your database as a byte array, below is a neat little method that accepts it as a parameter, converts it to a thumbnail and spit it back out as a byte array.

public static byte[] MakeThumbnail(byte[] myImage, int thumbWidth, int thumbHeight)
{
    using (MemoryStream ms = new MemoryStream())
    using (Image thumbnail = Image.FromStream(new MemoryStream(myImage)).GetThumbnailImage(thumbWidth, thumbHeight, null, new IntPtr()))
    {
        thumbnail.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
        return ms.ToArray();
    }
}