BitmapSource och Image
Ok, ibland tänker jag för mycket…
Jag använder ju nu ett renodlat WPF gränssnitt. I tidigare versioner jag påbörjade var det Winforms som gällde, och när det handlade om bildhantering så var det System.Drawing.Image objektet som jag använde för att hantera bilder, från databas upp till gränssnittet. Nu är det som sagt WPF som gäller och när man visar en bild i ett WPF-formulär är det istället en BitmapSource som används för att visa bilder. Objektet BitmapSource är en ny klass som använder DirectX för att rendera bilder, beroende på vilken hårdvara som finns i klienten och vilken version av DirectX som är installerad så hanterar denna klass detta automagiskt, och bättre prestanda erhålls för rendering av bilder.
Fantastiskt tänkte jag och började ändra min kod, från DAL till gränssnitt, dvs. jag bytte ut alla System.Drawing.Image objekt mot BitmapSource istället. Det var ju lättare sagt än gjort!
Först och främst, jag är så nöjd att jag kör TDD nu, all kod jag ändrade var täckt av unit tester, så listan över kompileringsfel var lång, och det var bara att kavla upp ärmarna. Ju mer jag jobbade med att implementera BitmapSource objektet för bilder desto mer skeptisk blev jag att det var rätt väg att gå. Jag var ju tvungen att lägga till referenser till PresentationCore.dll i DAL lagret vilket inte kändes helt ok. Jag googlade en hel del, men hittade inga bra källor som beskrev hur man ska hantera bilder från databasen upp till WPF-gränssnittet. Så när jag låg och försökte sova en natt tänkte jag på detta, och då slog det mig. P:et i WPF står för PRESENTATION, och då bestämde jag mig för att klasser som ingår i WPF har med presentationen att göra, inte dataacess, inte heller affärslogik. Så tillbaka till Visual Studio, och ändra tillbaka, återigen otroligt glad att jag har anammat TDD!
För att skicka en bild från databas till gränssnittet så har jag följande funktioner, mer än så behövs inte.
Först och främst, bilden är lagrad i Sql Server 2008 i ett Image fält, vilket sin tur översätts till System.Data.Linq.Binary. För att översätta detta till en Image har jag följande funktion:
public static Image ConvertLinqBinaryToBitmapImage(System.Data.Linq.Binary imageData)
{
if(imageData ==null)
return null;
using (MemoryStream pictureStream = new MemoryStream(imageData.ToArray()))
{
Image imageToReturn =Image.FromStream(pictureStream);
return imageToReturn;
}
}
Och för att konvertera en Image till System.Data.Linq.Binary har jag följande funktion:
public static System.Data.Linq.Binary ConvertImageToLinqBinary(Image picture)
{
if(picture==null)
return null;
using(MemoryStream pictureStream = new MemoryStream())
{
picture.Save(pictureStream, picture.RawFormat);
return pictureStream.ToArray();
}
}Ovanstående kod används alltså för att konvertera bilden fram och tillbaka till mitt objekt som har en bild som property, när jag vill hämta eller spara till Linq To Sql objektet.
I WPF formuläret behövs ju Image klassen konverteras till en BitmapSource, och det finns det inbyggt stöd för. Följande funktion konverterar en System.Drawing.Image till BitmapSource:
private static BitmapSource CreateBitmapSourceFromImage(Image sourceImage)
{
if(sourceImage ==null)
return null;
System.Drawing.Bitmap bitmap = new Bitmap(sourceImage);
return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
bitmap.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
}
Labels: Drawing, Linq To Sql, WPF
