How can I know what image format I get from a stream?

后端 未结 4 1206
南笙
南笙 2020-11-29 19:59

I get a byte stream from some web service. This byte stream contains the binary date of an image and I\'m using the method below to convert it to an Image instance.

4条回答
  •  一生所求
    2020-11-29 20:37

    In C#, we can use Image.RawFormat to check the ImageFormat of an Image. But property RawFormat seems not available in compact Framework. So I think you have to use the Imaging API. There are a lot of types needed. Here in the bellow I am giving you an example I think it will help you some what.

    using System;
    using System.Drawing;
    using System.IO;
    using System.Runtime.InteropServices;
    
    /// 
    /// This structure contains parameters related to an image.
    /// 
    [StructLayout(LayoutKind.Sequential)]
    internal struct ImageInfo
    {
        #region Fields
    
        /// 
        /// 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.
        /// 
        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
    }
    
    /// 
    /// COM IStream interface
    /// 
    [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);
    }
    
    /// 
    /// Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
    /// 
    [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
    }
    
    /// 
    /// Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
    /// 
    [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
    }
    
    /// 
    /// Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
    /// 
    [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);
    }
    
    /// 
    /// This structure defines the coordinates of the upper-left and lower-right corners of a rectangle. 
    /// 
    [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
    }
    
    /// 
    /// These values are flags used to identify the numerical formats of pixels in images.
    /// 
    [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
    }
    
    /// 
    /// Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
    /// 
    [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);
    }
    
    /// 
    /// Implmentation for the COM IStream interface
    /// 
    public sealed class StreamOnFile :
        IStream,
        IDisposable
    {
        #region Fields
    
        private readonly Stream stream;
        private readonly string fileName;
    
        #endregion
    
        #region Constructors
    
        /// 
        ///     Initializes a new instance of the  class.
        /// 
        /// File name to open
        /// 
        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
    
        /// 
        /// Gets the file name
        /// 
        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
    {
        /// 
        /// Indicates the Microsoft Windowsbitmap (BMP) format.
        /// 
        private static readonly Guid ImageFormatBMP = new Guid("B96B3CAB-0728-11D3-9D7B-0000F81EF32E");
    
        /// 
        /// Indicates the Enhanced Metafile (EMF) format.
        /// 
        private static readonly Guid ImageFormatEMF = new Guid("B96B3CAC-0728-11D3-9D7B-0000F81EF32E");
    
        /// 
        /// Indicates the Exif (Exchangeable Image File) format.
        /// 
        private static readonly Guid ImageFormatEXIF = new Guid("B96B3CB2-0728-11D3-9D7B-0000F81EF32E");
    
        /// 
        /// Indicates the Graphics Interchange Format (GIF) format.
        /// 
        private static readonly Guid ImageFormatGIF = new Guid("B96B3CB0-0728-11D3-9D7B-0000F81EF32E");
    
        /// 
        /// Indicates the Icon format.
        /// 
        private static readonly Guid ImageFormatIcon = new Guid("B96B3CB5-0728-11D3-9D7B-0000F81EF32E");
    
        /// 
        /// Indicates the JPEG format.
        /// 
        private static readonly Guid ImageFormatJPEG = new Guid("B96B3CAE-0728-11D3-9D7B-0000F81EF32E");
    
        /// 
        /// Indicates that the image was constructed from a memory bitmap.
        /// 
        private static readonly Guid ImageFormatMemoryBMP = new Guid("B96B3CAB-0728-11D3-9D7B-0000F81EF32E");
    
        /// 
        /// Indicates the Portable Network Graphics (PNG) format.
        /// 
        private static readonly Guid ImageFormatPNG = new Guid("B96B3CAF-0728-11D3-9D7B-0000F81EF32E");
    
        /// 
        /// Indicates the Tagged Image File Format (TIFF) format.
        /// 
        private static readonly Guid ImageFormatTIFF = new Guid("B96B3CB1-0728-11D3-9D7B-0000F81EF32E");
    
        /// 
        /// Indicates that Windows GDI+ is unable to determine the format.
        /// 
        private static readonly Guid ImageFormatUndefined = new Guid("B96B3CA9-0728-11D3-9D7B-0000F81EF32E");
    
        /// 
        /// Indicates the Windows Metafile Format (WMF) format.
        /// 
        private static readonly Guid ImageFormatWMF = new Guid("B96B3CAD-0728-11D3-9D7B-0000F81EF32E");
    
        internal const int S_OK = 0;
    
        /// 
        /// Gets the ImageType of the given file
        /// 
        /// Path of the file to get the info of
        /// ImageType of the given file
        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;
        }
    }
    

提交回复
热议问题