Checksum, CRC or something better?

  • Thread starter Thread starter Bob
  • Start date Start date
Hi again Peter,

I have attempted to use this hashing code in the following scenario:

Get an image, base64 encode and write to xml file.

Reverse this process to get image file back.

Compare hashes of before and after - they do not match... image looks
identical visually, and has same filesize and other properties... can you
suggest a way I can store these images to an XML file and get the exact same
file back when I extract the image again...?

The XML code is something like this:

Private Sub WriteXMLImage(ByVal strSourceFilePathAndName As String,
Optional ByVal strTargetFilePathAndName As String = "")

If strSourceFilePathAndName <> "" Then

Dim strSourceExtension As String = ""
strSourceExtension = strSourceFilePathAndName.Substring
(strSourceFilePathAndName.Length - 3)

'Destination filename not supplied so make one up
If strTargetFilePathAndName = "" Then
strTargetFilePathAndName =
strSourceFilePathAndName.Substring(0, strSourceFilePathAndName.Length
- 3)
& "xml"
End If

Dim xmlTextWriter As New XmlTextWriter
(strTargetFilePathAndName, Encoding.UTF8)
xmlTextWriter.Formatting = Formatting.Indented
xmlTextWriter.WriteStartDocument()

' Copy the picture into a MemoryStream.
Dim memory_stream As New MemoryStream
Dim objImageOriginal As Image

objImageOriginal = New Bitmap(strSourceFilePathAndName)
'objImageOriginal = objImageOriginal.FromFile
(strSourceFilePathAndName)
objImageOriginal.Save(memory_stream, GetFormat
(strSourceExtension))

' Copy the MemoryStream data into a Byte array.
Dim objBytes(memory_stream.Length - 1) As Byte
objBytes = memory_stream.ToArray()

' Make a Picture element.
xmlTextWriter.WriteStartElement("Picture")
xmlTextWriter.WriteAttributeString("Encoding",
Nothing,
"Base64")
' Save Image details and encoding as Attributes

xmlTextWriter.WriteAttributeString("Bytes",
objBytes.Length)
xmlTextWriter.WriteAttributeString("Height",
objImageOriginal.Height)
xmlTextWriter.WriteAttributeString("Width",
objImageOriginal.Width)
xmlTextWriter.WriteAttributeString("Type",
strSourceExtension)
xmlTextWriter.WriteBase64(objBytes, 0, objBytes.Length)
xmlTextWriter.WriteEndElement()
xmlTextWriter.WriteEndDocument()

xmlTextWriter.Close()
objImageOriginal.Dispose()
MsgBox("XML file created successfully ! ",
MsgBoxStyle.Information, "Success !")

Else
MsgBox("A target file name must be supplied.",
MsgBoxStyle.OKOnly + MsgBoxStyle.Exclamation, "Error")
Exit Sub
End If

End Sub

Private Sub ReadXMLImage(ByVal strSourceFilePathAndName As String)

If strSourceFilePathAndName <> "" Then

Dim objImageOriginal As Image
Dim blnValidXML As Boolean = False
Dim strImageExtension As String = ""
Dim strTargetFilePathAndName As String = ""

' Load the picture from XML
Dim xmlTextReader As New XmlTextReader
(strSourceFilePathAndName)

' Skip until we find the Picture node.
Do While xmlTextReader.Read()
' See if this is the Picture node.
If xmlTextReader.Name = "Picture" Then
blnValidXML = True
' Allocate room for the byte data and get all
attribute
values.
Dim intNumBytes As Integer =
xmlTextReader.GetAttribute
("Bytes")
Dim h As Integer =
xmlTextReader.GetAttribute("Height")
Dim w As Integer =
xmlTextReader.GetAttribute("Width")

strImageExtension =
xmlTextReader.GetAttribute("Type")

'Refresh the target file according to parameters
read
from XML file Type Attribute
strTargetFilePathAndName = Replace
(strSourceFilePathAndName, ".xml", "New." &
strImageExtension)
'lbl_Message.Text = "Source File : " &
strSourceFilePathAndName & vbCrLf & "Target File : " &
strTargetFilePathAndName

Dim bytes(intNumBytes - 1) As Byte

