Как я могу узнать, какой формат изображения я получаю из потока?

Я получаю поток байтов из некоторого веб-сервиса. Этот поток байтов содержит двоичную дату изображения, и я использую метод ниже, чтобы преобразовать его в экземпляр изображения.

Мне нужно знать, какой у меня образ. Является ли это простым растровым изображением (*.bmp) или изображением JPEG (*.jpg) или png-изображением?

Как я могу это узнать?

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

        return image;
    }

Ответ 1

Вы можете проверить свойство Image.RawFormat. Поэтому, как только вы загрузите изображение из потока, вы можете проверить:

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

Ответ 2

В С# мы можем использовать Image.RawFormat, чтобы проверить ImageFormat изображения. Но свойство RawFormat кажется недоступным в Compact Framework. Поэтому я считаю, что вам нужно использовать API обработки изображений. Нужно много типов. Здесь, в следующей главе, я приведу вам пример, я думаю, что это поможет вам в чем-то.

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;
    }
}

Ответ 3

Вы можете получить тип изображения из следующего кода:

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

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