Wie kann ich wissen, welches Bildformat ich von einem Stream erhalte?


77

Ich erhalte einen Byte-Stream von einem Webdienst. Dieser Bytestream enthält das Binärdatum eines Bildes und ich verwende die folgende Methode, um es in eine Bildinstanz zu konvertieren.

Ich muss wissen, was für ein Bild ich habe. Ist es eine einfache Bitmap ( *.bmp) oder ein JPEG-Bild ( *.jpg) oder ein PNG-Bild?

Wie kann ich das herausfinden?

    public static Image byteArrayToImage( byte[] bmpBytes )
    {
        Image image = null;
        using( MemoryStream stream = new MemoryStream( bmpBytes ) )
        {
            image = Image.FromStream( stream );
        }

        return image;
    }

3
Ich nehme meinen Code in einer anderen Frage an .
Ivan Kochurkin

3
Vergessen Sie nicht, diese Image-Instanz in eine eigene using-Anweisung zu setzen, da System.Drawing bekannt dafür ist, dass es sich nicht korrekt bereinigt.
Paul

Antworten:


121

Sie können die Image.RawFormatEigenschaft auschecken . Sobald Sie das Bild aus dem Stream geladen haben, können Sie Folgendes testen:

if (ImageFormat.Jpeg.Equals(image.RawFormat))
{
    // JPEG
}
else if (ImageFormat.Png.Equals(image.RawFormat))
{
    // PNG
}
else if (ImageFormat.Gif.Equals(image.RawFormat))
{
    // GIF
}
... etc

7
Beachten Sie, dass ImageFormat.Jpeg == image.RawFormatsich nicht , Sie arbeiten müssen verwendenImageFormat.Jpeg.Equals(image.RawFormat)
Dinei

Was ist mit JPG? Ich muss
JPG

1
@ Elnaz: Sie sind die gleichen.
Andreas

23

Sie können den Bildtyp aus dem folgenden Code abrufen:

//get your image from bytaArrayToImage
Image img = byteArrayToImage(new byte[] { });

//get the format/file type
string ext = new ImageFormatConverter().ConvertToString(img.RawFormat);

2
Das ist die beste Antwort !!
Casey Crookston

Dies scheint nur ein ToString zu sein und verarbeitet MemoryBmp nicht.
Chris

es wirft einen Fehler für mich aus. "Fehler: Das Format des Wertes 'Png' ist ungültig."
Dhara Vaghasiya

