Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/18: Рейтинг темы: голосов - 18, средняя оценка - 4.83
6 / 6 / 1
Регистрация: 22.12.2011
Сообщений: 134

Оптимизация UnsafeBitmap, или как ещё можно ускорить обработку Изображений?

23.03.2013, 16:00. Показов 3872. Ответов 9
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток..
У меня возникла такая проблема, пишу библиотеку на C# для работы с 2D графикой, в её функционал входит генерация, фильтрация и смешивание изображений.
Так как в будущем применяться она планируется именно в целях процедурной генерации для меня очень важна скорость её работы. Которая на данный момент оставляет желать лучшего :<.
И это при том что я уже применяю класс UnsafeBitmap. Вот его код.

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
using System;
using System.Drawing;
using System.Drawing.Imaging;
 
namespace TDRite
{
    public unsafe class UnsafeBitmap
    {
        Bitmap bitmap;
 
        int width;
        BitmapData bitmapData = null;
        Byte* pBase = null;
 
        public UnsafeBitmap(Bitmap bitmap)
        {
            this.bitmap = bitmap;
            LockBitmap();
        }
 
        public UnsafeBitmap(int width, int height)
        {
            this.bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
            LockBitmap();
        }
 
        public void Dispose()
        {
            bitmap.Dispose();
        }
 
        private Point PixelSize
        {
            get
            {
                GraphicsUnit unit = GraphicsUnit.Pixel;
                RectangleF bounds = bitmap.GetBounds(ref unit);
 
                return new Point((int)bounds.Width, (int)bounds.Height);
            }
        }
 
        private void LockBitmap()
        {
            GraphicsUnit unit = GraphicsUnit.Pixel;
            RectangleF boundsF = bitmap.GetBounds(ref unit);
            Rectangle bounds = new Rectangle((int)boundsF.X,
           (int)boundsF.Y,
           (int)boundsF.Width,
           (int)boundsF.Height);
 
            width = (int)boundsF.Width * sizeof(PixelData);
            if (width % 4 != 0)
            {
                width = 4 * (width / 4 + 1);
            }
            bitmapData = bitmap.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
 
            pBase = (Byte*)bitmapData.Scan0.ToPointer();
        }
 
        public PixelData GetPixel(int x, int y)
        {
            PixelData returnValue = *PixelAt(x, y);
            return returnValue;
        }
 
        public void SetPixel(int x, int y, PixelData color)
        {
            PixelData* pixel = PixelAt(x, y);
            *pixel = color;
        }
 
        public Bitmap UnlockBitmap()
        {
            bitmap.UnlockBits(bitmapData);
            bitmapData = null;
            pBase = null;
            return bitmap;
        }
        public PixelData* PixelAt(int x, int y)
        {
            return (PixelData*)(pBase + y * width + x * sizeof(PixelData));
        }
    }
    public struct PixelData
    {
        public byte blue;
        public byte green;
        public byte red;
        public byte alpha;
 
        public PixelData(byte R, byte G, byte B)
        {
            blue = B;
            green = G;
            red = R;
            alpha = 255;
        }
        public PixelData(byte R, byte G, byte B, byte A)
        {
            blue = B;
            green = G;
            red = R;
            alpha = A;
        }
        public PixelData(byte A)
        {
            blue = A;
            green = A;
            red = A;
            alpha = 255;
        }
        public PixelData(Color color)
        {
            blue = (byte)color.B;
            green = (byte)color.G;
            red = (byte)color.R;
            alpha = (byte)color.A;
        }
 
        public Color ToColor()
        {
            return Color.FromArgb(alpha, red, green, blue);
        }
    }
}
Подскажите может я что то не правильно делаю. + ко всему каким образом можно распределить вычисления на потоки?
пересчёт пикселей производится достаточно банальным способом:

C#
1
2
3
4
5
6
7
8
9
10
            UnsafeBitmap result = new UnsafeBitmap(Scale, Scale);
 
            for (int x = 0; x < newScale; x++)
                for (int y = 0; y < newScale; y++)
                {
                    //....определяем цвет пикселя
                    result.SetPixel(x, y, new PixelData(color));
                }
 
            return result.UnlockBitmap();
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
23.03.2013, 16:00
Ответы с готовыми решениями:

