Search code examples
c#.netwpfdotnetzip

Loading an Image from a DotNetZip Entry


How can I load an Image in WPF using the DotNetZip ZipEntry class.

using (ZipFile file = ZipFile.Read ("Images.zip"))
{
    ZipEntry entry = file["Image.png"];
    uiImage.Source = ??
}

Solution

  • ZipEntry type exposes an OpenReader() method that returns a readable stream. This may work for you in this way:

    // I don't know how to initialize these things
    BitmapImage image = new BitmapImage(...?...);
    ZipEntry entry = file["Image.png"];
    image.StreamSource = entry.OpenReader(); 
    

    I am not certain this will work because:

    • I don't know the BitmapImage class or how to manage it, or how to create one from a stream. I may have the code wrong there.

    • the ZipEntry.OpenReader() method internally sets and uses a file pointer that is managed by the ZipFile instance, and the readable stream is valid only for the lifetime of the ZipFile instance itself.
      The stream returned by ZipEntry.OpenReader() must be read before any subsequent calls to ZipEntry.OpenReader() for other entries, and before the ZipFile goes out of scope. If you need to extract and read multiple images from a zip file, in no particular order, or you need to read after you're finished with the ZipFile, then you'll need to work around that limitation. To do that, you could call OpenReader() and read all the bytes for each particular entry into a distinct MemoryStream.

    Something like this:

      using (ZipFile file = ZipFile.Read ("Images.zip"))        
      {        
          ZipEntry entry = file["Image.png"];
          uiImage.StreamSource = MemoryStreamForZipEntry(entry);        
      } 
    
     ....
    
    private Stream MemoryStreamForZipEntry(ZipEntry entry) 
    {
         var s = entry.OpenReader();
         var ms = new MemoryStream(entry.UncompressedSize);
         int n; 
         var buffer = new byte[1024];
         while ((n= s.Read(buffer,0,buffer.Length)) > 0) 
             ms.Write(buffer,0,n);
         ms.Seek(0, SeekOrigin.Begin);
         return ms;
    }