Image serialization

Hi everybody,

I’m working on a project that need to send a image from a pc to the chipworkx, the project its implemented throught WCF on MF 4.1 and the ChipworkX works like a client on this process.

I have tried to convert the image to string base 64 and it work, but the response time its excessive (about a minute). I have thought on use DataContract Serialization but i’m not sure if that would work, hope you can give me some clues and ideas

Thanks

Welcome to the forum!

How big is the image and what do you do with it after you get it to ChipworkX?

Hi, thanks for the quick attention,

The image is about 15 - 25KB, and it’s use is very simple, i display it on screen next to some text info about the image.

You say the response time is excessive, but you have not explained what this means. Do you mean the time it takes to convert to string base 64, or the time it takes to send the image to the chipworkx?

What method are you using to transfer the image to the chipworkx? Ethernet or serial?

Have you tried to determine exactly what step of the process is the bottleneck?

We need more details to help you.

Can you show us chipworkx code? How is chipworkX connected to the pc?

Thanks again for the atention,

Sorry for the lack of details, but i’ll try to be more precise,

  1. About the response time i was talking about the time it takes to deserialize the data from base64 it takes about 40 seconds to 1,2 minutes. And this process its the bottleneck, cause the transfer from the PC works fine.

  2. I’m using ethernet, to be more detailed, im using dpws to do the process.

Why are you converting the image? Why not send the image in BMP or JPG file format?

I serialized the image because I thought it takes less time to transfer the data, but did you mean to send it straight???

Another detail that i forgot to say about why im serializing the image its that im sending another data along with it as part of a DataContract

Conversion to a base 64 string does not reduce the amount of data. It actually increase the size of the data. If you can send it straight, do it.

As far as DataContracts and DPWS… I am not sure what DataContract means. Is this a DPWS term?

I have not heard of many people using DPWS. Seems like overkill for these small devices.

Actually DataContracts and DPWS are part of WCF, dpws its a set of minimal requirements that let devices detect other dpws enabled devices over a network and consume their web service, for the specific case of ChipworkX it has support for it.

Base64 is generally used to convert bytes to strings. So the 256 base byte is converted to some 64 base chars (which are sent as bytes over ethernet). So you actually increase the amount of data transfered. Also, the conversion between bases adds some extra time.

base64 increase the data by 33%

Thanks for the replies, i have made some test without serialize and it seems to work just fine, but now i have another issue, i’m using ws2007http binding and it seems to have a limited buffer size, it’s there a way to increase the size???

This is my code for the server on the PC:


 [ServiceContract(Namespace = "http://192.168.1.101:8090/")]
    public interface IInfoService
    {

        [OperationContract]
        EmployeeInfo GetEmployeeInfo(string message);

        byte[] ImageToByte(string message);
    }
 

