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

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

23.03.2013, 16:00. Показов 2667. Ответов 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
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
23.03.2013, 16:00
Ответы с готовыми решениями:

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

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

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

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

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

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
)))
610 / 409 / 55
Регистрация: 31.12.2009
Сообщений: 2,330
Записей в блоге: 3
24.03.2013, 03:05 5
Цитата Сообщение от 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  [ТС] 6
Прошу прощения если показалось что я претендую на авторство
название выбрано не случайно, ведь работает он напрямую с Bitmap, и написан он в unsafe
Да и большая часть класса скопипащена с сайта на котором увы я не нашёл автора
поэтому не счёл важным этот факт во внимание принимать..

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

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

Не по теме:

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

0
51 / 50 / 5
Регистрация: 14.08.2012
Сообщений: 248
27.03.2013, 22:45 9
Цитата Сообщение от SSTREGG Посмотреть сообщение
Вы явно что-то путаете, структура будет занимать 4 байта как на x86, так и на x64 системах. Какое-либо выравнивание здесь не требуется.
Да, извините, напутал. Выравнивание будет применяться, если поля структуры имеют разный тип.
0
0 / 0 / 0
Регистрация: 31.03.2015
Сообщений: 1
31.03.2015, 11:50 10
aleks_pilipenko, спасибо большое, код помог хоть и времени столько прошло.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
31.03.2015, 11:50

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

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

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

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

Ускорить обработку базы
Здравствуйте. Я постараюсь в одной теме уместить &quot;парочку&quot; вопросов. 1с 8.3, КА 1.1 01....

Как ускорить скрипт, чтобы он выполнялся еще быстрее, чем сейчас?
Как ускорить скрипт, чтобы он выполнялся еще быстрее, чем сейчас? from time import sleep import...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.