Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.95/21: Рейтинг темы: голосов - 21, средняя оценка - 4.95
3 / 3 / 3
Регистрация: 24.05.2017
Сообщений: 32
1
.NET 4.x

Переполнение памяти при работе с изображениями

20.06.2018, 23:30. Показов 4145. Ответов 27

Author24 — интернет-сервис помощи студентам
Суть проблемы такова:
Имеется код для отображения изображений на panel и дальнейшей работы с ними (добавление/удаление кастомных тегов, перемещения, ссылки на оригинал, каталогизация и тд)

Но при загрузке изображений в PictureBox RAM стремительно переполняется и вылазит исключение.

Использование GC.Collect, GC.AddMemoryPressure. Не сильно помогло. PicBox.Image.Dispose(); вызывает исключение System.ArgumentException: "Недопустимый параметр."

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

C#
1
2
3
4
5
6
7
8
        List<PictureBox> pictureBox = new List<PictureBox>();
        PictureBox PicBox;
        private string source_wayPanel = @"";
        private bool FirstImageWindow = true;
        private byte HMaxLocalImageWindow = 0;
        private int x = 0;
        private int y = 0;
        private int k = 0;
...
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
try
            {
                DebugBTN.Enabled = false;
                ResultPanel.AutoScroll = false;
                DirectoryInfo FileInfo = new DirectoryInfo(source_wayPanel);
                FileInfo[] Files = FileInfo.GetFiles("*");
                foreach (FileInfo file in Files)
                {
                    try
                    {
                        if (HMaxLocalImageWindow == 7) { y += 105; HMaxLocalImageWindow = 0; x = 0; FirstImageWindow = true; }
                        //создание
                        PicBox = new PictureBox();
                        if (FirstImageWindow) { PicBox.Left = 0; FirstImageWindow = false; HMaxLocalImageWindow++; }
                        else { x += 105; PicBox.Left = x; HMaxLocalImageWindow++; }
                        PicBox.Top = 20 + y;
                        PicBox.Height = 100;
                        PicBox.Width = 100;
                        PicBox.Visible = true;
                        string imageWay = Path.Combine(source_wayPanel, file.Name);
                        PicBox.Image = Image.FromFile(imageWay);
                        PicBox.SizeMode = PictureBoxSizeMode.StretchImage;
                        //размещаем на панели
                        ResultPanel.Controls.Add(PicBox);
                        //добавляем в коллекцию        
                        Image.FromFile(imageWay).Dispose();
 
                        GC.Collect(1, GCCollectionMode.Forced);
                        GC.AddMemoryPressure(1);
                        k++;
                    }
                    catch (Exception ex)
                    {
                        //MessageBox.Show(Convert.ToString(ex.Message));
                    }
                }
                ResultPanel.AutoScroll = true;
                DebugBTN.Enabled = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(Convert.ToString(ex.Message));
                ResultPanel.AutoScroll = true;
                DebugBTN.Enabled = true;
            }
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
20.06.2018, 23:30
Ответы с готовыми решениями:

Уменьшение используемого объёма памяти при работе с изображениями
Здравствуйте, вот сейчас я пытаюсь сделать простенькую игру. И вот я столкнулся со след. проблемой...

Переполнение оперативной памяти при работе макроса
Добрый всем вечер! Товарищи программисты, подскажите, пожалуйста, идеи по следующей проблеме....

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

При работе с 24-разрядными изображениями происходят искажения
пытаюсь заставить этот код работать, для начала просто открываю бмп файл, и сохраняю данные в...

27
-338 / 245 / 26
Регистрация: 01.06.2018
Сообщений: 3,137
21.06.2018, 04:50 2
как балбес в C# возможно задам глупый вопрос, но как вы будете потом обращаться к картинке в PicBox?
Возможно после ResultPanel.Controls.Add(PicBox); есть смысл сделать PicBox.Dispose()? Или в данном случае просто меняется Parent, а не копируется объект?
0
Эксперт .NET
12081 / 8389 / 1282
Регистрация: 21.01.2016
Сообщений: 31,601
21.06.2018, 04:51 3
MaikasUA, если вы в память грузите полторы тысячи изображений, то чему вы удивляетесь? Оперативка не Москва, она не резиновая.
0
-338 / 245 / 26
Регистрация: 01.06.2018
Сообщений: 3,137
21.06.2018, 05:29 4
Цитата Сообщение от Usaga Посмотреть сообщение
если вы в память грузите полторы тысячи изображений, то чему вы удивляетесь?
вопрос, там BMP будет валяться в оперативке или уже подросли и в компоненте можно настроить быть сжатыми? Давненько в Делфи приходилось ставить отдельный компонент, который в памяти держал GIF для растра без потерь и JPG для с потерями.
0
3 / 3 / 3
Регистрация: 24.05.2017
Сообщений: 32
21.06.2018, 06:07  [ТС] 5
Usaga, Так та оно так, но проблема в том что даже при загрузке 12 картинок программа кушает под 500мб.
0
-338 / 245 / 26
Регистрация: 01.06.2018
Сообщений: 3,137
21.06.2018, 06:14 6
Цитата Сообщение от MaikasUA Посмотреть сообщение
Так та оно так, но проблема в том что даже при загрузке 12 картинок программа кушает под 500мб.
А размер какой картинок?
Например 2000х2000 дадут 192 Мб, а учитывая еще объекты, не так и далеко получается.
0
Эксперт .NET
12081 / 8389 / 1282
Регистрация: 21.01.2016
Сообщений: 31,601
21.06.2018, 06:17 7
MaikasUA, опять же, если суммарный размер этих картинок и есть ~500Мб, то удивляться не стоит. Не забывайте, что изображения декодируются в BITMAP при загрузке в память. Это значит, что ваш JPG на мегабайт в памяти займёт несколько десятков метров.
0
3 / 3 / 3
Регистрация: 24.05.2017
Сообщений: 32
21.06.2018, 06:22  [ТС] 8
belalugoci,
Цитата Сообщение от belalugoci Посмотреть сообщение
но как вы будете потом обращаться к картинке в PicBox?
Это я пока не решил, думаю сделать так что бы при генерации PictureBox им присваивался уникальный ID с помощью которого можно было бы работать с тэгами и хранить их в xml документе. Я этим пока не заморачивался, мне нужно сперва решить проблему с утечкой памяти (костыли прикручу позже ). Если есть способ сжать эти изображения для превью показа то это было бы именно то что надо (Мне совершенно не нужно работать с самим изображением, нужна лишь возможность редактирования каталога тэгов, и прочего описания файла).

Уже пробовал писать
C#
1
2
ResultPanel.Controls.Add(PicBox);
PicBox.Dispose();
Все боксы становятся пустыми.

Цитата Сообщение от belalugoci Посмотреть сообщение
Или в данном случае просто меняется Parent, а не копируется объект?
Затрудняюсь ответить, я слишком плохо разбираюсь в программировании.
0
Эксперт .NET
12081 / 8389 / 1282
Регистрация: 21.01.2016
Сообщений: 31,601
21.06.2018, 06:25 9
MaikasUA, единственный совет, который тут можно дать: не тащите в память слишком много изображений. Если нужно загрузить новое, то ссылки на старое зануляйте, чтобы сборщик мусора мог их удалить.

Если на объект остаётся ссылка, то сборщик такой объект не тронет. Учитывайте это.
0
3 / 3 / 3
Регистрация: 24.05.2017
Сообщений: 32
21.06.2018, 06:26  [ТС] 10
Usaga, А вот это самое интересное! Сумарно все 17 тестовых файлов весят 14,6 mb но после обработки программа кушает 234 mb. (дефолтно 19 - 36 mb.) нынешний код это надстроенный модуль на уже готовую программу.
0
Эксперт .NET
12081 / 8389 / 1282
Регистрация: 21.01.2016
Сообщений: 31,601
21.06.2018, 06:27 11
MaikasUA, это может быть потому, что на диске у вас сжатые изображения (JPG, GIF, PNG, TIFF), а при загрузке они "распаковываются" в оригинальное представление - BITMAP, которое "весит" ого-го.
0
Эксперт .NET
10566 / 6490 / 1506
Регистрация: 25.05.2015
Сообщений: 19,662
Записей в блоге: 14
21.06.2018, 06:33 12
Тестовые файлы какого разрешения и формата?
Цитата Сообщение от MaikasUA Посмотреть сообщение
Сумарно все 17 тестовых файлов весят 14,6 mb но после обработки программа кушает 234 mb
Цитата Сообщение от Usaga Посмотреть сообщение
Не забывайте, что изображения декодируются в BITMAP при загрузке в память. Это значит, что ваш JPG на мегабайт в памяти займёт несколько десятков метров.
0
3 / 3 / 3
Регистрация: 24.05.2017
Сообщений: 32
21.06.2018, 06:33  [ТС] 13
Usaga,
Цитата Сообщение от Usaga Посмотреть сообщение
они "распаковываются"
Похоже вот моя проблема, можно это предотвратить?
0
Эксперт .NET
12081 / 8389 / 1282
Регистрация: 21.01.2016
Сообщений: 31,601
21.06.2018, 06:34 14
MaikasUA, это не проблема, такова природа цифровых изображений. Как "предотвратить" я уже сказал - не загружать одновременно много изображений.
0
3 / 3 / 3
Регистрация: 24.05.2017
Сообщений: 32
21.06.2018, 06:35  [ТС] 15
Rius, Тут настоящая коллекция (bmp, jpg, jpeg, png, gif)
229кб
94,8кб
290кб
2,75мб
102кб
93,2кб
336кб
4,26мб
264кб
36,2кб
340кб
8,14кб
2,38мб
387кб
1,31мб
437кб
1,42мб
0
Эксперт .NET
10566 / 6490 / 1506
Регистрация: 25.05.2015
Сообщений: 19,662
Записей в блоге: 14
21.06.2018, 06:36 16
MaikasUA, разрешение какое? Ширина * высота.
0
3 / 3 / 3
Регистрация: 24.05.2017
Сообщений: 32
21.06.2018, 06:44  [ТС] 17
Usaga, В таком случаи может есть возможность динамической погрузки и выгрузки?

Добавлено через 26 секунд
Rius,
Начиная от 259x194 и заканчивая 3000x2800
0
Эксперт .NET
12081 / 8389 / 1282
Регистрация: 21.01.2016
Сообщений: 31,601
21.06.2018, 06:49 18
Цитата Сообщение от MaikasUA Посмотреть сообщение
В таком случаи может есть возможность динамической погрузки и выгрузки?
Ну, я выше озвучил: подгружайте ограниченное количество. Ссылки на ненужные изображения затирайте (Null).
0
-338 / 245 / 26
Регистрация: 01.06.2018
Сообщений: 3,137
21.06.2018, 06:52 19
Лучший ответ Сообщение было отмечено MaikasUA как решение

Решение

Цитата Сообщение от MaikasUA Посмотреть сообщение
Это я пока не решил
А мне вот как-то кажется главным именно это решить, а уже потом делать реализацию загрузки.
Например если у вас на экране только 4-5 картинок одновременно, то может проще грузить картинки по мере их требования на экране в списке, а не все подряд? Ну как текстуры в играх, голову повернули направо, а все текстуры левой части игры удалились.

Цитата Сообщение от MaikasUA Посмотреть сообщение
Если есть способ сжать эти изображения для превью показа то это было бы именно то что надо
Хотел предложить такой вариант, если вам нужны только небольшие превью, то или делать кеш как делает винда (привет Thumbs.db) или при загрузке делать мелкую превью и ее добавлять в PicBox, а tempPicBox использовать для следующего файла, тогда у вас размеры уменьшатся.

Цитата Сообщение от MaikasUA Посмотреть сообщение
Мне совершенно не нужно работать с самим изображением
Тогда вам 100% нужен кеш картинок на диске или динамическое создание превью при загрузке. Первое кушает место на диске, второе - ЦПУ при работе.

Цитата Сообщение от MaikasUA Посмотреть сообщение
Все боксы становятся пустыми.
Это правильно, у вас все контролы в null превращаются.

Или в данном случае просто меняется Parent, а не копируется объект?
Цитата Сообщение от MaikasUA Посмотреть сообщение
Затрудняюсь ответить, я слишком плохо разбираюсь в программировании.
Parent, вы это узнали после эффекта от Dispose. Parent, это объект его (PicBox) содержащий. Можно разместить на панели или на форме.
2
3 / 3 / 3
Регистрация: 24.05.2017
Сообщений: 32
21.06.2018, 06:53  [ТС] 20
Usaga, Хорошо, буду пытаться переписать код
1
21.06.2018, 06:53
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
21.06.2018, 06:53
Помогаю со студенческими работами здесь

Ошибка доступа при работе с изображениями в DrawGrid
//при нажатии на кнопку в 1 ячейке 1 столбце должно появляться изображение, но выдает ошибку...

Переполнение стека при работе с матрицей
Доброго времени суток. У меня такой вопрос: у меня есть матрица 1000x1000 тип float компиллятор на...

Помогите разобраться с ошибкой при работе с изображениями, пожалуйста
Когда делал сайт под CMS MODx столкнулся с тем, что нужно было сделать галерею фотографий на сайте....

Ошибка при работе с изображениями: The name 'ResolveUrl' does not exist in the current context
Здравствуйте! Нашел пример как работать с изображениями, но выходит ошибка. Пример:...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru