Получить размеры изображения в Интернете - избежать лихорадки памяти?
Я получаю некоторые изображения с веб-страницы по указанному URL, я хочу получить их высоты и ширины. Я использую что-то вроде этого:
Stream str = null;
HttpWebRequest wReq = (HttpWebRequest)WebRequest.Create(ImageUrl);
HttpWebResponse wRes = (HttpWebResponse)(wReq).GetResponse();
str = wRes.GetResponseStream();
var imageOrig = System.Drawing.Image.FromStream(str);
int height = imageOrig.Height;
int width = imageOrig.Width;
Моя главная проблема в том, что файл изображения может быть очень большим,
Что я могу сделать? т.е. указать, чтобы получать изображения только если они меньше, чем 1 МБ? или есть лучший альтернативный подход к получению размера изображения с веб-страницы?
Спасибо
4 ответа
Некоторые (все?) Форматы изображений включают в себя свойство width и height в заголовке файла. Вы можете просто запросить достаточно байтов, чтобы иметь возможность прочитать заголовок, а затем проанализировать их самостоятельно. Вы можете добавить заголовок диапазона к вашему веб-запросу, который будет запрашивать только первые 50 байтов (50 - это просто пример, вам, вероятно, понадобится меньше) файла изображения с помощью:
wReq.AddRange(0, 50);
Я полагаю, это будет работать, только если вы знаете, что форматы, с которыми вы работаете, включают эти данные.
Редактировать: Похоже, я неправильно понял AddRange
метод до. Это сейчас исправлено. Я также пошел дальше и проверил это, получив ширину и высоту png, используя эту документацию.
static void Main(string[] args)
{
string imageUrl = "http://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png";
byte[] pngSignature = new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 };
HttpWebRequest wReq = (HttpWebRequest)WebRequest.Create(imageUrl);
wReq.AddRange(0, 30);
WebResponse wRes = wReq.GetResponse();
byte[] buffer = new byte[30];
int width = 0;
int height = 0;
using (Stream stream = wRes.GetResponseStream())
{
stream.Read(buffer, 0, 30);
}
// Check for Png
// 8 byte - Signature
// 4 byte - Chunk length
// 4 byte - Chunk type - IDHR (Image Header)
// 4 byte - Width
// 4 byte - Height
// Other stuff we don't care about
if (buffer.Take(8).SequenceEqual(pngSignature))
{
var idhr = buffer.Skip(12);
width = BitConverter.ToInt32(idhr.Skip(4).Take(4).Reverse().ToArray(), 0);
height = BitConverter.ToInt32(idhr.Skip(8).Take(4).Reverse().ToArray(), 0);
}
// Check for Jpg
//else if (buffer.Take(?).SequenceEqual(jpgSignature))
//{
// // Do Jpg stuff
//}
// Check for Gif
//else if (etc...
Console.WriteLine("Width: " + width);
Console.WriteLine("Height: " + height);
Console.ReadKey();
}
Вам нужно только скачать заголовок из графического файла, чтобы найти размер картинки, см....
BMP: (требуется только 26 байтов) http://www.fileformat.info/format/bmp/corion.htm
JPG: (отсканируйте маркер "Star of Frame") http://wiki.tcl.tk/757
GIF: (требуется 10 байтов, т.е. первые два слова дескриптора логического экрана) http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp
также обратите внимание на то, как вы можете прочитать первые пару байтов, чтобы узнать, что на самом деле является типом файла (не полагайтесь на расширение имени файла. Например, bmp может быть назван ".gif" случайно. Однажды Вы знаете тип файла, который вы смотрите в спецификации, чтобы узнать, какое смещение читать.
PS получите себе шестнадцатеричный редактор, такой как "Hex Editor XVI32", чтобы увидеть структуру файла. Вы можете скачать XVI32 здесь: http://www.chmaas.handshake.de/delphi/freeware/xvi32/xvi32.htm
Возможно, вы захотите написать веб-сервис, где, учитывая имя входного изображения, предоставляет размер в качестве ответа.
Исходя из результирующего значения, вы можете загрузить изображение.
Если вы хотите что-то более легкое, чем веб-сервис, воспользуйтесь обработчиком HTTP.
Вы можете попробовать использовать класс FileInfo, чтобы найти размер файла.
long fileSizeInKb = new FileInfo(fileName).Length / 1000;
if (fileSizeInKb < 1000)
{
// get image
}
Свойство Length возвращает количество байтов в текущем файле.