/// <summary> /// Helper methods for verifying image content types by validating the first bytes of the file. /// You can extend this class by adding additional XxxFirstBytes constants and IsXxx methods. /// </summary> public static class ImageHelper { // These are the first three bytes of a JPEG, usually enough to determine if the file is an image/jpeg private static readonly byte[] JpegFirstBytes = new byte[] { 0xFF, 0xD8, 0xFF }; // // More specific headers. Note that the 5th and 6th byte should be ignored. // The second pair and final five bytes is the application marker. The final byte should // always be 0x00 to terminate the JPEG header. // // JIFF, regular // new byte[] { 0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x00, 0x4A, 0x46, 0x49, 0x46, 0x00 } // // EXIF, Canon Digital Cameras // new byte[] { 0xFF, 0xD8, 0xFF, 0xE1, 0x00, 0x00, 0x45, 0x78, 0x69, 0x66, 0x00 } // /// <summary> /// Verify that the byte array matches a JPEG sequence. The first three bytes are enough. /// </summary> /// <param name="bytes">The byte array to verify.</param> /// <returns>True if the data matches a JPEG header, otherwise false.</returns> public static bool IsJpeg(byte[] bytes) { return VerifyBytes(bytes, JpegFirstBytes); } private static bool VerifyBytes(IList<byte> bytes, IList<byte> controlBytes) { // Do we have any data? if (bytes == null || bytes.Count < controlBytes.Count) return false; var xorSum = 0; for (var i = 0; i < controlBytes.Count && xorSum == 0; i += 1) // Use bitwise XOR to make sure the bytes match our array xorSum += bytes[i] ^ controlBytes[i]; // Since we used XOR, sum should be zero if this is a JPEG return xorSum == 0; } }