Cargar un archivo en un bitmap pero dejando el archivo original intacto

¿Cómo hacer esto en C #?

Si uso Bitmap.FromFile (), el archivo original está bloqueado.

Si utilizo Bitmap.FromStream (), el archivo original no está bloqueado, pero la documentación dice “Debe mantener la transmisión abierta durante toda la vida útil de la imagen”. Esto probablemente significa que el archivo todavía está vinculado al objeto de imagen (por ejemplo, quizás si el archivo cambia, también lo haga el objeto o viceversa).

Lo que quiero hacer es leer el bitmap y guardarlo en un objeto y después de eso no hay ningún vínculo entre el archivo y el objeto de imagen.

Alguna información de fondo sobre este comportamiento: Bitmap usa un archivo mapeado en memoria para acceder a los píxeles en el bitmap. Esa es una instalación muy básica en la API de Windows, permite un mapeo muy eficiente de la memoria a los datos del archivo. Los datos se leen del archivo solo cuando el progtwig lee la memoria, las páginas de la memoria virtual no ocupan espacio en el archivo de paginación de Windows.

El mismo mecanismo exacto se utiliza para cargar los ensamblados .NET. Es la asignación de memoria que pone un locking en el archivo. Es por eso que los ensamblajes se bloquean cuando se usan en un progtwig .NET. El método Image.Dispose () libera el locking. La lucha contra el locking a menudo indica que se está olvidando de disponer de sus mapas de bits. Muy importante, olvidarse de llamar a Dispose () a menudo no causa problemas para las clases .NET, excepto para Bitmap, ya que puede necesitar mucha memoria (no administrada).

Sí, FromStream () impide que la clase realice esta optimización. El costo es significativo, necesitará el doble de memoria cuando se cargue el bitmap. Esto será un problema cuando el bitmap sea grande. Está bordeando OOM cuando el progtwig se ha estado ejecutando durante un tiempo (fragmentando el espacio de direcciones) y no se está ejecutando en un sistema operativo de 64 bits. Definitivamente evite hacer esto si el ancho del bitmap x alto x 4> = 45 MB, más o menos.

Algún código, no tienes que saltar a través del aro CopyStream:

public static Image LoadImageNoLock(string path) { var ms = new MemoryStream(File.ReadAllBytes(path)); // Don't use using!! return Image.FromStream(ms); } 

Tenga en cuenta que no quiere deshacerse de MemoryStream, tendrá un diagnóstico difícil de diagnosticar “error genérico” cuando se use el bitmap, si lo hace. Causado por la clase de imagen de lectura perezosa la secuencia.

Lea el archivo en la memoria copiándolo de un FileStream a un MemoryStream . (Busque CopyStream en Stack Overflow para encontrar muchos ejemplos de cómo hacerlo de manera segura. Básicamente haga un bucle mientras lee, escribe cada fragmento en el flujo de memoria, hasta que no haya más datos para leer.) Luego, rebobine el MemoryStream (ajuste Position = 0 ) y luego pasar eso a Bitmap.FromStream .

Para crear una imagen sin bloquear el archivo, deberá crear una copia de FileStream de la imagen. Consulte esta página La mejor forma de copiar entre dos instancias de transmisión : C # para ver cómo copiar la transmisión.

Luego, simplemente cree su imagen desde el flujo copiado y estará listo para comenzar.

He utilizado esta técnica de copiar a MemoryStream y luego alimentar MemoryStream a Bitmap.FromStream muchas veces. Sin embargo, hay un gotcha con esta técnica también.

Si planea usar uno de los métodos Bitmap.Save más adelante en la imagen cargada, entonces tendrá que mantener la transmisión activa (es decir, no desecharla después de que se cargue la imagen), de lo contrario obtendrá la temida ” Se produjo un error genérico de GDI + “excepción!

    Intereting Posts