Как ускорить обработку обработку данных в Пайтон?!?!
Можно ли как-то ускорить обработку данных в Пайтон?!?! Мне нужно таблицу умножения I строк на J столбцов, где потом посчитать количество...

Оптимизация кода, структуры базы, или что еще можно сделать что бы быстрее работало!?
Всем привет! Господа, выручайте. Не пойму как еще оптимизировать... Есть куча связанных таблиц. Нужно выводить статистику используя...

Как ускорить обработку файла
Можно ли как-то ускорить обработку файла, который содержит тысячи строк? Нужно перебрать все строки в файле, сравнивая начало выбранной...

9
)))
 Аватар для aleks_pilipenko
610 / 423 / 55
Регистрация: 31.12.2009
Сообщений: 2,334
Записей в блоге: 3
23.03.2013, 19:47
Вообще-то без класса быстрее должно быть! Не нужно будет кучу объектов создавать...
Я недавно создавал черно-белое изображение с настройками по бегунком, типа: (A+R+G+B)/4<, то черное, т.е. х настраивался бегунком, почти сразу, без задержек делало для изображения в 2 МПа
0
6 / 6 / 1
Регистрация: 22.12.2011
Сообщений: 134
23.03.2013, 23:20  [ТС]
Нет, увы не быстрее
1) в своём классе я использовал модификатор unsafe что значит пиксели читаются и записываются напрямую из памяти
в заблокированном виде, разумеется..
2) у стандартного Bitmap методы GetPixel, SetPixel работают ужасно медленно, из за чего я собственно и написал unsafe копию
3) пересчёт зависит не только от быстроты кода, но и от кол-ва итераций.. другими словами разрешения изображения.
Как итог:
разность в скорости примерно в 3-4 раза быстрее в пользу unsafe
0
54 / 53 / 5
Регистрация: 14.08.2012
Сообщений: 252
24.03.2013, 00:05
Ну у вас качество кода не совсем оптимальное, можно сделать и чуть быстрее. Я тоже писал такой класс, даже название ему дал такое же и источник для справки брал этот же.
Завтра вечером выложу код, если надо, просто сейчас нет доступа к тому компьютеру..

C#
1
2
3
4
5
6
7
var tmp = new PixelData(color);
for (int x = 0; x < newScale; x++)
                for (int y = 0; y < newScale; y++)
                {
                    //....определяем цвет пикселя
                    result.SetPixel(x, y, tmp); //так немного быстрее будет.
                }
Сама структура у вас объявлена без атрибутов выравнивания, а поэтому занимать будет не 4 байта, а 32, а это очень расточительно.
Для ускорения еще можно отключить проверку переменных типа byte на переполнение с помощью слова unchecked.

В общем, завтра свой код выложу, если еще будет актуально.

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
public PixelData(byte R, byte G, byte B)
* * * * {
* * * * * * blue = B;
* * * * * * green = G;
* * * * * * red = R;
* * * * * * alpha = 255;
* * * * }
* * * * public PixelData(byte R, byte G, byte B, byte A)
* * * * {
* * * * * * blue = B;
* * * * * * green = G;
* * * * * * red = R;
* * * * * * alpha = A;
* * * * }
* * * * public PixelData(byte A)
* * * * {
* * * * * * blue = A;
* * * * * * green = A;
* * * * * * red = A;
* * * * * * alpha = 255;
* * * * }
* * * * public PixelData(Color color)
* * * * {
* * * * * * blue = (byte)color.B;
* * * * * * green = (byte)color.G;
* * * * * * red = (byte)color.R;
* * * * * * alpha = (byte)color.A;
* * * * }
Всё это лучше заменить этим:

C#
1
2
3
4
5
6
7
8
9
10
11
public PixelData(byte R, byte G, byte B):this(R, G, B, 255) { }
public PixelData(byte A) : this(A, A, A, 255) { }
public PixelData(Color color) : this((byte)color.R, (byte)color.G, (byte)color.B, (byte)color.A) { }
 
 public PixelData(byte R, byte G, byte B, byte A)
 {
        blue = B;
        green = G;
        red = R;
        alpha = A;
 }
1
)))
 Аватар для aleks_pilipenko
610 / 423 / 55
Регистрация: 31.12.2009
Сообщений: 2,334
Записей в блоге: 3
24.03.2013, 03:05
Цитата Сообщение от Shaman163 Посмотреть сообщение
Нет, увы не быстрее
я также перегонял Bitmap в массив байт, а потом уже делал без дополнительных классов.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
        private void conv(int AA)//цифра от которой зависит граница перевода в черный\белый цвет
        {
            if (Original == null) return;//оригинал рисунка
            NumImage = new Bitmap(Original);//после преобразования
            int xx = NumImage.Width, yy = NumImage.Height;
            Rectangle rect = new Rectangle(0, 0, xx,yy);
            BitmapData bmpData = NumImage.LockBits(rect, ImageLockMode.ReadWrite, NumImage.PixelFormat);
            IntPtr ptr = bmpData.Scan0;
            int bytes = Math.Abs(bmpData.Stride) * yy;
            byte[] RGB = new byte[bytes];
            Marshal.Copy(ptr, RGB, 0, bytes);
            //BGR..
            for (int i = 0; i < RGB.Length; i+=4)
            {
                if ((RGB[i] + RGB[i + 1] + RGB[i + 2]) / 3 < AA) RGB[i] = RGB[i + 1] = RGB[i + 2] = 0;
                else RGB[i] = RGB[i + 1] = RGB[i + 2] = 255;
            }
            Marshal.Copy(RGB, 0, ptr, bytes);
            NumImage.UnlockBits(bmpData);
        }
1
6 / 6 / 1
Регистрация: 22.12.2011
Сообщений: 134
26.03.2013, 19:09  [ТС]
Прошу прощения если показалось что я претендую на авторство
название выбрано не случайно, ведь работает он напрямую с Bitmap, и написан он в unsafe
Да и большая часть класса скопипащена с сайта на котором увы я не нашёл автора
поэтому не счёл важным этот факт во внимание принимать..

Большое спасибо, хотя бы за надежду. Ибо я уже в C++ от безысходности полез
Буду думать дальше.
надеюсь так же на вашу помощь..

Добавлено через 1 час 14 минут
aleks_pilipenko
не понял сначала что именно имелось в виду
да, наверное так действительно будет быстрее..
спасибо за наводку
0
)))
 Аватар для aleks_pilipenko
610 / 423 / 55
Регистрация: 31.12.2009
Сообщений: 2,334
Записей в блоге: 3
26.03.2013, 19:16
Почти весь код я брал на msdn, переделал только под свои нужды..
0
26.03.2013, 21:27

Не по теме:

Цитата Сообщение от AceOfSpades Посмотреть сообщение
занимать будет не 4 байта, а 32
Вы явно что-то путаете, структура будет занимать 4 байта как на x86, так и на x64 системах. Какое-либо выравнивание здесь не требуется.

0
54 / 53 / 5
Регистрация: 14.08.2012
Сообщений: 252
27.03.2013, 22:45
Цитата Сообщение от SSTREGG Посмотреть сообщение
Вы явно что-то путаете, структура будет занимать 4 байта как на x86, так и на x64 системах. Какое-либо выравнивание здесь не требуется.
Да, извините, напутал. Выравнивание будет применяться, если поля структуры имеют разный тип.
0
0 / 0 / 0
Регистрация: 31.03.2015
Сообщений: 1
31.03.2015, 11:50
aleks_pilipenko, спасибо большое, код помог хоть и времени столько прошло.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
31.03.2015, 11:50
Помогаю со студенческими работами здесь

Оптимизация программы. Как ускорить загрузку формы?
Как ускорить загрузку формы. unit Unit6; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics,...

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

Как еще можно изменить цвет, яркость или прозрачность произвольной области изображения?
Я решил сделать что-то вроде редактора карт на JS: пользователь, как в Photoshop'е лассо обводит контур какого-то объекта на картинке. ...

Разные способы подключения файла, или как еще можно передать функции двумерный массив?
Программа считает сумму положительных элементов каждого столбца и сумму отрицательных элементов каждой строки. Все работает как нужно, но...

У меня видеокарта GEFORCE на неё только можно устанавливать ATI,или можно ещё NVIDIA?
я хотел узнать вот у меня видеокарта GEFORCE на неё только можно устанавливать ATI,или можно ещё NVIDIA?


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит: токи, напряжения и их 1 и 2 производные при t = 0;. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru