49

I am using ASP.NET MVC and I've an action that uploads the file. The file is being uploaded properly. But I want width and height of the image. I think I need to convert the HttpPostedFileBase to Image first and then proceed. How do I do that?

And please let me know if there is another better way to get the width and height of the image.

Abdulsattar Mohammed
  • 8,916
  • 12
  • 49
  • 66

2 Answers2

105

I use Image.FromStream to as follows:

Image.FromStream(httpPostedFileBase.InputStream, true, true)

Note that the returned Image is IDisposable.

You'll need a reference to System.Drawing.dll for this to work, and Image is in the System.Drawing namespace.

Resizing the Image

I'm not sure what you're trying to do, but if you happen to be making thumbnails or something similar, you may be interested in doing something like...

try {
    var bitmap = new Bitmap(newWidth,newHeight);
    using (Graphics g = Graphics.FromImage(bitmap)) {
        g.SmoothingMode = SmoothingMode.HighQuality;
        g.PixelOffsetMode = PixelOffsetMode.HighQuality;
        g.CompositingQuality = CompositingQuality.HighQuality;
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.DrawImage(oldImage,
            new Rectangle(0,0,newWidth,newHeight),
            clipRectangle, GraphicsUnit.Pixel);
    }//done with drawing on "g"
    return bitmap;//transfer IDisposable ownership
} catch { //error before IDisposable ownership transfer
    if (bitmap != null) bitmap.Dispose();
    throw;
}

where clipRectangle is the rectangle of the original image you wish to scale into the new bitmap (you'll need to manually deal with aspect ratio). The catch-block is typical IDisposable usage inside a constructor; you maintain ownership of the new IDisposable object until it is returned (you may want to doc that with code-comments).

Saving as Jpeg

Unfortunately, the default "save as jpeg" encoder doesn't expose any quality controls, and chooses a terribly low default quality.

You can manually select the encoder as well, however, and then you can pass arbitrary parameters:

ImageCodecInfo jpgInfo = ImageCodecInfo.GetImageEncoders()
    .Where(codecInfo => codecInfo.MimeType == "image/jpeg").First();
using (EncoderParameters encParams = new EncoderParameters(1))
{
    encParams.Param[0] = new EncoderParameter(Encoder.Quality, (long)quality);
    //quality should be in the range [0..100]
    image.Save(outputStream, jpgInfo, encParams);
}
Eamon Nerbonne
  • 43,645
  • 18
  • 92
  • 161
  • Great code snippet! Why are you disposing of the image in your catch block and then rethrowing the exception instead of just using the finally block? – Jeff Widmer Jul 23 '09 at 13:54
  • 1
    because the finally block *always* executes - but the newly created image only needs to be disposed on error. If no error occurs, the new image was correctly constructed and becomes owned by the calling function - now it's their responsibility to dispose it. – Eamon Nerbonne Jul 23 '09 at 15:07
  • I'll add an explanation about the try-catch with IDisposable. – Eamon Nerbonne Jul 23 '09 at 15:12
  • hi, sorry to bring this dead thread alive, was wondering, do u know how i can save the file to a file system? i didn't wanna use the dbase for saving it,just the url maybe. also, im trying to figure out if i want to adjust sizes to 50x100 when the image size is like 150x150.is it recommended to always set the w and h to those numbers or do i just proportionately adjust it meet the limit? thanks! – gdubs Jul 25 '12 at 02:38
  • This code simply scales the image - you'll need to decide how to crop (`clipRectangle`) and you'll want to ensure the resultant aspect ratio isn't too far off. To save to the filesystem, simply pass the appropriate stream (in the example, it's named `outputStream`) to the `Save` method. – Eamon Nerbonne Aug 02 '12 at 22:06
  • When I use Image image = Image.FromStream(item.InputStream, true, true); code I get parameter is not valid exeption. Please tell me , How can i fixx this problem? – Elvin Mammadov Jul 29 '13 at 18:18
  • @ElvinArzumanoğlu: you should probably ask a new question if you can't easily solve the problem, because in your own question you can add all the relevant details. But as a general tip; try saving the stream to disk and reproducing the exception locally from a file stream - if you can do that, you have a fairly small test case and those are always easier to deal with. – Eamon Nerbonne Jul 29 '13 at 20:54
  • @Eamon,I am blocked for asking question,so I can't ask any question:(.at first my scenario is that I have a dropzone js library(http://www.dropzonejs.com/)for uploading image,what I can upload many images a time,I add these images to my httpPfile in this dropzone upload action and add this to Lis<>,,then I get this uploading files in save button,but in foreach loop when I write previous code I get parameter is not valid exeption,then i think this error means i can write this only first time in post action,then i try convert httpPoBase to image in dropezone action and so converting work fine – Elvin Mammadov Jul 30 '13 at 00:33
  • I don't quite understand what you said, but `httpPostedFileBase.InputStream` is only valid in the request in which the file was posted - in that request you will need to save the data somewhere, and you probably want to do image processing right away too. – Eamon Nerbonne Jul 31 '13 at 08:04
  • @EamonNerbonne below line of code is not working for me System.Drawing.Image sourceimage = System.Drawing.Image.FromStream(file.InputStream,true,true); – Heemanshu Bhalla Aug 03 '17 at 18:24
  • @HeemanshuBhalla: it's a standard function; so you might check the docs: https://msdn.microsoft.com/en-us/library/21zw9ah6 - or ask a new question with more details as to what isn't working. – Eamon Nerbonne Aug 11 '17 at 09:50
6

If you are sure, that the source is image and doesn't need editing, you can do it easily as described here

[HttpPost]
public void Index(HttpPostedFileBase file)
{
    if (file.ContentLength > 0)
    {
        var filename = Path.GetFileName(file.FileName);

        System.Drawing.Image sourceimage =
            System.Drawing.Image.FromStream(file.InputStream);
    }
}

To secure the file is image, add javascript validation to View by adding accept attribute with MIME type to input tag

<input type="file" accept="image/*">

and jQuery validation script

$.validator.addMethod('accept', function () { return true; });

The whole solution can be found here

Andree643
  • 95
  • 2
  • 8