Avatar billede eht Nybegynder
05. februar 2014 - 18:23 Der er 10 kommentarer og
1 løsning

Wpf: indlæse jpg direkte fra zip uden at gemme filen først

Jeg bruger DotNetZip.
Herunder 2 eksempler
I eksempel 1 indlæses billedfilen til en MemoryStream fra en zipfil.
For at teste om filen er loaded, gemmes denne MemoryStream som en fil.
I eksempel 2 indlæses billedfilen til en MemoryStream fra en almindelig fil.
Jeg har altså to Memorystream.
Den 2. kan efterfølgende indlæses i myImage, mens den anden ikke viser billedet.
Hvad er forskellen på de 2 MemoryStreams og hvorfor virker eksempel 1 ikke.


eksempel 1:
MemoryStream memoryStream1 = new MemoryStream();

ZipFile zip = ZipFile.Read(@"D:\myZipArcive.zip");

ZipEntry myEntry = zip["myfile.jpg"];
myEntry.Extract(memoryStream1);
memoryStream1.Close();

System.IO.File.WriteAllBytes(@"D:\saved.jpg", memoryStream1.ToArray());
        //gemmer som fil for at teste

BitmapImage src = new BitmapImage();
src.BeginInit();
src.CacheOption = BitmapCacheOption.OnLoad;
src.StreamSource = memoryStream1;
src.EndInit();

myImage.Source = src as ImageSource; //billedet vises ikke


eksempel 2.


FileStream fileStream = File.OpenRead(@"D:\myFile.jpg");

MemoryStream memoryStream2 = new MemoryStream();
memoryStream2.SetLength(fileStream.Length);
fileStream.Read(memoryStream2.GetBuffer(), 0, (int)fileStream.Length);

BitmapImage src = new BitmapImage();
src.BeginInit();
src.CacheOption = BitmapCacheOption.OnLoad;
src.StreamSource = memoryStream2;     
src.EndInit();

myImage.Source = src as ImageSource; //Billedet vises
Avatar billede arne_v Ekspert
05. februar 2014 - 19:22 #1
Jeg gaetter paa at denne sekvens er problemet:

memoryStream1.Close();
...
src.StreamSource = memoryStream1;

du forsoeger at bruge en stream som du har lukket.
Avatar billede eht Nybegynder
05. februar 2014 - 19:37 #2
Hej Arne

Umiddelbart hjælper det ikke at udelade memoryStream1.Close();

Alligevel er du nok på rette spor.

Jeg fik et svar fra http://stackoverflow.com med følgende svar og brugbare løsning:



The stream seems to be closed by the Extract method. You may however create a second MemoryStream from the buffer of the first one:

var zipFile = ZipFile.Read(@"D:\myZipArcive.zip");
var zipEntry = zipFile["myfile.jpg"];
var zipStream = new MemoryStream();
zipEntry.Extract(zipStream);

var bitmap = new BitmapImage();

using (var sourceStream = new MemoryStream(zipStream.ToArray()))
{
    bitmap.BeginInit();
    bitmap.CacheOption = BitmapCacheOption.OnLoad;
    bitmap.StreamSource = sourceStream;
    bitmap.EndInit();
}

myImage.Source = bitmap;

Tak for din kommentar.
Avatar billede arne_v Ekspert
06. februar 2014 - 01:43 #3
Nu har jeg ikke testet (har ikke DotNetZip downloadet), men hvad med:

var zipFile = ZipFile.Read(@"D:\myZipArcive.zip");
var zipEntry = zipFile["myfile.jpg"];
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = zipEntry.OpenReader();
bitmap.EndInit();
Avatar billede eht Nybegynder
06. februar 2014 - 07:38 #4
Hej Arne
Fantastisk. Det virker og er lidt mere enkelt end koden fra http://stackoverflow.com
1000 tak.
Smid et svar.
:-) Erik



var zipFile = ZipFile.Read(@"D:\myZipArcive.zip");
var zipEntry = zipFile["myfile.jpg"];
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = zipEntry.OpenReader();
bitmap.EndInit();
myImage.Source = bitmap;
Avatar billede eht Nybegynder
06. februar 2014 - 13:35 #5
I praksis ser det ud til at løsningen herunder fra http://stackoverflow.com læser billederne en hel del hurtigere.
Loader man f.eks. 3 billeder samtidigt. Det ses tydeligt, hvis man loader flere billeder lige efter hinanden.

var zipFile = ZipFile.Read(@"D:\myZipArcive.zip");
var zipEntry = zipFile["myfile.jpg"];
var zipStream = new MemoryStream();
zipEntry.Extract(zipStream);

var bitmap = new BitmapImage();

using (var sourceStream = new MemoryStream(zipStream.ToArray()))
{
    bitmap.BeginInit();
    bitmap.CacheOption = BitmapCacheOption.OnLoad;
    bitmap.StreamSource = sourceStream;
    bitmap.EndInit();
}

myImage.Source = bitmap;
Avatar billede arne_v Ekspert
06. februar 2014 - 21:32 #6
Hvad hvis du erstatter:

bitmap.StreamSource = zipEntry.OpenReader();

med:

bitmap.StreamSource = new BufferedStream(zipEntry.OpenReader(), 1024000);
Avatar billede eht Nybegynder
06. februar 2014 - 22:18 #7
Hej Arne

Så kom der mere fart på.
Nu loader billederne lige hurtigt med begge løsninger.
Avatar billede arne_v Ekspert
06. februar 2014 - 22:32 #8
Du er vel ikke tilfaeldigvis paa .NET 4.5+?

Der er nemlig indbygget support for zip filer, saa man ikke behoever DotNetZip.
Avatar billede arne_v Ekspert
07. februar 2014 - 01:34 #9
og et svar
Avatar billede eht Nybegynder
07. februar 2014 - 13:04 #10
Og mange tak for din hjælp.
Jeg er faktisk på NET 4.5, så det må jeg lige kigge på.
Jeg er ret ny på C#/Wpf efter at have programmeret Delphi i mange år.
Avatar billede arne_v Ekspert
07. februar 2014 - 13:56 #11
namespace er System.IO.Compression
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester