Base64-Bitmap/Image != Base64-Bitmap/Image?

28/12/2010 - 19:16 von Ralph Rutschmann | Report spam
Hallo liebe Profis,

in einer Schleife (for each) werden zuvor in einer ICollection (products)
gesammelte Datenbankeintràge (item) wie folgt durchlaufen:

using (StreamWriter sw = new StreamWriter("Products.txt", false,
System.Text.Encoding.Unicode))
{
// Obtain the persistent object class info required by the
GetObjects method
customClass = uow.GetClassInfo(typeof(Products));
// Create a sort list if objects must be processed in a
specific order
sortProps = new SortingCollection();
sortProps.Add(new SortProperty("Oid",
SortingDirection.Ascending));
// Call GetObjects
ICollection products = uow.GetObjects(customClass,
criteriaNull, sortProps, int.MaxValue, true, true);
byte[] blob;
System.Drawing.Image image;
MemoryStream stream = new MemoryStream();

string lineToWrite = String.Empty;
if (products != null && products.Count > 0)
{
foreach (Products item in products)
{
if (item.Picture != null)
{
image = item.Picture;
image.Save(stream, image.RawFormat);
blob = stream.ToArray();
}
else
{
blob = null;
}

string imageToAdd;
if (blob == null)
imageToAdd = null;
else
imageToAdd = Convert.ToBase64String(blob);

// Add some text to the file.
lineToWrite =
String.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}\t{9}\t{10}\t{11}",
item.Oid, // = 0
item.IsDeleted, // = 1
item.Sequence, // = 2
item.Supplier.Oid, // = 3
item.Purchaser, // = 4
item.ProductIdentifier, // = 5
item.ProductDescription, // = 6
//item.Remark, // = 7
string.Empty,
imageToAdd, // = 8
item.QuantityDescription, // = 9
item.VATCode, // = 10
item.VATPercentage); // = 11
sw.WriteLine(lineToWrite);
}
}
else
{
...
}
sw.Close();
stream.Close();
}

Damit speichere ich wie oben angegeben u.a. Images als Base64-string in
einem File. Das klappt wunderbar, auch der Import vom File in die Datenbank.
Die Bilder sehen (für mich zumindest) optisch genau so aus, hinterher wie
vorher. Leider sind es nicht genau die selben! Ein Vergleich bringt immer
ein: "imageFromFile == imageFromDatabase" = false!

Der Import (gekürzt) sieht so aus:

Bitmap imageFromFile = null;
Bitmap imageFromDatabase = null;

if (!string.IsNullOrEmpty(stringArray[8]))
{
imageFromFile = new
Bitmap(splittedStringToImage(stringArray[8]));
//splittetStringToImage(string p) siehe weiter unten...
imageFromDatabase = new Bitmap(product.Picture);
if (imageFromDatabase != null)
{
if (imageFromFile != imageFromDatabase) // ACHTUNG:
Hier liegt der Hase im Pfeffer, der immer 'true' zurückliefert!
{
product.Picture = imageFromFile;
}
}
else
{
imageFromFile = null;
imageFromDatabase = null;
product.Picture = null;
}
}

private static Image splittedStringToImage(string p)
{
Image image = null;
try
{
if (!string.IsNullOrEmpty(p))
{
byte[] blob;
blob = Convert.FromBase64String(p);
MemoryStream stream = new MemoryStream(blob, true);
image = Image.FromStream(stream);
stream.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return image;
}


Vergleiche ich die Bitmaps bitweise, sind immer einige Pixel anders.
Deswegen geht wohl auch der Vergleich "imageFromFile != imageFromDatabase"
immer auf 'true'.

Ich hab' das auch mit mit 'Image' statt 'Bitmap' probiert, leider mit dem
selben Ergebnis: die Bilder sind unterschiedlich, wenn auch nur in àüßerst
geringen Details.

Entweder codiert/decodiert 'Base64' vom File/aus der Datenbank nicht immer
identisch, oder ich mache was falsch. Denn auch die Strings aus
File/Datenbank sind unterschiedlich, wenn auch wiederum in àußerst geringen
Details. Je nach Größe der Bilder schàtzungsweise so ca. 0,001x - 0,1x
Prozent, aber das reicht ja, daß der Vergleich fehlschlàgt...

Die Bilder in der Datenbank sollen von der Importroutine aber nur
ausgetauscht werden, wenn sie sich geàndert haben und nicht jedesmal. Da der
Vergleich fehlschlàgt, obwohl die Bilder im Grunde aber identisch sind,
werden sie jedoch immer ausgetauscht. Gibt es da einen performanten Trick,
außer ein Flag im Export mit zu übergeben?

Irgend einen Tip?

Mit freundlichen Grüßen,

Ralph
 

Lesen sie die antworten

#1 Thomas Scheidegger
29/12/2010 - 01:38 | Warnen spam
?Ralph

eine maschinelle Fehlinterpretation der maschinellen Übersetzung.



naja, im englischen Original steht doch:
http://msdn.microsoft.com/en-us/lib...9ee4x.aspx
"You must keep the stream open for the lifetime of the Image."

Beide Strings geringfügig unterschiedlich



1.) sollte man nicht (nur) die Strings vergleichen,
sondern eher mal die Byte-Arrays (Byte-für-Byte) vor + nach Base64 -
codierung/rückwandlung.

2.) diese Byte-Arrays _müssen_ absolut identisch bleiben, alles andere ist
inakzeptabel.
Und Abweichungen liegen da kaum an .NET bzw Convert.ToBase64String /
FromBase64String,
sondern zB an deiner DB und/oder deinem übrigen Code
(uva berüchtigt, zB SQL-Queries, WebRequest URLs usw).
Solange die Byte-Arrays nicht absolut identisch bleiben,
ist es danach auch nicht mehr relevant/verwunderlich, ob die Bitmap/'Pixels'
unterschiedlich herauskommen.



Thomas Scheidegger - 'NETMaster'
http://dnetmaster.net/

Ähnliche fragen