' Translate the encoded data back into byte data.
Select Case xmlTextReader.GetAttribute
("Encoding").ToLower
Case "base64"
xmlTextReader.ReadBase64(bytes, 0,
intNumBytes)
Case "binhex"
xmlTextReader.ReadBinHex(bytes, 0,
intNumBytes)
Case Else
MsgBox("Unknown image encoding
'" &
xmlTextReader.GetAttribute("Encoding") & "'", _
MsgBoxStyle.Exclamation, "Unknown
Encoding")
Exit Sub
End Select

' Allocate a MemoryStream and a BinaryWriter
attached
to it.
Dim memory_stream As New MemoryStream
Dim binary_writer As BinaryWriter = New
BinaryWriter
(memory_stream)

' Copy the bytes into the BinaryWriter and
MemoryStream.
binary_writer.Write(bytes, 0, intNumBytes)
binary_writer.Flush()

' Load the picture from the memory stream and
save it
and show in the Picture box.
memory_stream.Position = 0
objImageOriginal = Image.FromStream(memory_stream)

'objImageOriginal.Save(strTargetFilePathAndName,
GetFormat(strImageExtension))
objImageOriginal.Save(strTargetFilePathAndName)
'Me.PB_sample.Image =
Image.FromStream(memory_stream)
'PB_sample.SizeMode =
PictureBoxSizeMode.CenterImage
binary_writer.Close()
Exit Do
End If
Loop

xmlTextReader.Close()
If blnValidXML Then
MsgBox(strImageExtension.ToUpper & " file created
successfully ! ", MsgBoxStyle.Information, "Success !")
Else
MsgBox("Invalid XML file format ! ",
MsgBoxStyle.Critical,
"Error !")
End If

Else
MsgBox("An xml file containing the image must be
selected.",
MsgBoxStyle.OKOnly + MsgBoxStyle.Information, "File error")
Exit Sub
End If

End Sub

Private Function GetFormat(ByVal ImageType As String) As
System.Drawing.Imaging.ImageFormat
Select Case ImageType.ToUpper
Case "JPG"
Return ImageFormat.Jpeg
Case "GIF"
Return ImageFormat.Gif
Case "PNG"
Return ImageFormat.Png
Case "BMP"
Return ImageFormat.Bmp
End Select
End Function

Also, I want (need) to do this for image formats that aren't recognised by
the image object (Wavelet Scalar Quantization .wsq format)... any idea how I
can achieve this?

Cheers again for you help...
 
Hi Bob,

Here is my code snipper.
Dim writer As New XmlTextWriter("c:\test.xml",
System.Text.Encoding.UTF8)
writer.WriteStartElement("ss")
writer.WriteBase64(arr, 0, len)
writer.WriteEndElement()
writer.Close()
Dim readoutbuffer(len) As Byte
Dim reader As New XmlTextReader("c:\test.xml")
reader.Read()
Dim rt As Integer = reader.ReadBase64(readoutbuffer, 0, len)
reader.Close()

I think the WriteBase64 of XmlTextWriter and the ReadBase64 of
XmlTextReader is what you want.
For more information, you may refer to the two methods in MSDN.
Please have a try and let me know the result.


Regards,
Peter Huang
Microsoft Online Partner Support
Get Secure! www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
Peter, you're too much...

Thanks again for your help... I was looking at this myself but hadn't got it
to work completely (was trying with filestream object)...

Cheers
 
Hi Bob,

Actually your code works well on my machines.
e.g.
the WriteXMLImage will write dafen.jpg into the dafen.xml
the ReadXMLImage will read dafen.xml and create a new file dafenNew.jpg

I then computer the two files dafen.jpg and dafenNew.jpg 's hash code ,
they are match.

I post my code snipper in the previous post, I hope you can creatd a simple
test project as what I did.
To isolate the problem, my idea is that write the jpg file into the xml
file and then read it back from the xml file.
Then you will know if there is any wrong with XMLwrite and XMLread steps.

I look forward to hearing from you.

Regards,
Peter Huang
Microsoft Online Partner Support
Get Secure! www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
Well, good to know you can get it to work... not sure why I had problems...
it did store the image to XML and recover it fine... the image opened and
looked identical... it was only the hash value that differed.

Still, your code is absolute simplicity compared to what I was using... it
works a treat...

If I can only get around the CD Writing issue I'll pretty much have a fully
functional prototype...

Cheers Peter...
 
Hi Bob,

As I mentioned in my last post, the method to troubleshooting the problem,
you encounter, is to isolate the problem. Everytime you read/write the
picture file may cause the problem. e.g. Although the dafen.jpg and
dafenNew.jpg looks identical but some merely difference may cause the hash
code different.

So my suggestion is
1. Read the dafen.jpg into byte array, I note it as A
2. Serialize it into XML file
3. Read the XML file back into byte array, note it as B
4. Computer the Hash code of the two byte array A & B to see the result.
5. If they are not identical, then you may try to use the code to compare A
& B byte by byte to look into the difference.

You may take the test and let me know the result.

As for the CD Writing issue, I am not an expert on this issue.
My colleague is following your up in that issue.

Regards,
Peter Huang
Microsoft Online Partner Support
Get Secure! www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
Back
Top