Ben Foster
Ben Foster

Reputation: 34800

Get ImageFormat from System.Drawing.Image.RawFormat

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

Upvotes: 14

Views: 34925

Answers (8)

Ali Karaca
Ali Karaca

Reputation: 3851

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);

Upvotes: 0

JohnnyIV
JohnnyIV

Reputation: 109

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);

Upvotes: 1

Samuel Joy
Samuel Joy

Reputation: 608

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.

Upvotes: 0

BoffinBrain
BoffinBrain

Reputation: 6525

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

Upvotes: -1

Mike
Mike

Reputation: 2557

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();
    }
}

Upvotes: 1

Cesare Imperiali
Cesare Imperiali

Reputation: 99

are you looking for this?


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

Upvotes: 8

Cheburek
Cheburek

Reputation: 2113

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";
}

Upvotes: 19

Matthias Wuttke
Matthias Wuttke

Reputation: 2032

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

Upvotes: 11

Related Questions