none
Uploading (WCF Service) png image directly from windows.controls.image using EditableImage and Pngencoder (Joe Stegman)

    Question

  • I have found this brilliant blog and tutorial from Victor Gaudioso here :

    http://victorgaudioso.wordpress.com/2010/05/01/new-silverlight-video-tutorial-how-to-save-an-image-in-your-silverlight-applications/

    I have applied it to my project and it works perfectly to save images to local disk.

    What I am trying to do now is using the same logic to upload the image to the server using a WCF Service. I am already successfully doing that using the OpenfileDialog and with jpeg files but I thought it would be great to be able to upload .png files directly from the image control in silverlight. I this can be done to save the files, it should be possible to upload the files and save them on the server.

    Unfortunately I didn't get this to work so far, so being a beginner, I may overlook something.

    The png files I am trying to upload are userpictures 100x100 and always end up to be 39.2 KB in size (just in case that is important). They end up in the image control (itself in a canvas - ImgHolder) after a crop operation. Saving the file is no problem, so the process works perfectly.

    What follows is the code I use to save the file (working well) and the code I am attempting to use to upload the image (not working). I am also posting the Server side code.

    Some help would be very much appreciated, I am obviously overlooking something.  

    private void SaveTheImg(FrameworkElement Holder)
            {
                WriteableBitmap _bitmap = new WriteableBitmap(Holder, null);
                SaveFileDialog sfd = new SaveFileDialog();
                sfd.Filter = "PNG Files (*.png)|*.png|All Files (*.*)|*.*";
                sfd.DefaultExt = ".png";
                sfd.FilterIndex = 1;
    
                if ((bool)sfd.ShowDialog())
                {
                    using (Stream fs = sfd.OpenFile())
                    {
                        int width = _bitmap.PixelWidth;
                        int height = _bitmap.PixelHeight;
    
                        EditableImage ei = new EditableImage(width, height);
    
                        for (int i = 0; i < height; i++)
                        {
                            for (int j = 0; j < width; j++)
                            {
                                int pixel = _bitmap.Pixels[(i * width) + j];
                                ei.SetPixel(j, i,
                                            (byte)((pixel >> 16) & 0xFF),
                                            (byte)((pixel >> 8) & 0xFF),
                                            (byte)(pixel & 0xFF),
                                            (byte)((pixel >> 24) & 0xFF)
                                );
                            }
                        }
                        Stream png = ei.GetStream();
                        int len = (int)png.Length;
                        byte[] bytes = new byte[len];
                        png.Read(bytes, 0, len);
                        fs.Write(bytes, 0, len);
                        
                    }
                    
                }
            }
    private void UploadTheImg(FrameworkElement Holder)
            {
                WriteableBitmap _bitmap = new WriteableBitmap(Holder, null);
      
                        int width = _bitmap.PixelWidth;
                        int height = _bitmap.PixelHeight;
    
                        EditableImage ei = new EditableImage(width, height);
    
                        for (int i = 0; i < height; i++)
                        {
                            for (int j = 0; j < width; j++)
                            {
                                int pixel = _bitmap.Pixels[(i * width) + j];
                                ei.SetPixel(j, i,
                                            (byte)((pixel >> 16) & 0xFF),
                                            (byte)((pixel >> 8) & 0xFF),
                                            (byte)(pixel & 0xFF),
                                            (byte)((pixel >> 24) & 0xFF)
                                );
                            }
                        }
                        byte[] bytes;
                        using (Stream png = ei.GetStream())
                        {
                            int len = (int)png.Length;
                            bytes = new byte[len];
                            png.Read(bytes, 0, len);
                            png.Close();
                        }                    
                        var usr = WebContext.Current.User.Name.ToLower();
                        PictureServiceClient service = new PictureServiceClient();
                        service.SaveImageAsync(bytes, usr);
            }
     void ImgHolder_MouseLeftButtonDown(object Sender, MouseButtonEventArgs e)
            {
                if (cropControl.Source != null)
                {
                    SaveTheImg(ImgHolder);
                }
                else
                {
                    tbCropControlEmpty.Visibility = Visibility.Visible;
                    tbPlsLogin.Visibility = Visibility.Collapsed;
                }
            }
    private void btnUpload_Click(object sender, RoutedEventArgs e)
            {
                if (WebContext.Current.User.IsAuthenticated)
                {     
    UploadTheImg(ImgHolder);
    }                                          
    [OperationContract]
            public void SaveImage(byte[] ImageData, string usr)
            {
                // Save your image here, you have the bytes now; the power is in your hands
                string path = HttpContext.Current.Server.MapPath("~/UserPictures");
                string filePath = path + "/" + usr + ".png";
                FileStream pictureStream = new FileStream(filePath, FileMode.Create);
                pictureStream.Write(ImageData, 0, ImageData.Length);
                pictureStream.Close();
                
            }







    Tuesday, July 31, 2012 11:05 AM

Answers

  • Victor Gaudioso was a great guy, his tutorials are most helpfull! 

    Here's my solution:

    Client Side:
    private void LoadWebImage(string path, int prepath)
            {
                //load the png file from storage to web site
                ImageTransfer FS = new ImageTransfer();
                byte[] fileContent;
                using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    using (var isoStream = store.OpenFile("Tempfile.png", FileMode.Open))
                    {
                        BinaryReader bin = new BinaryReader(isoStream);
                        fileContent = bin.ReadBytes((int)isoStream.Length);
                        FS.UploadImage("Tempfile.png", fileContent);
                        bin.Dispose();
                    }
                }
            }
    And in the web app.
    
    

    [EnableClientAccess()]
    public class ImageTransfer : DomainService
    {

    [Invoke]
    public void UploadImage(string FileName, byte[] Data)
    {
     string MyStr = HttpContext.Current.Server.MapPath("~/ClientBin/Bin");
     MyStr = string.Format("{0}\\{1}.png", MyStr, FileName);

    if (File.Exists(MyStr)) File.Delete(MyStr); // delete file if already used
    File.WriteAllBytes(MyStr, Data);
    }


     
    
    


    Tuesday, July 31, 2012 6:53 PM
  • I use isolated storage to resize and save in png format the file provided by the client (drag/down) before sending it to web.

    Using isolated storage is not that difficult - this link is a good example:

    http://www.c-sharpcorner.com/UploadFile/74f20d/using-isolated-storage-to-save-and-read-an-image-in-windows/

    and the following about images

    http://blog.meidianto.com/2009/10/13/working-with-imagesource-on-silverlight-3/

    Wednesday, August 01, 2012 4:04 AM

All replies

  • Why use the Image stuff?  Just send the bytes of the file.

    Tuesday, July 31, 2012 2:42 PM
  • That's exactly what I am doing, obviously without success.

    Tuesday, July 31, 2012 6:28 PM
  • Victor Gaudioso was a great guy, his tutorials are most helpfull! 

    Here's my solution:

    Client Side:
    private void LoadWebImage(string path, int prepath)
            {
                //load the png file from storage to web site
                ImageTransfer FS = new ImageTransfer();
                byte[] fileContent;
                using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    using (var isoStream = store.OpenFile("Tempfile.png", FileMode.Open))
                    {
                        BinaryReader bin = new BinaryReader(isoStream);
                        fileContent = bin.ReadBytes((int)isoStream.Length);
                        FS.UploadImage("Tempfile.png", fileContent);
                        bin.Dispose();
                    }
                }
            }
    And in the web app.
    
    

    [EnableClientAccess()]
    public class ImageTransfer : DomainService
    {

    [Invoke]
    public void UploadImage(string FileName, byte[] Data)
    {
     string MyStr = HttpContext.Current.Server.MapPath("~/ClientBin/Bin");
     MyStr = string.Format("{0}\\{1}.png", MyStr, FileName);

    if (File.Exists(MyStr)) File.Delete(MyStr); // delete file if already used
    File.WriteAllBytes(MyStr, Data);
    }


     
    
    


    Tuesday, July 31, 2012 6:53 PM
  • Thank you John,

    If I understand this right, you want to store a temporary file in the isolated storage and retrieve it from there to upload.

    I got as far of successfully having the file saved by the user by using the savefiledialog. Of course your solution is much better, especially in view of the user initiated restrictions in Silverlight.  The problem is I have no idea (yet) how to use the isolated storage :). I can of course read up on this but a little help would be more than welcome, I am planning and will need to use this in the future in my project. f.y.i. Saving the image follows exactly the procedure from V.G. (see my code)

    Regarding the web part, I am using a WCF service called "PictureServices" (see my code) but could switch. The filepath is constructed on the server using the username passed by the client.

     public void SaveImage(byte[] ImageData, string usr)
            {
                
                string path = HttpContext.Current.Server.MapPath("~/UserPictures");
                string filePath = path + "/" + usr + ".png";
                FileStream pictureStream = new FileStream(filePath, FileMode.Create);
                pictureStream.Write(ImageData, 0, ImageData.Length);
                pictureStream.Close();            
            }

    I have been working with Jpeg images using this service using the openfiledialog and that works very well.

    Thank you very, very much for your help.

    Marc 

          

    Tuesday, July 31, 2012 9:48 PM
  • I use isolated storage to resize and save in png format the file provided by the client (drag/down) before sending it to web.

    Using isolated storage is not that difficult - this link is a good example:

    http://www.c-sharpcorner.com/UploadFile/74f20d/using-isolated-storage-to-save-and-read-an-image-in-windows/

    and the following about images

    http://blog.meidianto.com/2009/10/13/working-with-imagesource-on-silverlight-3/

    Wednesday, August 01, 2012 4:04 AM
  • Well John, it's done :)

    In the mean time I came to terms with Isolated storage.

    I have used the domainservice as suggested. I tried with the existing service but failed somehow. The filename is now constructed on the client.

    So, I learned a lot, all thanks to you putting me on the right track.

    If you allow me, I will post this solution on here, this will definitely help other newbies.

    I will also let you know when I have deployed  the update including this part to the server.

    Thanks again, and I hope we can stay in touch.

    I can definitely mark this as answered.

    MARC

    Wednesday, August 01, 2012 1:15 PM