Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/18: Рейтинг темы: голосов - 18, средняя оценка - 4.67
 Аватар для SkyDen
1 / 1 / 0
Регистрация: 09.05.2017
Сообщений: 26

Как ускорить отрисовку изображения?

31.10.2017, 14:08. Показов 3461. Ответов 6

Студворк — интернет-сервис помощи студентам
Доброго времени суток. Столкнулся с такой проблемой: Необходимо загрузить инвертированное изображение, обратить цвета (сделать нормальным), и вывести это изображение. Я вывожу его в Picture Box. Для решения этой задачи я создал двумерный массив, который считывает пиксель изображения из загруженной картинки и инвертирует, сохраняя в другом массиве :
C#
1
2
3
4
5
6
7
8
9
10
11
12
Bitmap b1 = new Bitmap(bitmapFilePath);
Graphics drawing;
drawing = pictureBox1.CreateGraphics();
int hight = b1.Height;
int width = b1.Width;
Color[,] colorMatrixInv = new Color[width, hight];
Color[,] colorMatrix = new Color[width, hight];
 for (int j = 0; j < hight; j++)
    {
   colorMatrix[i, j] = b1.GetPixel(i, j);
   colorMatrixInv[i, j] = Color.FromArgb(colorMatrix[i, j].A, 0xFF - colorMatrix[i, j].R, 0xFF - colorMatrix[i, j].G, 0xFF - colorMatrix[i,j].B);
     }
После осуществляется вывод инвертированного изображения:
C#
1
2
3
4
5
6
7
 for (int i = 0; i < hight; i++)
            {
                for (int j = 0; j < width; j++)
                {
                        System.Drawing.SolidBrush myBrush = new System.Drawing.SolidBrush(colorMatrixInv[j, i]);
                        drawing.FillRectangle(myBrush, j, i, 1, 1);                                
            }
Но проблема в том, что изображение вырисовываться медленно. Дома на мощном железе, вырисовывается более менее шустро, но необходимо, чтобы оно выводилось сразу. В университете на тамошних компьютерах все отрисовываеться очень медленно. Пробовал отрисовывать изображение в созданную bitmap и выводить его сразу в picturebox,но вывод осуществлялся с такой же задержкой, что отрисовка попиксельно. Слышал про метод Двойной буферизации, но не как не смог его применить.
Подскажите, как решить эту проблему?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
31.10.2017, 14:08
Ответы с готовыми решениями:

Как ускорить отрисовку примитивов на PictureBox'e
Есть следующая проблема. По движению мыши на Bitmap'e рисую сплошную линию(с кистью в виде эллипсов). Затем переношу изображение на...

Как ускорить отрисовку изображения на PictureBox
Может кто знает как можно ускорить отрисовку загруженного изображения в PictureBox, (изображение довольно таки большое 1500х1500 и выше)...

Как ускорить отрисовку контролов на форме?
Програмно создаю на форме много контролов - кнопок (&gt;200) и возникают такие проблемы: 1. Контролы появляются не все сразу, а, как бы,...

6
677 / 479 / 216
Регистрация: 06.09.2013
Сообщений: 1,312
31.10.2017, 14:24
SkyDen, unsafe mode и адресная арифметика
0
 Аватар для SkyDen
1 / 1 / 0
Регистрация: 09.05.2017
Сообщений: 26
31.10.2017, 14:35  [ТС]
А не могли бы чуть чуть подробнее рассказать об этом методе?
0
1741 / 913 / 480
Регистрация: 05.12.2013
Сообщений: 3,074
31.10.2017, 15:04
Цитата Сообщение от SkyDen Посмотреть сообщение
Слышал про метод Двойной буферизации, но не как не смог его применить.
А это что значит? У формы есть свойство DoubleBuffered.
0
TheGreatCornholio
 Аватар для Woldemar89
1255 / 733 / 285
Регистрация: 30.07.2015
Сообщений: 2,408
31.10.2017, 15:42
Глянь тут и тут для правильной работы с контролами\моделью
0
315 / 244 / 149
Регистрация: 03.10.2017
Сообщений: 886
Записей в блоге: 1
31.10.2017, 15:50
Можно использовать Bitmap. Сначала нанести на него, а потом уже в pictureBox Вывести этот Bitmap
0
 Аватар для SkyDen
1 / 1 / 0
Регистрация: 09.05.2017
Сообщений: 26
31.10.2017, 18:03  [ТС]
Цитата Сообщение от Masson1848 Посмотреть сообщение
Можно использовать Bitmap. Сначала нанести на него, а потом уже в pictureBox Вывести этот Bitmap
Я так пробовал. Изображение в PictureBox выводиться с задержкой, равной той, что была бы при отрисовке по пиксельно. Я когда в цикле последовательность картинок вывожу задержка идёт.

Добавлено через 34 секунды
Попробовал вариант который предложил Woldemar89, изображение выводиться как надо, но в цикле почему то не меняются - всё время отображается одна картинка. Пробовал в конце цикла делать pbSource.Image = null, но тогда изображение не выводиться совсем.
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Net;
using System.Windows.Forms;
using System.Threading;
 
namespace WindowsFormsApp3
{
 
     public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
 
            for (int n = 1; n < 8; n++)
            {
                var img = (Bitmap)Image.FromFile(@"C:\res\" +n+".bmp");
                var pbSource = new PictureBox { Parent = this, SizeMode = PictureBoxSizeMode.Zoom, Width = 200, Height = 200 };
                pbSource.Image = imageOut(img);
            }
 
        }
 
        private Image imageOut(Bitmap img)
        {
            var res = (Bitmap)img.Clone();
            using (var wr = new ImageWrapper(res))
                foreach (var p in wr)
                {
                    var c = wr[p];
                    wr.SetPixel(p, 0xFF-c.R, 0xFF-c.G , 0xFF-c.B );
                }
            return res;
        }
    }
    
    public class ImageWrapper : IDisposable, IEnumerable<Point>
    {
        /// <summary>
        /// Ширина изображения
        /// </summary>
        public int Width { get; private set; }
        /// <summary>
        /// Высота изображения
        /// </summary>
        public int Height { get; private set; }
        /// <summary>
        /// Цвет по-умолачнию (используется при выходе координат за пределы изображения)
        /// </summary>
        public Color DefaultColor { get; set; }
 
        private byte[] data;//буфер исходного изображения
        private byte[] outData;//выходной буфер
        private int stride;
        private BitmapData bmpData;
        private Bitmap bmp;
 
        /// <summary>
        /// Создание обертки поверх bitmap.
        /// </summary>
        /// <param name="copySourceToOutput">Копирует исходное изображение в выходной буфер</param>
        public ImageWrapper(Bitmap bmp, bool copySourceToOutput = false)
        {
            Width = bmp.Width;
            Height = bmp.Height;
            this.bmp = bmp;
 
            bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            stride = bmpData.Stride;
 
            data = new byte[stride * Height];
            System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, data, 0, data.Length);
 
            outData = copySourceToOutput ? (byte[])data.Clone() : new byte[stride * Height];
        }
 
        /// <summary>
        /// Возвращает пиксел из исходнго изображения.
        /// Либо заносит пиксел в выходной буфер.
        /// </summary>
        public Color this[int x, int y]
        {
            get
            {
                var i = GetIndex(x, y);
                return i < 0 ? DefaultColor : Color.FromArgb(data[i + 3], data[i + 2], data[i + 1], data[i]);
            }
 
            set
            {
                var i = GetIndex(x, y);
                if (i >= 0)
                {
                    outData[i] = value.B;
                    outData[i + 1] = value.G;
                    outData[i + 2] = value.R;
                    outData[i + 3] = value.A;
                };
            }
        }
 
        /// <summary>
        /// Возвращает пиксел из исходнго изображения.
        /// Либо заносит пиксел в выходной буфер.
        /// </summary>
        public Color this[Point p]
        {
            get { return this[p.X, p.Y]; }
            set { this[p.X, p.Y] = value; }
        }
 
        /// <summary>
        /// Заносит в выходной буфер значение цвета, заданные в double.
        /// Допускает выход double за пределы 0-255.
        /// </summary>
        public void SetPixel(Point p, double r, double g, double b)
        {
            if (r < 0) r = 0;
            if (r >= 256) r = 255;
            if (g < 0) g = 0;
            if (g >= 256) g = 255;
            if (b < 0) b = 0;
            if (b >= 256) b = 255;
 
            this[p.X, p.Y] = Color.FromArgb((int)r, (int)g, (int)b);
        }
 
        int GetIndex(int x, int y)
        {
            return (x < 0 || x >= Width || y < 0 || y >= Height) ? -1 : x * 4 + y * stride;
        }
 
        /// <summary>
        /// Заносит в bitmap выходной буфер и снимает лок.
        /// Этот метод обязателен к исполнению (либо явно, лмбо через using)
        /// </summary>
        public void Dispose()
        {
            System.Runtime.InteropServices.Marshal.Copy(outData, 0, bmpData.Scan0, outData.Length);
            bmp.UnlockBits(bmpData);
        }
 
        /// <summary>
        /// Перечисление всех точек изображения
        /// </summary>
        public IEnumerator<Point> GetEnumerator()
        {
            for (int y = 0; y < Height; y++)
                for (int x = 0; x < Width; x++)
                    yield return new Point(x, y);
        }
 
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
 
        /// <summary>
        /// Меняет местами входной и выходной буферы
        /// </summary>
        public void SwapBuffers()
        {
            var temp = data;
            data = outData;
            outData = temp;
        }
    }
 
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
31.10.2017, 18:03
Помогаю со студенческими работами здесь

Как ускорить вывод изображения?
Здравствуйте уважаемые программисты! Вот я пишу игровой 2D движок на C++ directx9 и то, что у меня получилось сравниваю с американским 2D...

Как ускорить прорисовку изображения?
Добрый день! Решил написать небольшой просмотрщик изображений на WPF, и столкнулся с такой проблемой, когда загружаю достаточно большое...

Ускорить вывод изображения в JLabel
Подскажите, пожалуйста, можно ли каким-то образом ускорить вывод изображения в JLabel. Использую двойную буферизацию, как off-screen буфер...

Преобразование изображения: ускорить работу кода
Добрый. Как можно ускорить следующий код? Мне необходимо конвертировать определенный цвет в пространстве RGB в пространство LAB. Я хочу...

Как правильно организовать отрисовку 2D графики?
Планируется сделать векторный 2D редактор, с количеством примитивов (не полигонов) около 300 000 Градиентов не будет, только сплошные...


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru