Так что быстрее win32 gdi api или gdi+

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

twinzco
Начинающий
Начинающий
 
Сообщения: 23
Зарегистрирован: 22.05.2006 (Пн) 23:36

Так что быстрее win32 gdi api или gdi+

Сообщение twinzco » 13.06.2006 (Вт) 15:16

У меня следующая проблема, я рисую карту по значениям массива вида x,y,z - координаты и значение, соответсвенно рисуется прямоугольник соотвествующего цвета. А теперь вопрос, как сделать быстро? Картинка получается размера 1200x800 прямоугольников (пикселей) . Сначала написал на gdi+:
Код: Выделить всё
Private Sub customplot(ByRef g As Graphics, ByVal n As Integer, ByVal m As Integer, ByVal sxz As Single, ByVal syz As Single)
        Dim sclx, scly, count As Integer
        sclx = nx / pic.Width
        scly = ny / pic.Height
        count = 0
        If sclx = 0 Or scly = 0 Then
            Pbar.Maximum = nx
            Pbar.Value = 0
            plot(gr, nx, ny, sx, sy)
        Else
            Pbar.Maximum = nx / sclx
            Pbar.Value = 0
            For i = 0 To n - 1 Step sclx
                For j = 0 To m - 1 Step scly
                    k = Fix((data(i, Abs(m - j - 1)) - zmin) / cc)
                    mybrush = New SolidBrush(colors(k))
                    g.FillRectangle(mybrush, i * sxz, j * syz, sxz + sxz * sclx, syz + syz * scly)
                    mybrush.Dispose()
                Next j
                count = count + 1
                Pbar.PerformStep()
            Next i
        End If
    End Sub

Рисует достаточно медленно, тогда я переписал с помощью api:
Код: Выделить всё
Private Sub customplot(ByRef g As Graphics, ByVal n As Integer, ByVal m As Integer, ByVal sxz As Single, ByVal syz As Single)
        Dim LB As LOGBRUSH
        Dim R As RECT
        Dim hBrush As Integer
        Dim hdc As Integer
        Dim sclx, scly, count As Integer
        sclx = nx / pic.Width
        scly = ny / pic.Height
        count = 0
        If sclx = 0 Or scly = 0 Then
            Pbar.Maximum = nx
            Pbar.Value = 0
            plot(gr, nx, ny, sx, sy)
        Else
            Pbar.Maximum = nx / sclx
            Pbar.Value = 0
            hdc = g.gethdc()
            For i = 0 To n - 1 Step sclx
                For j = 0 To m - 1 Step scly
                    k = Fix((data(i, Abs(m - j - 1)) - zmin) / cc)
                    LB.lbColor = RGB(colorsx(k, 1), colorsx(k, 2), colorsx(k, 3))
                    hBrush = CreateBrushIndirect(LB)
                    SetRect(R, i * sxz, j * syz, i * sxz + sxz * sclx, j * syz + syz * scly)
                    FillRect(hdc, R, hBrush)
                    DeleteObject(hBrush)
                Next j
                count = count + 1
                Pbar.PerformStep()
            Next i
            g.ReleaseHdc()
        End If
    End Sub

