the data received for the graph is as under  "OBX|32|ED|15000^WBC Histogram. Binary^99MRC||^Application^Octer-stream^Base64^AAAAAAAAAAAAAAABAgQHDRcmO1Z3nMPg9P/98+HKsZl8aFdGMyUfHBwcHR8iJy02QUpLTU5PT09P

deepu Lovelesh
deepu Lovelesh used Ask the Experts™
on
the data received from the machine is as under and need to build the graph from the data received as under:-

"OBX|32|ED|15000^WBC Histogram. Binary^99MRC||^Application^Octer-stream^Base64^AAAAAAAAAAAAAAABAgQHDRcmO1Z3nMPg9P/98+HKsZl8aFdGMyUfHBwcHR8iJy02QUpLTU5PT09PTUxKSEZEQkBAPz4+PT09Pj49PDo5ODg3Nzg6PD5AQ0ZISUpMTU9RU1VWWFlZWlpaWlpaWlpbW1tbW1tcXV5fYGBhYWBgXl1bWVdVU1JQT01MSkhGREJAPj07OTg2NDMxLy0sKignJSQi"

or
"OBX|36|NM|15057^RBC Histogram. Total^99MRC||43822||||||F
OBX|37|ED|15050^RBC Histogram. Binary^99MRC||^Application^Octer-stream^Base64^AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAgIDAwUGCg4TGiIuOklYaX2OoLHD1OLu+P3//vny593Sw7Snmo1/dWthWFBJQjw2Mi8sKSclIyIgHx4cHBoaGBcWFBQTExISERAQEA8PDw4MDAsKCgoJCAgIBwcGBwcGBgYGBQQEBAQDBAMDAwMDAgICAgICAgEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==||||||F"

or

"OBX|42|ED|15100^PLT Histogram. Binary^99MRC||^Application^Octer-stream^Base64^HR0MHQwMFB0VDAsMDxQiHRoVEAwLCwsMDg8QFBoiLB0cGhcVEhAODAsLCwsLCwwMDQ4ODw8QEhQXGh4iJywzHRwcGxoZFxYVFBIREA8ODQwMCwsLCwsLCwsLCwsLDAwMDA0NDg4ODw8PDxAQERITFBYXGRocHiAiJCcpLDAzOB0=||||||F
"


would really be thankful if you could help to create a graph from above sequence.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Darrell PorterEnterprise Business Process Architect

Commented:
Public Function ConvertBase64ToByteArray(base64 As String) As Byte()
    Return Convert.FromBase64String(base64) 'Convert the base64 back to byte array.
End Function

Private Function convertbytetoimage(ByVal BA As Byte())
    Dim ms As MemoryStream = New MemoryStream(BA)
    Dim image = System.Drawing.Image.FromStream(ms)
    Return image
End Function

Open in new window


Just as a side note, where are these base64 strings coming from?

Author

Commented:
Dear Darrell

i had already tried the above method but i am getting error "Parameter is not valid" on this line
"Dim image = System.Drawing.Image.FromStream(ms)".


and answer to your query is that it is coming from a machine.
All your samples contains raw binary data encoding with base64. Not text (ASCII or unicode), not known image (gif,png,jpg,bmp). Just byte array. You need to know algorithm to plot these bytes - check user manual.
Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

Author

Commented:
Dear Ark

attached is the protocol manual for your reference and attached is the required graph output from the stream. can you please help me out to understand the same and generate the required graph.IMG-20181110-WA0000.jpg
Your help to generate this graph is really a great help and thanks a ton in advance.
BC-5800-LIS-Protocol-Manua.pdf
According manual "Application^Octer-stream^Base64" is application binary data, i.e. there is specific app which read base64 string, convert it to byte array and then plot the graph using  some algorithm. But luckely investigating bytes values I found that each byte seems to be an y-coordinate of graph. So:
Public Class OBXGraph
    Inherits PictureBox

    Private pts As New List(Of Point)
    Private count, m As Integer

    Public Sub Draw(b64 As String)
        Dim idx = b64.IndexOf("Octer-stream^Base64^")
        If idx = -1 Then idx = 0 Else idx += "Octer-stream^Base64^".Length
        Dim bytes = Convert.FromBase64String(b64.Substring(idx))
        pts.Clear()
        count = 0 : m = 0
        For Each b In bytes
            If b > m Then m = b
            pts.Add(New Point(count, b))
            count += 1
        Next
        Me.Invalidate()
    End Sub
    Protected Overrides Sub OnPaint(pe As PaintEventArgs)
        MyBase.OnPaint(pe)
        If pts.Count = 0 Then Return
        Dim dx = (Me.Width - 20) / count, dy = (20 - Me.Height) / m
        With pe.Graphics
            .ScaleTransform(dx, dy)
            .TranslateTransform(10 / dx, (-50 - Me.Height))
            .DrawCurve(Pens.Black, pts.ToArray)
        End With
    End Sub
