Проверить изображение из файла на C#
Я загружаю изображение из файла и хочу знать, как 9X_c-sharp проверить изображение, прежде чем оно будет 9X_.net полностью прочитано из файла.
string filePath = "image.jpg";
Image newImage = Image.FromFile(filePath);
Проблема возникает, когда 9X_.net-framework image.jpg на самом деле не является jpg. Например, если 9X_picture я создаю пустой текстовый файл и переименовываю 9X_dotnet его в image.jpg, при загрузке image.jpg 9X_dot-net возникает исключение OutOfMemory.
Я ищу функцию, которая 9X_images будет проверять изображение с учетом потока 9X_img или пути к файлу изображения.
Пример прототипа 9X_image функции
bool IsValidImage(string fileName);
bool IsValidImage(Stream imageStream);
- Почему бы не заключить этот код в блок try ... catch, и если он вызывает это исключение, вы можете считать его «недействительным»? Конечно, это наивна ...
Ответ #1
Ответ на вопрос: Проверить изображение из файла на C#
вот моя проверка изображения. Я не могу 9X_dot-net полагаться на расширения файлов и должен 9X_outfile проверять формат самостоятельно. Я загружаю 9X_.net-framework BitmapImages в WPF из байтовых массивов 9X_c#.net и заранее не знаю формат. WPF прекрасно 9X_images определяет формат, но не сообщает вам формат 9X_img изображения объектов BitmapImage (по крайней 9X_outfile мере, мне не известно об этом свойстве). И 9X_visual-c# я не хочу снова загружать изображение с 9X_infile помощью System.Drawing только для определения 9X_input-file формата. Это быстрое решение, которое мне 9X_.net-framework подходит.
public enum ImageFormat
{
bmp,
jpeg,
gif,
tiff,
png,
unknown
}
public static ImageFormat GetImageFormat(byte[] bytes)
{
// see http://www.mikekunz.com/image_file_header.html
var bmp = Encoding.ASCII.GetBytes("BM"); // BMP
var gif = Encoding.ASCII.GetBytes("GIF"); // GIF
var png = new byte[] { 137, 80, 78, 71 }; // PNG
var tiff = new byte[] { 73, 73, 42 }; // TIFF
var tiff2 = new byte[] { 77, 77, 42 }; // TIFF
var jpeg = new byte[] { 255, 216, 255, 224 }; // jpeg
var jpeg2 = new byte[] { 255, 216, 255, 225 }; // jpeg canon
if (bmp.SequenceEqual(bytes.Take(bmp.Length)))
return ImageFormat.bmp;
if (gif.SequenceEqual(bytes.Take(gif.Length)))
return ImageFormat.gif;
if (png.SequenceEqual(bytes.Take(png.Length)))
return ImageFormat.png;
if (tiff.SequenceEqual(bytes.Take(tiff.Length)))
return ImageFormat.tiff;
if (tiff2.SequenceEqual(bytes.Take(tiff2.Length)))
return ImageFormat.tiff;
if (jpeg.SequenceEqual(bytes.Take(jpeg.Length)))
return ImageFormat.jpeg;
if (jpeg2.SequenceEqual(bytes.Take(jpeg2.Length)))
return ImageFormat.jpeg;
return ImageFormat.unknown;
}
- просто добавьте эту последовательно ...
Ответ #2
Ответ на вопрос: Проверить изображение из файла на C#
Использование Windows Forms:
bool IsValidImage(string filename)
{
try
{
using(Image newImage = Image.FromFile(filename))
{}
}
catch (OutOfMemoryException ex)
{
//The file does not have a valid image format.
//-or- GDI+ does not support the pixel format of the file
return false;
}
return true;
}
В противном случае, если вы используете WPF, вы можете 9X_c#-language сделать следующее:
bool IsValidImage(string filename)
{
try
{
using(BitmapImage newImage = new BitmapImage(filename))
{}
}
catch(NotSupportedException)
{
// System.NotSupportedException:
// No imaging component suitable to complete this operation was found.
return false;
}
return true;
}
Вы должны освободить созданный 9X_.net-framework образ. В противном случае, когда вы вызываете 9X_infile эту функцию много раз, это вызовет OutOfMemoryException, потому 9X_input-file что в системе закончились ресурсы, а не 9X_image потому, что изображение повреждено, что 9X_visual-c# приводит к неправильному результату, и если 9X_c#.net вы удалите изображения после этого шага 9X_infile , вы потенциально можете удалить хорошие.
- OutOfMemoryException действительно является правильным исключением для ловушки согласно MSDN !!! http://msdn.microsoft.com/en-us/library/stf701f5.aspx Microsoft, вы никогда не перестан ...
Ответ #3
Ответ на вопрос: Проверить изображение из файла на C#
JPEG не имеет формального определения заголовка, но 9X_infile у них есть небольшой объем метаданных, которые 9X_images вы можете использовать.
- Смещение 0 (два байта): маркер SOI JPEG (шестнадцатеричный FFD8).
- Смещение 2 (два байта): ширина изображения в пикселях.
- Смещение 4 (два байта): высота изображения в пикселях.
- Смещение 6 (байт): количество компонентов (1 = оттенки серого, 3 = RGB).
После этого есть 9X_.net-framework еще пара вещей, но они не важны.
Вы можете 9X_fileinput открыть файл с помощью двоичного потока, прочитать 9X_images эти начальные данные и убедиться, что OffSet 9X_csharp 0 равен 0, а OffSet 6 равен 1,2 или 3.
Это, по 9X_c# крайней мере, даст вам немного больше точности.
Или 9X_c#.net вы можете просто перехватить исключение 9X_infile и двигаться дальше, но я думал, что вам 9X_dotnet нужен вызов :)
- Нет, но я не утверждал, что так будет.<p><span cla ...
Ответ #4
Ответ на вопрос: Проверить изображение из файла на C#
Что ж, я пошел дальше и написал набор функций 9X_visual-c# для решения проблемы. Сначала он проверяет 9X_pictures заголовок, а затем пытается загрузить изображение 9X_csharp в блоке try / catch. Он проверяет только 9X_file-io файлы GIF, BMP, JPG и PNG. Вы можете легко 9X_picture добавить больше типов, добавив заголовок 9X_input-file к imageHeaders.
static bool IsValidImage(string filePath)
{
return File.Exists(filePath) && IsValidImage(new FileStream(filePath, FileMode.Open, FileAccess.Read));
}
static bool IsValidImage(Stream imageStream)
{
if(imageStream.Length > 0)
{
byte[] header = new byte[4]; // Change size if needed.
string[] imageHeaders = new[]{
"\xFF\xD8", // JPEG
"BM", // BMP
"GIF", // GIF
Encoding.ASCII.GetString(new byte[]{137, 80, 78, 71})}; // PNG
imageStream.Read(header, 0, header.Length);
bool isImageHeader = imageHeaders.Count(str => Encoding.ASCII.GetString(header).StartsWith(str)) > 0;
if (isImageHeader == true)
{
try
{
Image.FromStream(imageStream).Dispose();
imageStream.Close();
return true;
}
catch
{
}
}
}
imageStream.Close();
return false;
}
- @ Джо, я не согласен. Он не должен закрывать или удалять поток в этой функции. Эта функция не создавала поток, поэтому не должна вести себя неожиданно. Также ... В случае успеха Image.FromStream будет использовать поток ...
Ответ #5
Ответ на вопрос: Проверить изображение из файла на C#
Вы можете произвести грубый набор текста, понюхав 9X_.net-framework заголовок.
Это означает, что каждый реализуемый 9X_c-sharp вами формат файла должен иметь идентифицируемый 9X_c# заголовок ...
JPEG: первые 4 байта - это 9X_visual-c# FF D8 FF E0 (на самом деле только первые 9X_img два байта будут делать это для не jfif jpeg, подробнее 9X_pictures here).
GIF: первые 6 байтов - это либо «GIF87a», либо 9X_outfile «GIF89a» (подробнее here)
PNG: первые 8 байтов: 89 9X_visual-c# 50 4E 47 0D 0A 1A 0A (подробнее here)
TIFF: первые 9X_dotnet 4 байта: II42 или MM42 (подробнее here)
и т. д. вы 9X_outfile можете найти информацию о заголовке / формате 9X_c#.net практически для любого графического формата, который 9X_file-io вам нужен, и при необходимости добавить 9X_input-file к тому, что он обрабатывает. Чего он не 9X_c-sharp сделает, так это того, что он скажет вам, является 9X_visual-c# ли файл допустимой версией этого типа, но 9X_dot-net даст вам подсказку о том, что «изображение, а 9X_file-io не изображение?». Это все еще может быть 9X_.net-framework поврежденный или неполный образ и, следовательно, сбой 9X_img при открытии, поэтому по-прежнему необходимо 9X_c-sharp попытаться поймать вызов .FromFile.
- хм .. четыре человека ответили ...
Ответ #6
Ответ на вопрос: Проверить изображение из файла на C#
2019 здесь, dotnet core 3.1. Я беру ответ 9X_input-file Alex и немного его актуализирую
public static bool IsImage(this byte[] fileBytes)
{
var headers = new List
{
Encoding.ASCII.GetBytes("BM"), // BMP
Encoding.ASCII.GetBytes("GIF"), // GIF
new byte[] { 137, 80, 78, 71 }, // PNG
new byte[] { 73, 73, 42 }, // TIFF
new byte[] { 77, 77, 42 }, // TIFF
new byte[] { 255, 216, 255, 224 }, // JPEG
new byte[] { 255, 216, 255, 225 } // JPEG CANON
};
return headers.Any(x => x.SequenceEqual(fileBytes.Take(x.Length)));
}
Использование:
public async Task UploadImage(Stream file)
{
using (MemoryStream ms = new MemoryStream())
{
await file.CopyToAsync(ms);
byte[] bytes = ms.ToArray();
if (!bytes.IsImage())
throw new ArgumentException("Not an image", nameof(file));
// Upload your file
}
}
Ответ #7
Ответ на вопрос: Проверить изображение из файла на C#
Это должно помочь - вам не нужно читать 9X_dot-net необработанные байты из заголовка:
using(Image test = Image.FromFile(filePath))
{
bool isJpeg = (test.RawFormat.Equals(ImageFormat.Jpeg));
}
Конечно, вам 9X_infile также следует перехватить OutOfMemoryException, что 9X_img спасет вас, если файл вообще не является 9X_csharp изображением.
И в ImageFormat есть предустановленные 9X_infile элементы для всех других основных типов 9X_visual-c# изображений, поддерживаемых GDI +.
Обратите 9X_images внимание: вы должны использовать .Equals(), а 9X_file-io не == для объектов ImageFormat (это не перечисление), потому 9X_outfile что оператор == не перегружен для вызова 9X_visual-c# метода Equals.
Ответ #8
Ответ на вопрос: Проверить изображение из файла на C#
Метод, который также поддерживает Tiff и 9X_.net Jpeg
private bool IsValidImage(string filename)
{
Stream imageStream = null;
try
{
imageStream = new FileStream(filename, FileMode.Open);
if (imageStream.Length > 0)
{
byte[] header = new byte[30]; // Change size if needed.
string[] imageHeaders = new[]
{
"BM", // BMP
"GIF", // GIF
Encoding.ASCII.GetString(new byte[]{137, 80, 78, 71}),// PNG
"MM\x00\x2a", // TIFF
"II\x2a\x00" // TIFF
};
imageStream.Read(header, 0, header.Length);
bool isImageHeader = imageHeaders.Count(str => Encoding.ASCII.GetString(header).StartsWith(str)) > 0;
if (imageStream != null)
{
imageStream.Close();
imageStream.Dispose();
imageStream = null;
}
if (isImageHeader == false)
{
//Verify if is jpeg
using (BinaryReader br = new BinaryReader(File.Open(filename, FileMode.Open)))
{
UInt16 soi = br.ReadUInt16(); // Start of Image (SOI) marker (FFD8)
UInt16 jfif = br.ReadUInt16(); // JFIF marker
return soi == 0xd8ff && (jfif == 0xe0ff || jfif == 57855);
}
}
return isImageHeader;
}
return false;
}
catch { return false; }
finally
{
if (imageStream != null)
{
imageStream.Close();
imageStream.Dispose();
}
}
}
Ответ #9
Ответ на вопрос: Проверить изображение из файла на C#
Обратил внимание на пару проблем со всеми 9X_pictures функциями выше. Прежде всего - Image.FromFile 9X_csharp открывает данное изображение и впоследствии 9X_visual-c# вызовет ошибку открытия файла, если кто-то 9X_pictures захочет открыть данный файл изображения 9X_.net-framework по любой причине. Даже само приложение - поэтому 9X_file-io я переключился на Image.FromStream.
После 9X_fileinput переключения api - тип исключения меняется 9X_file-io с OutOfMemoryException на ArgumentException 9X_.net-framework по непонятной мне причине. (Вероятно, ошибка 9X_dotnet .net framework?)
Также, если .net добавит 9X_c# больше поддерживаемых форматов файлов изображений, чем 9X_images в настоящее время, мы будем проверять их 9X_visual-c# по функциям - имеет смысл сначала попытаться 9X_img загрузить изображение, если только потом 9X_infile произойдет сбой - только после этого, чтобы 9X_img сообщить об ошибке.
Итак, мой код теперь 9X_infile выглядит так:
try {
using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
Image im = Image.FromStream(stream);
// Do something with image if needed.
}
}
catch (ArgumentException)
{
if( !IsValidImageFormat(path) )
return SetLastError("File '" + fileName + "' is not a valid image");
throw;
}
Где:
///
/// Check if we have valid Image file format.
///
///
/// true if it's image file
public static bool IsValidImageFormat( String path )
{
using ( FileStream fs = File.OpenRead(path) )
{
byte[] header = new byte[10];
fs.Read(header, 0, 10);
foreach ( var pattern in new byte[][] {
Encoding.ASCII.GetBytes("BM"),
Encoding.ASCII.GetBytes("GIF"),
new byte[] { 137, 80, 78, 71 }, // PNG
new byte[] { 73, 73, 42 }, // TIFF
new byte[] { 77, 77, 42 }, // TIFF
new byte[] { 255, 216, 255, 224 }, // jpeg
new byte[] { 255, 216, 255, 225 } // jpeg canon
} )
{
if (pattern.SequenceEqual(header.Take(pattern.Length)))
return true;
}
}
return false;
} //IsValidImageFormat
Ответ #10
Ответ на вопрос: Проверить изображение из файла на C#
Я взял ответ с точкой с запятой и преобразовал 9X_input-file его в VB:
Private Function IsValidImage(imageStream As System.IO.Stream) As Boolean
If (imageStream.Length = 0) Then
isvalidimage = False
Exit Function
End If
Dim pngByte() As Byte = New Byte() {137, 80, 78, 71}
Dim pngHeader As String = System.Text.Encoding.ASCII.GetString(pngByte)
Dim jpgByte() As Byte = New Byte() {255, 216}
Dim jpgHeader As String = System.Text.Encoding.ASCII.GetString(jpgByte)
Dim bmpHeader As String = "BM"
Dim gifHeader As String = "GIF"
Dim header(3) As Byte
Dim imageHeaders As String() = New String() {jpgHeader, bmpHeader, gifHeader, pngHeader}
imageStream.Read(header, 0, header.Length)
Dim isImageHeader As Boolean = imageHeaders.Count(Function(str) System.Text.Encoding.ASCII.GetString(header).StartsWith(str)) > 0
If (isImageHeader) Then
Try
System.Drawing.Image.FromStream(imageStream).Dispose()
imageStream.Close()
IsValidImage = True
Exit Function
Catch ex As Exception
System.Diagnostics.Debug.WriteLine("Not an image")
End Try
Else
System.Diagnostics.Debug.WriteLine("Not an image")
End If
imageStream.Close()
IsValidImage = False
End Function
-
4
-
4
-
3
-
3
-
16
-
2
-
2
-
2
-
4
-
43
-
7
-
15
-
10
-
11
-
2
-
6
-
4
-
4
-
4
-
8
-
2
-
5
-
4
-
6
-
6
-
2
-
3
-
11
-
5
-
8
-
5
-
5
-
5
-
4
-
7
-
2
-
3
-
5
-
2
-
5
-
6
-
2
-
4
-
8
-
3
-
17
-
5
-
4
-
3
-
3