Reputation: 34800
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
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
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
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
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
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
Reputation: 99
are you looking for this?
System.Drawing.Imaging.ImageFormat fmt = new System.Drawing.Imaging.ImageFormat(generatedImage.RawFormat.Guid);
Upvotes: 8
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
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