net - system drawing image c# save
Encuentra formato de imagen usando el objeto Bitmap en C# (11)
, me gustó su método de extensión y agregué una sobrecarga de cadena, además reduje el código para su método:
public static class ImageExtentions
{
public static ImageCodecInfo GetCodecInfo(this Image img) =>
ImageCodecInfo.GetImageDecoders().FirstOrDefault(decoder => decoder.FormatID == img.RawFormat.Guid);
// Note: this will throw an exception if "file" is not an Image file
// quick fix is a try/catch, but there are more sophisticated methods
public static ImageCodecInfo GetCodecInfo(this string file)
{
using (var img = Image.FromFile(file))
return img.GetCodecInfo();
}
}
// Usage:
string file = @"C:/MyImage.tif";
string description = $"Image format is {file.GetCodecInfo()?.FormatDescription ?? "unknown"}.";
Console.WriteLine(description);
Estoy cargando los bytes binarios del disco duro del archivo de imagen y cargándolo en un objeto Bitmap. ¿Cómo encuentro el tipo de imagen [JPEG, PNG, BMP, etc.] del objeto Bitmap?
Parece trivial. Pero, ¡no pude resolverlo!
¿Hay un enfoque alternativo?
Aprecia tu respuesta.
SOLUCIÓN CORRECTA ACTUALIZADA:
@CMS: ¡gracias por la respuesta correcta!
Código de muestra para lograr esto.
using (MemoryStream imageMemStream = new MemoryStream(fileData))
{
using (Bitmap bitmap = new Bitmap(imageMemStream))
{
ImageFormat imageFormat = bitmap.RawFormat;
if (bitmap.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Jpeg))
//It''s a JPEG;
else if (bitmap.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Png))
//It''s a PNG;
}
}
Aquí está mi método de extensión. Espero que esto ayude a alguien.
public static System.Drawing.Imaging.ImageFormat GetImageFormat(this System.Drawing.Image img)
{
if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Jpeg))
return System.Drawing.Imaging.ImageFormat.Jpeg;
if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Bmp))
return System.Drawing.Imaging.ImageFormat.Bmp;
if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Png))
return System.Drawing.Imaging.ImageFormat.Png;
if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Emf))
return System.Drawing.Imaging.ImageFormat.Emf;
if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Exif))
return System.Drawing.Imaging.ImageFormat.Exif;
if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Gif))
return System.Drawing.Imaging.ImageFormat.Gif;
if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Icon))
return System.Drawing.Imaging.ImageFormat.Icon;
if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.MemoryBmp))
return System.Drawing.Imaging.ImageFormat.MemoryBmp;
if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Tiff))
return System.Drawing.Imaging.ImageFormat.Tiff;
else
return System.Drawing.Imaging.ImageFormat.Wmf;
}
Basado en el trabajo anterior de Alex (que en realidad yo voto como la solución, ya que es una línea, pero aún no puedo votar, jaja), se me ocurrió la siguiente función para una biblioteca de imágenes. Requiere 4.0
Public Enum Formats
Unknown
Bmp
Emf
Wmf
Gif
Jpeg
Png
Tiff
Icon
End Enum
Public Shared Function ImageFormat(ByVal Image As System.Drawing.Image) As Formats
If Not System.Enum.TryParse(Of Formats)(System.Drawing.Imaging.ImageCodecInfo.GetImageDecoders().ToList().[Single](Function(ImageCodecInfo) ImageCodecInfo.FormatID = Image.RawFormat.Guid).FormatDescription, True, ImageFormat) Then
Return Formats.Unknown
End If
End Function
El método más simple fue ofrecido por Cesare Imperiali como este:
var format = new ImageFormat(Image.FromFile(myFile).RawFormat.Guid);
Sin embargo, .ToString () para .jpg devuelve "[ImageFormat: b96b3cae-0728-11d3-9d7b-0000f81ef32e]" en lugar de "Jpeg". Si eso es importante para usted, aquí está mi solución:
public static class ImageFilesHelper
{
public static List<ImageFormat> ImageFormats =>
typeof(ImageFormat).GetProperties(BindingFlags.Static | BindingFlags.Public)
.Select(p => (ImageFormat)p.GetValue(null, null)).ToList();
public static ImageFormat ImageFormatFromRawFormat(ImageFormat raw) =>
ImageFormats.FirstOrDefault(f => raw.Equals(f)) ?? ImageFormat.Bmp;
}
// usage:
var format = ImageFilesHelper.ImageFormatFromRawFormat(Image.FromFile(myFile).RawFormat);
No me molesto en un tema viejo, pero para completar esta discusión, quiero compartir mi camino para consultar todos los formatos de imagen, conocidos por Windows.
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
public static class ImageExtentions
{
public static ImageCodecInfo GetCodecInfo(this System.Drawing.Image img)
{
ImageCodecInfo[] decoders = ImageCodecInfo.GetImageDecoders();
foreach (ImageCodecInfo decoder in decoders)
if (img.RawFormat.Guid == decoder.FormatID)
return decoder;
return null;
}
}
Ahora puede usarlo como una extensión de imagen como se muestra a continuación:
public void Test(Image img)
{
ImageCodecInfo info = img.GetCodecInfo();
if (info == null)
Trace.TraceError("Image format is unkown");
else
Trace.TraceInformation("Image format is " + info.FormatDescription);
}
Simplemente hablando, no puedes. La razón por la cual es que Bitmap es un tipo de imagen de la misma manera que JPEG, PNG, etc. Una vez que cargue una imagen en un mapa de bits, aparecerá la imagen del formato de mapa de bits. No hay forma de mirar un mapa de bits y entender la codificación original de la imagen (si es incluso diferente a Bitmap).
Un par de métodos de extensión limpios en tipo Image
para determinar esto, basado en el hallazgo de Alex anterior ( ImageCodecInfo.GetImageDecoders()
).
Esto está altamente optimizado después de la primera llamada, ya que el ImageCodecsDictionary estático se guarda en la memoria (pero solo después de haber sido usado una vez).
public static class ImageCodecInfoX
{
private static Dictionary<Guid, ImageCodecInfoFull> _imageCodecsDictionary;
public static Dictionary<Guid, ImageCodecInfoFull> ImageCodecsDictionary
{
get
{
if (_imageCodecsDictionary == null) {
_imageCodecsDictionary =
ImageCodecInfo.GetImageDecoders()
.Select(i => {
var format = ImageFormats.Unknown;
switch (i.FormatDescription.ToLower()) {
case "jpeg": format = ImageFormats.Jpeg; break;
case "png": format = ImageFormats.Png; break;
case "icon": format = ImageFormats.Icon; break;
case "gif": format = ImageFormats.Gif; break;
case "bmp": format = ImageFormats.Bmp; break;
case "tiff": format = ImageFormats.Tiff; break;
case "emf": format = ImageFormats.Emf; break;
case "wmf": format = ImageFormats.Wmf; break;
}
return new ImageCodecInfoFull(i) { Format = format };
})
.ToDictionary(c => c.CodecInfo.FormatID);
}
return _imageCodecsDictionary;
}
}
public static ImageCodecInfoFull CodecInfo(this Image image)
{
ImageCodecInfoFull codecInfo = null;
if (!ImageCodecsDictionary.TryGetValue(image.RawFormat.Guid, out codecInfo))
return null;
return codecInfo;
}
public static ImageFormats Format(this Image image)
{
var codec = image.CodecInfo();
return codec == null ? ImageFormats.Unknown : codec.Format;
}
}
public enum ImageFormats { Jpeg, Png, Icon, Gif, Bmp, Emf, Wmf, Tiff, Unknown }
/// <summary>
/// Couples ImageCodecInfo with an ImageFormats type.
/// </summary>
public class ImageCodecInfoFull
{
public ImageCodecInfoFull(ImageCodecInfo codecInfo = null)
{
Format = ImageFormats.Unknown;
CodecInfo = codecInfo;
}
public ImageCodecInfo CodecInfo { get; set; }
public ImageFormats Format { get; set; }
}
aquí está mi código para esto. Primero debe cargar la imagen completa o el encabezado (primeros 4 bytes) en una matriz de bytes.
public enum ImageFormat
{
Bmp,
Jpeg,
Gif,
Tiff,
Png,
Unknown
}
public static ImageFormat GetImageFormat(byte[] bytes)
{
// see http://www.mikekunz.com/image_file_header.html
var bmp = Encoding.ASCII.GetBytes("BM"); // BMP
var gif = Encoding.ASCII.GetBytes("GIF"); // GIF
var png = new byte[] { 137, 80, 78, 71 }; // PNG
var tiff = new byte[] { 73, 73, 42 }; // TIFF
var tiff2 = new byte[] { 77, 77, 42 }; // TIFF
var jpeg = new byte[] { 255, 216, 255, 224 }; // jpeg
var jpeg2 = new byte[] { 255, 216, 255, 225 }; // jpeg canon
if (bmp.SequenceEqual(bytes.Take(bmp.Length)))
return ImageFormat.Bmp;
if (gif.SequenceEqual(bytes.Take(gif.Length)))
return ImageFormat.Gif;
if (png.SequenceEqual(bytes.Take(png.Length)))
return ImageFormat.Png;
if (tiff.SequenceEqual(bytes.Take(tiff.Length)))
return ImageFormat.Tiff;
if (tiff2.SequenceEqual(bytes.Take(tiff2.Length)))
return ImageFormat.Tiff;
if (jpeg.SequenceEqual(bytes.Take(jpeg.Length)))
return ImageFormat.Jpeg;
if (jpeg2.SequenceEqual(bytes.Take(jpeg2.Length)))
return ImageFormat.Jpeg;
return ImageFormat.Unknown;
}
por supuesto que puede. ImageFormat
no significa mucho. ImageCodecInfo
tiene mucho más significado.
red_dot.png
<a href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="red_dot.png" title="red_dot.png"/>
</a>
código:
using System.Linq;
//...
//get image
var file_bytes = System.Convert.FromBase64String(@"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==");
var file_stream = new System.IO.MemoryStream(file_bytes);
var file_image = System.Drawing.Image.FromStream(file_stream);
//list image formats
var image_formats = typeof(System.Drawing.Imaging.ImageFormat).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static).ToList().ConvertAll(property => property.GetValue(null, null));
System.Diagnostics.Debug.WriteLine(image_formats.Count, "image_formats");
foreach(var image_format in image_formats) {
System.Diagnostics.Debug.WriteLine(image_format, "image_formats");
}
//get image format
var file_image_format = typeof(System.Drawing.Imaging.ImageFormat).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static).ToList().ConvertAll(property => property.GetValue(null, null)).Single(image_format => image_format.Equals(file_image.RawFormat));
System.Diagnostics.Debug.WriteLine(file_image_format, "file_image_format");
//list image codecs
var image_codecs = System.Drawing.Imaging.ImageCodecInfo.GetImageDecoders().ToList();
System.Diagnostics.Debug.WriteLine(image_codecs.Count, "image_codecs");
foreach(var image_codec in image_codecs) {
System.Diagnostics.Debug.WriteLine(image_codec.CodecName + ", mime: " + image_codec.MimeType + ", extension: " + @image_codec.FilenameExtension, "image_codecs");
}
//get image codec
var file_image_format_codec = System.Drawing.Imaging.ImageCodecInfo.GetImageDecoders().ToList().Single(image_codec => image_codec.FormatID == file_image.RawFormat.Guid);
System.Diagnostics.Debug.WriteLine(file_image_format_codec.CodecName + ", mime: " + file_image_format_codec.MimeType + ", extension: " + file_image_format_codec.FilenameExtension, "image_codecs", "file_image_format_type");
salida de depuración:
image_formats: 10
image_formats: MemoryBMP
image_formats: Bmp
image_formats: Emf
image_formats: Wmf
image_formats: Gif
image_formats: Jpeg
image_formats: Png
image_formats: Tiff
image_formats: Exif
image_formats: Icon
file_image_format: Png
image_codecs: 8
image_codecs: Built-in BMP Codec, mime: image/bmp, extension: *.BMP;*.DIB;*.RLE
image_codecs: Built-in JPEG Codec, mime: image/jpeg, extension: *.JPG;*.JPEG;*.JPE;*.JFIF
image_codecs: Built-in GIF Codec, mime: image/gif, extension: *.GIF
image_codecs: Built-in EMF Codec, mime: image/x-emf, extension: *.EMF
image_codecs: Built-in WMF Codec, mime: image/x-wmf, extension: *.WMF
image_codecs: Built-in TIFF Codec, mime: image/tiff, extension: *.TIF;*.TIFF
image_codecs: Built-in PNG Codec, mime: image/png, extension: *.PNG
image_codecs: Built-in ICO Codec, mime: image/x-icon, extension: *.ICO
Built-in PNG Codec, mime: image/png, extension: *.PNG
un problema raro al que me enfrenté cuando estaba tratando de obtener el tipo de mimo usando imagecodeinfo ... para algunos archivos png las guias no eran exactamente las mismas ...
primero estaba comprobando con el ImageCodecinfo y si el código no encuentra el formato de imagen, comparé el formato de imagen con la solución de Matthias Wuttke.
si la solución mencionada anteriormente falló, entonces usó el método de extensión para obtener el tipo de archivo mime.
si el tipo de mime cambia, entonces el archivo también cambia, estábamos calculando la suma de comprobación de los archivos descargados para que coincida con la suma de comprobación del archivo original en el servidor ... así que para nosotros era importante obtener el archivo correcto como salida.