50% OFF!!!

Monday, November 22, 2010

Bootstrapper Package | Visual Studio 2010 | Microsoft .NET Framework Version 2.0 Redistributable


After long searching & reading, I created Bootstrapper package for using prerequisites on my setup project for my dot.net 2.0 application.

First of all, there must exist the Microsoft .NET Framework Version 2.0 Redistributable packages installation files:
1. dotnetfx.exe - for x86 (download here)
2. NetFx64.exe - for x64 (download here)
3. NetFx64.exe - for IA64-Itanium (download here)

Let's rename the files (respectively) so they will be more readable:
1. dotnetfx_x86.exe (for x86)
2. NetFx64_x64.exe (for x64)
3. NetFx64_IA64.exe (for IA64-Itanium)

Now, we have to create new Bootstrapper Package for this cause Visual Studio 2010 not contains in its setup prerequisites the Microsoft .NET Framework Version 2.0.

First we create a folder on C:\ and then copy the finished folder to the Bootstrapper folder.

Step 1
Create a folder under C:\ and name it DotNetFx20
Inside DotNetFx20, create:
a. copy the 3 downloaded Redistributable files to it (dotnetfx_x86.exe, NetFx64_x64.exe, NetFx64_IA64.exe)
b. create an (empty) XML file named Product.xml (will be edited later)
c. create a folder named en (for english locale) and create an (empty) XML file named package.xml

Step 2
[Expand/Collapse] Edit file Product.xml:

Step 3
[Expand/Collapse] Edit file package.xml:

Step 4
Copy the folder DotNetFx20 to the Bootstrapper packages folder which is under:
C:\Program Files\Microsoft SDKs\Windows\v7.0A\Bootstrapper\Packages\


Step 5
That's it.. :)

Here is the whole Bootstrapper Package ready-to-use folder to download without (dotnetfx_x86.exe, NetFx64_x64.exe, NetFx64_IA64.exe) which can be downloaded from MSDN directly (links above):
download here (updated file)

Update (29.11.2010):
There was problem with the Product.xml file, so file updated and also zip file for downloading. The filenames did NOT match...





Regards,
MDB-Blog


Sunday, November 14, 2010

C# | Winforms | Textbox within Button

Here is an example for creating a Button control which contains a Textbox inside it.
This is very usefull when the button functionality is based (only) on the textbox content text, and it is very usefull for the user.

Screenshot (image) example:


The Code:
class ButtonWithTextbox : Button
{
    TextBox _textbox = new TextBox();

    public int TextboxWidth
    {
        get { return _textbox.Width; }
        set { _textbox.Width = value; }
    }
    public Point TextboxLocation
    {
        get { return _textbox.Location; }
        set { _textbox.Location = value; }
    }
    /** And we may add all properties of the Textbox ***/

    public ButtonWithTextbox()
    {
        this.Controls.Add(_textbox);
    }
}

Also work great on the designer... :)

MDB-Blog
http://mdb-blog.blogspot.com

Wednesday, October 6, 2010

C# | How to deskew an image

I found this code on CodeProject site:
http://www.codeproject.com/KB/graphics/Deskew_an_Image.aspx
By mackenb | 25 Apr 2006

The article describes an algorithm to calculate the skew angle of an image.

This is converted to C#: (tested and working)
The Code:
using System.Drawing;
using System.Drawing.Imaging;
using System;
using System.Diagnostics;


public class gmseDeskew
{
    // Representation of a line in the image.
    public class HougLine
    {
        //' Count of points in the line.
        public int Count;
        //' Index in Matrix.
        public int Index;
        //' The line is represented as all x,y that solve y*cos(alpha)-x*sin(alpha)=d
        public double Alpha;
        public double d;
    }

    // The Bitmap
    Bitmap cBmp;
    // The range of angles to search for lines
    double cAlphaStart = -20;
    double cAlphaStep = 0.2;
    int cSteps = 40 * 5;
    // Precalculation of sin and cos.
    double[] cSinA;
    double[] cCosA;
    // Range of d
    double cDMin;
    double cDStep = 1;
    int cDCount;
    // Count of points that fit in a line.
    int[] cHMatrix;

    // calculate the skew angle of the image cBmp

    public double GetSkewAngle()
    {
        HougLine[] hl;
        int i;
        double sum = 0;
        int count = 0;

        //' Hough Transformation
        Calc();
        //' Top 20 of the detected lines in the image.
        hl = GetTop(20);
        //' Average angle of the lines
        for (i = 0; i < 19; i++)      
        {          
             sum += hl[i].Alpha;
             count += 1;
         }
         return sum / count;
     }

     //    ' Calculate the Count lines in the image with most points.
    private HougLine[] GetTop(int Count)
     {
         HougLine[] hl;
         int j;
         HougLine tmp;
         int AlphaIndex, dIndex;
         hl = new HougLine[Count];
         for (int i = 0; i < Count; i++)
         {
             hl[i] = new HougLine();
         }
         for (int i = 0; i < cHMatrix.Length - 1; i++)
         {
             if (cHMatrix[i] > hl[Count - 1].Count)
            {
                hl[Count - 1].Count = cHMatrix[i];
                hl[Count - 1].Index = i;
                j = Count - 1;
                while (j > 0 && hl[j].Count > hl[j - 1].Count)
                {
                    tmp = hl[j];
                    hl[j] = hl[j - 1];
                    hl[j - 1] = tmp;
                    j -= 1;
                }
            }
        }
        for (int i = 0; i < Count; i++)
         {
             dIndex = hl[i].Index / cSteps;
             AlphaIndex = hl[i].Index - dIndex * cSteps;
             hl[i].Alpha = GetAlpha(AlphaIndex);
             hl[i].d = dIndex + cDMin;
         }
         return hl;
     }
     public void New(Bitmap bmp)
     {
         cBmp = bmp;
     }

     //    ' Hough Transforamtion:
     private void Calc()
     {
         int x;
         int y;
         int hMin = cBmp.Height / 4;
         int hMax = cBmp.Height * 3 / 4;
         Init();
         for (y = hMin; y < hMax; y++)
         {
             for (x = 1; x < cBmp.Width - 2; x++)
             {
                 //' Only lower edges are considered.
                 if (IsBlack(x, y) == true)
                 {
                     if (IsBlack(x, y + 1) == false)
                     {
                         Calc(x, y);
                     }
                 }
             }
         }
     }

     //    ' Calculate all lines through the point (x,y).
     private void Calc(int x, int y)
     {
         double d;
         int dIndex;
         int Index;
         for (int alpha = 0; alpha < cSteps - 1; alpha++)
         {
             d = y * cCosA[alpha] - x * cSinA[alpha];
             dIndex = (int)CalcDIndex(d);
             Index = dIndex * cSteps + alpha;

             try
             {
                 cHMatrix[Index] += 1;
             }
             catch (Exception ex)
             {
                 Debug.WriteLine(ex.ToString());
             }
         }
     }
     private double CalcDIndex(double d)
     {
         return Convert.ToInt32(d - cDMin);
     }
     private bool IsBlack(int x, int y)
     {
         Color c;
         double luminance;
         c = cBmp.GetPixel(x, y);
         luminance = (c.R * 0.299) + (c.G * 0.587) + (c.B * 0.114);
         return luminance < 140;
     }
     private void Init()
     {
         double angle;
         //' Precalculation of sin and cos.
         cSinA = new double[cSteps - 1];
         cCosA = new double[cSteps - 1];
         for (int i = 0; i < cSteps - 1; i++)
         {
             angle = GetAlpha(i) * Math.PI / 180.0;
             cSinA[i] = Math.Sin(angle);
             cCosA[i] = Math.Cos(angle);
         }
         //' Range of d
:         cDMin = -cBmp.Width;
         cDCount = (int)(2 * (cBmp.Width + cBmp.Height) / cDStep);
         cHMatrix = new int[cDCount * cSteps];
     }
     public double GetAlpha(int Index)
     {
         return cAlphaStart + Index * cAlphaStep;
     }     public static Bitmap RotateImage(Bitmap bmp, double angle)
     {
         Graphics g;
         Bitmap tmp = new Bitmap(bmp.Width, bmp.Height, PixelFormat.Format32bppRgb);
         tmp.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);
         g = Graphics.FromImage(tmp);
         try       
         {
             g.FillRectangle(Brushes.White, 0, 0, bmp.Width, bmp.Height);
             g.RotateTransform((float)angle);
             g.DrawImage(bmp, 0, 0);
         }
         finally
         {
             g.Dispose();
         }
         return tmp;
     }
 }


enjoy...

Monday, October 4, 2010

Trim Image white-spaces (black&white) | C# Winforms

I searched for a simple code that preform "TRIMMING" to an image.
By "trimming" i mean, that if i have a LARGE image that contains information (painting/drawing...) only in small part of the image and all other is white-space (WHITE or BLACK pixels).

I needed to remove such whitespace and also to decrease image size.
Following three code examples:

Code #1 - Gets the NON-WHITE-SPACE bounds of an image
private Rectangle GetImageNonWhiteSpaceBounds(Bitmap p_img, bool p_isBlackWhitespace)
{
    Rectangle rect = new Rectangle();
    unsafe
    {
        BitmapData bdActual = null;
        try
        {
            int width = p_img.Width;
            int height = p_img.Height;

            bdActual = p_img.LockBits(new Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
            Int32 i;
            Int32 pSize = 3;
            Byte whiteTrashold = (Byte)240;
            Byte blackTrashold = (Byte)10;
            Byte* sourceRow;

            Int32 minX = width;
            Int32 maxX = 0;
            Int32 minY = height;
            Int32 maxY = 0;
            bool isWhitepace;

            for (Int32 _y = 0; _y < height; ++_y)             {                 sourceRow = (Byte*)bdActual.Scan0 + (_y * bdActual.Stride);                 for (Int32 _x = 0; _x < width; ++_x)                 {                     i = _x * pSize;                     isWhitepace =                         (p_isBlackWhitespace && sourceRow[i] <= blackTrashold && sourceRow[i + 1] <= blackTrashold && sourceRow[i + 2] <= blackTrashold)                         ||                         (!p_isBlackWhitespace && sourceRow[i] >= whiteTrashold && sourceRow[i + 1] >= whiteTrashold && sourceRow[i + 2] >= whiteTrashold);

                    if (isWhitepace == false)
                    {
                        // NO whitespace!!!
                        minX = Math.Min(_x, minX);
                        maxX = Math.Max(_x, maxX);

                        minY = Math.Min(_y, minY);
                        maxY = Math.Max(_y, maxY);
                    }
                }
            }

            rect.X = minX;
            rect.Y = minY;
            rect.Width = maxX - minX;
            rect.Height = maxY - minY;
        }
        finally
        {
            if (bdActual != null)
            {
                p_img.UnlockBits(bdActual);
            }
        }
    }
    return rect;
}

Code #2 - Draw rectangle around the NON-WHITE-SPACE
private void DrawNonWhiteSpaceRectangle(Bitmap p_img, bool p_isBlackWhitespace, Color p_color)
{
    unsafe
    {
        BitmapData bdActual = null;
        try
        {
            int width = p_img.Width;
            int height = p_img.Height;

            bdActual = p_img.LockBits(new Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            Int32 i;
            Int32 pSize = 3;
            Byte whiteTrashold = (Byte)240;
            Byte blackTrashold = (Byte)10;
            Byte* sourceRow;

            Int32 minX = width;
            Int32 maxX = 0;
            Int32 minY = height;
            Int32 maxY = 0;
            bool isWhitepace;

            for (Int32 _y = 0; _y < height; ++_y)             {                 sourceRow = (Byte*)bdActual.Scan0 + (_y * bdActual.Stride);                 for (Int32 _x = 0; _x < width; ++_x)                 {                     i = _x * pSize;                     isWhitepace =                         (p_isBlackWhitespace && sourceRow[i] <= blackTrashold && sourceRow[i + 1] <= blackTrashold && sourceRow[i + 2] <= blackTrashold)                         ||                         (!p_isBlackWhitespace && sourceRow[i] >= whiteTrashold && sourceRow[i + 1] >= whiteTrashold && sourceRow[i + 2] >= whiteTrashold);

                    if (isWhitepace == false)
                    {
                        // NO whitespace!!!
                        minX = Math.Min(_x, minX);
                        maxX = Math.Max(_x, maxX);

                        minY = Math.Min(_y, minY);
                        maxY = Math.Max(_y, maxY);
                    }
                }
            }

            // draw rectagle:
            for (Int32 _y = minY; _y <= maxY; ++_y)             {                 sourceRow = (Byte*)bdActual.Scan0 + (_y * bdActual.Stride);                 i = minX * pSize;                 sourceRow[i] = (Byte)p_color.R;                 sourceRow[i + 1] = (Byte)p_color.G;                 sourceRow[i + 2] = (Byte)p_color.B;                 i = maxX * pSize;                 sourceRow[i] = (Byte)p_color.R;                 sourceRow[i + 1] = (Byte)p_color.G;                 sourceRow[i + 2] = (Byte)p_color.B;             }             Byte* sourceRowX1 = (Byte*)bdActual.Scan0 + (minY * bdActual.Stride);             Byte* sourceRowX2 = (Byte*)bdActual.Scan0 + (maxY * bdActual.Stride);             for (Int32 _x = minX; _x <= maxX; ++_x)             {                 i = _x * pSize;                 sourceRowX1[i] = (Byte)p_color.R;                 sourceRowX1[i + 1] = (Byte)p_color.G;                 sourceRowX1[i + 2] = (Byte)p_color.B;                 sourceRowX2[i] = (Byte)p_color.R;                 sourceRowX2[i + 1] = (Byte)p_color.G;                 sourceRowX2[i + 2] = (Byte)p_color.B;             }         }         finally         {             if (bdActual != null)             {                 p_img.UnlockBits(bdActual);             }         }     } }


Code #3 - Trim Image whitespaces
private Bitmap CropImageWhitespaces(Bitmap p_img, bool p_isBlackWhitespace)
{
    Rectangle rect = new Rectangle();
    unsafe
    {
        BitmapData bdActual = null;
        try
        {
            int width = p_img.Width;
            int height = p_img.Height;

            bdActual = p_img.LockBits(new Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
            Int32 i;
            Int32 pSize = 3;
            Byte whiteTrashold = (Byte)240;
            Byte blackTrashold = (Byte)10;
            Byte* sourceRow;

            Int32 minX = width;
            Int32 maxX = 0;
            Int32 minY = height;
            Int32 maxY = 0;
            bool isWhitepace;

            for (Int32 _y = 0; _y < height; ++_y)             {                 sourceRow = (Byte*)bdActual.Scan0 + (_y * bdActual.Stride);                 for (Int32 _x = 0; _x < width; ++_x)                 {                     i = _x * pSize;                     isWhitepace =                         (p_isBlackWhitespace && sourceRow[i] <= blackTrashold && sourceRow[i + 1] <= blackTrashold && sourceRow[i + 2] <= blackTrashold)                         ||                         (!p_isBlackWhitespace && sourceRow[i] >= whiteTrashold && sourceRow[i + 1] >= whiteTrashold && sourceRow[i + 2] >= whiteTrashold);

                    if (isWhitepace == false)
                    {
                        // NO whitespace!!!
                        minX = Math.Min(_x, minX);
                        maxX = Math.Max(_x, maxX);

                        minY = Math.Min(_y, minY);
                        maxY = Math.Max(_y, maxY);
                    }
                }
            }

            rect.X = minX;
            rect.Y = minY;
            rect.Width = maxX - minX;
            rect.Height = maxY - minY;
        }
        finally
        {
            if (bdActual != null)
            {
                p_img.UnlockBits(bdActual);
            }
        }
    }

    return p_img.Clone(rect, p_img.PixelFormat);
}

I hope it will be helpful for you.
this code if fast and easy to use.