(.Net Core 3 Preview 5 und
höher

5

In C # können wir Image.RawFormat verwenden , um das ImageFormat eines Bildes zu überprüfen. Die Eigenschaft RawFormat scheint jedoch in Compact Framework nicht verfügbar zu sein. Ich denke, Sie müssen die Imaging-API verwenden. Es werden viele Typen benötigt. Hier im Folgenden gebe ich Ihnen ein Beispiel, von dem ich denke, dass es Ihnen etwas helfen wird.

using System;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;

/// <summary>
/// This structure contains parameters related to an image.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct ImageInfo
{
    #region Fields

    /// <summary>
    /// A GUID value that identifies the file format for the native image data. This value is an image format identifier. For more information, see Imaging GUIDs.
    /// </summary>
    public Guid RawDataFormat;

    public PixelFormatID PixelFormat;

    public uint Width;

    public uint Height;

    public uint TileWidth;

    public uint TileHeight;

    public double Xdpi;

    public double Ydpi;

    public SinkFlags Flags;

    #endregion
}

[StructLayout(LayoutKind.Sequential)]
public struct FILETIME
{
    #region Fields

    public int dwLowDateTime;

    public int dwHighDateTime;

    #endregion
}

[StructLayout(LayoutKind.Sequential)]
internal struct BitmapData
{
    #region Fields

    public int Width;

    public int Height;

    public int Stride;

    public PixelFormatID PixelFormat;

    public IntPtr Scan0;

    public IntPtr Reserved;

    #endregion
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct STATSTG
{
    #region Fields

    [MarshalAs(UnmanagedType.LPWStr)]
    public string pwcsName;

    public int type;

    public long cbSize;

    public FILETIME mtime;

    public FILETIME ctime;

    public FILETIME atime;

    public int grfMode;

    public int grfLocksSupported;

    public Guid clsid;

    public int grfStateBits;

    public int reserved;

    #endregion
}

/// <summary>
/// COM IStream interface
/// </summary>
[ComImport]
[Guid("0000000c-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IStream
{
    void Read([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, IntPtr pcbRead);

    void Write([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, IntPtr pcbWritten);

    void Seek(long dlibMove, int origin, IntPtr plibNewPosition);

    void SetSize(long libNewSize);

    void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten);

    void Commit(int grfCommitFlags);

    void Revert();

    void LockRegion(long libOffset, long cb, int lockType);

    void UnlockRegion(long libOffset, long cb, int lockType);

    void Stat(out STATSTG pstatstg, int grfStatFlag);

    void Clone(out IStream ppstm);
}

/// <summary>
/// Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
/// </summary>
[ComImport]
[Guid("327ABDAA-072B-11D3-9D7B-0000F81EF32E")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComVisible(true)]
internal interface IBitmapImage
{
    uint GetSize(out Size size);

    uint GetPixelFormatID(out PixelFormatID pixelFormat);

    uint LockBits(ref RECT rect, uint flags, PixelFormatID pixelFormat, ref BitmapData lockedBitmapData);

    uint UnlockBits(ref BitmapData lockedBitmapData);

    uint GetPalette(); // This is a place holder

    uint SetPalette(); // This is a place holder
}

/// <summary>
/// Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
/// </summary>
[ComImport]
[Guid("327ABDA7-072B-11D3-9D7B-0000F81EF32E")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComVisible(true)]
internal interface IImagingFactory
{
    uint CreateImageFromStream(IStream stream, out IImage image);

    uint CreateImageFromFile(string filename, out IImage image);

    // We need the MarshalAs attribute here to keep COM interop from sending the buffer down as a Safe Array.
    // uint CreateImageFromBuffer([MarshalAs(UnmanagedType.LPArray)] byte[] buffer, uint size, BufferDisposalFlag disposalFlag, out IImage image);
    uint CreateImageFromBuffer(IntPtr buffer, uint size, BufferDisposalFlag disposalFlag, out IImage image);

    uint CreateNewBitmap();            // This is a place holder

    uint CreateBitmapFromImage(IImage image, uint width, uint height, PixelFormatID pixelFormat, InterpolationHint hints, out IBitmapImage bitmap);      // This is a place holder

    uint CreateBitmapFromBuffer();     // This is a place holder

    uint CreateImageDecoder();         // This is a place holder

    uint CreateImageEncoderToStream(); // This is a place holder

    uint CreateImageEncoderToFile(ref Guid clsid, string filename, out IImageEncoder encoder);

    uint GetInstalledDecoders([Out] out uint size, [Out] out IntPtr decoders);

    uint GetInstalledEncoders([Out] out uint size, [Out] out IntPtr ecoders);

    uint InstallImageCodec();          // This is a place holder

    uint UninstallImageCodec();        // This is a place holder
}

/// <summary>
/// Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
/// </summary>
[ComImport]
[Guid("327ABDAC-072B-11D3-9D7B-0000F81EF32E")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IImageEncoder
{
    int InitEncoder(IStream stream);

    int TerminateEncoder();

    int GetEncodeSink();

    int SetFrameDimension(ref Guid dimensionID);

    int GetEncoderParameterListSize(out uint size);

    int GetEncoderParameterList(uint size, out IntPtr @params);

    int SetEncoderParameters(IntPtr param);
}

/// <summary>
/// This structure defines the coordinates of the upper-left and lower-right corners of a rectangle. 
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct RECT
{
    #region Fields

    public int left;

    public int top;

    public int right;

    public int bottom;

    #endregion
}

// Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
internal enum BufferDisposalFlag : int
{
    BufferDisposalFlagNone,
    BufferDisposalFlagGlobalFree,
    BufferDisposalFlagCoTaskMemFree,
    BufferDisposalFlagUnmapView
}

// Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
internal enum InterpolationHint : int
{
    InterpolationHintDefault,
    InterpolationHintNearestNeighbor,
    InterpolationHintBilinear,
    InterpolationHintAveraging,
    InterpolationHintBicubic
}

/// <summary>
/// These values are flags used to identify the numerical formats of pixels in images.
/// </summary>
[Flags]
public enum PixelFormatID
{
    PixelFormatIndexed = 0x00010000,

    PixelFormatGDI = 0x00020000,

    PixelFormatAlpha = 0x00040000,

    PixelFormatPAlpha = 0x00080000,

    PixelFormatExtended = 0x00100000,

    PixelFormatCanonical = 0x00200000,

    PixelFormatUndefined = 0,

    PixelFormat1bppIndexed = (1 | (1 << 8) | PixelFormatIndexed | PixelFormatGDI),

    PixelFormat4bppIndexed = (2 | (4 << 8) | PixelFormatIndexed | PixelFormatGDI),

    PixelFormat16bppGrayScale = (4 | (16 << 8) | PixelFormatExtended),

    PixelFormat8bppIndexed = (3 | (8 << 8) | PixelFormatIndexed | PixelFormatGDI),

    PixelFormat16bppRGB555 = (5 | (16 << 8) | PixelFormatGDI),

    PixelFormat16bppRGB565 = (6 | (16 << 8) | PixelFormatGDI),

    PixelFormat16bppARGB1555 = (7 | (16 << 8) | PixelFormatAlpha | PixelFormatGDI),

    PixelFormat24bppRGB = (8 | (24 << 8) | PixelFormatGDI),

    PixelFormat32bppRGB = (9 | (32 << 8) | PixelFormatGDI),

    PixelFormat32bppARGB = (10 | (32 << 8) | PixelFormatAlpha | PixelFormatGDI | PixelFormatCanonical),

    PixelFormat32bppPARGB = (11 | (32 << 8) | PixelFormatAlpha | PixelFormatPAlpha | PixelFormatGDI),

    PixelFormat48bppRGB = (12 | (48 << 8) | PixelFormatExtended),

    PixelFormat64bppARGB = (13 | (64 << 8) | PixelFormatAlpha | PixelFormatCanonical | PixelFormatExtended),

    PixelFormat64bppPARGB = (14 | (64 << 8) | PixelFormatAlpha | PixelFormatPAlpha | PixelFormatExtended),

    PixelFormatMax = 15
}

[Flags]
internal enum SinkFlags : uint
{
    // Low-word: shared with ImgFlagx
    Scalable = 0x0001,
    HasAlpha = 0x0002,
    HasTranslucent = 0x0004,
    PartiallyScalable = 0x0008,

    ColorSpaceRGB = 0x0010,
    ColorSpaceCMYK = 0x0020,
    ColorSpaceGRAY = 0x0040,
    ColorSpaceYCBCR = 0x0080,
    ColorSpaceYCCK = 0x0100,

    // Low-word: image size info
    HasRealDPI = 0x1000,
    HasRealPixelSize = 0x2000,

    // High-word
    TopDown = 0x00010000,
    BottomUp = 0x00020000,
    FullWidth = 0x00040000,
    Multipass = 0x00080000,
    Composite = 0x00100000,
    WantProps = 0x00200000
}

/// <summary>
/// Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
/// </summary>
[ComImport]
[Guid("327ABDA9-072B-11D3-9D7B-0000F81EF32E")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComVisible(true)]
internal interface IImage
{
    uint GetPhysicalDimension(out Size size);

    uint GetImageInfo(ref ImageInfo info);

    uint SetImageFlags(uint flags);

    // "Correct" declaration: uint Draw(IntPtr hdc, ref Rectangle dstRect, ref Rectangle srcRect);
    uint Draw(IntPtr hdc, ref RECT dstRect, IntPtr srcRect);

    uint PushIntoSink(); // This is a place holder

    uint GetThumbnail(uint thumbWidth, uint thumbHeight, out IImage thumbImage);
}

/// <summary>
/// Implmentation for the COM IStream interface
/// </summary>
public sealed class StreamOnFile :
    IStream,
    IDisposable
{
    #region Fields

    private readonly Stream stream;
    private readonly string fileName;

    #endregion

    #region Constructors

    /// <summary>
    ///     Initializes a new instance of the <see cref="StreamOnFile"/> class.
    /// </summary>
    /// <param name="fileName">File name to open
    /// </param>
    internal StreamOnFile(string fileName)
    {
        this.fileName = fileName;

        // prevent another processes/threads (mainly delete from web) from using this file while Imaging API is trying to access it
        this.stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.None);
    }

    #endregion

    #region Properties

    /// <summary>
    /// Gets the file name
    /// </summary>
    public string FileName
    {
        get
        {
            return this.fileName;
        }
    }

    #endregion

    #region Methods

    public void Read(byte[] pv, int cb, IntPtr pcbRead)
    {
        int val = this.stream.Read(pv, 0, cb);
        if (pcbRead != IntPtr.Zero)
        {
            Marshal.WriteInt32(pcbRead, val);
        }
    }

    public void Write(byte[] pv, int cb, IntPtr pcbWritten)
    {
        this.stream.Write(pv, 0, cb);
        if (pcbWritten != IntPtr.Zero)
        {
            Marshal.WriteInt32(pcbWritten, cb);
        }
    }

    public void Seek(long dlibMove, int origin, IntPtr plibNewPosition)
    {
        long val = this.stream.Seek(dlibMove, (SeekOrigin)origin);
        if (plibNewPosition != IntPtr.Zero)
        {
            Marshal.WriteInt64(plibNewPosition, val);
        }
    }

    public void SetSize(long libNewSize)
    {
        throw new NotImplementedException("The method or operation is not implemented.");
    }

    public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten)
    {
        throw new NotImplementedException("The method or operation is not implemented.");
    }

    public void Commit(int grfCommitFlags)
    {
        throw new NotImplementedException("The method or operation is not implemented.");
    }

    public void Revert()
    {
        throw new NotImplementedException("The method or operation is not implemented.");
    }

    public void LockRegion(long libOffset, long cb, int lockType)
    {
        throw new NotImplementedException("The method or operation is not implemented.");
    }

    public void UnlockRegion(long libOffset, long cb, int lockType)
    {
        throw new NotImplementedException("The method or operation is not implemented.");
    }

    public void Stat(out STATSTG pstatstg, int grfStatFlag)
    {
        throw new NotImplementedException("The method or operation is not implemented.");
    }

    public void Clone(out IStream ppstm)
    {
        throw new NotImplementedException("The method or operation is not implemented.");
    }

    public void Dispose()
    {
        if (this.stream != null)
        {
            this.stream.Close();
        }
    }

    #endregion
}

public enum ImageType
{
    Undefined,
    MemoryBMP,
    BMP,
    EMF,
    WMF,
    JPEG,
    PNG,
    GIF,
    TIFF,
    EXIF,
    Icon
}

public static class BitmapProperties
{
    /// <summary>
    /// Indicates the Microsoft Windowsbitmap (BMP) format.
    /// </summary>
    private static readonly Guid ImageFormatBMP = new Guid("B96B3CAB-0728-11D3-9D7B-0000F81EF32E");

    /// <summary>
    /// Indicates the Enhanced Metafile (EMF) format.
    /// </summary>
    private static readonly Guid ImageFormatEMF = new Guid("B96B3CAC-0728-11D3-9D7B-0000F81EF32E");

    /// <summary>
    /// Indicates the Exif (Exchangeable Image File) format.
    /// </summary>
    private static readonly Guid ImageFormatEXIF = new Guid("B96B3CB2-0728-11D3-9D7B-0000F81EF32E");

    /// <summary>
    /// Indicates the Graphics Interchange Format (GIF) format.
    /// </summary>
    private static readonly Guid ImageFormatGIF = new Guid("B96B3CB0-0728-11D3-9D7B-0000F81EF32E");

    /// <summary>
    /// Indicates the Icon format.
    /// </summary>
    private static readonly Guid ImageFormatIcon = new Guid("B96B3CB5-0728-11D3-9D7B-0000F81EF32E");

    /// <summary>
    /// Indicates the JPEG format.
    /// </summary>
    private static readonly Guid ImageFormatJPEG = new Guid("B96B3CAE-0728-11D3-9D7B-0000F81EF32E");

    /// <summary>
    /// Indicates that the image was constructed from a memory bitmap.
    /// </summary>
    private static readonly Guid ImageFormatMemoryBMP = new Guid("B96B3CAB-0728-11D3-9D7B-0000F81EF32E");

    /// <summary>
    /// Indicates the Portable Network Graphics (PNG) format.
    /// </summary>
    private static readonly Guid ImageFormatPNG = new Guid("B96B3CAF-0728-11D3-9D7B-0000F81EF32E");

    /// <summary>
    /// Indicates the Tagged Image File Format (TIFF) format.
    /// </summary>
    private static readonly Guid ImageFormatTIFF = new Guid("B96B3CB1-0728-11D3-9D7B-0000F81EF32E");

    /// <summary>
    /// Indicates that Windows GDI+ is unable to determine the format.
    /// </summary>
    private static readonly Guid ImageFormatUndefined = new Guid("B96B3CA9-0728-11D3-9D7B-0000F81EF32E");

    /// <summary>
    /// Indicates the Windows Metafile Format (WMF) format.
    /// </summary>
    private static readonly Guid ImageFormatWMF = new Guid("B96B3CAD-0728-11D3-9D7B-0000F81EF32E");

    internal const int S_OK = 0;

    /// <summary>
    /// Gets the ImageType of the given file
    /// </summary>
    /// <param name="fileName">Path of the file to get the info of</param>
    /// <returns>ImageType of the given file</returns>
    public static ImageType GetImageType(string fileName)
    {
        IImage imagingImage = null;

        try
        {
            if (File.Exists(fileName))
            {
                using (StreamOnFile fileStream = new StreamOnFile(fileName))
                {
                    imagingImage = BitmapProperties.GetImage(fileStream);
                    if (imagingImage != null)
                    {
                        ImageInfo info = new ImageInfo();
                        uint ret = imagingImage.GetImageInfo(ref info);
                        if (ret == BitmapProperties.S_OK)
                        {
                            if (info.RawDataFormat == BitmapProperties.ImageFormatBMP)
                            {
                                return ImageType.BMP;
                            }
                            else if (info.RawDataFormat == BitmapProperties.ImageFormatEMF)
                            {
                                return ImageType.EMF;
                            }
                            else if (info.RawDataFormat == BitmapProperties.ImageFormatEXIF)
                            {
                                return ImageType.EXIF;
                            }
                            else if (info.RawDataFormat == BitmapProperties.ImageFormatGIF)
                            {
                                return ImageType.GIF;
                            }
                            else if (info.RawDataFormat == BitmapProperties.ImageFormatIcon)
                            {
                                return ImageType.Icon;
                            }
                            else if (info.RawDataFormat == BitmapProperties.ImageFormatJPEG)
                            {
                                return ImageType.JPEG;
                            }
                            else if (info.RawDataFormat == BitmapProperties.ImageFormatMemoryBMP)
                            {
                                return ImageType.MemoryBMP;
                            }
                            else if (info.RawDataFormat == BitmapProperties.ImageFormatPNG)
                            {
                                return ImageType.PNG;
                            }
                            else if (info.RawDataFormat == BitmapProperties.ImageFormatTIFF)
                            {
                                return ImageType.TIFF;
                            }
                            else if (info.RawDataFormat == BitmapProperties.ImageFormatWMF)
                            {
                                return ImageType.WMF;
                            }
                        }
                    }
                }
            }

            return ImageType.Undefined;
        }
        finally
        {
            if (imagingImage != null)
            {
                Marshal.ReleaseComObject(imagingImage);
            }
        }
    }

    private static IImage GetImage(StreamOnFile stream)
    {
        IImagingFactory factory = null;
        try
        {
            factory = (IImagingFactory)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("327ABDA8-072B-11D3-9D7B-0000F81EF32E")));
            if (factory != null)
            {
                IImage imagingImage;
                uint result = factory.CreateImageFromStream(stream, out imagingImage);
                if (result == BitmapProperties.S_OK)
                {
                    return imagingImage;
                }
            }
        }
        catch (COMException)
        {
        }
        catch (IOException)
        {
        }
        finally
        {
            if (factory != null)
            {
                Marshal.ReleaseComObject(factory);
            }
        }

        return null;
    }
}

4
Ich gebe Ihnen ein Beispiel, von dem ich denke, dass es Ihnen etwas helfen wird. Einige "was" in der Tat.
ta.speot.is

1

Das Parsen eines Byte-Arrays in ein tatsächliches Bildobjekt kann insbesondere für große Datenmengen ressourcenintensiv sein

Sie können stattdessen Magic Numbers verwenden

JPEG-Bilddateien beginnen mit FF D8 und enden mit FF D9

...

PNG-Bilddateien beginnen mit einer 8-Byte-Signatur, die die Datei als PNG-Datei identifiziert und die Erkennung häufiger Probleme bei der Dateiübertragung ermöglicht: (89 50 4E 47 0D 0A 1A 0A)

usw.

Ein Beispielcode für Sie:

public bool IsPng(byte[] array)
{
    return array != null
        && array.Length > 8
        && array[0] == 0x89
        && array[1] == 0x50
        && array[2] == 0x4e
        && array[3] == 0x47
        && array[4] == 0x0d
        && array[5] == 0x0a
        && array[6] == 0x1a
        && array[7] == 0x0a
}

Natürlich sollten Sie die Daten nach dieser schnellen Überprüfung weiter validieren, um 100% sicher zu sein, dass das Format sicher ist und ein tatsächliches Bild ist.

PS So machen es Browser

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.