[ServiceBehavior(Namespace = "http://192.168.1.101:8090/")]
    public class InfoService : IInfoService
    {
        EmployeeInfo employee = new EmployeeInfo();

        public EmployeeInfo GetEmployeeInfo(string message)
        {
            employee.photo = ImageToByte(@ "C:\" + message);
            employee.Name = "Snake";
            employee.ID = 666;
            return employee;
        }

        public byte[] ImageToByte(string message)
        {
            Bitmap bmp = new Bitmap(message);
            MemoryStream ms = new MemoryStream();
            bmp.Save(ms, ImageFormat.Jpeg);
            byte[] bmpBytes = ms.GetBuffer();
            bmp.Dispose();
            ms.Close();
            return bmpBytes;
        }
    }


[DataContract(Namespace = "http://192.168.1.101:8090/")]
    public class EmployeeInfo
    {
        private string eName;
        private int eId;
        private byte[] jpegImage;

        [DataMember]
        public string Name
        {
            get { return eName; }
            set { eName = value; }
        }

        [DataMember]
        public int ID
        {
            get { return eId; }
            set { eId = value; }
        }

        /*public ServerImage(string jpegPath)
        {
            this.jpegImage = Image.FromFile(jpegPath);
        }*/

        [DataMember]
        public byte[] photo
        {
            get { return jpegImage; }
            set { jpegImage = value; }
        }
    }

And this is the web.config for the server


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

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <bindings>
      <ws2007HttpBinding>
        <binding name="binding" maxBufferPoolSize="9999999" maxReceivedMessageSize="9999999"
          messageEncoding="Mtom">
          <readerQuotas maxDepth="9999999" maxStringContentLength="9999999"
            maxArrayLength="9999999" maxBytesPerRead="9999999" maxNameTableCharCount="9999999" />
        </binding>
      </ws2007HttpBinding>
    </bindings>
    <services>
      <service name="OvasysHumanInfo.InfoService">
        <clear/>
        <endpoint address="" binding="ws2007HttpBinding"
          bindingConfiguration="binding" contract="OvasysHumanInfo.IInfoService"
          listenUriMode="Explicit">          
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
          contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
          <serviceDiscovery/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
  
</configuration>

As you can see the reader quotas are fine, but this is on server side. This is the code that i’m deploying on the chipworkx



    public class Program : Microsoft.SPOT.Application
    {
        //Windows
        private Window mainWindow;
        private Image imageView;

        public static void Main()
        {
            Program myApplication = new Program();

            Window mainWindow = myApplication.CreateWindow();

            // Create the object that configures the GPIO pins to buttons.
            GPIOButtonInputProvider inputProvider = new GPIOButtonInputProvider(null);

            // Start the application
            myApplication.Run(mainWindow);
        }

        public void GetImage(ClientApp test)
        {
            NetworkInterface networkInterface;

            while (true)
            {
                networkInterface = NetworkInterface.GetAllNetworkInterfaces()[0];
                if (networkInterface.IPAddress != "0.0.0.0") break;

                Thread.Sleep(1000);
            }

            test.Run();
            Debug.Print(test.response.GetEmployeeInfoResult.photo.ToString());
            Deserialize(test.response.GetEmployeeInfoResult.photo);

        }

        public Window CreateWindow()
        {
            // Create a window object and set its size to the
            // size of the display.
            mainWindow = new Window();
            mainWindow.Height = SystemMetrics.ScreenHeight;
            mainWindow.Width = SystemMetrics.ScreenWidth;
            mainWindow.Background = new SolidColorBrush(Color.Black);

            imageView = new Image();
            imageView.HorizontalAlignment = Microsoft.SPOT.Presentation.HorizontalAlignment.Center;
            imageView.VerticalAlignment = Microsoft.SPOT.Presentation.VerticalAlignment.Center;
            mainWindow.Child = imageView;
            
            // Connect the button handler to all of the buttons.
            mainWindow.AddHandler(Buttons.ButtonUpEvent, new RoutedEventHandler(OnButtonUp), false);

            // Set the window visibility to visible.
            mainWindow.Visibility = Visibility.Visible;

            // Attach the button focus to the window.
            Buttons.Focus(mainWindow);

            return mainWindow;
        }

        private void OnButtonUp(object sender, RoutedEventArgs evt)
        {
            ClientApp test = new ClientApp();
            GetImage(test);              
        }

        public void Deserialize(byte[] byteArray)
        {
                     
            if (byteArray.Length > 0)
            {
                mainWindow.Background = new SolidColorBrush(Colors.Black);
                imageView.Bitmap = new Bitmap(byteArray, Bitmap.BitmapImageType.Jpeg);
                imageView.Invalidate();
            }            
        }
    }


public class ClientApp
    {
        IInfoServiceClientProxy m_clientProxy;
        public GetEmployeeInfoResponse response;

        private bool Discover(IInfoServiceClientProxy proxy)
        {
            DpwsServiceTypes typeProbes = new DpwsServiceTypes();
            typeProbes.Add(new DpwsServiceType("IInfoService", "http://192.168.1.101:8090/InfoService"));

            DpwsServiceDescriptions descriptions = proxy.DiscoveryClient.Probe(typeProbes, 1, 2000);

            if (descriptions.Count > 0)
            {
                proxy.EndpointAddress = descriptions[0].Endpoint.Address.AbsoluteUri;
                return true;
            }

            return false;
        }

        public void Run()
        {
            Uri remoteEp = new Uri("http://192.168.1.101:8090/InfoService");
            
            HttpTransportBindingConfig tbc = new HttpTransportBindingConfig(remoteEp);
            HttpTransportBindingElement el = new HttpTransportBindingElement(tbc);
            ArrayList al = new ArrayList();
            
            WS2007HttpBinding binding = new WS2007HttpBinding(tbc, al);
            binding.Elements.GetBindingProperty("maxBufferPoolSize");


            ProtocolVersion ver = new ProtocolVersion11();
            m_clientProxy = new IInfoServiceClientProxy(binding, ver);
            m_clientProxy.IgnoreRequestFromThisIP = false;

            if (!Discover(m_clientProxy))
            {
                Debug.Print("Error");
                m_clientProxy.EndpointAddress = "http://192.168.1.101:8090/InfoService";
            }

            GetEmployeeInfo req = new GetEmployeeInfo();
            req.message = "death.jpg";

            try
            {
                response = m_clientProxy.GetEmployeeInfo(req);                             
            }
            catch (WsFaultException ex)
            {
                Debug.Print("DPWS Fault: " + ex.Message);
            }
            finally
            {
                m_clientProxy.Dispose();
            }

        }
        
    }