Friday, September 21, 2012

POST image from webcam in Silverlight window to MVC Controller

POST image from webcam in Silverlight window to MVC Controller

I have an MVC 4 application with a button for taking a photo that opens up a new window with javascript which contains a silverlight application in it. The silverlight application can then take a photo using the webcam and store it as a Writeable Bitmap. What I would like to do is then push that bitmap onto an action in my controller for saving to the database and refreshing the view.

I know I need to send the image as a post to my controller, but any code examples or suggestions on how I would go about doing that would be greatly appreciated. I think it should work as follows, Button Click for saving the image in my silverlight application would call a POST to the MVC controller and attach the image stream as a parameter in the controller, and the controller can then take the stream and push it up to the database then I can close the silverlight window. Just not sure how to go about coding that.

Answers & Comments...

Answer: 1

You could send the image using a WebClient. Let's suppose that you have the image inside your Silverlight application in a byte array:

byte[] image = ... get the image from your webcam var client = new WebClient(); var uri = new Uri("http://example.com/photos/upload"); client.OpenWriteCompleted += (sender, e) => {     var buffer = (byte[])e.UserState;     e.Result.Write(buffer, 0, buffer.Length);     e.Result.Close(); }; client.OpenWriteAsync(uri, "POST", image); 

and on the MVC side:

[HttpPost] public ActionResult Upload() {     byte[] image = new byte[Request.InputStream.Length];     Request.InputStream.Read(image, 0, image.Length);     // TODO: do something with the uploaded image here ... } 
by : Darin Dimitrovhttp://stackoverflow.com/users/29407

Answer: 2

Thank you for the reply. This is exactly what I was looking for, however ive run into a problem. Silverlight gives me the webcam snapshot as a WriteableBitmap type. Which I then tried to convert to a byte[] array before sending it over to MVC. It is saving to the database successfully, however it does not appear to be a valid image when I try to pull it back out from the database and display it. Is there an issue that you can see with my conversion code? Or perhaps can I send it over as an image type, or can I only send over byte[] arrays through http posts like this?

In my Silverlight application:

    private void SendImage()     {         var client = new WebClient();         var uri = new Uri("http://localhost:4600/GuestBadge/GetCameraImage");         client.OpenWriteCompleted += (sender, e) =>         {             var buffer = (byte[])e.UserState;             e.Result.Write(buffer, 0, buffer.Length);             e.Result.Close();         };         client.OpenWriteAsync(uri, "POST", ToByteArray(SnapShot));     }      public static byte[] ToByteArray(WriteableBitmap bmp)     {         // Init buffer         int w = bmp.PixelWidth;         int h = bmp.PixelHeight;         int[] p = bmp.Pixels;         int len = p.Length;         byte[] result = new byte[4 * w * h];          // Copy pixels to buffer         for (int i = 0, j = 0; i < len; i++, j += 4)         {             int color = p[i];             result[j + 0] = (byte)(color >> 24); // A             result[j + 1] = (byte)(color >> 16); // R             result[j + 2] = (byte)(color >> 8);  // G             result[j + 3] = (byte)(color);       // B         }          return result;     } 

And in my controller:

    [HttpPost]     public ActionResult GetCameraImage()     {         byte[] image = new byte[Request.InputStream.Length];         Request.InputStream.Read(image, 0, image.Length);         var getPerson = (from a in db.Persons where a.PersonID == 3 select a).FirstOrDefault();         getPerson.Picture = image;         db.SaveChanges();         return null;     } 
by : Bacarathttp://stackoverflow.com/users/1159181

Answer: 3

I ended up using FJCore http://code.google.com/p/fjcore/ to encode my WriteableBitmap into JPEG and then converted that to BASE64 using code I found at this question Using FJCore to encode Silverlight WriteableBitmap THANKS!. Then in turn converted that out to a byte[] array and sent it to MVC using your code and now its working great. I'm pretty new at all this stuff and didn't quite understand the encoding process enough before. Below is the code I used for this. Thanks again for your help!

    private static string GetBase64Jpg(WriteableBitmap bitmap)     {         int width = bitmap.PixelWidth;         int height = bitmap.PixelHeight;         int bands = 3;         byte[][,] raster = new byte[bands][,];          for (int i = 0; i < bands; i++)         {             raster[i] = new byte[width, height];         }          for (int row = 0; row < height; row++)         {             for (int column = 0; column < width; column++)             {                 int pixel = bitmap.Pixels[width * row + column];                 raster[0][column, row] = (byte)(pixel >> 16);                 raster[1][column, row] = (byte)(pixel >> 8);                 raster[2][column, row] = (byte)pixel;             }         }          ColorModel model = new ColorModel { colorspace = ColorSpace.RGB };         FluxJpeg.Core.Image img = new FluxJpeg.Core.Image(model, raster);         MemoryStream stream = new MemoryStream();         JpegEncoder encoder = new JpegEncoder(img, 90, stream);         encoder.Encode();          stream.Seek(0, SeekOrigin.Begin);         byte[] binaryData = new Byte[stream.Length];         long bytesRead = stream.Read(binaryData, 0, (int)stream.Length);          string base64String =                 System.Convert.ToBase64String(binaryData,                                               0,                                               binaryData.Length);          return base64String;     }       private void SendImage()     {         var client = new WebClient();         var uri = new Uri("http://localhost:4600/GuestBadge/GetCameraImage");         client.OpenWriteCompleted += (sender, e) =>         {             var buffer = (byte[])e.UserState;             e.Result.Write(buffer, 0, buffer.Length);             e.Result.Close();         };         client.OpenWriteAsync(uri, "POST", Convert.FromBase64String(GetBase64Jpg(SnapShot)));     } 
by : Bacarathttp://stackoverflow.com/users/1159181




No comments:

Post a Comment

Send us your comment related to the topic mentioned on the blog