76

I have a file called FPN = "c:\ggs\ggs Access\images\members\1.jpg "

I'm trying to get the dimension of image 1.jpg, and I'd like to check whether image dimension is valid or not before loading.

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
user682417
  • 1,478
  • 4
  • 25
  • 46

4 Answers4

147
System.Drawing.Image img = System.Drawing.Image.FromFile(@"c:\ggs\ggs Access\images\members\1.jpg");
MessageBox.Show("Width: " + img.Width + ", Height: " + img.Height);
John T
  • 23,735
  • 11
  • 56
  • 82
  • 1
    @User1: You should edit your question to be more clear as to the meaning of "size". – Joel Etherton Jun 23 '11 at 15:01
  • This would work in terms of working out the size of the image, but if the file is not a valid image file it will throw an exception on the first line rather than the file having 0 height or width. Not sure why the OP thinks that checking if the dimensions of the image are 0 by 0 is an appropriate way to check for a valid image file. – Ben Robinson Jun 23 '11 at 15:02
  • 4
    it throws an excpetion saying that out of memory – user682417 Jun 23 '11 at 15:11
  • Depending on the image sizes you may be better off storing them in a byte array. – John T Jun 23 '11 at 15:15
  • is it possible to use a uri as a paremeter for FromFile()? – mko Nov 06 '17 at 11:23
  • 5
    @user682417 consider `Image.FromStream` so you might avoid loading the whole file into memory (and faster) -- see https://www.roelvanlisdonk.nl/2012/02/28/fastest-way-to-read-dimensions-from-a-picture-image-file-in-c/ – drzaus Nov 26 '18 at 18:35
  • 2
    For .net core nuget System.Drawing.Common re: https://www.hanselman.com/blog/HowDoYouUseSystemDrawingInNETCore.aspx – sobelito Mar 11 '20 at 08:56
50

Wpf class System.Windows.Media.Imaging.BitmapDecoder doesn't read whole file, just metadata.

using(var imageStream = File.OpenRead("file"))
{
    var decoder = BitmapDecoder.Create(imageStream, BitmapCreateOptions.IgnoreColorProfile,
        BitmapCacheOption.Default);
    var height = decoder.Frames[0].PixelHeight;
    var width = decoder.Frames[0].PixelWidth;
}

Update 2019-07-07 Dealing with exif'ed images is a little bit more complicated. For some reasons iphones save a rotated image and to compensate they also set "rotate this image before displaying" exif flag as such.

Gif is also a pretty complicated format. It is possible that no frame has full gif size, you have to aggregate it from offsets and frames sizes.

So I used ImageProcessor instead, which deals with all the problems for me. Never checked if it reads the whole file though, because some browsers have no exif support and I had to save a rotated version anyway.

using (var imageFactory = new ImageFactory())
{
    imageFactory
        .Load(stream)
        .AutoRotate(); //takes care of ex-if
    var height = imageFactory.Image.Height,
    var width = imageFactory.Image.Width
}
ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
Atomosk
  • 1,871
  • 2
  • 22
  • 26
  • This should be the top answer because it actually answers the question. – person27 Jul 05 '19 at 23:19
  • @person27 Thanks for comment, I've totaly forgot about that answer by the time QA had fed some nasty images to my code. Now answer is updated. – Atomosk Jul 07 '19 at 04:22
  • The ImageProcessor site does not list how to use...nor does the Nuget Package page to install. Am I missing something? – ΩmegaMan Apr 04 '20 at 18:19
  • 1
    @ΩmegaMan There is 3 links on the top, clicking `ImageProcessor` gives me https://imageprocessor.org/imageprocessor/imagefactory/#example and `Getting Started` has `Install Via Nuget` section. – Atomosk Apr 06 '20 at 00:40
4

For .NET Core users and anyone who don't want to use 3rd parity libraries (and like me read the specifications and keep things simple), here is solution for JPEG dimensions:

public class JPEGPicture
{
  private byte[] data;
  private ushort m_width;
  private ushort m_height;

  public byte[] Data { get => data; set => data = value; }
  public ushort Width { get => m_width; set => m_width = value; }
  public ushort Height { get => m_height; set => m_height = value; }
    
  public void GetJPEGSize()
  {
    ushort height = 0;
    ushort width = 0;
    for (int nIndex = 0; nIndex < Data.Length; nIndex++)
    {
      if (Data[nIndex] == 0xFF)
      {
        nIndex++;
        if (nIndex < Data.Length)
        {
          /*
              0xFF, 0xC0,             // SOF0 segement
              0x00, 0x11,             // length of segment depends on the number of components
              0x08,                   // bits per pixel
              0x00, 0x95,             // image height
              0x00, 0xE3,             // image width
              0x03,                   // number of components (should be 1 or 3)
              0x01, 0x22, 0x00,       // 0x01=Y component, 0x22=sampling factor, quantization table number
              0x02, 0x11, 0x01,       // 0x02=Cb component, ...
              0x03, 0x11, 0x01        // 0x03=Cr component, ...
          */
          if (Data[nIndex] == 0xC0)
          {
            Console.WriteLine("0xC0 information:"); // Start Of Frame (baseline DCT)
            nIndex+=4;
            if (nIndex < Data.Length-1)
            {
              // 2 bytes for height
              height = BitConverter.ToUInt16(new byte[2] { Data[++nIndex], Data[nIndex-1] }, 0);
              Console.WriteLine("height = " + height);
            }
            nIndex++;
            if (nIndex < Data.Length - 1)
            {
              // 2 bytes for width
              width = BitConverter.ToUInt16(new byte[2] { Data[++nIndex], Data[nIndex-1] }, 0);
              Console.WriteLine("width = " + width);
            }
          }
        }
      }
    }
    if (height != 0)
      Height = height;
    if (width != 0)
      Width = width;
  }

  public byte[] ImageToByteArray(string ImageName)
  {
    FileStream fs = new FileStream(ImageName, FileMode.Open, FileAccess.Read);
    byte[] ba = new byte[fs.Length];
    fs.Read(ba, 0, Convert.ToInt32(fs.Length));
    fs.Close();

    return ba;
   }
 }

class Program
{
  static void Main(string[] args)
  {
    JPEGPicture pic = new JPEGPicture();
    pic.Data = pic.imageToByteArray("C:\\Test.jpg");
    pic.GetJPEGSize();
  }
}
    

I leave a space for anyone who wants to improve the code for progressive DCT:

if (Data[nIndex] == 0xC2)
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
3

Unfortunately, System.Drawing and ImageProcessor are supported only on the Windows platform because they are a thin wrapper over GDI (Graphics Device Interface) which is very old Win32 (Windows) unmanaged drawing APIs.

Instead, just install the SixLabors/ImageSharp library from NuGet. And here is how you can get size with it:

using (var image = SixLabors.ImageSharp.Image.Load("image-path."))
{
    var width = image.Width;
    var height = image.Height;
}
Palindromer
  • 854
  • 1
  • 10
  • 29