Laurent Ellerbach

Ce blog est principalement destiné à publier des informations relatives à Microsoft, à ses technologies, aux outils Visual Studio et à ses versions Express notamment Visual Basic

November, 2011

  • Laurent Ellerbach

    Dynamically watermark a picture in a ASP.NET page

    • 0 Comments

    In a previous post, I’ve explain how to use generic ASP.NET handlers to display a picture. The concept is easy to use and perfect to manipulate any kind of document you want to output in your web server. There equivalent of this in technologies like PHP or Java but it’s so easy to do using ASP.NET. In my previous post, I’ve used VB, so I’ll continue with VB Sourire Don’t worry, it’s as easy to do in C#!

    The overall code to watermark an image dynamically using the generic handler and the minimum manipulation code is here:

    <%@ WebHandler Language="VB" Class="Image" %>
    
    Imports System
    Imports System.Web
    Imports System.Net
    Imports System.IO
    Imports System.Drawing
    Imports System.Drawing.Imaging
    Imports System.Drawing.Drawing2D
    
    Public Class Image : Implements IHttpHandler
        
        Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
            context.Response.ContentType = "image/jpeg"
            context.Response.AddHeader("Cache-Control", "private,must-revalidate,post-check=1,pre-check=2,no-cache")
                    
            Dim instanceHTTP As New WebClient
            Dim MaCamera As New Camera
            Dim MyUri As New Uri("file://c:/Temp/image.jpg")
            Dim returnValue As Stream
            
            Try
                
                returnValue = instanceHTTP.OpenRead(MyUri)
                
                Dim MyImage As System.Drawing.Image = System.Drawing.Image.FromStream(returnValue)
                
                Dim MyText As String = Now.ToString("yyy-MM-dd HH-mm")
                Dim MyGraphics As Graphics = Graphics.FromImage(MyImage)
                Dim MyFont As Font = New Font(FontFamily.GenericSerif, 12)
                MyGraphics.DrawString(MyText, MyFont, Brushes.White, 100, 100)
                            
                MyImage.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)
                MyGraphics.Dispose()
                MyImage.Dispose()
                
            Catch ex As Exception
                context.Response.Write("Error")
            End Try
            
        End Sub
     
        Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
            Get
                Return False
            End Get
        End Property
    
    End Class
    

    I will not explain again what I’ve explain in the previous post on the way handlers are working. So I’ll just concentrate on the image manipulation and how to write text in an image dynamically.

    returnValue = instanceHTTP.OpenRead(MyUri)
    
    Dim MyImage As System.Drawing.Image = System.Drawing.Image.FromStream(returnValue)
    
    Dim MyText As String = Now.ToString("yyy-MM-dd HH-mm")
    Dim MyGraphics As Graphics = Graphics.FromImage(MyImage)
    Dim MyFont As Font = New Font(FontFamily.GenericSerif, 12)
    MyGraphics.DrawString(MyText, MyFont, Brushes.White, 100, 100)
                
    MyImage.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)
    MyGraphics.Dispose()
    MyImage.Dispose()

    I first open a URI which contains an image. In my case a static image sitting on the hard drive but the idea here is to take it from a webcam for example. The URI is open as a stream and passed to an Image object.

    The idea here is to watermark the image with the date. So I create a simple string containing the date and time in a dedicated formatting. I like this formatting "yyy-MM-dd HH-mm" as it’s easy to sort especially with files. It does return a text like “2011-11-24 10-47”.

    Then I create a graphics object pointing on the image. This object is directly link to the image we have loaded and any modification made on the graphics object will impact the image. It’s the basic concept of pointers used here.

    In order to write text, you’ll have to choose a font. Again, nothing complicated here, choose your preferred font and the size. A good Serif and a 12 size will be enough in my example.

    And let the magic work using the DrawString method to draw in the graphics, so in the image your text. The 100 and 100 params are the X and Y starting point where to write the text. It starts on the upper left corner of the image. You can also use predefined points. But for the example, I keep it very simple.

    And as explain in the previous post, you just have to save your watermarked picture into the output stream and you’re done. Or almost done, don’t forget to dispose the graphics objects, better to do it especially if you want to scale up. The garbage collector will thank you Sourire

    Final result will look like that:

    image

    And of course, you can do more, much more using this handler. You can add shapes, transform the color schemas, apply filters, etc. .NET is full or very efficient graphics manipulations. so just use them! In my case I use it to tag pictures with date and time as in this example but also to control when I can access an image on some webcam. I do not expose them directly to the web. They are only accessible thru handlers like this. And only to specific persons (with a login and password) and on specific time. Maybe more in a next example!

    As always, feedback welcome Sourire The code and blog post written in a plane from Paris to Zagreb Sourire

  • Laurent Ellerbach

    Writing a generic ASP.NET handler to return an image and control the image

    • 1 Comments

    In one of my project, I want to integrate the picture from an IP camera to a web site. The idea is to be able to put a IP camera in my Lego room and see it for real. Especially to be able to control it. this project is linked to the one to light my Lego city. Instead of having the static image of the city, I want to be able to show the real time image. For this project, I’m using a netduino and .NET Microframework.

    Most IP camera do propose a simple URL where you can get the image. So it is very easy to integrate. But what if you want to control when to display the picture? Let say you don’t want to display the picture over night or just in small period of time? Or you want to dynamically add something to the picture like a layer? Well, IP camera are not smart enough to do it. So you’ll have to write some code.

    In ASP.NET you cant easily write a generic handler with the .ashx extension. that’s what I’ll do. And I’ll do it in VB.NET, that will change from my previous post that I did in C#. And no, I won’t do it in C++, php or Java Tire la langue. Yes, I do love VB too. Not only C#. As started developing a very long ago when the only thing you had on a PC was BASICA, the BASIC that was implemented in the IBM PC ROM. My father had a PC at home he was using for his own business.I was allow to use it but as I did not get any floppy disk, the only thing I was able to do was coding. And that’s at this time at 10 I started to code… in BASIC. and since then I never stopped coding Sourire 

    The simple code is the following one:

    <%@ WebHandler Language="VB" Class="Image" %>
    
    Imports System
    Imports System.Web
    Imports System.Net
    Imports System.IO
    Imports System.Drawing
    Imports System.Drawing.Imaging
    Imports System.Drawing.Drawing2D
    
    Public Class Image : Implements IHttpHandler
        
        Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
            context.Response.ContentType = "image/jpeg"
            context.Response.AddHeader("Cache-Control", 
    "private,must-revalidate,post-check=1,pre-check=2,no-cache") Dim instanceHTTP As New WebClient Dim MyUri As New Uri("http://yourcameraurl/image.jpg") Dim returnValue As Stream Try returnValue = instanceHTTP.OpenRead(MyUri) Dim MyImage As System.Drawing.Image = System.Drawing.Image.FromStream(returnValue) MyImage.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg) MyImage.Dispose() Catch ex As Exception context.Response.Write("Error") End Try End Sub Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable Get Return False End Get End Property End Class

    On top the page, you have to declare that it’s a WebHandler and implement IHttpHandler. When you’ve done that, add the ProcessRequest function as following:

    Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest

    And also the read only property IsReusable. This function basically allow you to control if you want the ProcessRequest function to be reusable without executing the code or not. Here, the idea is to refresh the image each time the function is called so the property will return false.

    The ProcessRequest function gives you a HttpContext object. This object allow you to get many information like the brower type, the IP request address and more. But it also allow you to write in the response object. And that’s what interest us here as we want to send back an image.

    context.Response.ContentType = "image/jpeg"
    context.Response.AddHeader("Cache-Control", "private,must-revalidate,post-check=1,pre-check=2,no-cache")

    Those 2 just set the content type as an image so the browser will know how to interpret the content before having it at all. It does this interpretation automatically based on the extension of the file usually even if the type is not set. But here, it is mandatory to define as the extension of you file is .ASHX. And is it not interpreted as an image by any browser Sourire and the .ASHX can virtually return anything, it can be images, text, videos, PowerPoint, Excel file, Word docs, zip or whatever you want. So don’t forget this line! Still the browser (at least Internet Explorer Sourire) is smart enough to figure out that when you are in the “Error” returned in the stream is text and not a jpg…

    the second line is about adding a header. Here, I’m not really sure I do it correctly but I try to specify that the browser can’t cache the image as I want always a fresh image.

            Dim instanceHTTP As New WebClient
            Dim MyUri As New Uri("http://yourcameraurl/image.jpg")
            Dim returnValue As Stream

    The instanceHTTP variable will be used to download the image from the web cam. It’s a WebClient which allow to do this kind of operation. It can be done synchronously or asynchronously.

    The MyURI is used to create the URI that will be used to download the picture. So put in the string the address of your webcam. It is quite easy to find, just open your webcam in a browser, usually it display a page which includes the picture of your image. Right click on the image and you get the URL.

    Then we will need a stream object to put the image in and resend to the response object. that’s what returnValue is.

            Try
                returnValue = instanceHTTP.OpenRead(MyUri)
                
                Dim MyImage As System.Drawing.Image = System.Drawing.Image.FromStream(returnValue)
                            
                MyImage.Save(context.Response.OutputStream, 
    System.Drawing.Imaging.ImageFormat.Jpeg)MyImage.Dispose() Catch ex As Exception context.Response.Write("Error") End Try

    I know you are a good developer so I know when you are trying to access critical resources or resources that may not be present that you are using a try catch section. Good, you are a great developer Sourire. The fact is that trying to download a picture from a webcam may not work. The webcam may be down, your kids may have switch it off or your cat or your mother or whatever can happen.

    returnValue = instanceHTTP.OpenRead(MyUri)

    The 3 variables created previously are used in this line of code. It does open a stream (returnValue) from the WebClient (instanceHTTP) which has a URI (MyURI). That’s done, we are ready to download the picture from the camera.

    Dim MyImage As System.Drawing.Image = System.Drawing.Image.FromStream(returnValue)

    So I create an Image object which I get from the camera thru the function FromStream. On this image, I can do whatever I want. Add text, change the size, colors or do any manipulation.

    MyImage.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)

    Here, I just save the image as a jpeg in the Response object. And I don’t forget to dispose the image as I don’t need it anymore.

    And that’s it! And you can image returning video or file you have created on the flight. Or pages or whatever you want. It is as simple to use handlers in ASP.NET. This implementation as it is as not really a usage. It is much simple to directly use the address of the camera. The only usage you can see is to secure your internal network and the access to the camera. By doing this you are impersonalizing the access to the camera. It is view as a black box from your web server.

    I’ll try to do couple of more post to show examples on how you can create thumbnails on the flight using this technic or maybe how you can restrict access regarding hours. I’m just a marketing guy with a technical background doing code in planes and enjoying it Sourire So any feedback on the code an those articles is welcome. And I see in my stats you are more and more to read them!

  • Laurent Ellerbach

    Read a setup file in .NET Microframework

    • 0 Comments

    In my previous post, I’ve explain how to read the content of a file in .NET Microframework. The idea now is to read a setup file. I want to store the position of the lamp icon I’d like to display on my Lego city map. More information on what I want to do in this post.

    First I’d like to explain the final structure of object I want to setup with my file. I have created a class which will contain a name, a position, the information if the light is on or not. The class is very simple, here is the code:

    public class LegoLight
    {
        private string myName = "";
        private int myPosX = 0;
        private int myPosY = 0;
        private byte myNetwork = 0;
        private bool myLight = false;
    
        public string Name
        {
            get { return myName; }
            set { myName = value; }
        }
        public int PosX
        {
            get { return myPosX; }
            set { myPosX = value; }
        }
        public int PosY
        {
            get { return myPosY; }
            set { myPosY = value; }
        }
        public byte Network
        {
            get { return myNetwork; }
            set { myNetwork = value; }
        }
        public bool Light
        {
            get { return myLight; }
            set { myLight = value; }
        }
    }

    Then I create an Array to store all the LegoLight objects. The good news with array is that you can easily add, remove, search in the array. The main problem is that the object you are adding are just objects. so you need a cast to force the kind of object you want to play with. But as you are the developer, you know what you’ve put in your array Sourire or if you don’t know, just guess Tire la langue

    static ArrayList myLegoLight = new ArrayList();

    I decided to create a simple setup file with the name, network and both position saved in the file. The concept of network is to be able to display all lights that are part of a network at the same time. The position is the position in pixel on the main image of the led to display. The name will be able to be displayed in the alt attribute of the file but also to be able to display the information on a regular page and not on the map. And I don’t save the state of the light, by default, it will be off.

    There is no serialization implemented in netduino so to store a save and read a file, you’ll have to do it manually. You have basically 2 options. First is to save the binary state of your object. That’s approximately what the serialize function is doing and the second is to do like the old ini files readable by a human. I will go for the second option just because I’m a human and it will be easiest for me to create the setup file. I can do it easily with notepad.

    So I have decided to use the following format: name(string);network(number in a string);PosX(number in a string); PosY(number in a string)\r

    As an example, it gives for one LegoLight object: mairie;1;158;59
    and for an array:

    mairie;1;158;59
    station;1;208;300
    train;1;10;10
    rue;1;700;550

    Now the challenge is to read a file like this. The code I wrote is the following (ParamSeparator = ‘;’, strDefaultDir and strFileSetup contains the path of the file and the name):

    LegoLight mLegoLight = new LegoLight();
    FileStream fileToRead = null;
    try
    {
        fileToRead = new FileStream(strDefaultDir+"\\"+strFileSetup, FileMode.Open, FileAccess.Read);
        long fileLength = fileToRead.Length;
        // Send HTTP headers. Content lenght is ser
        Debug.Print("File length " + fileLength);
        // Now loops sending all the data.
    
        //file length has to be less than 1024 otherwise, it will raise an exception
        byte[] buf = new byte[fileLength];
        string mySetupString="";
        
        // Reads the data.
        fileToRead.Read(buf, 0, (int)fileLength);
        // convert the read into a string
        mySetupString = new String(Encoding.UTF8.GetChars(buf));
        //find "\r"
        int i = mySetupString.IndexOf("\r");
        string mySubstring = "";
        string[] myParam;
        int j=0;
        while ((i < mySetupString.Length) && (i != -1))
        { 
            //split the substring in 3
            mySubstring = mySetupString.Substring(j, i - j);
            myParam = mySubstring.Split(ParamSeparator);
            mLegoLight = new LegoLight();
            mLegoLight.Name = myParam[0];
            int myint = 0;
            Convert.ToInt(myParam[1], out myint);
            mLegoLight.Network = (byte)myint;
            Convert.ToInt(myParam[2], out myint);
            mLegoLight.PosX = myint;
            Convert.ToInt(myParam[3], out myint);
            mLegoLight.PosY = myint;
            myLegoLight.Add(mLegoLight);
    
            //next string
            j = i+1;
            if (j < mySetupString.Length)
                i = mySetupString.IndexOf("\r", j);
            else
                i = -1;
            
        }
        fileToRead.Close();
    }
    catch (Exception e)
    {
        if (fileToRead != null)
        {
            fileToRead.Close();
        }
        throw e;
    }

    First, it create the LegoLight array and a file stream. Then, in a try catch, it starts to open and read the content of the file. See the previous post for most details on how to read a file on a SD. Please note here that the file as to be smaller than the max size of the buffer. For the netduino it is 1024. So the total length of the setup file has to be smaller than 1K. 1 LegoLight is about 35o so it allow to store about 30 objects. Which is quite enough for my needs. I did not test it in my code. I’m the only user of the solution and if I distribute it, I’ll have to do couple of additional check. But as we are in a try catch section, the code will just raise an exception and it will continue to work anyway.

    The second part is more interesting as it is where the parameters will be read and converted. First the buffer is converted into a string. the mySetupString now contains strings that’s has to be analyzed. I had 2 ways to do it there. The first one was to split the string using mySubstring.Split function with the "’\r’ and then for each object in the string, split it again finding the ‘;’. I did it for the first part in the “old way” with a simple while loop and finding the next occurrence of the ‘\r’. That is basically what the Split function is doing anyway to produce the array of strings.

    mySetupString = new String(Encoding.UTF8.GetChars(buf));
    //find "\r"
    int i = mySetupString.IndexOf("\r");
    string mySubstring = "";
    string[] myParam;
    int j=0;
    while ((i < mySetupString.Length) && (i != -1))
    { 
        //split the substring in 3
        mySubstring = mySetupString.Substring(j, i - j);
        myParam = mySubstring.Split(ParamSeparator);
        mLegoLight = new LegoLight();
        mLegoLight.Name = myParam[0];
        int myint = 0;
        Convert.ToInt(myParam[1], out myint);
         mLegoLight.Network = (byte)myint;
        Convert.ToInt(myParam[2], out myint);
        mLegoLight.PosX = myint;
        Convert.ToInt(myParam[3], out myint);
        mLegoLight.PosY = myint;
        myLegoLight.Add(mLegoLight);
    
        //next string
        j = i+1;
        if (j < mySetupString.Length)
            i = mySetupString.IndexOf("\r", j);
        else
            i = -1;
        
    }

    When a line of parameters like “station;1;208;300” is in the myParam string array, the first param contains “station”, the second one “1”, the third one “208” and the last one “300”. As the numbers are in a string format, they need to be converted into real numeric numbers. In a previous post, I’ve created couple of functions that allow an easy conversion, that’s the job of the Convert.ToInt function. The LegoLight object is then added to the array.

    This is an easy and cheap way in terms of memory print to read a setup file and restore the state of objects. For biggest objects or file, you’ll may have to store the binary representation of the data and read by chunk. that should be as efficient but use less memory print. And ob course, avoid XML format they are too big and too costly in foot print. Remember, you have very limited resources, you need to tune them and make sure you are using them very carefully.

    If you want to save your parameters, here is the code (in the previous code, ParamSeparator = ‘;’). Nothing really complicated, it just create a string with all the parameters, add the separators and finally saved them in a file.

    string strSer = "";
    LegoLight mLegoLight;
    for(int i=0; i<myLegoLight.Count; i++)
    {
        mLegoLight=(LegoLight)myLegoLight[i];
        strSer += mLegoLight.Name + ";" 
    + mLegoLight.Network.ToString() + ";"
    + mLegoLight.PosX.ToString() + ";"
    + mLegoLight.PosY.ToString() + '\r'; } File.WriteAllBytes(strDefaultDir + "\\" + strFileSetup, Encoding.UTF8.GetBytes(strSer));

    If you do it in your code, don’t forget the try catch section and make sure you do not exceed the capacity of the memory for string objects. Remember it is 1024 char in netduino. So the build string has to be smallest. If not, you’ll have to write the file by small write up to the end. You’ll need to open the file before the loop, and write each stream in the file each time and finally close the file. And again, don’t forget the try catch. You never know what can happen. And as you are designing an embedded system, it has to work and just work!

    So I hope I’ve shown you the basic method to read a setup file and save it. Nothing really complicated there. I’m just a marketing director writing code mainly in planes and testing back home Sourire

Page 1 of 1 (3 items)