C# Image ExternalException и прочие превратности класса

Апрель 6th, 2012 § 0 comments

В последние дни намучился с этим классом и хочу поделится своим опытом, что бы вы не совершали моих ошибок, а совершали свои ))) Начнем, первое, что нужно это загрузить изображение вот наш первый и самый большой айсберг. У нас есть несколько простых способов как это сделать.


Image img = Image.FromFile("someimg.jpg");

FileStream fileStream = new FileStream("someimg2.jpg",FileMode.Open);

Image img2 = Image.FromStream(fileStream );

MemoryStream memStream = new MemoryStream(File.ReadAllBites("someimg3.jpg"));

Image img3 = Image.FromStream(memStream );

У меня тут разобрано 2 варианта загрузка из файла методом FromFile и два способа загрузки из потока. Разберем в чем преимущества и недостатки этих способов. Первый способ самый простой и очевидный, но есть одно замечание если вы провели какие -то манипуляции с изображением и решили сохранить его в тот же файл, то у вас ничего не выйдет т.к. пока не вызван метод Dispose()  с открытым файлом проводить манипуляции запрещено. Каков же выход можно создать полную копию оригинального Image вызвать Dispose(), а потом уже сохранить в файл. Выглядеть это будет примерно так.

class Program
{
static void Main(string[] args)
{
string filename = "temp.jpg";
Image img = Image.FromFile(filename);
Image img2 = CloneImage(img);
img.Dispose();
img2.Save(filename);
}
public static Image CloneImage(Image img)
{
Image temp = new Bitmap(img.Width, img.Height);
Graphics g = Graphics.FromImage(temp);
g.DrawImage(img, new Rectangle(0, 0, temp.Width, temp.Height), 0, 0, img.Width,
img.Height, GraphicsUnit.Pixel);
return temp;
}
}

Выглядит не очень согласитесь, особенно если изображений много такой метод может быть затратным. Идем дальше используем FileStream после того как мы передаем его функции, должно возникнуть естественное желание закрыть поток, но не тут то было закрывать нельзя. Поток будет закрыт сам после вызова метода Dispose() и опять-таки попробовав сохранить в тот же файл получим Image ExternalException. Я встречал примеры действующих решений, когда закрывают поток сразу после инициализации и вроде все нормально работает, но признаться не знаю уж, почему получал не понятное поведение, в одних случаях я получал ExternalException в других нет при попытке сохранить в тот же файл что, и был открыт. В общем, если будете закрывать поток сразу же после инициализации файла ожидайте танцев с бубном. По этому феномену мне на stackoverflow отписали, что при закрытии потока после инициализации читается только часть информации из файла, в том числе метаинформация, такая как ширина, высота и прочее, но стоит начать делать манипуляции вроде SetPixel как тут же должны вывалится ошибки.

Так что господа используйте последний вариант MemoryStream файл будет, грузится в память и вам ничто не помешает сохранить его в тот же самый файл, из которого он был прочитан. Недостатки вполне очевидны, что файл будет, хранится в памяти, поэтому выбирайте решение по себе в зависимости от тех нужд, что стоят перед вами. Если есть какие либо замечание пишите в коменты я подправлю.

Tagged

Оставить комментарий

Ваш email не будет опубликован. Обязательные поля отмечены *

Вы можете использовать это HTMLтеги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Смотреть фильмы онлайн