net - image save c#
¿Hay alguna razón por la cual Image.FromFile arroje una excepción OutOfMemoryException para un formato de imagen no válido? (4)
Estoy escribiendo código que capta esta OutOfMemoryException
y arroja una nueva excepción más intuitiva:
/// ...
/// <exception cref="FormatException">The file does not have a valid image format.</exception>
public static Image OpenImage( string filename )
{
try
{
return Image.FromFile( filename );
}
catch( OutOfMemoryException ex )
{
throw new FormatException( "The file does not have a valid image format.", ex );
}
}
¿Este código es aceptable para su usuario, o se está OutOfMemoryException
intencionalmente por un motivo en particular?
Bueno, es un buen ejemplo de cómo una excepción no siempre significa lo que dice. Este caso particular ( OutOfMemoryException
para un archivo no válido) se remonta a .Net 1.0, que tenía un conjunto más limitado de tipos de excepción de los que los programadores de esta biblioteca podían elegir. Supongo que no se ha modificado desde entonces para mantener la compatibilidad con versiones anteriores (también conocido como "tirar un buen dinero después de malo").
Para ser justos, creo que fue la peor opción posible para el tipo de excepción que podrían haber hecho aquí. Cuando abres un archivo, y resulta ser grande, y obtienes una OutOfMemoryException
, es lógico suponer que en realidad te has OutOfMemoryException
sin memoria e ir a buscar el árbol equivocado por un tiempo (hay más de una pregunta en sobre esto )
Es una excepción engañosa. Microsoft dice :
Recibe un mensaje de error "System.OutOfMemoryException" cuando intenta utilizar el método Bitmap.FromFile en .NET Framework 1.0
Este problema puede ocurrir cuando utiliza el método Bitmap.FromFile y una de las siguientes condiciones es verdadera:
- El archivo de imagen está dañado.
- El archivo de imagen está incompleto.
Nota : puede experimentar este problema si su aplicación está intentando utilizar el método Bitmap.FromFile en una secuencia de archivos que no ha terminado de escribir en un archivo. * El archivo de imagen no tiene un formato de imagen válido o GDI + no es compatible con el formato de píxel del archivo. * El programa no tiene permisos para acceder al archivo de imagen. * La propiedad BackgroundImage se establece directamente desde el método Bitmap.FromFile .
(Mapa de bits desciende de la imagen)
Por supuesto, también es posible obtener esta excepción cuando intenta cargar una imagen que es demasiado grande. Entonces debes considerar eso.
No, es historia. GDI + fue escrito bastante tiempo antes de que llegara .NET. El contenedor SDK para ello fue escrito en C ++. Las excepciones son dudosas en C ++, no todo el mundo compra en ellas. Google no, por ejemplo. Para mantenerlo compatible, informa problemas con los códigos de error. Eso simplemente nunca se adapta bien, los programadores de bibliotecas hacen que sea una meta limitar intencionalmente la cantidad de posibles códigos de error, esto disminuye la carga de que el programador cliente tenga que informarlos.
GDI + tiene este problema en picas, solo define 20 códigos de error. Eso no es mucho para una porción tan grande de código con tantas dependencias externas. Lo que en sí mismo es un problema, hay muchas maneras de estropear un archivo de imagen. De ninguna manera los informes de error de una biblioteca pueden ser lo suficientemente precisos como para cubrirlos todos. El hecho de que estos códigos de error se eligieron mucho antes de que los tipos derivados de Expectativas definidas .NET ciertamente no sirvieran de nada.
El código de error Status :: OutOfMemory se sobrecargó para significar cosas diferentes. A veces realmente significa memoria insuficiente, no puede asignar suficiente espacio para almacenar los bits del mapa de bits. Lamentablemente, un problema de formato de archivo de imagen se informa con el mismo código de error. La fricción aquí es que no es posible decidir si el ancho * alto * píxeles que lee del archivo de imagen es un problema porque no hay suficiente espacio de almacenamiento disponible para el mapa de bits. O si los datos en el archivo de imagen son basura. Asume que el archivo de imagen no es basura, llamada justa, ese es el problema de otro programa. Entonces OOM es lo que informa.
Para completar, estos son los códigos de error:
enum Status
{
Ok = 0,
GenericError = 1,
InvalidParameter = 2,
OutOfMemory = 3,
ObjectBusy = 4,
InsufficientBuffer = 5,
NotImplemented = 6,
Win32Error = 7,
WrongState = 8,
Aborted = 9,
FileNotFound = 10,
ValueOverflow = 11,
AccessDenied = 12,
UnknownImageFormat = 13,
FontFamilyNotFound = 14,
FontStyleNotFound = 15,
NotTrueTypeFont = 16,
UnsupportedGdiplusVersion = 17,
GdiplusNotInitialized = 18,
PropertyNotFound = 19,
PropertyNotSupported = 20,
#if (GDIPVER >= 0x0110)
ProfileNotFound = 21,
#endif //(GDIPVER >= 0x0110)
};
Si es porque el archivo no es válido, probablemente solo trate de adivinar qué tan grande es el buffer que necesita basado en algunos bytes en lo que cree que es el encabezado. Documente su intención claramente con una prueba y debería estar bien.