А скорость такая-же :(
Что посоветуете?

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 13.06.2006 (Вт) 23:16

Ты бы хоть код в порядок привел :?
Вставил в проект - половина переменных не обьявлена, а голову ломать никакого желания
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

twinzco
Начинающий
Начинающий
 
Сообщения: 23
Зарегистрирован: 22.05.2006 (Пн) 23:36

Сообщение twinzco » 13.06.2006 (Вт) 23:43

По-моему очевидно, что это кусок кода и есть глобальные переменные. Могу выложить урезанный. Разве это поможет?

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 14.06.2006 (Ср) 0:05

Вырежь из проекта все ненужное и выложи. Главное чтобы отрисовка работала.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

twinzco
Начинающий
Начинающий
 
Сообщения: 23
Зарегистрирован: 22.05.2006 (Пн) 23:36

Сообщение twinzco » 14.06.2006 (Ср) 1:10

Вот оно. Вырезал долго :lol:
Там же файлик, который нужно открывать.
Вложения
tovbstreets.rar
(308.34 Кб) Скачиваний: 101

baha76
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 168
Зарегистрирован: 07.01.2004 (Ср) 10:59
Откуда: Ташкент

Сообщение baha76 » 14.06.2006 (Ср) 7:18

Насколько я осведомлен, GDI+ это и есть инкапсулированный Win32 API в FW. Значит скорость их работы равнозначная...

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 14.06.2006 (Ср) 9:25

baha76 писал(а):Насколько я осведомлен, GDI+ это и есть инкапсулированный Win32 API в FW. Значит скорость их работы равнозначная...

http://bbs.vbstreets.ru/viewtopic.php?p=6610543#6610543
Изображение

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 14.06.2006 (Ср) 9:42

А этот файл ты сам генеришь? Было бы неплохо избавиться от Single и Double - слишком много расчетов. А по поводу графики на досуге подумаю.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

twinzco
Начинающий
Начинающий
 
Сообщения: 23
Зарегистрирован: 22.05.2006 (Пн) 23:36

Сообщение twinzco » 14.06.2006 (Ср) 14:16

К сожалению нет. Кстати это стандартный binary grid файл пакета Golden Software Surfer - достаточно известный и активно использующийся в "гисах".
Последний раз редактировалось twinzco 15.06.2006 (Чт) 1:30, всего редактировалось 1 раз.

twinzco
Начинающий
Начинающий
 
Сообщения: 23
Зарегистрирован: 22.05.2006 (Пн) 23:36

Сообщение twinzco » 15.06.2006 (Чт) 1:28

Короче говоря- фигня вышла :oops:
У меня случился какой-то глюк и в папке \bin судя по всему не было release версии. После перезагрузки все неожиданно встало на свои места! На моем компе для сравнения GDI+ рисует за 7 секунд. А winapi за ~1 секунду!

Но зато появился следующий вопрос почему чтение файла с помощью тех же api скорость медленнее чем со stream, кручусь уже несколько часов :(
Код: Выделить всё

    Public Const GENERIC_WRITE As Integer = &H40000000
    Public Const GENERIC_READ As Integer = &H80000000
    Const FILE_ATTRIBUTE_NORMAL As Short = &H80S
    Const CREATE_ALWAYS As Short = 2
    Const OPEN_ALWAYS As Short = 4
    Const INVALID_HANDLE_VALUE As Short = -1
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Integer) As Integer
    Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Integer, ByVal dwShareMode As Integer, ByVal lpSecurityAttributes As Integer, ByVal dwCreationDisposition As Integer, ByVal dwFlagsAndAttributes As Integer, ByVal hTemplateFile As Integer) As Integer
    Declare Function ReadFile Lib "kernel32" (ByVal hFile As Integer, ByRef lpBuffer As Double, ByVal nNumberOfBytesToRead As Integer, ByRef lpNumberOfBytesRead As Integer, ByVal lpOverlapped As Integer) As Integer
    Declare Function ReadFile Lib "kernel32" (ByVal hFile As Integer, ByRef lpBuffer As Single, ByVal nNumberOfBytesToRead As Integer, ByRef lpNumberOfBytesRead As Integer, ByVal lpOverlapped As Integer) As Integer
    Declare Function ReadFile Lib "kernel32" (ByVal hFile As Integer, ByRef lpBuffer As Byte, ByVal nNumberOfBytesToRead As Integer, ByRef lpNumberOfBytesRead As Integer, ByVal lpOverlapped As Integer) As Integer
    Declare Function ReadFile Lib "kernel32" (ByVal hFile As Integer, ByRef lpBuffer As Short, ByVal nNumberOfBytesToRead As Integer, ByRef lpNumberOfBytesRead As Integer, ByVal lpOverlapped As Integer) As Integer

.....

