C #: Как уменьшить потребление памяти и процессора при работе с растровыми изображениями? - PullRequest
2 голосов
/ 23 августа 2011

У меня есть проект приложения Windows, который занимается редактированием изображений (кадрирование и изменение размера). К сожалению, эти обработки изображений потребляют много ресурсов памяти и ЦП (легко достигают 600 МБ или 50% ЦП), и все дело в обрезке и изменении размера только одного изображения GIF, которое весит 2,5 МБ (2300 * 5400 пикселей) Более того, из-за большого потребления ресурсов программа зависает при изменении размера ...

    public static Image Resize(Image imgToResize, Size size)
    {
        Bitmap b = new Bitmap(size.Width, size.Height);
        Graphics g = Graphics.FromImage((Image)b);
        g.InterpolationMode = InterpolationMode.Default;
        g.SmoothingMode = SmoothingMode.HighSpeed;
        g.PixelOffsetMode = PixelOffsetMode.Default;
        g.DrawImage(imgToResize, 0, 0, size.Width, size.Height);
        g.Dispose();

       return (Image)b;
    }

    public static Image Crop(Image img, Point p1, Point p2)
    {
        Rectangle cropArea = new Rectangle(p1.X, p1.Y, p2.X - p1.X, p2.Y - p1.Y);
        return (img as Bitmap).Clone(cropArea, img.PixelFormat);
    }

Какие методы я должен использовать, чтобы избежать этого? Я уже пытался сжать его в поток памяти в нескольких форматах, но это не помогло (даже ухудшило его)

ПРИМЕЧАНИЕ. Я использую стандартные библиотеки рисования .NET: System.Drawing, System.Drawing.Imaging

Ответы [ 5 ]

3 голосов
/ 23 августа 2011

Ваш код создает копии образа, поэтому при вызове этих методов следует ожидать увеличения неуправляемой памяти.Важным является то, что вы делаете с оригиналом.Было бы разумно избавиться от него, чтобы он больше не занимал память.Для этого вы должны вызвать его метод Dispose ().Ожидание сборщика мусора, чтобы сделать это занимает слишком много времени.Класс Bitmap занимает очень мало управляемой памяти, но создает кучу неуправляемой памяти.

1 голос
/ 23 августа 2011

Из более ранней версии этого вопроса: http://snippets.dzone.com/posts/show/4336

Кроме того, AForge.net имеет несколько функций изменения размера

0 голосов
/ 22 декабря 2012

написать приложение. DoEvents (); в ваших функциях, по крайней мере, это не застрянет

0 голосов
/ 23 августа 2011

Еще раз подсказка:

Например, при изменении размера, как указывал @Hans, вы создаете новое растровое изображение, которое является вашим узким местом.

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

После кадрирования, что если вы просто нарисуете часть растрового изображения, которое обрезает пользователь, так что пользователь увидит только этот прямоугольник.

Я имею в виду, в целом, оперируйте уже имеющимся изображением и постарайтесь (насколько это возможно) не инициализировать новый объект для него.

Привет.

0 голосов
/ 23 августа 2011

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

Затем вы изменяете размеры компонентов изображения по одному, каждый раз, гарантируя, что компонент удаляется перед переходом к следующему. Как только вы все закончите, вы соедините их вместе, а затем обрежете.

ОСНОВНАЯ ПРОБЛЕМА с этим подходом - если вы изменяете размер в сторону увеличения , этот подход наложит швы на ваше изображение, так как при интерполяции не будут угадываться окружающие пиксели. Но я думаю, что этот подход будет хорошо работать с изменением размера вниз.

НТН.

...