Archive for the 'Learn Everyday' Category



C# How to: Bitmap Pixel manipulation using LINQ Queries

Article Purpose

In this article we explore manipulating a  ’s underlying pixel data. The process of Pixel data manipulation at its core feature the implementation of Queries targeting raw pixel data.

Update: I’ve published a follow-up article – Part 2: The banner images in this article were generated using the concepts explored in the follow-up article. The source image has been licenced under the Creative Commons Attribution-Share Alike 3.0 Unported license and can be downloaded from .

Led_Banner1

Sample source code

This article is accompanied by a sample source code Visual Studio project which is available for download here.

Led_Banner2

Using the sample Application

This article’s associated sample source code defines a sample application, detailing the concepts explored by this article. The sample application implements two types of image filters: Swapping each pixel’s colour components and shifting pixels to different locations within the image data buffer.

The image shown below is a screenshot of the Bitmap Pixel Manipulation application in action:

BitmapPixelManipulation

The sample application allows the user to specify an input source image which can then be modified by implementing an image filter. If desired the user has the option to save the new/result image to the file system.

Led_Banner3

Extracting Pixel values from a Bitmap image

The sample source code defines the ArgbPixel class which is implemented to represent an individual pixel. The definition as follows:

public class ArgbPixel
{
    public byte blue = 0;
    public byte green = 0;
    public byte red = 0;
    public byte alpha = 0;

public ArgbPixel() { }
public ArgbPixel(byte[] colorComponents) { blue = colorComponents[0]; green = colorComponents[1]; red = colorComponents[2]; alpha = colorComponents[3]; }
public byte[] GetColorBytes() { return new byte[]{blue, green, red, alpha}; } }

Each pixel is defined by four member variables of type byte: blue, red, green and alpha. The ArgbPixel class defines an overloaded constructor which allows for creating an instance by specifying the four colour components as byte values. By invoking the GetColorBytes method the calling code can access the underlying colour component byte values in the form of a byte array.

Led_Banner1

The Colour Swap filter

The Colour swap filter acts as an image filter by implementing various combinations of swapping each individual pixel’s Alpha, Red, Green and Blue colour channels. The sample source code defines the ColorSwapType , intended to provide a collection of possible pixel colour channel swap operations. The code snippet listed below provides the definition of the ColorSwapType type:

public enum ColourSwapType
{
    ShiftRight,
    ShiftLeft,
    SwapBlueAndRed,
    SwapBlueAndRedFixGreen,
    SwapBlueAndGreen,
    SwapBlueAndGreenFixRed,
    SwapRedAndGreen,
    SwapRedAndGreenFixBlue
}

The following section provides an explanation of each Colour Swap method:

  • ShiftRight – Starting with Blue each colour channel’s value will be copied to the colour channel to the right.
  • ShiftLeft – Starting with Blue each colour channel’s value will be copied to the colour channel to the left.
  • SwapBlueAndRed – Blue and Red values are swapped, Green remains unchanged.
  • SwapBlueAndRedFixGreen – Blue and Red values are swapped, each pixel’s Green value is set to the same value as specified by the calling code.
  • SwapBlueAndGreen – Blue and Green values are swapped, Red remains unchanged.
  • SwapBlueAndGreenFixRed – Blue and Green values are swapped, each pixel’s Red value is set to the same value as specified by the calling code.
  • SwapRedAndGreen – Red and Green values are swapped, Blue remains unchanged.
  • SwapRedAndGreenFixBlue – Red and Green values are swapped, each pixel’s Blue value is set to the same value as specified by the calling code.

Led_Banner2

From a Bitmap buffer to a Pixel List

The sample source provides the definition for the GetPixelListFromBitmap method. The purpose behind this method is to read a ’s underlying colour component byte buffer data and create a generic collection of type ArgbPixel. By representing the data as a generic collection we are able implement query operations. The code snippet below details the GetPixelListFromBitmap method definition.

private static List<ArgbPixel> GetPixelListFromBitmap(Bitmap sourceImage)
{
     BitmapData sourceData = sourceImage.LockBits(new Rectangle(0, 0, 
                 sourceImage.Width, sourceImage.Height), 
                 ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

byte[] sourceBuffer = new byte[sourceData.Stride * sourceData.Height]; Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, sourceBuffer.Length); sourceImage.UnlockBits(sourceData);
List<ArgbPixel> pixelList = new List<ArgbPixel>(sourceBuffer.Length / 4);
using (MemoryStream memoryStream = new MemoryStream(sourceBuffer)) { memoryStream.Position = 0; BinaryReader binaryReader = new BinaryReader(memoryStream);
while (memoryStream.Position + 4 <= memoryStream.Length) { ArgbPixel pixel = new ArgbPixel(binaryReader.ReadBytes(4)); pixelList.Add(pixel); }
binaryReader.Close(); }
return pixelList; }

The GetPixelListFromBitmap accepts a parameter and returns a generic collection of type ArgbPixel. Within the method body the first operation performed involves locking the pixel data in memory by invoking the method. By locking data in memory we are in effect signalling the to not shift around in memory the underlying data whilst we are busy accessing the data.

Next, the sample source code implements the method in order to copy the ’s colour component data in the form of a byte array. Once we’ve copied the pixel data we can unlock the by invoking .

The final operation performed by the GetPixelListFromBitmap involves iterating through the byte array of colour components. With each loop we make use of a , reading four bytes at a time and passing the result to the overloaded constructor exposed by the ArgbPixel class.

Led_Banner3

Applying Linq queries to Pixel Data

This article’s sample source code implements queries through the SwapColors extension method which targets the Bitmap class. The definition is detailed by the following code snippet:

 public static Bitmap SwapColors(this Bitmap sourceImage, 
                                 ColourSwapType swapType, 
                                 byte fixedValue = 0)
{
     List<ArgbPixel> pixelListSource = GetPixelListFromBitmap(sourceImage);

List<ArgbPixel> pixelListResult = null;
switch (swapType) { case ColourSwapType.ShiftRight: { pixelListResult = (from t in pixelListSource select new ArgbPixel { blue = t.red, red = t.green, green = t.blue, alpha = t.alpha}).ToList(); break; } case ColourSwapType.ShiftLeft: { pixelListResult = (from t in pixelListSource select new ArgbPixel { blue = t.green, red = t.blue, green = t.red, alpha = t.alpha}).ToList(); break; } case ColourSwapType.SwapBlueAndRed: { pixelListResult = (from t in pixelListSource select new ArgbPixel { blue = t.red, red = t.blue, green = t.green, alpha = t.alpha}).ToList(); break; case ColourSwapType.SwapBlueAndRedFixGreen: { pixelListResult = (from t in pixelListSource select new ArgbPixel { blue = t.red, red = t.blue, green = fixedValue, alpha = t.alpha}).ToList(); break; } case ColourSwapType.SwapBlueAndGreen: { pixelListResult = (from t in pixelListSource select new ArgbPixel { blue = t.green, red = t.red, green = t.blue, alpha = t.alpha}).ToList(); break; } case ColourSwapType.SwapBlueAndGreenFixRed: { pixelListResult = (from t in pixelListSource select new ArgbPixel { blue = t.green, red = fixedValue, green = t.blue, alpha = t.alpha}).ToList(); break; } case ColourSwapType.SwapRedAndGreen: { pixelListResult = (from t in pixelListSource select new ArgbPixel { blue = t.blue, red = t.green, green = t.red, alpha = t.alpha}).ToList(); break; } case ColourSwapType.SwapRedAndGreenFixBlue: { pixelListResult = (from t in pixelListSource select new ArgbPixel { blue = fixedValue, red = t.green, green = t.red, alpha = t.alpha}).ToList(); break; } }
Bitmap resultBitmap = GetBitmapFromPixelList(pixelListResult, sourceImage.Width, sourceImage.Height);
return resultBitmap; }

The SwapColors extension method accepts as parameters an value of type ColourSwapType and a byte parameter fixedValue defined with a default value of 0.

The GetPixelListFromBitmap method discussed earlier is implemented in order to create a generic of type ArgbPixel. The bulk of the method’s implementation is performed next by applying a switch statement on the ColourSwapType parameter. The original List<ArgbPixel> collection is used to populate a resulting List<ArgbPixel> collection. Assignment from source to result collection occurs through a query implementing the relevant ColourSwapType.

The last operation performed by the SwapColors extension method involves converting the resulting List<ArgbPixel> collection back to a object through invoking the GetBitmapFromPixelList method. The following section provides a description of the GetBitmapFromPixelList method.

Led_Banner1

From a Pixel List to a Bitmap

In the sample source code the GetPixelListFromBitmap method discussed earlier, is complimented by its inverse, the GetBitmapFromPixelList method. As the name implied the GetBitmapFromPixelList method’s purpose is to convert a generic of type ArgbPixel to a object. The definition as follows:

private static Bitmap GetBitmapFromPixelList(List<ArgbPixel> pixelList, int width, int height)
{
     Bitmap resultBitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);

BitmapData resultData = resultBitmap.LockBits(new Rectangle(0, 0, resultBitmap.Width, resultBitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
byte[] resultBuffer = new byte[resultData.Stride * resultData.Height];
using (MemoryStream memoryStream = new MemoryStream(resultBuffer)) { memoryStream.Position = 0; BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
foreach (ArgbPixel pixel in pixelList) { binaryWriter.Write(pixel.GetColorBytes()); }
binaryWriter.Close(); }
Marshal.Copy(resultBuffer, 0, resultData.Scan0, resultBuffer.Length); resultBitmap.UnlockBits(resultData);
return resultBitmap; }

The GetBitmapFromPixelList method accepts as parameters a generic of type ArgbPixel, width and height of type int. The width and height parameters indicates the size of the original , which will be used when creating a new resulting .

The first step performed by the GetBitmapFromPixelList method is to create a resulting object and locking into memory the underlying data by invoking the method.

The bulk of the work performed by the GetBitmapFromPixelList method occurs in the form of iterating the List of ArgbPixel parameter and writing the Pixel’s underlying colour components to a byte buffer related to the resulting .

In the last step being performed byte array of colour component data is copied to the resulting by invoking .

Led_Banner2

Reversing a List of Pixels

As an additional example the sample source code also defines the FlipPixels extension method. This method provides a quick implementation of turning a image upside down. The implementation as follows:

public static Bitmap FlipPixels(this Bitmap sourceImage)
{
     List<ArgbPixel> pixelList = GetPixelListFromBitmap(sourceImage);

pixelList.Reverse();
Bitmap resultBitmap = GetBitmapFromPixelList(pixelList, sourceImage.Width, sourceImage.Height);
return resultBitmap; }

The FlipPixels extension method targets the class and returns a object. As discussed earlier the method invokes the GetPixelListFromBitmap and GetBitmapFromPixelList methods. Reversing the order of the ArgbPixel objects is achieved through invoking the method.

Led_Banner3

Filter implementation examples

This section contains the eye candy of this article. The following set of images were created from a single input source image. The original image is licensed under the Creative Commons Attribution 2.0 Generic license and can be downloaded from Wikipedia.

The Original Image

SunflowerSunset2

Shift Left

ShiftLeft

Shift Right

ShiftRight

Swap Blue and Red

SwapBlueAndRed

Swap Blue and Red, fix Green at 0

SwapBlueAndRedFixGreen0

Swap Blue and Green

SwapBlueAndGreen

Swap Blue and Green, fix Red at 25

SwapBlueAndGreenFixRed25

Swap Red and Green

SwapRedAndGreen

Swap Red and Green, fix Blue at 0

SwapRedAndGreenFixBlue0

Swap Red and Green, fix Blue at 115

SwapRedAndGreenFixBlue115

Swap Red and Green, fix Blue at 200

SwapRedAndGreenFixBlue200

C# How to: Bitmap Colour Substitution implementing thresholds

Article Purpose

This article is aimed at detailing how to implement the process of substituting the colour values that form part of a image. Colour substitution is implemented by means of a threshold value. By implementing a threshold a range of similar colours can be substituted.

Sample source code

This article is accompanied by a sample source code Visual Studio project which is available for download here.

Using the sample Application

The provided sample source code builds a Windows Forms application which can be used to test/implement the concepts described in this article. The sample application enables the user to load an file from the file system, the user can then specify the colour to replace, the replacement colour and the threshold to apply. The following image is a screenshot of the sample application in action.

BitmapColourSubstitution_Scaled

The scenario detailed in the above screenshot shows the sample application being used to create an where the sky has more of a bluish hue when compared to the original .

Notice how replacement colour does not simply appear as a solid colour applied throughout. The replacement colour gets implemented matching the intensity of the colour being substituted.

The colour filter options:

FilterOptions

The colour to replace was taken from the original , the replacement colour is specified through a colour picker dialog. When a user clicks on either displayed, the colour of the pixel clicked on sets the value of the replacement colour. By adjusting the threshold value the user can specify how wide or narrow the range of colours to replace should be. The higher the threshold value, the wider the range of colours that will be replaced.

The resulting image can be saved by clicking the “Save Result” button. In order to apply another colour substitution on the resulting image click the button labelled “Set Result as Source”.

Colour Substitution Filter Data

The sample source code provides the definition for the ColorSubstitutionFilter class. The purpose of this class is to contain data required when applying colour substitution. The ColorSubstitutionFilter class is defined as follows:

public class ColorSubstitutionFilter
{
    private int thresholdValue = 10;
    public int ThresholdValue
    {
        get { return thresholdValue; }
        set { thresholdValue = value; }
    }

private Color sourceColor = Color.White; public Color SourceColor { get { return sourceColor; } set { sourceColor = value; } }
private Color newColor = Color.White; public Color NewColor { get { return newColor; } set { newColor = value; } } }

To implement a colour substitution filter we first have to create an object instance of type ColorSubstitutionFilter. A colour substitution requires specifying a SourceColor, which is the colour to replace/substitute and a NewColour, which defines the colour that will replace the SourceColour. Also required is a ThresholdValue, which determines a range of colours based on the SourceColor.

Colour Substitution implemented as an Extension method

The sample source code defines the ColorSubstitution extension method which targets the class. Invoking the ColorSubstitution requires passing a parameter of type ColorSubstitutionFilter, which defines how colour substitution is to be implemented. The following code snippet contains the definition of the ColorSubstitution method.

public static Bitmap ColorSubstitution(this Bitmap sourceBitmap, ColorSubstitutionFilter filterData)
{
    Bitmap resultBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height, PixelFormat.Format32bppArgb);

BitmapData sourceData = sourceBitmap.LockBits(new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); BitmapData resultData = resultBitmap.LockBits(new Rectangle(0, 0, resultBitmap.Width, resultBitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
byte[] resultBuffer = new byte[resultData.Stride * resultData.Height]; Marshal.Copy(sourceData.Scan0, resultBuffer, 0, resultBuffer.Length);
sourceBitmap.UnlockBits(sourceData);
byte sourceRed = 0, sourceGreen = 0, sourceBlue = 0, sourceAlpha = 0; int resultRed = 0, resultGreen = 0, resultBlue = 0;
byte newRedValue = filterData.NewColor.R; byte newGreenValue = filterData.NewColor.G; byte newBlueValue = filterData.NewColor.B;
byte redFilter = filterData.SourceColor.R; byte greenFilter = filterData.SourceColor.G; byte blueFilter = filterData.SourceColor.B;
byte minValue = 0; byte maxValue = 255;
for (int k = 0; k < resultBuffer.Length; k += 4) { sourceAlpha = resultBuffer[k + 3];
if (sourceAlpha != 0) { sourceBlue = resultBuffer[k]; sourceGreen = resultBuffer[k + 1]; sourceRed = resultBuffer[k + 2];
if ((sourceBlue < blueFilter + filterData.ThresholdValue && sourceBlue > blueFilter - filterData.ThresholdValue) &&
(sourceGreen < greenFilter + filterData.ThresholdValue && sourceGreen > greenFilter - filterData.ThresholdValue) &&
(sourceRed < redFilter + filterData.ThresholdValue && sourceRed > redFilter - filterData.ThresholdValue)) { resultBlue = blueFilter - sourceBlue + newBlueValue;
if (resultBlue > maxValue) { resultBlue = maxValue;} else if (resultBlue < minValue) { resultBlue = minValue;}
resultGreen = greenFilter - sourceGreen + newGreenValue;
if (resultGreen > maxValue) { resultGreen = maxValue;} else if (resultGreen < minValue) { resultGreen = minValue;}
resultRed = redFilter - sourceRed + newRedValue;
if (resultRed > maxValue) { resultRed = maxValue;} else if (resultRed < minValue) { resultRed = minValue;}
resultBuffer[k] = (byte)resultBlue; resultBuffer[k + 1] = (byte)resultGreen; resultBuffer[k + 2] = (byte)resultRed; resultBuffer[k + 3] = sourceAlpha; } } }
Marshal.Copy(resultBuffer, 0, resultData.Scan0, resultBuffer.Length); resultBitmap.UnlockBits(resultData);
return resultBitmap; }

The ColorSubstitution method can be labelled as due to its implementation. Being implies that the source/input data will not be modified, instead a new instance will be created reflecting the source data as modified by the operations performed in the particular method.

The first statement defined in the ColorSubstitution method body instantiates an instance of a new , matching the size dimensions of the source object. Next the method invokes the method on the source and result instances. When invoking the underlying data representing a will be locked in memory. Being locked in memory can also be described as signalling/preventing the Garbage Collector to not move around in memory the data being locked. Invoking results in the Garbage Collector functioning as per normal, moving data in memory and updating the relevant memory references when required.

The source code continues by copying all the representing the source to an array of bytes that represents the resulting . At this stage the source and result s are exactly identical and as yet unmodified. In order to determine which pixels based on colour should be modified the source code iterates through the byte array associated with the result .

Notice how the for loop increments by 4 with each loop. The underlying data represents a 32 Bits per pixel Argb , which equates to 8 bits/1 representing an individual colour component, either Alpha, Red, Green or Blue. Defining the for loop to increment by 4 results in each loop iterating 4 or 32 bits, in essence 1 pixel.

Within the for loop we determine if the colour expressed by the current pixel adjusted by the threshold value forms part of the colour range that should be updated. It is important to remember that an individual colour component is a byte value and can only be set to a value between 0 and 255 inclusive.

The Implementation

The ColorSubstitution method is implemented by the sample source code  through a Windows Forms application. The ColorSubstitution method requires that the source specified must be  formatted as a 32 Bpp Argb . When the user loads a source image from the file system the sample application attempts to convert the selected file by invoking the Format32bppArgbCopy which targets the class. The definition is as follows:

public static Bitmap Format32bppArgbCopy(this Bitmap sourceBitmap)
{
    Bitmap copyBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height, PixelFormat.Format32bppArgb);

using (Graphics graphicsObject = Graphics.FromImage(copyBitmap)) { graphicsObject.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; graphicsObject.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; graphicsObject.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; graphicsObject.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
graphicsObject.DrawImage(sourceBitmap, new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), GraphicsUnit.Pixel); }
return copyBitmap; }

Colour Substitution Examples

The following section illustrates a few examples of colour substitution result . The source image features Bellis perennis also known as the common European Daisy (see Wikipedia). The image file is licensed under the Creative Commons Attribution-Share Alike 2.5 Generic license. The original image can be downloaded here. The following image is a scaled down version of the original:

Bellis_perennis_white_(aka)_scaled

Light Blue Colour Substitution

Colour Component Source Colour Substitute Colour
Red   255   121
Green   223   188
Blue   224   255

Daisy_light_blue

Medium Blue Colour Substitution

Colour Component Source Colour Substitute Colour
Red   255   34
Green   223   34
Blue   224   255

Daisy_medium_blue

Medium Green Colour Substitution

Colour Component Source Colour Substitute Colour
Red   255   0
Green   223   128
Blue   224   0

Daisy_medium_green

Purple Colour Substitution

Colour Component Source Colour Substitute Colour
Red   255   128
Green   223   0
Blue   224   255

Daisy_purple

Related Articles and Feedback

Feedback and questions are always encouraged. If you know of an alternative implementation or have ideas on a more efficient implementation please share in the comments section.

I’ve published a number of articles related to imaging and images of which you can find URL links here:

C# How to: Encoding Base64 Thumbnails

Article purpose

This details how to read files from the file system, create and then encoding to strings.

Sample source code

This is accompanied by a sample source code Visual Studio project which is available for download .

Images as Base64 strings

From :

Base64 is a group of similar encoding schemes that represent in an ASCII string format by translating it into a -64 representation. The Base64 term originates from a specific .

Base64 encoding schemes are commonly used when there is a need to encode binary data that need to be stored and transferred over media that are designed to deal with textual data. This is to ensure that the data remain intact without modification during transport. Base64 is commonly used in a number of applications including via , and storing complex data in .

From the definition quoted above the need for base64 encoding becomes more clear. From :

The base-64 digits in ascending order from zero are the uppercase characters "A" to "Z", the lowercase characters "a" to "z", the numerals "0" to "9", and the symbols "+" and "/". The valueless character, "=", is used for trailing padding.

encoding allows developers to expose binary data without potentially encountering conflicts in regards to the transfer medium. encoded binary data serves ideally when performing data transfer operations using platforms such as html, xml, email.

A common implementation of encoding can be found when transferring data. This article details how to convert/encode object to strings.

Base64 Image encoding implemented as an extension method

The code snippet listed below details the ToBase64String targeting the class.

public static string ToBase64String(this Image bmp)
{
    string base64String = string.Empty;
    MemoryStream memoryStream = null;

try { memoryStream = new MemoryStream(); bmp.Save(memoryStream, ImageFormat.Png); } catch (Exception exc) { return String.Empty; }
memoryStream.Position = 0; byte[] byteBuffer = memoryStream.ToArray();
memoryStream.Close();
base64String = Convert.ToBase64String(byteBuffer, Base64FormattingOptions.InsertLineBreaks); byteBuffer = null;
return base64String; }

The ToBase64String method writes the targeted object’s pixel data to a object using the Png . Next a array is extracted and passed to the method , which is responsible for implementing the encoding.

Creating an Image tag implementing a Base64 string

The sample source code in addition also defines an to generate html image tags to display a string encoded .

public static string ToBase64ImageTag(this Image bmp)
{
    string imgTag = string.Empty;
    string base64String = string.Empty;

base64String = bmp.ToBase64String();
imgTag = "<img src=\\"data:image/" + "png" + ";base64,"; imgTag += base64String + "\\" "; imgTag += "width=\\"" + bmp.Width.ToString() + "\\" "; imgTag += "height=\\"" + bmp.Height.ToString() + "\\" />";
return imgTag; }

The ToBase64ImageTag invokes the ToBase64String in order to retrieve encoded the data. The Html image tag has only to be slightly modified from the norm in order to accommodate encoded strings.

Creating Image thumbnails

The class conveniently provides the method , which we’ll be using to create from existing objects. The sample source code defines the method ToBase64Thumbnail, as listed below:

public static string ToBase64Thumbnail(this Image bmp, int width, int height, bool wrapImageTag)
{
    Image.GetThumbnailImageAbort callback = new Image.GetThumbnailImageAbort(ThumbnailCallback);

Image thumbnailImage = bmp.GetThumbnailImage(width, height, callback, new IntPtr());
string base64String = String.Empty;
if (wrapImageTag == true) { base64String = thumbnailImage.ToBase64ImageTag(); } else { base64String = thumbnailImage.ToBase64String(); }
thumbnailImage.Dispose();
return base64String; }
private static bool ThumbnailCallback() { return true; }

The ToBase64Thumbnail is defined as an targeting the class. The calling code is required to specify the width and height of the output and in addition whether to wrap the encoded string in an Html <img> tag.

Note the definition of ThumnailCallback, the method requires calling code to specify a callback delegate.

Based on the value of the parameter wrapImageTag, we next invoke either ToBase64ImageTag or ToBase64String, as defined/discussed earlier.

Reading Image files from the file system

The starting point in creating encoded would be to read the local file system, searching for files. The ToBase64Thumbnails method is defined as an targeting the string class. When invoking the ToBase64Thumbnails method users are expected to provide a directory path, width and height of output , whether to add Html <img> tags and which file types to process. The code snippet below details the implementation of the ToBase64Thumbnails method.

public static List<string> ToBase64Thumbnails(this string path, int width, int height, bool wrapImageTag, params string[] fileTypes)
{
    List<string> base64Thumbnails = new List<string>();

string searchFilter = String.Empty;
if (fileTypes != null) { for (int k = 0; k < fileTypes.Length; k++) { searchFilter += "*." + fileTypes[k];
if (k < fileTypes.Length - 1) { searchFilter += "|"; } } } else { searchFilter = "*.*"; }
string[] files = Directory.GetFiles(path, searchFilter);
for (int k = 0; k < files.Length; k++) { StreamReader streamReader = new StreamReader(files[k]); Image img = Image.FromStream(streamReader.BaseStream); streamReader.Close();
base64Thumbnails.Add(img.ToBase64Thumbnail(width, height, wrapImageTag));
img.Dispose(); }
return base64Thumbnails; }

The ToBase64Thumbnails method implements the static method in order to search a specified directory path. When invoking the ToBase64Thumbnails method the calling code can optionally specify a number of file extensions, which results in only files having file extensions conforming to the specified extensions being encoded.

Once an array of file paths have been determined the sample code iterates the array creating an object of each file specified. The final step required is to invoke the ToBase64Thumbnail.

The implementation

The sample source code defines a console based application, used to test/illustrate creating encoded based on a specified directory path.  Included in the sample code is a template html file. The Main method generates a list of encoded by invoking ToBase64Thumbnails, defined as an targeting the String class. The resulting encoded are defined as Html <img> tags, added to a copy of the html template file. The Console application’s definition:

static void Main(string[] args)
{
    string path = "Images";

List<string> thumbnailTags = path.ToBase64Thumbnails(100, 100, true, null);
StreamReader streamreader = new StreamReader("HtmlTemplate.htm"); StringBuilder htmlPage = new StringBuilder(streamreader.ReadToEnd()); streamreader.Close();
StringBuilder imageTags = new StringBuilder();
for (int k = 0; k < thumbnailTags.Count; k++) { imageTags.AppendLine("<p>"); imageTags.AppendLine(thumbnailTags[k]); imageTags.AppendLine("</p>"); }
htmlPage.Replace("<!--Tags_Placeholder-->", imageTags.ToString());
StreamWriter streamwriter = new StreamWriter("TempPage.htm", false, Encoding.UTF8); streamwriter.Write(htmlPage.ToString()); streamwriter.Close();
Process.Start("TempPage.htm");
Console.ReadKey(); }

The resulting encoded image viewed as html <img> tags forming part of an html file, as viewed in Microsoft Internet Explorer 9:

Base64Thumbnails

C# How to: Decoding/Converting Base64 strings to Bitmap images

Article purpose

This details how to decode or convert encoded back into by means of the class.

Note: This article is an update that builds upon the article:

Sample source code

This is accompanied by a sample source code Visual Studio project which is available for download .

Images as Base64 strings

From :

Base64 is a group of similar encoding schemes that represent in an ASCII string format by translating it into a -64 representation. The Base64 term originates from a specific .

Base64 encoding schemes are commonly used when there is a need to encode binary data that need to be stored and transferred over media that are designed to deal with textual data. This is to ensure that the data remain intact without modification during transport. Base64 is commonly used in a number of applications including email via MIME, and storing complex data in XML.

From the definition quoted above the need for encoding becomes more clear. From :

The base-64 digits in ascending order from zero are the uppercase characters "A" to "Z", the lowercase characters "a" to "z", the numerals "0" to "9", and the symbols "+" and "/". The valueless character, "=", is used for trailing padding.

encoding allows developers to expose without potentially encountering conflicts in regards to the transfer medium. encoded serves ideally when performing data transfer operations using platforms such as html, json, rest, xml, email.

A common implementation of encoding can be found when transferring data. This details how to convert/decode a back into a Bitmap .

Base64 String to Bitmap decoding implemented as an extension method

The code snippet listed below details the Base64StringToBitmap targeting the .

public static Bitmap Base64StringToBitmap(this string
                                           base64String)
{
    Bitmap bmpReturn = null;

byte[] byteBuffer = Convert.FromBase64String(base64String); MemoryStream memoryStream = new MemoryStream(byteBuffer);
memoryStream.Position = 0;
bmpReturn = (Bitmap)Bitmap.FromStream(memoryStream);
memoryStream.Close(); memoryStream = null; byteBuffer = null;
return bmpReturn; }

The parameter is first converted to a array by invoking the method. Next we create a against the resulting array, which serves as a parameter to the class’ static method.

The implementation

The Base64StringToBitmap is implemented in a console based application. The creates a instance from the local file system, which is then converted to a .

An article detailing how to convert to encoded can be found here:

– The you are currently reading was published as a follow up .

Next the newly created is converted back to a by invoking the Base64StringToBitmap . In order to test if the was decoded successfully the is saved to the local file system and displayed in the default installed application associated with png . The implementation as follows:

static void Main(string[] args)
{
    StreamReader streamReader = new StreamReader(
                                   "NavForward.png");

Bitmap bmp = new Bitmap(streamReader.BaseStream); streamReader.Close();
string base64ImageString = bmp.ToBase64String( ImageFormat.Png);
Console.WriteLine(base64ImageString);
Bitmap bmpFromString = base64ImageString.Base64StringToBitmap();
bmpFromString.Save("FromBase64String.png", ImageFormat.Png);
Process.Start("FromBase64String.png");
Console.ReadKey(); }

Related Articles and Feedback

Feedback and questions are always encouraged. If you know of an alternative implementation or have ideas on a more efficient implementation please share in the comments section.

Dewald Esterhuizen

I’ve published a number of articles related to imaging and images of which you can find URL links here:

C# How to: Generate a Web Service from WSDL

Article purpose

Image FiltersWeb Service Definition Language (WSDL) is an Xml based schema that exactly details the custom data types and web service methods exposed by a web service. Developers usually generate web service client proxy code in order to call into web services. Since WSDL is an exact description of a web service it is also possible to generate code that represents the service in the form of web method stubs. This article illustrates how to generate a web service from WSDL.

Introduction

Image FiltersI’ve often found myself in a scenario where I have to interface with third parties via web services. It is often the case that third party service are proprietary, usually I find that I have very little control over the web services I’m required to interface to. Countless hours are wasted because of out dated test environments, missing/incorrect security certificates or even just trying to get hold of log files.

Image FiltersTime spent on development and testing can be significantly reduced in most cases if I had a local copy of a web service available to me. Having access to source code would be even more beneficial, being able to manipulate the data returned, testing timeouts etc. After surprisingly little effort I manage to develop a utility application capable of generating web method stubs and custom defined types in C# source code. The only required input in generating a web service is the WSDL of an existing web service.

Sample source code

Image FiltersThis article is accompanied by sample source code in a Visual Studio project which is available for download .

 

Input Web service WSDL

Image FiltersThe sample source accompanying this article defines a very simplistic web service, consisting of one web method HelloWorld(). The source code is listed below:

 [WebService (Namespace = "http://softwarebydefault.com" )]
 [WebServiceBinding (ConformsTo = WsiProfiles.BasicProfile1_1)]
 [System.ComponentModel.ToolboxItem (false )]
 public class TestWebService : System.Web.Services.WebService 
 {
     [WebMethod ]
     public string  HelloWorld()
     {
         return "Hello World";
     }
 }
 

The resulting WSDL is generated as illustrated by the following snippet:

<?xml version="1.0" encoding="utf-8"?>

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://softwarebydefault.com" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://softwarebydefault.com" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">

  <wsdl:types>

    <s:schema elementFormDefault="qualified" targetNamespace="http://softwarebydefault.com">

      <s:element name="HelloWorld">

        <s:complexType />

      </s:element>

      <s:element name="HelloWorldResponse">

        <s:complexType>

          <s:sequence>

            <s:element minOccurs="0" maxOccurs="1" name="HelloWorldResult" type="s:string" />

          </s:sequence>

        </s:complexType>

      </s:element>

    </s:schema>

  </wsdl:types>

  <wsdl:message name="HelloWorldSoapIn">

    <wsdl:part name="parameters" element="tns:HelloWorld" />

  </wsdl:message>

  <wsdl:message name="HelloWorldSoapOut">

    <wsdl:part name="parameters" element="tns:HelloWorldResponse" />

  </wsdl:message>

  <wsdl:portType name="TestWebServiceSoap">

    <wsdl:operation name="HelloWorld">

      <wsdl:input message="tns:HelloWorldSoapIn" />

      <wsdl:output message="tns:HelloWorldSoapOut" />

    </wsdl:operation>

  </wsdl:portType>

  <wsdl:binding name="TestWebServiceSoap" type="tns:TestWebServiceSoap">

    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />

    <wsdl:operation name="HelloWorld">

      <soap:operation soapAction="https://softwarebydefault.com/HelloWorld" style="document" />

      <wsdl:input>

        <soap:body use="literal" />

      </wsdl:input>

      <wsdl:output>

        <soap:body use="literal" />

      </wsdl:output>

    </wsdl:operation>

  </wsdl:binding>

  <wsdl:binding name="TestWebServiceSoap12" type="tns:TestWebServiceSoap">

    <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />

    <wsdl:operation name="HelloWorld">

      <soap12:operation soapAction="https://softwarebydefault.com/HelloWorld" style="document" />

      <wsdl:input>

        <soap12:body use="literal" />

      </wsdl:input>

      <wsdl:output>

        <soap12:body use="literal" />

      </wsdl:output>

    </wsdl:operation>

  </wsdl:binding>

  <wsdl:service name="TestWebService">

    <wsdl:port name="TestWebServiceSoap" binding="tns:TestWebServiceSoap">

      <soap:address location="http://localhost:6078/TestWS.asmx" />

    </wsdl:port>

    <wsdl:port name="TestWebServiceSoap12" binding="tns:TestWebServiceSoap12">

      <soap12:address location="http://localhost:6078/TestWS.asmx" />

    </wsdl:port>

  </wsdl:service>

</wsdl:definitions>

Generating the Web service from input WSDL

Image FiltersThe crux of this article revolves around the Generate method defined in the associated sample source code. The method makes use of the ServiceDescription and ServiceDescriptionImporter classes to reference the WSDL generated earlier. The code defined by the Generate method is very similar to the code that would generate web service client proxy code. Make note of the Style property of the ServiceDescriptionImporter object being set to ServiceDescriptionImportStyle.Server. By setting the style to server we indicate that any code generated should reflect the server interface. Had the property being set to ServiceDescriptionImportStyle.Client web service client proxy code would be generated.

Image FiltersAfter importing the service descriptions as defined by the specified WSDL and if no errors occurred we generate C# source code based on the service descriptions imported. The resulting source code generated is then saved to the file system based on the file path passed as method parameter.

 public  static  void  Generate(string  wsdlPath, string  outputFilePath)
 {
     if  (File.Exists(wsdlPath) == false )
     {
         return;
     }

     ServiceDescription  wsdlDescription = ServiceDescription .Read(wsdlPath);
     ServiceDescriptionImporter  wsdlImporter = new  ServiceDescriptionImporter ();

     wsdlImporter.ProtocolName = "Soap12";
     wsdlImporter.AddServiceDescription(wsdlDescription, null , null );
     wsdlImporter.Style = ServiceDescriptionImportStyle .Server;

     wsdlImporter.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions .GenerateProperties;

     CodeNamespace codeNamespace = new  CodeNamespace();
     CodeCompileUnit codeUnit = new  CodeCompileUnit();
     codeUnit.Namespaces.Add(codeNamespace);

     ServiceDescriptionImportWarnings importWarning = wsdlImporter.Import(codeNamespace, codeUnit);

     if  (importWarning == 0)
     {
         StringBuilder stringBuilder = new StringBuilder();
         StringWriter stringWriter = new StringWriter(stringBuilder);

         CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("CSharp");
         codeProvider.GenerateCodeFromCompileUnit(codeUnit, stringWriter, new CodeGeneratorOptions());

         stringWriter.Close();

         File.WriteAllText(outputFilePath, stringBuilder.ToString(), Encoding.UTF8);
     }
     else 
     {
         Console.WriteLine(importWarning);
     }
 }
 

Image FiltersNotice the use of the CodeDomProvider class, creating an instance of this class allows us to generate source code. This class can also be used to compile source code to assemblies, in essence it allows developers access to a set of compilers accessible from code. As described by MSDN documentation:

A CodeDomProvider implementation typically provides code generation and/or code compilation interfaces for generating code and managing compilation for a single programming language. Several languages are supported by CodeDomProvider implementations that ship with the Windows Software Development Kit (SDK). These languages include C#, Visual Basic, C++, and JScript. Developers or compiler vendors can implement the ICodeGenerator and ICodeCompiler interfaces and provide a CodeDomProvider that extends CodeDOM support to other programming languages.

The Generated Code

Image FiltersThe code generated comes in the form of abstract classes and methods. The snippet below illustrates the raw generated code:

 [System.CodeDom.Compiler.GeneratedCodeAttribute("WSDLToWebService" , "1.0.0.0" )]
 [System.Web.Services.WebServiceAttribute(Namespace="http://softwarebydefault.com" )]
 [System.Web.Services.WebServiceBindingAttribute(Name="TestWebServiceSoap12" , Namespace="http://softwarebydefault.com" )]
 public  abstract  partial  class  TestWebService  : System.Web.Services.WebService {
     
     [System.Web.Services.WebMethodAttribute()]
     [System.Web.Services.Protocols.SoapDocumentMethodAttribute("https://softwarebydefault.com/HelloWorld" ,
         RequestNamespace="http://softwarebydefault.com" , ResponseNamespace="http://softwarebydefault.com" ,
         Use=System.Web.Services.Description.SoapBindingUse.Literal, 
         ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
     public  abstract  string  HelloWorld();
 }
 

Image FiltersThe code generated compiles without issue, but being declared abstract prevents the code from functioning as a web service implementation. I find the easiest method is to refactor the code instead of implementing inheritance. The snippet listed below represents the generated code refactored to reflect a web service implementation.

[System.CodeDom.Compiler.GeneratedCodeAttribute ("WSDLToWebService" , "1.0.0.0" )]
[System.Web.Services.WebServiceAttribute (Namespace = "http://softwarebydefault.com" )]
[System.Web.Services.WebServiceBindingAttribute (Name = "TestWebService" , Namespace = "http://softwarebydefault.com" )]
public  class  TestWebService  : System.Web.Services.WebService 
{
     [System.Web.Services.WebMethodAttribute()]
     [System.Web.Services.Protocols.SoapDocumentMethodAttribute("https://softwarebydefault.com/HelloWorld" ,
     RequestNamespace = "http://softwarebydefault.com" , ResponseNamespace = "http://softwarebydefault.com" ,
     Use = System.Web.Services.Description.SoapBindingUse.Literal, 
     ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
     public  string  HelloWorld()
     {
         return  "Hello Generated World" ;
     }
 }
 

Image FiltersThe TestWebService class and HelloWorld method is now no longer defined as abstract. In addition HelloWorld now defines a method body as required by not being an abstract method anymore.

 

About the Icons

I’ve written a number of articles exploring the topic of Colour filters. All of the Light bulb icon images featured in this article were generated from same source image, each having been manipulated by various colour filters. I made use of sample applications accompanying some of the articles I’ve published.

Image Filters Image Filters Image Filters Image Filters Image Filters Image Filters Image Filters Image Filters

If you are interested in Image filters or would like to download the sample applications and source code please have a look at the following links to articles published on this site:

 

Image Filters Image Filters Image Filters Image Filters Image Filters Image Filters Image Filters Image Filters

The original source image used to generate the icon images featured in this article has been licensed under the Creative Commons Attribution-Share Alike 3.0 Unported license and can be downloaded from .


Dewald Esterhuizen

Unknown's avatar

Blog Stats

  • 892,465 hits

Enter your email address to follow and receive notifications of new posts by email.

Join 91 other subscribers

Archives

RSS SoftwareByDefault on MSDN

  • An error has occurred; the feed is probably down. Try again later.