End Class

Open in new window

Add this class to your project, build solution, add OBXGraph control on form and call:
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim s = "OBX|32|ED|15000^WBC Histogram. Binary^99MRC||^Application^Octer-stream^Base64^AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAgIDAwUGCg4TGiIuOklYaX2OoLHD1OLu+P3//vny593Sw7Snmo1/dWthWFBJQjw2Mi8sKSclIyIgHx4cHBoaGBcWFBQTExISERAQEA8PDw4MDAsKCgoJCAgIBwcGBwcGBgYGBQQEBAQDBAMDAwMDAgICAgICAgEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
        ObxGraph1.Draw(s)
    End Sub

Open in new window

PS. Alternatively you can plot graph in excel. Add reference to excel.
Imports Excel = Microsoft.Office.Interop.Excel

Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim s = "OBX|32|ED|15000^WBC Histogram. Binary^99MRC||^Application^Octer-stream^Base64^AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAgIDAwUGCg4TGiIuOklYaX2OoLHD1OLu+P3//vny593Sw7Snmo1/dWthWFBJQjw2Mi8sKSclIyIgHx4cHBoaGBcWFBQTExISERAQEA8PDw4MDAsKCgoJCAgIBwcGBwcGBgYGBQQEBAQDBAMDAwMDAgICAgICAgEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
        GraphToExcel(s)
    End Sub

    Private Sub GraphToExcel(b64 As String)
        Dim idx = b64.IndexOf("Octer-stream^Base64^")
        If idx = -1 Then idx = 0 Else idx += "Octer-stream^Base64^".Length
        Dim bytes = Convert.FromBase64String(b64.Substring(idx))
        Dim app = New Excel.Application
        app.Visible = True
        Dim wb = app.Workbooks.Add
        Dim sheet As Excel.Worksheet = wb.Sheets(1)
        For i = 1 To bytes.Count
            sheet.Range("A" & i).Value2 = bytes(i - 1)
        Next
        Dim charts As Excel.ChartObjects = sheet.ChartObjects()
        Dim chartObject = charts.Add(60, 10, 600, 300)
        Dim chart = chartObject.Chart
        Dim rng = sheet.Range("A1:A" & bytes.Count.ToString)
        chart.SetSourceData(rng)

        chart.ChartType = Excel.XlChartType.xlLine
        chart.ChartWizard(Source:=rng)
    End Sub
End Class

Open in new window

PS2. Note that OBX Histogram looks like expected while PLT is different (see attached)OBXPLT

Author

Commented:
Thanks Ark

Wonderful answer and demo.

Cheers.......
Imports System.ComponentModel

