我从某个Web服务获取字节流。此字节流包含图像的二进制日期,我使用下面的方法将其转换为Image实例。
我需要知道我有什么样的形象。它是简单的位图(*.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;
}
答案 0 :(得分:112)
您可以结帐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
答案 1 :(得分:18)
您可以从以下代码中获取图像类型:
//get your image from bytaArrayToImage
Image img = byteArrayToImage(new byte[] { });
//get the format/file type
string ext = new ImageFormatConverter().ConvertToString(img.RawFormat);
答案 2 :(得分:7)
在C#中,我们可以使用Image.RawFormat来检查图像的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;
}
}
答案 3 :(得分:1)
将字节数组解析为实际的图像对象可能会占用大量资源,尤其是对于大量数据而言
您可以改用Magic Numbers
JPEG图像文件以FF D8开头,以FF D9结尾
...
PNG图像文件以8字节签名开头,用于标识 文件作为PNG文件,并允许检测常见文件传输 问题:(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
}
当然,您应该在进行此快速检查后进一步验证数据,以100%确定格式是安全的并且是实际图像。
P.S。这是浏览器的方式
答案 4 :(得分:1)
这是我根据 Alex 提到的方法和参考文章编写的一个非常轻量级的 ImageDetector 类:
namespace ImageDetection
{
using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.Linq;
// based on https://devblogs.microsoft.com/scripting/psimaging-part-1-test-image/
public class ImageDetector
{
// https://en.wikipedia.org/wiki/List_of_file_signatures
/* Bytes in c# have a range of 0 to 255 so each byte can be represented as
* a two digit hex string. */
private static readonly Dictionary<ImageFormat, string[][]> SignatureTable = new Dictionary<ImageFormat, string[][]>
{
{
ImageFormat.Jpeg,
new[]
{
new[] {"FF", "D8", "FF", "DB"},
new[] {"FF", "D8", "FF", "EE"},
new[] {"FF", "D8", "FF", "E0", "00", "10", "4A", "46", "49", "46", "00", "01"}
}
},
{
ImageFormat.Gif,
new[]
{
new [] { "47", "49", "46", "38", "37", "61" },
new [] { "47", "49", "46", "38", "39", "61" }
}
},
{
ImageFormat.Png,
new[]
{
new[] {"89", "50", "4E", "47", "0D", "0A", "1A", "0A"}
}
},
{
ImageFormat.Bmp,
new []
{
new[] { "42", "4D" }
}
}
};
/// <summary>
/// Takes a byte array and determines the image file type by
/// comparing the first few bytes of the file to a list of known
/// image file signatures.
/// </summary>
/// <param name="imageData">Byte array of the image data</param>
/// <returns>ImageFormat corresponding to the image file format</returns>
/// <exception cref="ArgumentException">Thrown if the image type can't be determined</exception>
public static ImageFormat GetImageType(byte[] imageData)
{
foreach (KeyValuePair<ImageFormat, string[][]> signatureEntry in SignatureTable)
{
foreach (string[] signature in signatureEntry.Value)
{
bool isMatch = true;
for (int i = 0; i < signature.Length; i++)
{
string signatureByte = signature[i];
// ToString("X") gets the hex representation and pads it to always be length 2
string imageByte = imageData[i]
.ToString("X2");
if (signatureByte == imageByte)
continue;
isMatch = false;
break;
}
if (isMatch)
{
return signatureEntry.Key;
}
}
}
throw new ArgumentException("The byte array did not match any known image file signatures.");
}
}
}
答案 5 :(得分:1)
我需要一个简单的 Java 图像格式检测器(用于 Android 应用程序),因此改编 @Jared_Beach 答案,还添加了 WebP 格式检测:
import com.sun.istack.internal.Nullable;
// based on https://devblogs.microsoft.com/scripting/psimaging-part-1-test-image/
public class ImageDetector
{
final static String[] imgFormats = {"jpg", "gif", "png", "bmp", "webp"};
private enum ImageFormat {
Jpeg (new int[][]{
{0xFF, 0xD8, 0xFF, 0xDB},
{0xFF, 0xD8, 0xFF, 0xEE},
{0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01}
}),
Gif (new int[][]{
{0x47, 0x49, 0x46, 0x38, 0x37, 0x61},
{0x47, 0x49, 0x46, 0x38, 0x39, 0x61}
}),
Png (new int[][]{
{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}
}),
Bmp (new int[][]{
{0x42, 0x4D}
}),
WebP (new int[][]{
// Ignores zeroes - image size goes there
{ 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P'}
});
final byte[][] _bts;
ImageFormat(int[][] b) {
_bts = new byte[b.length][];
for (int i = 0; i < b.length; i++) {
_bts[i] = new byte[b[i].length];
for (int j = 0; j < b[i].length; j++)
_bts[i][j] = (byte) b[i][j];
}
}
}
/**
Takes a byte array and determines the image file type by
comparing the first few bytes of the file to a list of known
image file signatures.
@param imageData Byte array of the image data
@return type from imgFormats, it can be a MIME too type with "image/"+imgFormats[i], or simply file name extension,
or null if type not recognized.
*/
@Nullable
public static String getImageType(byte[] imageData)
{
if (imageData.length > 16) { // too small, avoid index out of bounds exception
for (ImageFormat imgF : ImageFormat.values()) {
for (byte[] sig : imgF._bts) {
boolean isMatch = true;
for (int i = 0; i < sig.length; i++) {
if ((sig[i] != 0 || imgF != ImageFormat.WebP) && sig[i] != imageData[i]) {
isMatch = false;
break;
}
}
if (isMatch)
return imgFormats[imgF.ordinal()];
}
}
}
return null;
}
}
这是一个小测试函数:
static void testImageDetector() {
final String[] fileNames = {
"C:/tmp/test.jpg",
"C:/tmp/test.gif",
"C:/tmp/test.png",
"C:/tmp/test.bmp",
"C:/tmp/test.webp",
};
FileInputStream fis = null;
try {
byte[] buf = new byte[64];
String type;
for (String fName : fileNames) {
fis = new FileInputStream(fName);
fis.read(buf);
fis.close(); fis = null;
String ext = fName.substring(fName.lastIndexOf('.') + 1);
type = ImageDetector.getImageType(buf);
System.out.println("File: " + fName + ", type: " + type);
if (!ext.equals(type))
throw new AssertionError("Wrong type detected!");
}
}
catch (IOException iox) {
System.out.println("IOException: " + iox);
iox.printStackTrace();
}
catch (AssertionError ae) {
ae.printStackTrace();
}
finally {
if (fis != null) try {
fis.close();
} catch (IOException ignore) {}
}
}