C# How to Test a File Is a Jpeg

C# How can I test a file is a jpeg?

Several options:

You can check for the file extension:

static bool HasJpegExtension(string filename)
{
// add other possible extensions here
return Path.GetExtension(filename).Equals(".jpg", StringComparison.InvariantCultureIgnoreCase)
|| Path.GetExtension(filename).Equals(".jpeg", StringComparison.InvariantCultureIgnoreCase);
}

or check for the correct magic number in the header of the file:

static bool HasJpegHeader(string filename)
{
using (BinaryReader br = new BinaryReader(File.Open(filename, FileMode.Open, FileAccess.Read)))
{
UInt16 soi = br.ReadUInt16(); // Start of Image (SOI) marker (FFD8)
UInt16 marker = br.ReadUInt16(); // JFIF marker (FFE0) or EXIF marker(FFE1)

return soi == 0xd8ff && (marker & 0xe0ff) == 0xe0ff;
}
}

Another option would be to load the image and check for the correct type. However, this is less efficient (unless you are going to load the image anyway) but will probably give you the most reliable result (Be aware of the additional cost of loading and decompression as well as possible exception handling):

static bool IsJpegImage(string filename)
{
try
{
using (System.Drawing.Image img = System.Drawing.Image.FromFile(filename))
{
// Two image formats can be compared using the Equals method
// See http://msdn.microsoft.com/en-us/library/system.drawing.imaging.imageformat.aspx
//
return img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
catch (OutOfMemoryException)
{
// Image.FromFile throws an OutOfMemoryException
// if the file does not have a valid image format or
// GDI+ does not support the pixel format of the file.
//
return false;
}
}

determine if file is an image

Check the file for a known header. (Info from link also mentioned in this answer)

The first eight bytes of a PNG file always contain the following (decimal) values: 137 80 78 71 13 10 26 10

How to check if a jpeg image file is actually a valid image before trying to load?

As far I as I know all JPEGs begin internally with same 10 character ASCII string although I can't remember what the first 6 characters are. This is quick/dirty method of indentifying a jpeg image even if the file extension is wrong.

grep -P '^......JFIF' ./'raccoon paint.jpeg'

If the image is not a jpeg the match will fail.

Good way to check if file extension is of an image or not

You could use .endsWith(ext). It's not a very secure method though: I could rename 'bla.jpg' to 'bla.png' and it would still be a jpg file.

public static bool HasImageExtension(this string source){
return (source.EndsWith(".png") || source.EndsWith(".jpg"));
}

This provides a more secure solution:

string InputSource = "mypic.png";
System.Drawing.Image imgInput = System.Drawing.Image.FromFile(InputSource);
Graphics gInput = Graphics.fromimage(imgInput);
Imaging.ImageFormat thisFormat = imgInput.rawformat;

Validate image from file in C#

JPEG's don't have a formal header definition, but they do have a small amount of metadata you can use.

  • Offset 0 (Two Bytes): JPEG SOI marker (FFD8 hex)
  • Offset 2 (Two Bytes): Image width in pixels
  • Offset 4 (Two Bytes): Image height in pixels
  • Offset 6 (Byte): Number of components (1 = grayscale, 3 = RGB)

There are a couple other things after that, but those aren't important.

You can open the file using a binary stream, and read this initial data, and make sure that OffSet 0 is 0, and OffSet 6 is either 1,2 or 3.

That would at least give you slightly more precision.

Or you can just trap the exception and move on, but I thought you wanted a challenge :)

How can I determine if a file is an image file in .NET?

  1. You will only notice a performance hit from exceptions if you are constantly throwing them. So unless your program expects to see many invalid images (hundreds per second) you should not notice the overhead of exception handling.
  2. This is really the only way to tell if the image is a full image or corrupt. You can check the headers as the other people recommend, but that only checks to see if the beginning few bytes are correct, anything else could be garbage. Whether this is good enough or not depends on the requirements of your application. Just reading the header might be good enough for your use case.
  3. Yes, this is rather poor design on the BCL team's part. If you are loading many large images you very well could be hitting a real OOM situation in the large object heap. As far as I know, there is no way to differentiate the two exceptions.

How to check if image file is valid?

First of all, don't try to use System.Drawing in .NET Core applications. It's deprecated and works only on Windows anyway. The MSDN docs themselves suggest using ImageSharp or SkiaSharp instead.

Image files start with bytes that identify the file format. You'll have to read at least some of the file's contents to read image metadata like the image size, resolution etc. You can use ImageSharp's Identify method to read only the format and image properties, without loading the entire image.

You can read an uploaded file's contents using IFormFile.OpenReadStream.

using var stream=image.OpenReadStream();
try
{
var imageInfo=Image.Identify(stream, out var format);
if(imageInfo!=null)
{
var formatName=format.Name;
var width=imageInfo.Width;
var height=imageInfo.Height;
}
}
catch(InvalidImageContentException exc)
{
//Invalid content ?
}

The format parameter is an IImageFormat value that contains information about the image format, including its name and mime types.

The IImageInfo object returned contains the image dimensions, pixel type, resolution etc.

The method documentation explains that the return value will be null if no suitable decoder is found:

The IImageInfo or null if a suitable info detector is not found.

But an exception will be thrown if the content is invalid:

InvalidImageContentException Image contains invalid content.

Without testing this, I assume that a text file will result in a null but a file with just a GIF header without valid content will result in an exception.

You can use ImageSharp to resize the image or convert it to another format. In that case it's not enough to just load the metadata. You can use Load to load the image from the stream, detect its format and then manipulate it.

using var stream=image.OpenReadStream();
var image=Image.Load(stream, out var format);

var formatName=format.Name;
if (notOk(formatName,image.Height,image.Width))
{
using var outStream=new MemoryStream();
image.Mutate(x => x.Resize(desiredWidth, desiredHeight));
image.SaveAsPng(outStream);
outStream.Position=0;
//Store the contents of `outStream`
}

How to check Is Valid Image File in C#

I think you can check the file header.

    public static ImageType CheckImageType(string path)
{
byte[] buf = new byte[2];
try
{
using (StreamReader sr = new StreamReader(path))
{
int i = sr.BaseStream.Read(buf, 0, buf.Length);
if (i != buf.Length)
{
return ImageType.None;
}
}
}
catch (Exception exc)
{
//Debug.Print(exc.ToString());
return ImageType.None;
}
return CheckImageType(buf);
}

public static ImageType CheckImageType(byte[] buf)
{
if (buf == null || buf.Length < 2)
{
return ImageType.None;
}

int key = (buf[1] << 8) + buf[0];
ImageType s;
if (_imageTag.TryGetValue(key, out s))
{
return s;
}
return ImageType.None;
}

public enum ImageType
{
None = 0,
BMP = 0x4D42,
JPG = 0xD8FF,
GIF = 0x4947,
PCX = 0x050A,
PNG = 0x5089,
PSD = 0x4238,
RAS = 0xA659,
SGI = 0xDA01,
TIFF = 0x4949
}

How to cover image conversion in a C# unit test?

First of all, your unit test does not expose actual implementation. You use mocks. The goal should be to verify that methods are called and given mock implementation returns expected result.


Often people mix unit test with integration tests and have problems with responsibility in general. What you described seems to be an integration test.

One way would be to create an ImageDifference function to get mean difference:
Sample Image
Sample Image

Images are taken from Wolfram Mathematica documentation. Given correct tools and pre-knowledge this is a really easy problem (but very often it is not).

In the case of a lossy image, you would get something that looks like a shadow image. However, you do not need to compute the image, just a double describing the difference. To test it:

Assert.That(expected, Is.EqualTo(actual).Within(tolerance));

Let's say that your expected is 0.03 and actual are 0.01638489638 and tolerance is 0.005. That would test if an image contains 97% quality image with 0.5% error.

I hope you found this was helpful.

How to validate image file format in C#

Use Image.RawFormat. The result is an instance of the ImageFormat class which can be compared against the static properties of ImageFormat.

See the ImageFormat class properties for more details.



Related Topics



Leave a reply



Submit