스트림에서 가져온 이미지 형식을 어떻게 알 수 있습니까?
일부 웹 서비스에서 바이트 스트림을 얻습니다. 이 바이트 스트림에는 이미지의 이진 날짜가 포함되어 있으며 아래 방법을 사용하여 이미지 인스턴스로 변환하고 있습니다.
어떤 이미지를 가지고 있는지 알아야합니다. 간단한 비트 맵 ( *.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;
}
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
다음 코드에서 이미지 유형을 가져올 수 있습니다.
//get your image from bytaArrayToImage
Image img = byteArrayToImage(new byte[] { });
//get the format/file type
string ext = new ImageFormatConverter().ConvertToString(img.RawFormat);
C #에서는 Image.RawFormat 을 사용 하여 Image의 ImageFormat을 확인할 수 있습니다 . 그러나 속성 RawFormat은 컴팩트 프레임 워크에서 사용할 수 없습니다. 따라서 Imaging 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;
}
}
바이트 배열을 실제 이미지 객체로 구문 분석하는 것은 특히 막대한 양의 데이터에 대해 리소스 집약적 일 수 있습니다.
대신 매직 넘버 를 사용할 수 있습니다.
JPEG 이미지 파일은 FF D8로 시작하고 FF D9로 끝납니다.
...
PNG 이미지 파일은 파일을 PNG 파일로 식별하고 일반적인 파일 전송 문제를 감지 할 수있는 8 바이트 서명으로 시작합니다. (89 50 4E 47 0D 0A 1A 0A)
기타
몇 가지 예제 코드 :
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
}
Of course, you should further validate the data after this quick check to be 100% sure the format is safe and is an actual image.
P.S. this is how browsers do it
참고URL : https://stackoverflow.com/questions/5209506/how-can-i-know-what-image-format-i-get-from-a-stream
'developer tip' 카테고리의 다른 글
대체 사전을 사용하여 문자열을 대체하는 가장 쉬운 방법은 무엇입니까? (0) | 2020.11.04 |
---|---|
Python 스크립트 중간에있는 모든 변수를 지우려면 어떻게해야합니까? (0) | 2020.11.04 |
GIT-.suo 파일을 무시할 수 없습니다. (0) | 2020.11.04 |
Scala에서 HTTP 요청 수행 (0) | 2020.11.04 |
JSON 본문을 사용한 POST 요청 (0) | 2020.11.04 |