Private Sub readbinfile_()
        Dim fHandle As Integer
        Dim fSuccess As Integer
        Dim lBytesRead As Integer
        Dim str As Byte
        Dim temp As Single
        fHandle = CreateFile(dlgopen.FileName, GENERIC_WRITE Or GENERIC_READ, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)
        Pbar.Value = 0
        If fHandle <> INVALID_HANDLE_VALUE Then
            fSuccess = ReadFile(fHandle, str, 1, lBytesRead, 0)
            fSuccess = ReadFile(fHandle, str, 1, lBytesRead, 0)
            fSuccess = ReadFile(fHandle, str, 1, lBytesRead, 0)
            fSuccess = ReadFile(fHandle, str, 1, lBytesRead, 0)
            fSuccess = ReadFile(fHandle, nx, 2, lBytesRead, 0)
            fSuccess = ReadFile(fHandle, ny, 2, lBytesRead, 0)
            fSuccess = ReadFile(fHandle, xmin, 8, lBytesRead, 0)
            fSuccess = ReadFile(fHandle, xmax, 8, lBytesRead, 0)
            fSuccess = ReadFile(fHandle, ymin, 8, lBytesRead, 0)
            fSuccess = ReadFile(fHandle, ymax, 8, lBytesRead, 0)
            fSuccess = ReadFile(fHandle, zmin, 8, lBytesRead, 0)
            fSuccess = ReadFile(fHandle, zmax, 8, lBytesRead, 0)
            Pbar.Maximum = ny
            ReDim data(nx, ny)
            For j = 0 To ny - 1
                For i = 0 To nx - 1
                    fSuccess = ReadFile(fHandle, temp, 4, lBytesRead, 0)
                    data(i, j) = temp
                Next i
                Pbar.PerformStep()
            Next j
            fSuccess = CloseHandle(fHandle)
        End If
    End Sub

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 16.06.2006 (Пт) 10:26

Графика.
Примерно в 5-7 раз быстрее без использования Api.
А чем тебя не устраивает Stream?
Вложения
tovbstreets1.rar
(303.87 Кб) Скачиваний: 113
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

twinzco
Начинающий
Начинающий
 
Сообщения: 23
Зарегистрирован: 22.05.2006 (Пн) 23:36

Сообщение twinzco » 16.06.2006 (Пт) 20:13

Nord777
...ну пока я разбираюсь с твоим кодом. А stream при размерах файла более 50 Mb начинает буксовать, вот я и думал использовать api. В принципе если ты видел реализацию моей функции отрисовки, то она выкидывает "незначащие" участки с шагом кратным размеру картинки, т.к. если целиком грузить будет то-же самое. Соответсвенно при использовании зума, будет считываться из файла необхожимая порция данных, а Stream при файле в ~ 1.2 Gb очень прилично тормозит, полагаю, что с api будет быстрее (пока не пробовал). Где-то здесь читал, что на самом деле Stream при небольших размерах целиком считывает файл в память, попробую использовать некий буфер, думаю должно ускориться. Любые идеи - welcome.

P.S. а unmanaged code не грозит траблами? (про marshal)

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 17.06.2006 (Сб) 1:24

P.S. а unmanaged code не грозит траблами? (про marshal)

И это говорит человек, усиленно использующий Api
А дорогу переходить не грозит траблами?:D

Вот что тебе грозит:
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
В том примере что я прислал такого безобразия мне так и не удалось добиться. Это произойдет если массив VBuffer обьявить внутри процедуры и изменять размеры формы.
Хотя можно перестраховаться и сделать так, чтобы Сборщик Мусора не перемещал блок памяти, которую отводишь под массив:
Код: Выделить всё
Dim GCH As GCHandle

    Public Sub Init(ByVal PB As PictureBox, ByVal W As Integer, ByVal H As Integer)
        If GCH.IsAllocated Then GCH.Free()

        ReDim Preserve VBufer(H - 1, W - 1)
        GCH = GCHandle.Alloc(VBufer, GCHandleType.Pinned)
        Dim Ptr As IntPtr = GCH.AddrOfPinnedObject

        PB.BackgroundImage = New Bitmap(W, H, W * 4, Imaging.PixelFormat.Format32bppArgb, Ptr)
    End Sub


По поводу файла:
быстродействие должно по идее увеличиться если читать весь файл за раз(в смысле не отдельными записями). Вот только позволит ли тебе
это твой обьем оперативной памяти?
С другой стороны можно читать кусками, как ты делаешь при выводе на экран.
Если честно, достаточно сложно дать какой либо совет - слишком мало информации.

PS: Проблема решается просто - 4Гб ОЗУ и RAID-массив :wink:
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5


Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 81

    TopList