13

This code fails when trying to call Image.Save(MemoryStream, ImageFormat).

I get the exception:

a Value cannot be null.Parameter name: encoder"

ImageFormat format = generatedImage.RawFormat as ImageFormat;
image.ImageData = generatedImage.Save(format);

It works if I pass in an ImageFormat object directly e.g. ImageFormat.Jpeg.

What is the best way of converting the rawformat to ImageFormat (ideally without a switch statement or lots of if statements)

Thanks Ben

Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
Ben Foster
  • 34,340
  • 40
  • 176
  • 285

8 Answers8

18

I use following hepler method for the same:

public static string GetMimeType(Image i)
{
    var imgguid = i.RawFormat.Guid;
    foreach (ImageCodecInfo codec in ImageCodecInfo.GetImageDecoders()) 
    {
        if (codec.FormatID == imgguid)
            return codec.MimeType;
    }
    return "image/unknown";
}
Cheburek
  • 2,103
  • 21
  • 32
11

I'm sorry, I found no possibility to directly extract a "proper" ImageFormat from the parsed or generated Image object.

This is my code, you can adopt it by storing the static ImageFormat member instead of the mimetype.

                if (image.RawFormat.Equals(ImageFormat.Jpeg))
                    binary.MetaInfo.Mimetype = "image/jpeg";
                else if (image.RawFormat.Equals(ImageFormat.Bmp))
                    binary.MetaInfo.Mimetype = "image/bmp";
                else if (image.RawFormat.Equals(ImageFormat.Emf))
                    binary.MetaInfo.Mimetype = "image/emf";
                else if (image.RawFormat.Equals(ImageFormat.Exif))
                    binary.MetaInfo.Mimetype = "image/exif";
                else if (image.RawFormat.Equals(ImageFormat.Gif))
                    binary.MetaInfo.Mimetype = "image/gif";
                else if (image.RawFormat.Equals(ImageFormat.Icon))
                    binary.MetaInfo.Mimetype = "image/icon";
                else if (image.RawFormat.Equals(ImageFormat.Png))
                    binary.MetaInfo.Mimetype = "image/png";
                else if (image.RawFormat.Equals(ImageFormat.Tiff))
                    binary.MetaInfo.Mimetype = "image/tiff";
                else if (image.RawFormat.Equals(ImageFormat.Wmf))
                    binary.MetaInfo.Mimetype = "image/wmf";

You could tidy it up by using an array of static ImageFormat members, but I think you won't be able to avoid a switch or a loop.

Best regards, Matthias

Matthias Wuttke
  • 1,982
  • 2
  • 21
  • 38
7

are you looking for this?


System.Drawing.Imaging.ImageFormat fmt = new System.Drawing.Imaging.ImageFormat(generatedImage.RawFormat.Guid);
1

There's also a way to save an Image in its RawFormat to some Stream. See http://bytes.com/topic/c-sharp/answers/944402-how-access-raw-image-data-resource-file#post3733044

For me that works like the following:

byte[] GetRawImageData(Image img)
{
    using(MemoryStream ms = new MemoryStream())
    {
        img.Save(ms, img.RawFormat);
        return ms.ToArray();
    }
}
Mike
  • 2,468
  • 3
  • 25
  • 36
1

Cesare Imperiali's answer above worked in my tests. The only downside (if it matters) is that the .ToString() for a Jpeg returns "[ImageFormat: b96b3cae-0728-11d3-9d7b-0000f81ef32e]" instead of "Jpeg".

If that matters to you, one way you can get the precise static ImageFormat's with less code is this way:

public static class ImageFilesHelper
{
    public static List<ImageFormat> ImageFormats =>
        typeof(ImageFormat).GetProperties(BindingFlags.Static | BindingFlags.Public)
          .Select(p => (ImageFormat)p.GetValue(null, null)).ToList();

    public static ImageFormat ImageFormatFromRawFormat(ImageFormat raw) =>
        ImageFormats.FirstOrDefault(f => raw.Equals(f)) ?? ImageFormat.Bmp;

}
// Usage:
var format = ImageFilesHelper.ImageFormatFromRawFormat(Image.FromFile(myFile).RawFormat);
JohnnyIV
  • 109
  • 5
0

The VB.NET translation of Cheburek's answer:

Private Function GetMimeType(i As Drawing.Image) As String
    Dim imgguid As Guid = i.RawFormat.Guid
    For Each codec As ImageCodecInfo In ImageCodecInfo.GetImageDecoders()
        If (codec.FormatID = imgguid) Then
            Return codec.MimeType
        End If
    Next
    Return "image/unknown"
End Function
BoffinBrain
  • 6,337
  • 6
  • 33
  • 59
0

I tried Cheburek method of comparing the guid. but for some of the png images the guids were not matching. so i had to write a logic which will use both the methods mentioned by Matthias Wuttke's solution and Cheburek's solution.

first i was checking with the ImageCodecinfo and if code does not find the imageformat then i compared the imageformat using Matthias Wuttke's solution.

if both the above mentioned solution failed then used the extension method to get the file mime type..

if the mime type changes then the file also changes, we were calculating the downloaded files checksum to match with the checksum of the original file on the server .. so for us it was importent to get proper file as output.

Undo
  • 25,519
  • 37
  • 106
  • 129
Samuel Joy
  • 578
  • 5
  • 8
0

A fresh, modern and general answer for finding an image extension from RawFormat and saving is like this:

var formatDescription = ImageCodecInfo.GetImageDecoders().FirstOrDefault(w => w.FormatID == image.RawFormat.Guid)?.FormatDescription;

filePath = Path.ChangeExtension(filePath, formatDescription);

image.Save(filePath);
Ali Karaca
  • 3,365
  • 1
  • 35
  • 41