Public Class LIS_Graph
    Inherits PictureBox

    Public Class MsgInfo
        Public Property MessageType As String
        Public Property SequenceId As String
        Public Property DataType As String
        Public Property ObservationID As String
        Public Property ObservationName As String
        Public Property EncodeSys As String
        Public Property Value As String
        Public Property Units As String
        Public Property RefRange As String
        Public Sub Clear()
            MessageType = "" : SequenceId = "" : DataType = "" : ObservationID = "" : ObservationName = "" : EncodeSys = "" : Value = "" : Units = "" : RefRange = ""
        End Sub
        Public Overrides Function ToString() As String
            Dim sb As New Text.StringBuilder
            For Each p In [GetType].GetProperties(Reflection.BindingFlags.Public Or Reflection.BindingFlags.Instance)
                Dim s As String = p.GetValue(Me)
                sb.AppendLine(String.Format("{0}: {1}", p.Name, s))
            Next
            Return sb.ToString
        End Function

    End Class

    Private _graphBytes As Byte()
    Private _lblInfo As New Label With {.AutoSize = False, .Width = 240, .Height = 140, .BorderStyle = BorderStyle.FixedSingle, .Padding = New Padding(5)}
    Public Sub New()
        Info = New MsgInfo
        SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
        Controls.Add(_lblInfo)
    End Sub
    Public Sub New(msg As String)
        Info = New MsgInfo
        SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
        Message = msg
    End Sub

    <TypeConverter(GetType(PointFConverter)), DefaultValue(GetType(PointF), "1.4, 1.0")> Public Property UnitsScale As PointF = New PointF(1.4F, 1.0F)
    <DefaultValue(GetType(Point), "50, 50")> Public Property LinesStep As Point = New Point(50, 50)
    <DefaultValue(GetType(Point), "20, 20")> Public Property Offset As Point = New Point(20, 20)
    <DefaultValue(True)> Public Property CursorLines As Boolean = True
    <DefaultValue(True)> Public Property ShowInfo As Boolean = True
    <Browsable(False)> Public ReadOnly Property Info As MsgInfo
    Public WriteOnly Property Message As String
        Set(value As String)
            Parse(value)
        End Set
    End Property

    Public Sub RefreshGraph()
        Image = CreateGraph()
        _lblInfo.Visible = ShowInfo
    End Sub

    Private ReadOnly Property GraphSize As Size
        Get
            Return New Size(Width - Offset.X * 2, Height - Offset.Y * 2)
        End Get
    End Property
    Private ReadOnly Property GraphScale As PointF
        Get
            If _graphBytes Is Nothing OrElse _graphBytes.Length = 0 Then Return New PointF(1.0, 1.0)
            Dim sz = GraphSize
            Return New PointF(sz.Width / _graphBytes.Count, sz.Height / _graphBytes.Max)
        End Get
    End Property

    Private Sub Parse(lisString As String)
        Clear()
        Dim parts = lisString.Split("|"c)
        Info.MessageType = parts(0)
        If parts.Length > 1 Then Info.SequenceId = parts(1)
        If parts.Length > 2 Then Info.DataType = parts(2)
        If parts.Length > 3 Then
            Dim observation = parts(3)
            If observation <> "" Then
                Dim oParts = observation.Split("^"c)
                Info.ObservationID = oParts(0)
                Info.ObservationName = oParts(1).Replace(". ", ".")
                Info.EncodeSys = oParts(2)
            End If
        End If
        If parts.Length > 5 Then Info.Value = parts(5)
        If Info.Value.StartsWith("^Application^Octer-stream^Base64^") Then
            _graphBytes = Convert.FromBase64String(Info.Value.Replace("^Application^Octer-stream^Base64^", ""))
            Info.Value = "Base64 encoded graph data"
            Image = CreateGraph()
        End If
        If parts.Length > 6 Then Info.Units = parts(6)
        If parts.Length > 7 Then Info.RefRange = parts(7)
        _lblInfo.Visible = ShowInfo
        _lblInfo.Text = Info.ToString
    End Sub

    Private Sub Clear()
        _graphBytes = Nothing
        Info.Clear()
        Image = Nothing
    End Sub

    Private Function CreateGraph() As Bitmap
        If _graphBytes Is Nothing OrElse _graphBytes.Length = 0 Then
            Return Nothing
        End If

        Dim graph As New Bitmap(ClientSize.Width, ClientSize.Height)
        Dim pts As New List(Of Point)
        Dim count = 0, sz = GraphSize, scale = GraphScale
        For Each b In _graphBytes
            pts.Add(New Point(count * scale.X + Offset.X, b * scale.Y + Offset.Y))
            count += 1
        Next
        Dim w = sz.Width + Offset.X, h = sz.Height + Offset.Y
        Using g = Graphics.FromImage(graph)
            g.CompositingQuality = Drawing2D.CompositingQuality.HighQuality
            g.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAliasGridFit
            Using f As New Font("Arial", 8, FontStyle.Regular, GraphicsUnit.Point)
                Using linePen = New Pen(Color.Black) With {.DashStyle = Drawing2D.DashStyle.Dash}
                    Dim sf As New StringFormat With {.Alignment = StringAlignment.Far, .LineAlignment = StringAlignment.Center}
                    For i = 0 To _graphBytes.Max * UnitsScale.Y Step LinesStep.Y
                        Dim y = h - i * scale.Y / UnitsScale.Y
                        Dim p = If(i = 0, Pens.Black, linePen)
                        g.DrawLine(p, Offset.X, y, w, y)
                        g.DrawString(i, f, Brushes.Black, Offset.X, y, sf)
                    Next
                    sf = New StringFormat With {.Alignment = StringAlignment.Center, .LineAlignment = StringAlignment.Near}
                    For i = 0 To count * UnitsScale.X Step LinesStep.X
                        Dim x = Offset.X + i * scale.X / UnitsScale.X
                        Dim p = If(i = 0, Pens.Black, linePen)
                        g.DrawLine(p, x, 0, x, h)
                        g.DrawString(i, f, Brushes.Black, x, h, sf)
                    Next
                End Using
            End Using
            g.ScaleTransform(1.0F, -1.0F)
            g.TranslateTransform(0.0F, -h - Offset.Y)
            g.DrawCurve(Pens.Black, pts.ToArray)
            g.ResetTransform()

            'If ShowInfo Then
            '    Dim rc = New Rectangle(w - 240, Offset.Y, 240, 130)
            '    g.FillRectangle(Brushes.White, rc)
            '    g.DrawRectangle(Pens.Black, rc)
            '    rc.Inflate(-5, -5)
            '    g.DrawString(Info.ToString, Font, Brushes.Black, rc)
            'End If
        End Using
        Return graph
    End Function

    Private Sub LIS_Graph_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
        If Not CursorLines OrElse _graphBytes Is Nothing OrElse _graphBytes.Length = 0 Then Return
        Refresh()
        Dim scale = GraphScale, sz = GraphSize
        Dim w = sz.Width + Offset.X, h = sz.Height + Offset.Y
        If e.X < Offset.X OrElse e.X > w OrElse e.Y < Offset.Y OrElse e.Y > h Then Return
        Using p = New Pen(Brushes.Red) With {.DashStyle = Drawing2D.DashStyle.Dash}
            Using g = Graphics.FromHwnd(Handle)
                g.DrawLine(p, 0, e.Y, Width, e.Y)
                g.DrawLine(p, e.X, 0, e.X, Height)
                Dim sf As New StringFormat With {.LineAlignment = StringAlignment.Far}
                Dim dX = If(e.X > GraphSize.Width / 2 + Offset.X, -80, 3)
                Dim pt = New Point(e.X + dX, e.Y - 3)
                Dim x As Integer = (e.X - Offset.X) * UnitsScale.X / scale.X,
                    y As Integer = (h - e.Y) * UnitsScale.Y / scale.Y
                g.DrawString(String.Format("x = {0}; y = {1}", x, y), Font, Brushes.Red, pt, sf)
            End Using
        End Using
    End Sub
    Private Sub LIS_Graph_MouseLeave(sender As Object, e As EventArgs) Handles Me.MouseLeave
        Refresh()
    End Sub
    Private Sub LIS_Graph_SizeChanged(sender As Object, e As EventArgs) Handles Me.SizeChanged
        Image = CreateGraph()
        _lblInfo.Location = New Point(GraphSize.Width + Offset.X - _lblInfo.Width, Offset.Y)
    End Sub

