Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Power Basic

Страница: 1 | 2 |

 

  Вопрос: Оптимизировать, но как? Добавлено: 12.05.05 22:09  

Автор вопроса:  SyavX
Hello, World!
Вопрос знающим от незнающего:
Как можно оптимизировать этот код?

Sub SetRgnMask Alias "SetRgnMask" (ByVal hWndDest As Long, ByVal hWndSrc As Long, ByVal hDCSrc As Long, ByVal lMaskColor As Long) Export
Dim CurRgn As Long, TempRgn As Long
Dim WndRect As RECT, Result As Long
Dim lHeight As Long, lWidth As Long
Dim X As Long, Y As Long
    Result = GetWindowRect(hWndSrc, WndRect)
    lHeight = WndRect.nBottom - WndRect.nTop
    lWidth = WndRect.nRight - WndRect.nLeft
    CurRgn = CreateRectRgn(0, 0, lWidth, lHeight)
    Do While Y <= lHeight
        Do While X <= lWidth
            If GetPixel(hDCSrc, X, Y) = lMaskColor Then
                TempRgn = CreateRectRgn(X, Y, X + 1, Y + 1)
                Result = CombineRgn(CurRgn, CurRgn, TempRgn, %RGN_DIFF)
                Result = DeleteObject(TempRgn)
            End If
            X = X + 1
        Loop
            Y = Y + 1
            X = 0
    Loop
    Result = SetWindowRgn(hWndDest, CurRgn, %True)
    Result = DeleteObject(CurRgn)
    Result = DeleteObject(TempRgn)
End Sub


Если использовать его через BP'шную DLL, он выполняется быстрей чем посто в VB, но разница не большая (~ 3/4). Возможно просто есть другое решение этой задачи (создание региона по маске) ?

Ответить

  Ответы Всего ответов: 19  

Номер ответа: 1
Автор ответа:
 CyRax



Разработчик Offline Client

ICQ: 204447456 

Вопросов: 180
Ответов: 4229
 Web-сайт: basicproduction.nm.ru
 Профиль | | #1
Добавлено: 13.05.05 11:21
Do While замени на For

Ответить

Номер ответа: 2
Автор ответа:
 SyavX



Вопросов: 25
Ответов: 149
 Профиль | | #2 Добавлено: 13.05.05 21:12
