Introduction
.NET is productive! There's no doubt in that. The framework contains huge number of classes, which encapsulate many of the tasks required by the developer during the course of development. Take for instance, the TCPListener
class that has simplified design of a TCP server to few lines of code, from the huge bunch that was written back in the days of Winsock. Another good example is that of working with images, in particular, converting images from one format to another, which is the main focus of this article.
I shall start off by introducing to the classes involved in working with images and their conversion, and show you how that is done. Finally, we build a real-life application: a .NET XML Webservice that shall convert images from one file format to another, on the fly! Next, we shall also have a look at a very simple C# client that shall invoke the webservice and convert images using it. So, without any further delay, lets get started.
Creating and converting image
The very first step in working with images is to create an object of the Image
class object, which is present in the System.Drawing
namespace. Since converting image file format requires the image to be present as a file, we shall create the Image object using the FromFile
static
method of the class, as shown below:
Image imgInFile=Image.FromFile(strFileName);
strFileName
is the complete path to the image file. Now that we have an Image
object ready, the second line of code that converts the image to a specified file format is this:
imgInFile.Save(strOutFileName,ImageFormat.Bmp);
The first parameter to the Save
method is the complete path to the output filename, while the second parameter is an enumeration, defined in System.Drawing.Imaging
, that lets you specify the format in which the file should be saved. The above code saves the image as a .BMP file, but there are 8 more image file formats in which the image can be saved.
Now that we have seen what all it takes to convert an image into a different format (which isn't much, right ?), lets have a look at our image format conversion webservice.
Inside WSC_ConvertImage
Here's the code to our image conversion webservice:
<%@ WebService language="C#" class="WSC_ConvertImage" %>
using System;
using System.Web.Services;
using System.Xml.Serialization;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
public class WSC_ConvertImage : WebService {
[WebMethod]
public bool ConvertImage(byte[] bytInFile, int intToFormat,
out byte[] bytOutFile)
{
bytOutFile=null;
if (bytInFile.Length==0)
{
return false;
}
string strFileName=Server.MapPath(".")+"\\"+
Guid.NewGuid().ToString();
FileStream fsFile=null;
try
{
fsFile=File.Create(strFileName);
}
catch
{
return false;
}
try
{
fsFile.Write(bytInFile,0,bytInFile.Length);
}
catch
{
fsFile.Close();
return false;
}
fsFile.Close();
Image imgInFile=Image.FromFile(strFileName);
string strOutFileName=strFileName;
switch(intToFormat)
{
case 1:
strOutFileName=strOutFileName+".BMP";
imgInFile.Save(strOutFileName,ImageFormat.Bmp);
break;
case 2:
strOutFileName=strOutFileName+".EXIF";
imgInFile.Save(strOutFileName,ImageFormat.Exif);
break;
case 3:
strOutFileName=strOutFileName+".EMF";
imgInFile.Save(strOutFileName,ImageFormat.Emf);
break;
case 4:
strOutFileName=strOutFileName+".GIF";
imgInFile.Save(strOutFileName,ImageFormat.Gif);
break;
case 5:
strOutFileName=strOutFileName+".ICO";
imgInFile.Save(strOutFileName,ImageFormat.Icon);
break;
case 6:
strOutFileName=strOutFileName+".JPG";
imgInFile.Save(strOutFileName,ImageFormat.Jpeg);
break;
case 7:
strOutFileName=strOutFileName+".PNG";
imgInFile.Save(strOutFileName,ImageFormat.Png);
break;
case 8:
strOutFileName=strOutFileName+".TIFF";
imgInFile.Save(strOutFileName,ImageFormat.Tiff);
break;
case 9:
strOutFileName=strOutFileName+".WMF";
imgInFile.Save(strOutFileName,ImageFormat.Wmf);
break;
default:
strOutFileName=strOutFileName+".BMP";
imgInFile.Save(strOutFileName,ImageFormat.Bmp);
break;
}
try
{
fsFile=File.Open(strOutFileName,FileMode.Open,FileAccess.Read);
}
catch
{
return false;
}
try
{
int iSize=Convert.ToInt32(fsFile.Length);
bytOutFile = new byte[iSize];
fsFile.Read(bytOutFile,0,iSize);
}
catch
{
fsFile.Close();
return false;
}
fsFile.Close();
try
{
File.Delete(strFileName);
File.Delete(strOutFileName);
}
catch
{
}
return true;
}
}
Lets follow the top down approach. The code places references to required namespaces, including System.Drawing
for using the Image
class, System.Drawing.Imaging
for using the ImageFormat
enumeration, and finally, System.IO
for working with files (we will see why, shortly).
Now, since this webservice has to convert an image from one format to another, it must have access to that image, and it will have to return the converted image. There are couple of issues here:
- The webservice could be located anywhere globally, while the image could be someplace other than the webservice server.
- We can't transfer files, as such, using webservices.
- Once the converted image is created on the webservice server, how do we return it to the client? Refer to the second issue.
The single solution, which handles these issues gracefully, is to send the image as an array of bytes, which the webservice processes, and returns the converted image as a byte array. And this is how the ConvertImage
web method has been implemented. The first parameter to the method is the byte array of the source image file. The client of the webservice is responsible for creating this byte array. The second parameter specifies the format in which the image is to be converted. Numeric values are used to specify the format, as can be seen from the switch-case construct further down the code. Finally, the third parameter is an out parameter, and is a byte array in which the converted image will be returned, and the webservice client shall create a file out of this byte array. The webmethod returns a boolean to indicate the success of the conversion.
Now that we have discussed the design implications behind the signature of the webmethod, lets understand how the webservice actually works.
How ConvertImage
works?
The webmethod starts of by initializing the outbound array to null. Next, it is checked if bytes comprising the image to be converted have been sent or not. Incase not, then false is returned. Otherwise, a unique filename is generated using the NewGuid
method of the Guid
structure so that each webmethod call has a unique filename for processing the inptu bytes. Incase you don't know, GUIDs are 128bit numbers that are used in COM for specifying various kinds of identifiers, and are almost guaranteed to be unique.
Next, the input bytes are written to the file, created from the unqiue filename generated previosuly, and an Image object is created by loading the image using the FromFile
static
method. If any exception is thrown, the method returns false. Subsequently, depending upon the kind of conversion specified by the ToFormat parameter, appropriate output filename is generated, by prefixing the relevant image file extension, to the generated input filename. Next, the SaveAs
method is called, with the appropriate enumeration value (corresponding to the format in which the image should be converted), and the image conversion takes place.
The final portion deals with opening and reading the output file, and transferring the bytes of the converted image file in the out byte array, that shall be sent back to the client, which will then write to a file. Finally, true is returned if everything has gone fine, to indicate a successful image conversion.
The Client
Now that we have seen how the webservice works, here's a look into a simple client for the webservice:
using System;
using System.IO;
public class TestImage
{
public static void Main()
{
Console.WriteLine("Enter filename: ");
string strFileName=Console.ReadLine();
FileStream fs=File.Open(strFileName,FileMode.Open,FileAccess.Read);
byte[] inByte = new byte[fs.Length];
fs.Read(inByte,0,inByte.Length);
fs.Close();
WSC_ConvertImage wsc = new WSC_ConvertImage();
byte[] outByte=null;
if (wsc.ConvertImage(inByte,1,out outByte)==false)
Console.WriteLine("Covnersion failed");
else
{
fs=File.Create("output.bmp");
fs.Write(outByte,0,outByte.Length);
fs.Close();
Console.WriteLine("Conversion over");
}
}
}
The client starts of by opening the input file specified in the read mode, and reading its contents in a byte array. Next, it creates an object of the webservice, wsc, and invokes the webmethod. If an error occurs, approprate message is displayed. Otherwise, a file by the name of output.bmp is created (since the client is performing the conversion to BMP format), and the bytes sent out by the webmethod, comprising of the converted image file, are written to the created file. Hence, the conversion takes place.
Conclusion
Its very obvious that webservices carry a lot of punch, especially with what all they can do with the framework's support. This was a very simple exemplification of the future of distributed software services. Hope you felt the power and flexibility.
I hold Early Acheiver in MCSE 2000, MCSE NT 4.0, MCP+I, and actively involved in programming using C/C++, .NET framework, C#, Win32 API, VB, ASP and MFC.
I also have various publications to my credit at MSDN Online Peer Journal, Windows Developer Journal (http://www.wdj.com/), Developer 2.0 (http://www.developer2.com/), and PC Quest (http://www.pcquest.com/).