End Class

Public Class PointFConverter
    Inherits ExpandableObjectConverter

    Public Overrides Function CanConvertFrom(context As ITypeDescriptorContext, sourceType As Type) As Boolean
        If sourceType = GetType(String) Then
            Return True
        Else
            Return MyBase.CanConvertFrom(context, sourceType)
        End If
    End Function

    Public Overrides Function ConvertFrom(context As ITypeDescriptorContext, culture As System.Globalization.CultureInfo, value As Object) As Object
        If TypeOf value Is String Then
            Try
                Dim s As String = DirectCast(value, String)
                Dim converterParts As String() = s.Split(";"c)
                Dim x As Single = 0.0F, y As Single = 0.0F
                If converterParts.Length > 1 Then
                    x = Single.Parse(converterParts(0).Trim())
                    y = Single.Parse(converterParts(1).Trim())
                ElseIf converterParts.Length = 1 Then
                    x = Single.Parse(converterParts(0).Trim())
                End If
                Return New PointF(x, y)
            Catch
                Throw New ArgumentException("Cannot convert [" + value.ToString() + "] to pointF")
            End Try
        End If
        Return MyBase.ConvertFrom(context, culture, value)
    End Function

    Public Overrides Function ConvertTo(context As ITypeDescriptorContext, culture As System.Globalization.CultureInfo, value As Object, destinationType As Type) As Object
        If destinationType = GetType(String) AndAlso TypeOf value Is PointF Then
            Dim pt As PointF = value
            Return String.Format("{0}; {1}", pt.X, pt.Y)
        End If

        Return MyBase.ConvertTo(context, culture, value, destinationType)
    End Function
End Class

Open in new window

Using:
   Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim graph = New LIS_Graph With {.Dock = DockStyle.Fill}
        Controls.Add(graph)
        graph.Message = "OBX|32|ED|15000^WBC Histogram. Binary^99MRC||^Application^Octer-stream^Base64^AAAAAAAAAAAAAAABAgQHDRcmO1Z3nMPg9P/98+HKsZl8aFdGMyUfHBwcHR8iJy02QUpLTU5PT09PTUxKSEZEQkBAPz4+PT09Pj49PDo5ODg3Nzg6PD5AQ0ZISUpMTU9RU1VWWFlZWlpaWlpaWlpbW1tbW1tcXV5fYGBhYWBgXl1bWVdVU1JQT01MSkhGREJAPj07OTg2NDMxLy0sKignJSQi"
    End Sub

Open in new window

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial