2009-02-12 8 views
5

Cuando intento guardar un BitmapSource que cargué anteriormente, se emite un System.IO.IOException indicando que otro proceso está accediendo a ese archivo y no se puede abrir el archivo.Cargue un BitmapSource y guárdelo usando el mismo nombre en WPF -> IOException

Si solo guardo sin cargar antes, todo funciona bien.

El código de carga:

BitmapImage image = new BitmapImage(); 

image.BeginInit(); 
image.UriSource = uri; 

if (decodePixelWidth > 0) 
image.DecodePixelWidth = decodePixelWidth; 

image.EndInit(); 

el código ahorro:

using (FileStream fileStream = new FileStream(Directory + "\\" + FileName + ".jpg", FileMode.Create)) 
{ 
    JpegBitmapEncoder encoder = new JpegBitmapEncoder(); 
    encoder.Frames.Add(BitmapFrame.Create((BitmapImage)image)); 
    encoder.QualityLevel = 100; 
    encoder.Save(fileStream); 
} 

Parece que después de cargar los datos de la imagen, el archivo está siendo bloqueado una nunca puede ser sobrescrita mientras que la aplicación que abrió todavía está funcionando. ¿Alguna idea de como resolver esto? Muchas gracias por cualquier solución.

Respuesta

9

Inspirado por los comentarios que obtuve sobre este tema, resolví el problema leyendo todos los bytes en un flujo de memoria y usándolo como Sreamsource de BitmapImage.

Esta funciona perfectamente:

if (File.Exists(filePath)) 
{ 
    MemoryStream memoryStream = new MemoryStream(); 

    byte[] fileBytes = File.ReadAllBytes(filePath); 
    memoryStream.Write(fileBytes, 0, fileBytes.Length); 
    memoryStream.Position = 0; 

    image.BeginInit(); 
    image.StreamSource = memoryStream; 

    if (decodePixelWidth > 0) 
     image.DecodePixelWidth = decodePixelWidth; 

    image.EndInit(); 
} 
+0

¿Tomó los comentarios de otros, no votó mejor que nadie, creó una solución derivada que publicó como respuesta, y se dio la votación de Respuesta aprobada por el Póster? – hughdbrown

+15

Soy nuevo en stackoverflow. Como puedes ver Por lo tanto, no puedo retribuir a los demás hasta que tenga una reputación de 15. Y como los demás me proporcionaron amablemente buenas sugerencias, pero ninguna solución real para las personas que tienen el mismo problema, yo mismo proporcioné la respuesta como resultado de mi propia investigación. ¿Problema? – sdippl

0

ahora no estoy seguro si esto se puede aplicar a BitmapImage pero que tenía un problema muy similar a guardar una imagen modificada con el archivo original en GDI + here

El método para cargar la imagen de archivo mantiene una Bloqueo abierto en el archivo hasta que el objeto imagen se elimine.

Tal vez sea lo mismo con bitmapimage.urisource. Sin jugar podría copiar la imagen en la memoria y deshacerse del original desbloqueando el archivo?

3

Añadir la siguiente línea a su código de carga:

image.CacheOption = BitmapCacheOption.OnLoad; 

Esto cargará abrir el archivo, leerlo en la memoria, y cerrarla durante toda image.EndInit. El valor predeterminado de BitmapCacheOption.Default tiene el extraño comportamiento de abrir el archivo, leerlo en la memoria, pero aún no cerrarlo durante image.EndInit.

+1

Esto funciona, pero también hay que utilizar BitmapCreateOptions.IgnoreImageCache en caso de que se crea una nueva BitmapImage utilizando la misma ruta más adelante en el proceso. Esto se debe a que BitmapImage almacenará en caché los datos de la imagen en las instancias de la clase BitmapImage. – manu08

+0

@ manu08: si tan solo pudiera votarte por esto de alguna manera. Pasé mucho tiempo mirando alrededor y no pude encontrar la solución a mi problema. Mientras escribía mi propia pregunta sobre SO, tuve suerte y encontré su comentario, ¡y era exactamente lo que necesitaba! – Dave

0

Establecer CacheOption en BitmapCacheOption.OnLoad, no resolverá su problema. Creo que hay un error, pero tuve el mismo problema. Finalmente, cargué mi imagen en una secuencia de memoria y eliminé BitmapImage antes de guardar la imagen en el archivo.

+0

En realidad, funciona bien para mí. Debe crear BitmapImage, llamar a BeginInit(), luego establecer CacheOption, luego configurar el UriSource y luego llamar a EndInit(). –

7

Aquí hay otra solución, basada en el código original de carga:

var image = new BitmapImage(); 
image.BeginInit(); 

// overwrite cache if already exists, to refresh image 
image.CreateOptions = BitmapCreateOptions.IgnoreImageCache; 
// load into memory and unlock file 
image.CacheOption = BitmapCacheOption.OnLoad; 

image.UriSource = uri; 
if (decodePixelWidth > 0) image.DecodePixelWidth = decodePixelWidth; 
image.EndInit(); 
Cuestiones relacionadas