Уже делал. Разница около 0,01 - 0,05 сек., причем то с Do While быстрей, то с For :(

Ответить

Номер ответа: 3
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #3 Добавлено: 13.05.05 22:04
Нет смысла пытаться оптимизировать этот код.
Львиная доля времени уходит на работу API функций GetPixel, CreateRectRgn, CombineRgn и DeleteObject. А их работу ты никак не ускоришь.
Те места, что можно ускорить - это капля в море, имхо нет смысла заниматься этими каплями.
Надо искать другой алгоритм (если он существует).

Ответить

Номер ответа: 4
Автор ответа:
 alex



Вопросов: 84
Ответов: 453
 Профиль | | #4 Добавлено: 13.05.05 23:30
Согласен с HOOLIGAN, в этом исходнике ничего не соптимизируешь, разве только переписать его на встроенном ассемблере, но это добавит 2-3 процента производительности, не больше

Ответить

Номер ответа: 5
Автор ответа:
 SyavX



Вопросов: 25
Ответов: 149
 Профиль | | #5 Добавлено: 13.05.05 23:35
Жалко... А другого алгоритма нигде и не встречал :(

Ответить

Номер ответа: 6
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #6 Добавлено: 14.05.05 01:06
А что в конечном итоге вырезает этот алгоритм?
Всё время разное или нет?

Ответить

Номер ответа: 7
Автор ответа:
 Morpheus



Вопросов: 224
Ответов: 3777
 Web-сайт: xury.zx6.ru
 Профиль | | #7
Добавлено: 14.05.05 01:21
Этот каод вроде как должен окно по картинке вырезать? Попробуем ё нить сделать:

Можно ускорить процесс перебирая не всю картинку, а начинать с краёв и до первого пиксела. Может поможет. Только тогда форма будет без "отверстий".

Воторй способ - это перебрать картинку ОДИН раз и где то в тектовом файл сохранить координты вершин. Конечно, их много будет. Но поробывать стоит

Ответить

Номер ответа: 8
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #8 Добавлено: 14.05.05 01:49
Основной тормоз - необходимость проверки GetPixel'ом всего региона на предмет lMaskColor. Т.е. у тебя там рисунок (на hDCSrc).
Может такой вариант: не полагаясь на GetPixel, даже не рисуя предварительно этот рисунок, попытаться (изучив формат bmp), достать информацию о цвете непосредственно из структуры рисунка. Эмулировать GetPixel.

Ответить

Номер ответа: 9
Автор ответа:
 SyavX



Вопросов: 25
Ответов: 149
 Профиль | | #9 Добавлено: 14.05.05 17:24
2HOOLIGAN: А как это?
         
А вообще если писать для одного битмапа, то можно что-то такое учудить:


...
 While Y <= lHeight
  While X <= lWidth
   If X = 7 And Y < lHeight - 7 Then X = lWidth - 7
   If Y = 7 Then Y = lHeight - 7
...


Это если надо вырезать по углам

Ответить

Номер ответа: 10
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #10 Добавлено: 14.05.05 19:27
Если у тебя одна или несколько фиксированных картинок, которые надо вырезать, самое простое и быстрое - это в дизайнтайме заранее создать массив точек, обрамляющих регион и по ходу программы только вызвать один раз ф-цию CreatePolygonRgn, указав ей готовый массив точек, по которому она вырежет регион. Это будет намного быстрее, чем попиксельно создавать регионы и затем комбинировать их. Или сохранить вообще регион в файл (где-то на форуме видел тему с таким фокусом) и подгружать его во время работы программы.

Если картинки, по которым вырезается, заранее неизвестны, то попробовать поковырять структуру BITMAP этих картинок на предмет вытянуть из этой структуры информацию о цветах точек изображения, возможно это удастся и будет быстрее, чем получать информацию о цвете точки через GetPixel.

Ответить

Номер ответа: 11
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #11 Добавлено: 14.05.05 19:35
Ещё одна мысль, возвращаясь к твоему коду:
На данный момент ты найдя точку нужного цвета, вырезаешь регион и затем комбинируешь его с CurRgn, постепенно получая окончательный регион.
А если найдя точку нужного цвета, не вырезать регион, а просто занести координаты этой точки в массив, и после того, как все точки будут просмотрены и массив полностью сформирован из точек этого цвета, взять и за один проход вырезать целый регион по этому массиву точек?
Исключается непроизводительная вырезка кучи промежуточных регионов. Может стоит над этим подумать?

Ответить

Номер ответа: 12
Автор ответа:
 SyavX



Вопросов: 25
Ответов: 149
 Профиль | | #12 Добавлено: 15.05.05 02:43
К #10
1. CreatePolygonRgn создает регион, обрезаный по линии между первой и последней найденой точкой или что-то вроде то...
2. Поскольку словосочетание "структура BITMAP" мне ни о чем не говорит, то этот вариант отвергаю.

К #11

за один проход вырезать целый регион по этому массиву точек

Если я правильно понял:
...
    Do While Y <= lHeight
        Do While X <= lWidth
            If GetPixel(hDCSrc, X, Y) = lMaskColor Then
                Count = Count + 1
                Arr(Count).x = X
                Arr(Count).y = Y
            End If
            X = X + 1
        Loop
            Y = Y + 1
            X = 0
    Loop


    For i = 1 To Count
        TempRgn = CreateRectRgn(Arr(i).x, Arr(i).y, Arr(i).x + 1, Arr(i).y + 1)
        Result = CombineRgn(CurRgn, CurRgn, TempRgn, %RGN_DIFF)
    Next X
...

Но тогода отличий почти нет. Или я не так понял?

Ответить

Номер ответа: 13
Автор ответа:
 SyavX



Вопросов: 25
Ответов: 149
 Профиль | | #13 Добавлено: 21.05.05 12:26
Родилась прикольная идея.

    Do While Y <= lHeight
        Do While X <= lWidth
            lColor = GetPixel(hDCSrc, X, Y)
            For i = 1 To 255
                If lColor = RGB(255, i, 255) Then
                    Count = Count + 1
                    Arr(i).x = X
                    Arr(i).y = Y
                End If
            Next i
            X = X + 1
        Loop
            Y = Y + 1
            X = 0
    Loop

    CurRgn = CreatePolygonRgn(Arr(1), Count, 1)

В данном случае надо будет ручками попорядку проставить на битмапе точки с цветами от

RGB(255, 1, 255) до RGB(255, 255, 255) (это будут "вершины региона";). Если все сделать
правильно, то будеть работать. Увиличение скорости не наблюдалось :(

Ответить

Номер ответа: 14
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #14 Добавлено: 21.05.05 13:36
Увиличение скорости не наблюдалось :(


:)))
Кто же так делает? Зачем ещё третий цикл???

    Dim i As Long, j As Long, a As Long, Count As Long, t As Single
    Dim hdc As Long, clr As Long, arr(0 To 45000) As POINTAPI
    hdc = Me.hdc
    t = Timer
    For i = 0 To 300
        For j = 0 To 150
            clr = GetPixel(ByVal hdc, ByVal i, ByVal j)
            If (clr And &HFF0000) = &HFF0000 Then
                If (clr And &HFF) = 255 Then
                    arr(Count).x = i
                    arr(Count).y = j
                    Count = Count + 1
                End If
            End If
        Next j
    Next i


Так работает в 15 раз быстрее :)
Только замени циклы For - Next на свои Do - While.
Это на VB, думаю перевести на РВ нетрудно.

Ответить

Номер ответа: 15
Автор ответа:
 SyavX



Вопросов: 25
Ответов: 149
 Профиль | | #15 Добавлено: 21.05.05 17:37
Гы, попробуем...

Ответить

Страница: 1 | 2 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам