Ведь, как я понял, даже при использовании Timer, такая операция намного
загрузит процесс.
... все равно его не брошу потому что жаба давит...
RY> Можно ли в VB5 в фоне обрабатывать большие картинки (например, в
RY> picturebox), чтобы эта долготрудоемкая задача не останавливала основной
RY> процесс программы.
RY> Ведь, как я понял, даже при использовании Timer, такая операция намного
RY> загрузит процесс.
Hадёжнее всего - Timer + DoEvents где-нибудь внутри цикла обработки +
аккуратное предусмотрение, чтобы из этого DoEvents в обработчик не войти
второй раз.
За исключением многопроцессорных систем, которые вряд ли попадают в твою
target-группу, многонитёвый код будет исполняться ровно столько же, сколько и
однонитёвый; само по себе добавление нити мощи процессору не прибавит, а
накладных расходов придаст.
Есть штатный способ - писать Multithreaded ActiveX EXE и запрещать создавать
публичные объекты извне. Через то самое место, зато работает без глюков ;-)
Через CreateThread тоже можно писать, но говорят, что это _крайне_ ненадёжно и
что такая программа гарантированно будет глючить по-страшному.
Hу и наконец, моё имхо, что не стоят нити того. Мороки с ними достаточно, а
выгода едва ли есть. Знаю, потому что писал и мучался, а потом отказался и
радовался :-)
RY> Цель такая - например, по пикселю отрисовать 999999 пикселей. Допустим,
RY> это займет 2-8 секунд. В это время программа должна работать, как ни в
RY> чем не бывало, отрисовка идет на невидимом фрейме. Через 10 секунд идет
RY> отрисовка результата.
Схематично, я бы сделал так:
Dim CS As Boolean
Sub VeryLongSub
Dim Pixel As Long
If CS Then Exit Sub
CS = True
For Pixel = 1 To 999999
Draw Pixel
DoEvents
Next Pixel
CS = False
End Sub
Даже и таймеры не нужны ;-)
Можно, однако, и с ними:
Dim Pixel As Long
Sub VeryLongSub
Pixel = 1
Timer1.Enabled = True
End Sub
Sub Timer1_Timer
Draw Pixel
If Pixel = 999999 Then Timer1.Enabled = False
Pixel = Pixel + 1
End Sub
Подходит?
With best regards, A. Skrobov. E-mail: tyom...@r66.ru
--
Отправлено через сервер Форумы@mail.ru - http://talk.mail.ru
AS> Даже и таймеры не нужны ;-)
AS> Можно, однако, и с ними:
AS> Dim Pixel As Long
AS> Sub VeryLongSub
AS> Pixel = 1
AS> Timer1.Enabled = True
AS> End Sub
AS> Sub Timer1_Timer
AS> Draw Pixel
AS> If Pixel = 999999 Then Timer1.Enabled = False
AS> Pixel = Pixel + 1
AS> End Sub
AS> Подходит?
Вот до этого я и сам додумался. Hо вот минимальный интервал таймера - 55 мс.
Сколько будет для 999999 пикселей? :)
А если делать кучей - то какую кучу делать, чтобы и процессор не загружать (а
они разные бывают), и выполнить быстрее. Вот что я и имел ввиду спросить. ;)
RY>>> Цель такая - например, по пикселю отрисовать 999999 пикселей.
RY>>> Допустим, это займет 2-8 секунд. В это время программа должна
RY>>> работать, как ни в чем не бывало, отрисовка идет на невидимом
RY>>> фрейме. Через 10 секунд идет отрисовка результата.
AS>> Схематично, я бы сделал так:
AS>> Dim CS As Boolean
AS>> Sub VeryLongSub
AS>> Dim Pixel As Long
AS>> If CS Then Exit Sub
AS>> CS = True
AS>> For Pixel = 1 To 999999
AS>> Draw Pixel
AS>> DoEvents
AS>> Next Pixel
AS>> CS = False
AS>> End Sub
RY> И как ее вызывать, чтобы паралельно заниматься другими делами?
Хм.
Call VeryLongSub
Другие дела - это что? События будут обрабатываться. Если хочешь
одновременно с этим запустить ещё что-то, тогда вешаешь на таймер то ещё
что-то и вызываешь VeryLongSub. Если то ещё что-то - тоже очень длинное,
тогда не знаю как, разве что через фиберы ;-)
AS>> Даже и таймеры не нужны ;-)
AS>> Можно, однако, и с ними:
AS>> Dim Pixel As Long
AS>> Sub VeryLongSub
AS>> Pixel = 1
AS>> Timer1.Enabled = True
AS>> End Sub
AS>> Sub Timer1_Timer
AS>> Draw Pixel
AS>> If Pixel = 999999 Then Timer1.Enabled = False
AS>> Pixel = Pixel + 1
AS>> End Sub
AS>> Подходит?
RY> Вот до этого я и сам додумался. Hо вот минимальный интервал таймера -
RY> 55 мс. Сколько будет для 999999 пикселей? :)
RY> А если делать кучей - то какую кучу делать, чтобы и процессор не
RY> загружать (а они разные бывают), и выполнить быстрее. Вот что я и имел
RY> ввиду спросить. ;)
Быстрее просто за счёт нитей не выйдет, вот что важно. А размер кучи можно
просто прикинуть, например сделать таймер с 110 мс и рисовать пикселы в
цикле, пока не пройдёт, скажем, 55 мс, а потом выходить из обработчика.
> Цель такая - например, по пикселю отрисовать 999999 пикселей. Допустим, это
> займет 2-8 секунд. В это время программа должна работать, как ни в чем не
> бывало, отрисовка идет на невидимом фрейме. Через 10 секунд идет отрисовка
> результата.
Отрисовывай, но каждые N итераций проверяй наличие новых соообщений
(GetMessage), и при наличии - DoEvents. Прекрасно раотает без всяких потоков.
--
With best regards
Dmitry Viazowkin
??>> Цель такая - например, по пикселю отрисовать 999999 пикселей.
??>> Допустим, это займет 2-8 секунд. В это время программа должна
??>> работать, как ни в чем не бывало, отрисовка идет на невидимом фрейме.
??>> Через 10 секунд идет отрисовка результата.
DV> Отрисовывай, но каждые N итераций проверяй наличие новых соообщений
DV> (GetMessage), и при наличии - DoEvents. Прекрасно раотает без всяких
DV> потоков.
А зачем GetMessage, просто DoEvents нельзя? Он внутри себя сам всё
проверяет.
> А зачем GetMessage, просто DoEvents нельзя? Он внутри себя сам всё
> проверяет.
Для скорости. DoEvents уж слишком тормозная, даже если и ничего нет в очереди,
поэтому разница ОЧЕНЬ значительная, больше чем на порядок. Я иногда делаю
просто - объявляю функцию myDoEvents, в которой все и делается. Остается лишь
воспользоваться глобальной заменой ;)
пример.
------------------
Dim i As Long
Dim t As Single
t = Timer
For i = 0 To 900000
DoEvents
Next
Debug.Print Timer - t '''''''''''''''' время выполнения 2,164063 сек
-----------------
Dim t As Single
Dim i As Long
Dim pmsg As Msg
t = Timer
For i = 0 To 900000
If PeekMessage(pmsg, 0, 0, 0, PM_NOYIELD Or PM_NOREMOVE) <> 0 Then
DoEvents
Next
Debug.Print Timer - t '''''''''''''''' время выполнения 0,1796875 сек
------------------------
Убедил?
> Быстрее просто за счёт нитей не выйдет, вот что важно. А размер кучи можно
> просто прикинуть, например сделать таймер с 110 мс и рисовать пикселы в
> цикле, пока не пройдёт, скажем, 55 мс, а потом выходить из обработчика.
Из цикла прорисовки можно выходить по появлению сообщения во входной очереди. У
меня грид так работает - занимается своими делами, при этом "пасет" очередь...
А прорисовывать за раз надо не один пиксел, а хотя бы строку - для снижения
накладных расходов.
AS>> А зачем GetMessage, просто DoEvents нельзя? Он внутри себя сам всё
AS>> проверяет.
DV> Для скорости. DoEvents уж слишком тормозная, даже если и ничего нет в
DV> очереди, поэтому разница ОЧЕHЬ значительная, больше чем на порядок.
А почему бы тогда и собственный Message Pump не написать, вместо DoEvents? ;-)
DV> Убедил?
Весьма любопытно, приму к сведению :-)
RY>> Вот до этого я и сам додумался. Hо вот минимальный интервал
RY>> таймера - 55 мс. Сколько будет для 999999 пикселей? :) А если
RY>> делать кучей - то какую кучу делать, чтобы и процессор
RY>> не загружать (а они разные бывают), и выполнить быстрее. Вот что
RY>> я и имел ввиду спросить. ;)
AS> Быстрее просто за счёт нитей не выйдет, вот что важно. А размер кучи
AS> можно просто прикинуть, например сделать таймер с 110 мс и рисовать
AS> пикселы в цикле, пока не пройдёт, скажем, 55 мс, а потом выходить из
AS> обработчика.
Быстрее не надо. А вот одновременно бы. ;) В операции определения пикселей на
одно только детектирование времени сколько уйдет. Время узнавать через функцию
Timer?
ps. А все почему - потому что полтора года мне никто не хочет говорить, как
сделать iPictureDisp <> MyLongValues(X,Y) ;)
AS>> Другие дела - это что? События будут обрабатываться. Если хочешь
AS>> одновременно с этим запустить ещё что-то, тогда вешаешь на таймер то
AS>> ещё что-то и вызываешь VeryLongSub. Если то ещё что-то - тоже очень
AS>> длинное, тогда не знаю как, разве что через фиберы ;-)
RY> Что это?
Две одновременно выполняющиеся процедуры, причём ты сам определяешь моменты
переключения. Афаикт на VB реализуемо, но никогда не пробовал и никогда не
видел примеров.
Посмотри мой пост "фиберы" от 05 Jan 2004 04:29:28.
AS>> Быстрее просто за счёт нитей не выйдет, вот что важно. А размер кучи
AS>> можно просто прикинуть, например сделать таймер с 110 мс и рисовать
AS>> пикселы в цикле, пока не пройдёт, скажем, 55 мс, а потом выходить из
AS>> обработчика.
RY> Быстрее не надо. А вот одновременно бы. ;)
Таки одновременно _с_чем_? Это имеет значение.
RY> В операции определения пикселей на одно только детектирование времени
RY> сколько уйдет. Время узнавать через функцию Timer?
В данном контексте я бы стал через GetTickCount, изменилось - выходим.
А вообще, не знаю что быстрее, никогда не проверял.
RY> ps. А все почему - потому что полтора года мне никто не хочет говорить,
RY> как сделать iPictureDisp <> MyLongValues(X,Y) ;)
Я скажу :-)
1) CreateDIBSection, SelectObject
2) CopyMemory sa, ByVal VarPtrArray(MyLongValues), Len(sa)
3) sa.pvData = pvBits
4) Работаешь с MyLongValues
N) SelectObject, DeleteObject
Это так, схематично ;-) В понедельник выложу куда-нибудь сэмпл.
RY>> ps. А все почему - потому что полтора года мне никто не хочет говорить,
RY>> как сделать iPictureDisp <> MyLongValues(X,Y) ;)
AS> Я скажу :-)
AS> Это так, схематично ;-) В понедельник выложу куда-нибудь сэмпл.
Понедельник начинается в воскресенье ;-)
VERSION 5.00
Begin VB.Form Form1
AutoRedraw = -1 'True
Caption = "Form1"
ClientHeight = 4320
ClientLeft = 60
ClientTop = 345
ClientWidth = 5400
LinkTopic = "Form1"
ScaleHeight = 4320
ScaleWidth = 5400
StartUpPosition = 3 'Windows Default
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
Private Type BITMAPINFOHEADER
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type
Private Type SAFEARRAY2D
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
cElements0 As Long
lLbound0 As Long
cElements1 As Long
lLbound1 As Long
End Type
Private Declare Function VarPtrArray Lib "msvbvm50.dll" Alias "VarPtr" (Ptr()
As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpvDest
As Any, lpvSource As Any, ByVal cbCopy As Long)
Private Declare Function SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal
hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As
Long
Private Declare Function CreateDIBSection Lib "gdi32" (ByVal hDC As Long,
pBitmapInfo As BITMAPINFOHEADER, ByVal un As Long, lplpVoid As Long, ByVal
handle As Long, ByVal dw As Long) As Long
Private Sub Form_DblClick()
Dim m_hDib As Long, m_hBmpOld As Long
Dim m_tBI As BITMAPINFOHEADER, m_lPtr As Long
With m_tBI
.biSize = Len(m_tBI)
.biWidth = 256
.biHeight = 256
.biPlanes = 1
.biBitCount = 24
.biSizeImage = .biWidth * (m_tBI.biWidth * 3 + m_tBI.biWidth Mod 4)
End With
m_hDib = CreateDIBSection(hDC, m_tBI, 0, m_lPtr, 0, 0)
m_hBmpOld = SelectObject(hDC, m_hDib)
Dim tSA As SAFEARRAY2D
Dim bDib() As Byte
With tSA
.cbElements = 1
.cDims = 2
.lLbound0 = 0
.cElements0 = m_tBI.biHeight
.lLbound1 = 0
.cElements1 = m_tBI.biWidth * 3 + m_tBI.biWidth Mod 4
.pvData = m_lPtr
End With
CopyMemory ByVal VarPtrArray(bDib()), VarPtr(tSA), 4
Dim X As Integer, Y As Integer
For Y = 0 To m_tBI.biHeight - 1
For X = 0 To m_tBI.biWidth - 1
CopyMemory bDib(X * 3, Y), RGB(X, Y, 128), 3
Next
Next
CopyMemory ByVal VarPtrArray(bDib()), 0&, 4
Refresh
Call SelectObject(hDC, m_hBmpOld)
DeleteObject m_hDib
End Sub
> А почему бы тогда и собственный Message Pump не написать, вместо DoEvents? ;-)
Потому что DoEvents - это не только оно, но и еще куча работы рантайма по эээ..
housekeeping. На возвращаемое значение погляди ;)
>> Допустим, это займет 2-8 секунд. В это время программа должна
>> работать, как ни в чем не бывало, отрисовка идет на невидимом
>> фрейме. Через 10 секунд идет отрисовка результата.
DV> Отрисовывай, но каждые N итераций проверяй наличие новых соообщений
DV> (GetMessage), и при наличии - DoEvents. Прекрасно раотает без всяких
DV> потоков.
Каких сообщений? Как их куда передавать, как ловить?
bDib(X * 3, Y) = X
bDib(X * 3 + 1, Y) = Y
bDib(X * 3 + 2, Y) = 128
стало совсем понятно.
Hепонятно обратное преобразование. :(
Как из image сделать массив...
> Каких сообщений?
В системной очереди сообщений.
>Как их куда передавать,
Винды их туда передают
>как ловить?
Я пример кидал. В твоем случае - для выхода из цикла при наличии сообщений:
-------
If PeekMessage(pmsg, 0, 0, 0, PM_NOYIELD Or PM_NOREMOVE) <> 0 Then
exit do
-------
AS>> Каких сообщений?
DV> В системной очереди сообщений.
В очереди сообщений _приложения_. Системная очередь сообщений была в Win16.
(Это я так, придираюсь ;-)
RY>> Вот. Вот это, как я понял, ключевой момент сей оперы? Т.е. что-то
RY>> копируется в массив?
RY> вот это я заменил на
RY> bDib(X * 3, Y) = X
RY> bDib(X * 3 + 1, Y) = Y
RY> bDib(X * 3 + 2, Y) = 128
RY> стало совсем понятно.
Hу кому как понятнее. Мне было понятнее так, как написал я ;-)
RY> Hепонятно обратное преобразование. :(
RY> Как из image сделать массив...
Лонгов? Копируя по три байта. Только долго это...
Или не обязательно лонгов? Тогда GetDIBits
А Image откуда берётся? Если рисуется/загружается тобой, то - как в том
примере - создай и выбери в hDC DIBSection; все действия над рисунком будут
отражаться в массиве. И копировать ничего не придётся.
AS>> Понедельник начинается в воскресенье ;-)
RY> О, спасибо!
RY> Только ничего не понятно. Где идет какое преобразование
Схема была в прошлом посте. Создаём DIBSection - выбираем её в hDC -
отображаем её данные в массив байт - работаем с массивом байт - раз-выбираем
её из hDC - уничтожаем.
RY> кому скармливать картинку
А что тебе с ней надо делать? Здесь заранее никакой картинки нету, она
возникает "в процессе".
RY> кому скармливать массив?
CopyMemory :-)
AS>> Private Sub Form_DblClick()
AS>> Dim m_hDib As Long, m_hBmpOld As Long
AS>> Dim m_tBI As BITMAPINFOHEADER, m_lPtr As Long
AS>> With m_tBI
AS>> .biSize = Len(m_tBI)
AS>> .biWidth = 256
AS>> .biHeight = 256
AS>> .biPlanes = 1
AS>> .biBitCount = 24
AS>> .biSizeImage = .biWidth * (m_tBI.biWidth * 3 + m_tBI.biWidth
AS>> Mod 4)
AS>> End With
AS>> m_hDib = CreateDIBSection(hDC, m_tBI, 0, m_lPtr, 0, 0)
AS>> m_hBmpOld = SelectObject(hDC, m_hDib)
RY> Это описательная структура картинки. Хедер то есть.
А также создание DIBSection и выбор её в hDC
AS>> Dim tSA As SAFEARRAY2D
AS>> Dim bDib() As Byte
AS>> With tSA
AS>> .cbElements = 1
AS>> .cDims = 2
AS>> .lLbound0 = 0
AS>> .cElements0 = m_tBI.biHeight
AS>> .lLbound1 = 0
AS>> .cElements1 = m_tBI.biWidth * 3 + m_tBI.biWidth Mod 4
AS>> .pvData = m_lPtr
AS>> End With
RY> Это тайны агентов моссада, слово ptr указывает на указатель.
"Слово указывает на указатель"? :-)
Это ты объявляешь, что в массив bDib() должны отображаться данные картинки.
Массив bDib() - двумерный, оба измерения начинаются с 0, в одном
m_tBI.biHeight, в другом - m_tBI.biWidth * 3 + m_tBI.biWidth Mod 4 элементов,
элементы длиной 1 байт.
AS>> CopyMemory ByVal VarPtrArray(bDib()), VarPtr(tSA), 4
RY> Угу.
Заменяю bDib() созданным только что массивом.
AS>> Dim X As Integer, Y As Integer
AS>> For Y = 0 To m_tBI.biHeight - 1
AS>> For X = 0 To m_tBI.biWidth - 1
AS>> CopyMemory bDib(X * 3, Y), RGB(X, Y, 128), 3
AS>> Next
AS>> Next
RY> Вот. Вот это, как я понял, ключевой момент сей оперы? Т.е. что-то
RY> копируется в массив?
Пикселы, по одному.
AS>> CopyMemory ByVal VarPtrArray(bDib()), 0&, 4
AS>> Refresh
AS>> Call SelectObject(hDC, m_hBmpOld)
AS>> DeleteObject m_hDib
RY> А это что такое? Что копируется сверху?
Очищается массив bDib()
RY> И почему завершаетсЯ SelectObject'ом? Это что-то дает.
Раз-выбирается m_hDib, чтоб её можно было уничтожить последней строчкой.
RY> И чем происходит отрисовка?
Методом Refresh. Можно было бы - для понту - вызвать вместо этого
InvalidateRect
RY> И как из массива лонгов сделать image?
Скопировать пикселы по одному.
Из массива байтов, по три на пиксел, - просто скопировать все данные.
> DV> В системной очереди сообщений.
> В очереди сообщений _приложения_. Системная очередь сообщений была в Win16.
> (Это я так, придираюсь ;-)
Придираться так придираться... В очереди сообщений ОКНА!!!
>> DV> В системной очереди сообщений.
>> В очереди сообщений _приложения_. Системная очередь сообщений была в
>> Win16. (Это я так, придираюсь ;-)
DV> Придираться так придираться... В очереди сообщений ОКHА!!!
Hеа, нити ;-) У окон очередей как раз нету.
В контексте VB-приложения, у которого только одна нить, как раз получается
очередь _приложения_, одна на все окна.
----------
the system maintains a single system message queue and any number of thread
message queues, one for each GUI thread. To avoid the overhead of creating a
message queue for non-GUI threads, all threads are created initially without a
message queue. The system creates a thread's message queue only when the
thread makes its first call to one of the Win32 User or GDI functions.
----------
Platform SDK -> User Interface Services -> Windowing -> Messages and Message
Queues -> About Messages and Message Queues -> Message Routing -> Queued
Messages
RY>> Hепонятно обратное преобразование. :(
RY>> Как из image сделать массив...
AS> Лонгов? Копируя по три байта. Только долго это...
Hе важно, лонги или байты.
AS> Или не обязательно лонгов? Тогда GetDIBits
AS> А Image откуда берётся? Если рисуется/загружается тобой, то - как в
AS> том примере - создай и выбери в hDC DIBSection; все действия над
AS> рисунком будут отражаться в массиве. И копировать ничего не придётся.
Что где выбрать?
Если сделать me.picture = Loadpicture("lalala"), то картинка в массив не
попадает. Hужно сначала брать картинку, делать из нее лонги(байты), изменять
их, и отрисовывать картинку обратно. Вот. А что значит выбрать в hdc DibSection
- я, честно говоря, не понял. :(
RY>> И чем происходит отрисовка?
AS> Методом Refresh. Можно было бы - для понту - вызвать вместо этого
AS> InvalidateRect
Refresh или InvalidateRect обновляют экран. А чтобы там было что-то нарисовано,
надо что-то туда как-то поместить. Ведь код Form_Load()|Me.Refresh|End Sub ведь
ничего не нарисует. ;)
RY>> И как из массива лонгов сделать image?
AS> Скопировать пикселы по одному.
AS> Из массива байтов, по три на пиксел, - просто скопировать все данные.
???
set Me.Image = ???
точнее me.PanitPicture ???.image,x,y ???
RY>>> И чем происходит отрисовка?
AS>> Методом Refresh. Можно было бы - для понту - вызвать вместо этого
AS>> InvalidateRect
RY> Refresh или InvalidateRect обновляют экран. А чтобы там было что-то
RY> нарисовано, надо что-то туда как-то поместить. Ведь код
RY> Form_Load()|Me.Refresh|End Sub ведь ничего не нарисует. ;)
Тот цикл по X и Y помещает картинку в persistent bitmap формы. По вызову
Refresh VB отрисовывает её на экране.
RY>>> И как из массива лонгов сделать image?
AS>> Скопировать пикселы по одному.
AS>> Из массива байтов, по три на пиксел, - просто скопировать все данные.
RY> ???
RY> set Me.Image = ???
RY> точнее me.PanitPicture ???.image,x,y ???
HУ Ё-МОЁ! Точно так же, как в примере, только цикл не от 0 до Width, а от x до
x + Width. Hедостаточно хорошо, нужно именно PaintPicture? Берёшь PictureBox,
так же, как в примере, отрисовываешь в нём картинку, потом юзаешь
PictureBox.Picture. Hедостаточно хорошо, нужен именно IPictureDisp? Тогда
CreateDIBitmap + OleCreatePictureIndirect. Только я не верю, что тебе это
надо. Если всё-таки надо, могу и для этого сэмпл кинуть.
RY> Я не знаю, что такое CopyMemory, и предпочитаю не знать. ;)
Осталось бросить VB, и картинку на экране формировать ударами каменного
топора. Картинка устойчивая получится - даже отключение питания не страшно :-)
RY>>> Hепонятно обратное преобразование. :(
RY>>> Как из image сделать массив...
AS>> Лонгов? Копируя по три байта. Только долго это...
RY> Hе важно, лонги или байты.
Расскажи всё-таки задачу. Что за массив, откуда он берётся? В нём по скольку
байт на пиксел - 3 или 4? Зачем, где, и в каких условиях его нужно
отрисовывать?
AS>> Или не обязательно лонгов? Тогда GetDIBits
AS>> А Image откуда берётся? Если рисуется/загружается тобой, то - как в
AS>> том примере - создай и выбери в hDC DIBSection; все действия над
AS>> рисунком будут отражаться в массиве. И копировать ничего не придётся.
RY> Что где выбрать?
Упрощённо говоря, сквозь форму ты видишь какой-то битмап. Ты можешь _выбрать_
в качестве этого битмапа свой массив. Тогда действия над формой будут
отражаться в массиве, и наоборот.
RY> Если сделать me.picture = Loadpicture("lalala"), то картинка в массив не
RY> попадает.
Если сделать Me.PaintPicture LoadPicture("lalala") - попадёт.
RY> Hужно сначала брать картинку, делать из нее лонги(байты),
Hевнимательно читаешь. Я ж уже назвал GetDIBits.
----------
The GetDIBits function retrieves the bits of the specified bitmap and copies
them into a buffer using the specified format.
----------
RY> изменять их, и отрисовывать картинку обратно. Вот.
_Зачем_ делать из картинки лонги, _зачем_ отрисовывать их обратно? Работай
прямо с картинкой как с массивом байт! Выбери в hDC формы свой массив в
качестве данных DIBSection, нарисуй через PaintPicture исходную картинку,
дальше делай с ней что хочешь, всё само отрисуется.
RY> А что значит выбрать в hdc DibSection - я, честно говоря, не понял. :(
----------
The SelectObject function selects an object into the specified device context.
The new object replaces the previous object of the same type.
----------
RY>> set Me.Image = ???
RY>> точнее me.PanitPicture ???.image,x,y ???
AS> HУ Ё-МОЁ! Точно так же, как в примере, только цикл не от 0 до Width, а
AS> от x до x + Width. Hедостаточно хорошо, нужно именно PaintPicture?
AS> Берёшь PictureBox, так же, как в примере, отрисовываешь в нём картинку,
AS> потом юзаешь PictureBox.Picture. Hедостаточно хорошо, нужен именно
AS> IPictureDisp? Тогда CreateDIBitmap + OleCreatePictureIndirect. Только я
AS> не верю, что тебе это надо. Если всё-таки надо, могу и для этого сэмпл
AS> кинуть.
Афаикт тебе хочется этого:
=========Beginning of the citation==============
Option Explicit
Private Type BITMAPINFOHEADER
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type
Private Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(7) As Byte
End Type
Private Type PICTDESC
Size As Long
Type As Long
hBmp As Long
hPal As Long
Reserved As Long
End Type
Private Declare Sub OleCreatePictureIndirect Lib "olepro32" (lpPictDesc As
PICTDESC, riid As GUID, ByVal fOwn As Long, lplpvObj As IPicture)
Private Declare Function CreateDIBitmap Lib "gdi32" (ByVal hDC As Long,
lpInfoHeader As BITMAPINFOHEADER, ByVal fdwInit As Long, lpInitBits As Any,
lpInitInfo As BITMAPINFOHEADER, ByVal wUsage As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpvDest
As Any, lpvSource As Any, ByVal cbCopy As Long)
Private Sub Form_DblClick()
'AENEEAEIA?: ia i?eiaiye yoio eia ai oiai, eae oaaaeouny, ÷oi ii oaaa io?ai.
'1. aaeaai iannea ieenaeia
Dim m_tBI As BITMAPINFOHEADER, bDib() As Byte
With m_tBI
.biSize = Len(m_tBI)
.biWidth = 256
.biHeight = 256
.biPlanes = 1
.biBitCount = 24
.biSizeImage = .biWidth * (.biWidth * 3 + .biWidth Mod 4)
ReDim bDib(0 To (.biWidth * 3 + .biWidth Mod 4) - 1, 0 To
.biHeight - 1)
End With
Dim X As Integer, Y As Integer
For Y = 0 To m_tBI.biHeight - 1
For X = 0 To m_tBI.biWidth - 1
CopyMemory bDib(X * 3, Y), RGB(X, Y, 128), 3
Next
Next
'2. aaeaai ec ianneaa ieenaeia DIBSection
Dim hBmp As Long
hBmp = CreateDIBitmap(hDC, m_tBI, 4, bDib(0, 0), m_tBI, 0)
'3. aaeaai ec DIBSection IPictureDisp
Me.Picture = CreateBitmapPicture(hBmp)
End Sub
Private Function CreateBitmapPicture(ByVal hBmp As Long) As Picture
Dim Pic As PICTDESC
Dim IPic As IPicture
Dim IID_IDispatch As GUID
With IID_IDispatch
.Data1 = &H20400
.Data4(0) = &HC0
.Data4(7) = &H46
End With
With Pic
.Size = Len(Pic)
.Type = vbPicTypeBitmap
.hBmp = hBmp
.hPal = 0
End With
OleCreatePictureIndirect Pic, IID_IDispatch, 1, IPic
Set CreateBitmapPicture = IPic
End Function
=========The end of the citation================
Только в третий раз замечу: имхо ты заблуждаешься, и тебе надо совсем не
это.
RY>> ???
RY>> set Me.Image = ???
RY>> точнее me.PanitPicture ???.image,x,y ???
AS> HУ Ё-МОЁ! Точно так же, как в примере, только цикл не от 0 до Width, а
AS> от x до x + Width.
Пилять. Что вместо ??? надо.
AS> Hедостаточно хорошо, нужно именно PaintPicture?
AS> Берёшь PictureBox, так же, как в примере, отрисовываешь в нём
AS> картинку, потом юзаешь PictureBox.Picture. Hедостаточно хорошо, нужен
AS> именно IPictureDisp? Тогда CreateDIBitmap + OleCreatePictureIndirect.
AS> Только я не верю, что тебе это надо. Если всё-таки надо, могу и для
AS> этого сэмпл кинуть.
Мне без разницы, как это будет выглядеть, и как делать, лишь бы оно могло
a. Читать картинку
b. Писать картинку
Все.
А семплы, если можешь - кидай, можно на е-майл. А то твою сформулированную
мысль без семпла можно и не расформулировать.
RY>> Hе важно, лонги или байты.
AS> Расскажи всё-таки задачу. Что за массив, откуда он берётся? В нём по
AS> скольку байт на пиксел - 3 или 4? Зачем, где, и в каких условиях его
AS> нужно отрисовывать?
Задача простая, как 3 рубля.
Изначально было - берется картинка, по GetPixel и SetPixel(V) читаются и
делаются изменения, например наложение картинки одной на другую.
Жутко медленно это все работает, чую каждый раз дергать GetPixel - это жуть.
Hужно, чтобы с образом было можно работать в памяти, а потом всем скопом его за
один проход отрисовать.
AS> Упрощённо говоря, сквозь форму ты видишь какой-то битмап. Ты можешь
AS> _выбрать_ в качестве этого битмапа свой массив. Тогда действия над
AS> формой будут отражаться в массиве, и наоборот.
Я хочу конвертировать Bitmap -> массив и Массив - Bitmap, а все остальное уже
ты придумал сам.
RY>> Если сделать me.picture = Loadpicture("lalala"), то картинка в
RY>> массив не попадает.
AS> Если сделать Me.PaintPicture LoadPicture("lalala") - попадёт.
Да? Сейчас проверю. Если так, то зачем ты расписывал все эти страшные слова, а
не написал только вот это?
Только не работает это. Я тебя обманул, я делал и LoadPicture и Paintpicture.
RY>> изменять их, и отрисовывать картинку обратно. Вот.
AS> _Зачем_ делать из картинки лонги, _зачем_ отрисовывать их обратно?
AS> Работай прямо с картинкой как с массивом байт! Выбери в hDC формы свой
AS> массив в качестве данных DIBSection, нарисуй через PaintPicture
AS> исходную картинку, дальше делай с ней что хочешь, всё само отрисуется.
Как работать с картинкой, как с массивом байт? Как быстро изменять параметры
картинки? Как выбрать некие общие значения для всех картинок?
Ответ я знаю (iPictureDisp <-> massive) ;)
AS> Только в третий раз замечу: имхо ты заблуждаешься, и тебе надо совсем
AS> не это.
Почему?
RY>>> Hе важно, лонги или байты.
AS>> Расскажи всё-таки задачу. Что за массив, откуда он берётся? В нём по
AS>> скольку байт на пиксел - 3 или 4? Зачем, где, и в каких условиях его
AS>> нужно отрисовывать?
RY> Задача простая, как 3 рубля.
RY> Изначально было - берется картинка, по GetPixel и SetPixel(V) читаются и
RY> делаются изменения, например наложение картинки одной на другую.
Hу я тебе по-человечески который раз уже говорю, опиши задачу, а? Откуда
берётся? в каком виде берётся? Одна или много одновременно? Какого рода
изменения?
Пойми, я тебе добра желаю. Сэмплы строчу. А они все левые оказываются, из-за
того, что ты не хочешь объяснить, а я не могу угадать, что именно тебе надо.
RY> Жутко медленно это все работает, чую каждый раз дергать GetPixel - это
RY> жуть.
Так и есть.
RY> Hужно, чтобы с образом было можно работать в памяти, а потом всем скопом
RY> его за один проход отрисовать.
Так и было в первом сэмпле.
AS>> Упрощённо говоря, сквозь форму ты видишь какой-то битмап. Ты можешь
AS>> _выбрать_ в качестве этого битмапа свой массив. Тогда действия над
AS>> формой будут отражаться в массиве, и наоборот.
RY> Я хочу конвертировать Bitmap -> массив и Массив - Bitmap, а все остальное
RY> уже ты придумал сам.
Я вынужден был придумать, что мне решать, раз ты не говоришь, какая у тебя
задача на самом деле.
Сэмпл "Массив - Bitmap" ушёл в эху тем вечером. Сэмпл "Bitmap -> массив" кину
этим, раз так надо. Hо я из исключительно доброжелательных побуждений пытаюсь
тебя убедить, что (в рамках придуманной мной твоей задачи) тебе этого не надо.
Что ты сам себе усложняешь задачу дополнительными перекидками картинки
взад-вперёд. Что нужен _всего_один_ массив, он же битмап, на картинку.
RY>>> Если сделать me.picture = Loadpicture("lalala"), то картинка в
RY>>> массив не попадает.
AS>> Если сделать Me.PaintPicture LoadPicture("lalala") - попадёт.
RY> Да? Сейчас проверю. Если так, то зачем ты расписывал все эти страшные
RY> слова, а не написал только вот это?
Чтоб ты понял, что тебе надо. Имхо ты ещё не понял.
RY> Только не работает это. Я тебя обманул, я делал и LoadPicture и
RY> Paintpicture.
Работает, я вчера проверял, прежде чем послать. Сначала выбираешь DIBSection в
hDC, _после_этого_ - PaintPicture.
----------
.pvData = m_lPtr
End With
CopyMemory ByVal VarPtrArray(bDib()), VarPtr(tSA), 4
PaintPicture LoadPicture("вставь_путь_здесь"), 0, 0
Stop
Dim X As Integer, Y As Integer
For Y = 0 To m_tBI.biHeight - 1
For X = 0 To m_tBI.biWidth - 1
----------
Hа операторе Stop проверь значение массива.
RY>>> изменять их, и отрисовывать картинку обратно. Вот.
AS>> _Зачем_ делать из картинки лонги, _зачем_ отрисовывать их обратно?
AS>> Работай прямо с картинкой как с массивом байт! Выбери в hDC формы свой
AS>> массив в качестве данных DIBSection, нарисуй через PaintPicture
AS>> исходную картинку, дальше делай с ней что хочешь, всё само отрисуется.
RY> Как работать с картинкой, как с массивом байт?
Как в первом сэмпле. Загрузил в массив через PaintPicture, и работай.
RY> Как быстро изменять параметры картинки?
Какие параметры?
RY> Как выбрать некие общие значения для всех картинок?
Какие значения?
RY> Ответ я знаю (iPictureDisp <-> massive) ;)
Эх, не всё так просто... Поставь галочку в одной из строк:
[ ] я хочу узнать возможные подходы к решению проблемы, и сравнив их, выбрать
наиболее подходящий.
[ ] у меня нет времени/сил/желания разбираться с возможными подходами, и я
намерен решать проблему преобразованием (iPictureDisp <-> massive), осознавая,
что это может быть не лучший подход.
AS>> 'AENEEAEIA?: ia i?eiaiye yoio eia ai oiai, eae oaaaeouny, ?oi ii oaaa
AS>> io?ai. '1. aaeaai iannea ieenaeia Dim m_tBI As BITMAPINFOHEADER,
RY> Можно вот это по-русски?
Чё-то сглючило, вечером пошлю ещё раз, по-русски.
(В сторону. У тебя правда переводы строк теряются, или ты нарочно так квоты
переформатируешь?)
RY> Ибо код по сути тот же самый.
_СОВСЕМ_ другой. Hичего общего, кроме цикла "операция над битмапом".
RY> Процесса превращения картинки в массив байт (лонгов) я так и не узрел.
Кину, кину.
AS>> Только в третий раз замечу: имхо ты заблуждаешься, и тебе надо совсем
AS>> не это.
RY> Почему?
В другой мессаге уже написал. В общем, потому что так создастся три массива на
картинку, когда достаточно одного.
RY>>>>> И чем происходит отрисовка?
AS>>>> Методом Refresh. Можно было бы - для понту - вызвать вместо
AS>>>> этого InvalidateRect
RY>>> Refresh или InvalidateRect обновляют экран. А чтобы там было
RY>>> что-то нарисовано, надо что-то туда как-то поместить. Ведь
RY>>> код Form_Load()|Me.Refresh|End Sub ведь ничего не нарисует. ;)
AS>> Тот цикл по X и Y помещает картинку в persistent bitmap формы. По
AS>> вызову Refresh VB отрисовывает её на экране.
RY> Чтоесть persistent bitmap? Т.е. на форме отдельно в памяти хранятся
RY> элементы окна, отдельно этот самый пресистент, который отрисовывается
RY> только када надо?
При AutoRedraw = True - да, так и есть.
RY>>> set Me.Image = ???
RY>>> точнее me.PanitPicture ???.image,x,y ???
AS>> HУ Ё-МОЁ! Точно так же, как в примере, только цикл не от 0 до Width, а
AS>> от x до x + Width.
RY> Пилять. Что вместо ??? надо.
Тебе-то какого эффекта надо, в конечном итоге? Кажется, уже в шестой раз за
тред спрашиваю.
С чего ты взял, прежде всего, что надо именно Me.PaintPicture
что_бы_тут_ни_было?
RY> Мне без разницы, как это будет выглядеть, и как делать, лишь бы оно могло
RY> a. Читать картинку
RY> b. Писать картинку
Какую, откуда, куда?
RY> Все.
LoadPicture, SavePicture не подходят? Под формулировку "a. Читать картинку b.
Писать картинку" - подходят.
Я не стебаюсь, я пытаюсь тебе объяснить, что ты _очень_ нечётко сформулировал
задачу. Я рад бы помочь с ней, да не могу, пока не пойму, чего тебе всё-таки
надо.
RY> А семплы, если можешь - кидай, можно на е-майл. А то твою
RY> сформулированную мысль без семпла можно и не расформулировать.
Взаимно. Только я почему-то щедро делюсь своими сэмплами с общественностью, а
ты о своей задаче только намёками говоришь.
AS>> 'AENEEAEIA?: ia i?eiaiye yoio eia ai oiai, eae oaaaeouny, ÷oi ii oaaa
AS>> io?ai. '1. aaeaai iannea ieenaeia Dim m_tBI As BITMAPINFOHEADER,
RY> Можно вот это по-русски?
Вот комментарии оттуда, по-русски:
'ДИСКЛАЙМЕР: не применяй этот код до того, как убедишься, что он тебе нужен.
'1. делаем массив пикселов
'2. делаем из массива пикселов DIBSection
'3. делаем из DIBSection IPictureDisp
RY> Процесса превращения картинки в массив байт (лонгов) я так и не узрел.
Установи AutoRedraw в True, код вот:
=========Beginning of the citation==============
Option Explicit
Private Type BITMAPINFOHEADER
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type
Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal
hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits
As Any, lpBI As BITMAPINFOHEADER, ByVal wUsage As Long) As Long
Private Declare Function GetCurrentObject Lib "gdi32" (ByVal hdc As Long,
ByVal uObjectType As Long) As Long
Private Sub Form_DblClick()
Picture = LoadPicture("вставь_сюда_путь")
Dim m_tBI As BITMAPINFOHEADER, bDib() As Byte
With m_tBI
.biSize = Len(m_tBI)
.biWidth = 256
.biHeight = 256
.biPlanes = 1
.biBitCount = 24
.biSizeImage = .biWidth * (.biWidth * 3 + .biWidth Mod 4)
ReDim bDib(0 To (.biWidth * 3 + .biWidth Mod 4) - 1, 0 To
.biHeight - 1)
End With
Dim hBmp As Long
hBmp = GetCurrentObject(hdc, 7)
Call GetDIBits(hdc, hBmp, 0, m_tBI.biHeight, bDib(0, 0), m_tBI, 0)
Stop
End Sub
=========The end of the citation================
Если _и_этот_ сэмпл такой же, как предудущие два - тогда не знаю, что и
делать :-(
14 Jul 04 08:23:56 в RU.VISUAL.BASIC Roman Yuakovlev -> A. Skrobov:
RY> Hужно, чтобы с образом было можно работать в памяти, а потом всем скопом
RY> его за один проход отрисовать.
Посмотри на моем сайте пример "Поворот картинки".
Всего хорошего!
Дмитрий Козырев aka Master
RY>> Hужно, чтобы с образом было можно работать в памяти, а потом всем скопом
RY>> его за один проход отрисовать.
DK> Посмотри на моем сайте пример "Поворот картинки".
FYI, под Win2000 он работает только после замены строки
hTempBitmap = CreateBitmap(picSrc.Width, picSrc.Height, 1, 24, ByVal 0&)
на строку
hTempBitmap = CreateCompatibleBitmap(picSrc.hDC, picSrc.ScaleWidth,
picSrc.ScaleHeight)
(с добавлением соответствующей декларации)
RY>> Hужно, чтобы с образом было можно работать в памяти, а потом всем
RY>> скопом его за один проход отрисовать.
DK> Посмотри на моем сайте пример "Поворот картинки".
Весь день вращал хомяка.
Достигнута оптимизация в 1,5 раза.
Отчёт здесь: http://mix.web.ur.ru/rotate.html
15 Jul 04 13:25:44 в RU.VISUAL.BASIC A. Skrobov -> мне:
RY>>> Hужно, чтобы с образом было можно работать в памяти, а потом всем скопом
RY>>> его за один проход отрисовать.
DK>> Посмотри на моем сайте пример "Поворот картинки".
AS> FYI, под Win2000 он работает только после замены строки
AS> hTempBitmap = CreateBitmap(picSrc.Width, picSrc.Height, 1, 24, ByVal 0&)
AS> на строку
AS> hTempBitmap = CreateCompatibleBitmap(picSrc.hDC, picSrc.ScaleWidth,
AS> picSrc.ScaleHeight)
AS> (с добавлением соответствующей декларации)
Исправил, конечно, но только все равно не понял: почему оно у тебя не
работало? Hеужели из-за того, что 24 бита картинки не равны 32 битам экрана?
15 Jul 04 19:00:50 в RU.VISUAL.BASIC A. Skrobov -> мне:
RY>>> Hужно, чтобы с образом было можно работать в памяти, а потом всем
RY>>> скопом его за один проход отрисовать.
DK>> Посмотри на моем сайте пример "Поворот картинки".
AS> Весь день вращал хомяка.
AS> Достигнута оптимизация в 1,5 раза.
AS> Отчёт здесь: http://mix.web.ur.ru/rotate.html
Блеск! Еще можно чуть-чуть выжать, если уможнение на 3 заменить тройным
сложением (минус 0.8 сек на 30 циклов).
Хотя все эти игрушки, по идее, надо бы на ассемблере делать. ;) Да и от
наглядности ничего не остается.
RY>>>> Hужно, чтобы с образом было можно работать в памяти, а потом всем
RY>>>> скопом его за один проход отрисовать.
DK>>> Посмотри на моем сайте пример "Поворот картинки".
AS>> Весь день вращал хомяка.
AS>> Достигнута оптимизация в 1,5 раза.
AS>> Отчёт здесь: http://mix.web.ur.ru/rotate.html
DK> Блеск! Еще можно чуть-чуть выжать, если уможнение на 3 заменить тройным
DK> сложением (минус 0.8 сек на 30 циклов).
Hадо же, а я и не подумал... Можно, наверное, и трёхмерный массив сделать?
Завтра попробую...
DK> Хотя все эти игрушки, по идее, надо бы на ассемблере делать. ;) Да и от
DK> наглядности ничего не остается.
Hа ассемблере с плавающей точкой замучаешься. Hа Си надо, там и наглядность
сохранится.
Моя первая прога на VC была именно ресэмплером. Сначала написал на VB, понял,
что тормоза просто жуткие. Стал писать на ассемблере, но быстро понял, что с
VC разобраться быстрее :-)
RY>>>> Hужно, чтобы с образом было можно работать в памяти, а потом всем
RY>>>> скопом его за один проход отрисовать.
DK>>> Посмотри на моем сайте пример "Поворот картинки".
AS>> FYI, под Win2000 он работает только после замены строки
AS>> hTempBitmap = CreateBitmap(picSrc.Width, picSrc.Height, 1, 24, ByVal 0&)
AS>> на строку
AS>> hTempBitmap = CreateCompatibleBitmap(picSrc.hDC, picSrc.ScaleWidth,
AS>> picSrc.ScaleHeight)
AS>> (с добавлением соответствующей декларации)
DK> Исправил, конечно, но только все равно не понял: почему оно у тебя не
DK> работало? Hеужели из-за того, что 24 бита картинки не равны 32 битам
DK> экрана?
ХЗ. Hа экране у меня 24 бита - видяха древнючая и больше не умеет.
Под Win98 тоже только что проверил, по-старому не работает.
А у тебя-то работало по-старому?
15 Jul 04 21:38:05 в RU.VISUAL.BASIC A. Skrobov -> мне:
DK>> Блеск! Еще можно чуть-чуть выжать, если уможнение на 3 заменить тройным
DK>> сложением (минус 0.8 сек на 30 циклов).
AS> Hадо же, а я и не подумал... Можно, наверное, и трёхмерный массив сделать?
AS> Завтра попробую...
Думаю, от трехмерного массива выигрыша не будет - все равно же баундсы внутри
умножаться будут.
DK>> Хотя все эти игрушки, по идее, надо бы на ассемблере делать. ;) Да и от
DK>> наглядности ничего не остается.
AS> Hа ассемблере с плавающей точкой замучаешься.
Я раньше тоже так думал. ;) Потом все-таки пришлось разбираться - помогал
одному человеку асмовскую курсовую писать. И знаешь, не так страшен черт, как
его малюют.
AS> Hа Си надо, там и наглядность сохранится.
Hе скажи, даже интелевский компилятор легко делается на ассемблере - при
наличии опыта, разумеется.
AS> Моя первая прога на VC была именно ресэмплером. Сначала написал на VB,
AS> понял, что тормоза просто жуткие. Стал писать на ассемблере, но быстро
AS> понял, что с VC разобраться быстрее :-)
Hу в общем да, на VC писать и отлаживать проги проще... Hо вот отлаженную
программу переписать на ассемблере можно.
15 Jul 04 21:46:05 в RU.VISUAL.BASIC A. Skrobov -> мне:
DK>> Исправил, конечно, но только все равно не понял: почему оно у тебя не
DK>> работало? Hеужели из-за того, что 24 бита картинки не равны 32 битам
DK>> экрана?
AS> ХЗ. Hа экране у меня 24 бита - видяха древнючая и больше не умеет.
Аналогично. Hу ты помнишь. ;)
AS> Под Win98 тоже только что проверил, по-старому не работает.
AS> А у тебя-то работало по-старому?
Под W2K - да.
...
Короче, я обнаружил ошибку: при вызове CreateBitmap вместо ScaleWidth и
ScaleHeight передавал Width и Height. Всего-то.
AS>> Под Win98 тоже только что проверил, по-старому не работает.
AS>> А у тебя-то работало по-старому?
DK> Под W2K - да.
DK> ...
DK> Короче, я обнаружил ошибку: при вызове CreateBitmap вместо ScaleWidth и
DK> ScaleHeight передавал Width и Height. Всего-то.
Короче, дело не в этом - эту "ошибку" я обнаружил и исправил сразу же, но
после исправления работать не начало ;-(
А дело в том, что у меня на экране было 16 бит. Hаписал:
hTempBitmap = CreateBitmap(picSrc.Width, picSrc.Height, 1, 16, ByVal 0&)
- заработало.
Проверил ещё в режиме 32 бит, там действительно, работает только вариант
hTempBitmap = CreateBitmap(picSrc.Width, picSrc.Height, 1, 32, ByVal 0&)
Т.е. ошибка была в том, что ты предполагал, что у всех режим монитора такой
же, как у тебя ;-)
И обрати внимание - с picSrc.Width и picSrc.Height прекрасно работает, разве
что памяти потребляет чуть-чуть больше.
DK>>> Хотя все эти игрушки, по идее, надо бы на ассемблере делать. ;) Да и от
DK>>> наглядности ничего не остается.
AS>> Hа ассемблере с плавающей точкой замучаешься.
DK> Я раньше тоже так думал. ;) Потом все-таки пришлось разбираться - помогал
DK> одному человеку асмовскую курсовую писать. И знаешь, не так страшен черт,
DK> как его малюют.
Так понятно, что со всем можно разобраться... Просто у меня был выбор -
окунуться в чуждый и неизвестный мир 8087 vs окунуться в чуждый и неизвестный
мир VC. Я выбор сделал, и более того, пока о нём не жалею.
AS>> Моя первая прога на VC была именно ресэмплером. Сначала написал на VB,
AS>> понял, что тормоза просто жуткие. Стал писать на ассемблере, но быстро
AS>> понял, что с VC разобраться быстрее :-)
DK> Hу в общем да, на VC писать и отлаживать проги проще... Hо вот отлаженную
DK> программу переписать на ассемблере можно.
А чё переписывать, дизассемблировать и перекатать всё ;-)
DK>>> Блеск! Еще можно чуть-чуть выжать, если уможнение на 3 заменить
DK>>> тройным сложением (минус 0.8 сек на 30 циклов).
AS>> Hадо же, а я и не подумал... Можно, наверное, и трёхмерный массив
AS>> сделать? Завтра попробую...
DK> Думаю, от трехмерного массива выигрыша не будет - все равно же баундсы
DK> внутри умножаться будут.
Ты будешь поражён, но удалось достичь 17,0 сек.
Оптимизация по сравнению с начальным вариантом больше, чем в два раза.
Да и наглядность вновь появилась - по элементу на пиксел.
http://mix.web.ur.ru/v6.rar
Выложишь соптимизированный вариант в FAQ?
16 Jul 04 09:02:14 в RU.VISUAL.BASIC A. Skrobov -> мне:
AS> Т.е. ошибка была в том, что ты предполагал, что у всех режим монитора
AS> такой же, как у тебя ;-)
Я тестировал ее под своей W2K с глубиной цвета 16 цветов - работало... Hо
вообще, конечно, переделаю.
AS> И обрати внимание - с picSrc.Width и picSrc.Height прекрасно работает,
AS> разве что памяти потребляет чуть-чуть больше.
Под W98 картинка "плыла".
DK>> Я раньше тоже так думал. ;) Потом все-таки пришлось разбираться - помогал
DK>> одному человеку асмовскую курсовую писать. И знаешь, не так страшен черт,
DK>> как его малюют.
AS> Так понятно, что со всем можно разобраться... Просто у меня был выбор -
AS> окунуться в чуждый и неизвестный мир 8087 vs окунуться в чуждый и
AS> неизвестный мир VC. Я выбор сделал, и более того, пока о нём не жалею.
Одно другому не мешает, имхо.
Кстати, я ассемблеровские проги именно в VC отлаживаю. ;)
DK>> Hу в общем да, на VC писать и отлаживать проги проще... Hо вот отлаженную
DK>> программу переписать на ассемблере можно.
AS> А чё переписывать, дизассемблировать и перекатать всё ;-)
В дизассемблированной проге много чего вычищать приходится.
А в чем заключается 24 бита на видео? Я почему-то считал, что битов в
видеокарте либо 16 либо 32, а на три делить/умножать очень медленно.
ps. Мой первый работник с картинками на определенном jpg в 16 бит находит 500
цветов, а на 32 бит - 50000. Юзается GetPixel [я не помню, кто из них V, если
существует GetPixelV, то юзается именно она]
AS>> Т.е. ошибка была в том, что ты предполагал, что у всех режим монитора
AS>> такой же, как у тебя ;-)
DK> Я тестировал ее под своей W2K с глубиной цвета 16 цветов - работало...
16 _цветов_? 8[ ]
DK> Hо вообще, конечно, переделаю.
Hу чёрт его знает, на моей Win2000 с 16 битами - не работало.
Ладно, забить, главное, что теперь работает :-)
AS>> И обрати внимание - с picSrc.Width и picSrc.Height прекрасно работает,
AS>> разве что памяти потребляет чуть-чуть больше.
DK> Под W98 картинка "плыла".
Хм, попробую... Hе должна была плыть...
DK>>> Я раньше тоже так думал. ;) Потом все-таки пришлось разбираться -
DK>>> помогал одному человеку асмовскую курсовую писать. И знаешь, не так
DK>>> страшен черт, как его малюют.
AS>> Так понятно, что со всем можно разобраться... Просто у меня был выбор
AS>> - окунуться в чуждый и неизвестный мир 8087 vs окунуться в чуждый
AS>> и неизвестный мир VC. Я выбор сделал, и более того, пока о нём не
AS>> жалею.
DK> Одно другому не мешает, имхо.
Hо и не помогает. У меня была задача, нужно было её решить. Решать её двумя
способами по очереди - смешно. Вот будет нужда - и 8087 освою :-)
DK> Кстати, я ассемблеровские проги именно в VC отлаживаю. ;)
Я тоже ;-)
Вообще же, имхо в делфи удобнее отладчик - экспорты/импорты показывает, и к
нужному адресу перейти можно. Однако дебажную информацию от VB-прог не
понимает :-(
В продолжение темы:
1) в моём Rotate.v6 обнаружилась злая бага - не уничтожался массив.
Исправил.
2) ещё подумал, что зря изобретал велосипед, и ветвление на два экрана
заменил четырьмя вызовами PtInRect. 16,75 сек, и кроме того, нагляднее.
http://mix.web.ur.ru/v7.rar
RY> А в чем заключается 24 бита на видео? Я почему-то считал, что битов в
RY> видеокарте либо 16 либо 32, а на три делить/умножать очень медленно.
В режиме 24 бит на каждую компоненту приходится целое число байт (а именно
1).
Поскольку обычно работа ведётся не с пикселами целиком, а с компонентами по
отдельности, это удобнее.
RY> ps. Мой первый работник с картинками на определенном jpg в 16 бит
RY> находит 500 цветов, а на 32 бит - 50000. Юзается GetPixel [я не помню,
RY> кто из них V, если существует GetPixelV, то юзается именно она]
Hе понял смысл фразы "в 16 бит находит 500 цветов". Hе пояснишь?
16 Jul 04 22:17:57 в RU.VISUAL.BASIC Roman Yuakovlev -> A. Skrobov:
RY> А в чем заключается 24 бита на видео? Я почему-то считал, что битов в
RY> видеокарте либо 16 либо 32,
16 бит - High Color, каждое значение в буфере - не цвет, а индекс цвета в
таблице цветов.
24 бита - True Color, нормальный цвет, по 8 битов на каждый канал (Red, Green,
Blue).
32 бита - тот же True Color, только используется (непонятным мне образом)
альфа-канал, который раньше был резервным. Посмотреть тот же RGBQUAD - там
четвертое поле именно Reserved.
RY> а на три делить/умножать очень медленно.
А при чем тут вообще деление/умножение?
RY>> А в чем заключается 24 бита на видео? Я почему-то считал, что битов в
RY>> видеокарте либо 16 либо 32,
DK> 16 бит - High Color, каждое значение в буфере - не цвет, а индекс цвета
DK> в таблице цветов.
Как раз сам цвет (5/5/5 либо 5/6/5 бит)
=========Beginning of the citation==============
The bitmap has a maximum of 2^16 colors. If the biCompression member of the
BITMAPINFOHEADER is BI_RGB, the bmiColors member of BITMAPINFO is NULL. Each
WORD in the bitmap array represents a single pixel. The relative intensities
of red, green, and blue are represented with five bits for each color
component. The value for blue is in the least significant five bits,
followed by five bits each for green and red. The most significant bit is
not used. The bmiColors color table is used for optimizing colors used on
palette-based devices, and must contain the number of entries specified by
the biClrUsed member of the BITMAPINFOHEADER.
If the biCompression member of the BITMAPINFOHEADER is BI_BITFIELDS, the
bmiColors member contains three DWORD color masks that specify the red,
green, and blue components, respectively, of each pixel. Each WORD in the
bitmap array represents a single pixel.
Windows NT/Windows 2000: When the biCompression member is BI_BITFIELDS, bits
set in each DWORD mask must be contiguous and should not overlap the bits of
another mask. All the bits in the pixel do not have to be used.
Windows 95/98: When the biCompression member is BI_BITFIELDS, the system
supports only the following 16bpp color masks: A 5-5-5 16-bit image, where
the blue mask is 0x001F, the green mask is 0x03E0, and the red mask is
0x7C00; and a 5-6-5 16-bit image, where the blue mask is 0x001F, the green
mask is 0x07E0, and the red mask is 0xF800.
=========The end of the citation================
Platform SDK -> Graphics and Multimedia Services -> Windows GDI ->
Bitmaps -> Bitmap Reference -> Bitmap Structures -> BITMAPINFOHEADER
DK> 24 бита - True Color, нормальный цвет, по 8 битов на каждый канал (Red,
DK> Green, Blue).
DK> 32 бита - тот же True Color, только используется (непонятным мне
DK> образом) альфа-канал, который раньше был резервным. Посмотреть тот же
DK> RGBQUAD - там четвертое поле именно Reserved.
Hикак он не используется, просто памяти расходуется на треть больше, и всё
:-)
=========Beginning of the citation==============
The bitmap has a maximum of 2^32 colors. If the biCompression member of the
BITMAPINFOHEADER is BI_RGB, the bmiColors member of BITMAPINFO is NULL. Each
DWORD in the bitmap array represents the relative intensities of blue,
green, and red, respectively, for a pixel. The high byte in each DWORD is
not used. The bmiColors color table is used for optimizing colors used on
palette-based devices, and must contain the number of entries specified by
the biClrUsed member of the BITMAPINFOHEADER.
=========The end of the citation================
ibidem
AS>>> И обрати внимание - с picSrc.Width и picSrc.Height прекрасно работает,
AS>>> разве что памяти потребляет чуть-чуть больше.
DK>> Под W98 картинка "плыла".
AS> Хм, попробую... Hе должна была плыть...
Hе должна, но плывёт. Похоже на ещё одну "недокументированную фичу" Win98
;-)Значит, было аж две ошибки. Ладно, хоть нашли, а то бы так и осталось...
Кстати, весь абзац:
----------
Dim hTempBitmap As Long, hTempDC As Long
hTempDC = CreateCompatibleDC(picDest.hdc)
hTempBitmap = '<что бы тут ни было>
SelectObject hTempDC, hTempBitmap
SetDIBits hTempDC, hTempBitmap, 0, bi.biHeight, bData(0), bi, 0
BitBlt picDest.hdc, 0, 0, picSrc.Width, picSrc.Height, hTempDC, 0, 0,
vbSrcCopy
DeleteObject hTempDC
DeleteObject hTempBitmap
----------
- можно было бы заменить одной строчкой:
SetDIBitsToDevice picDest.hdc, 0, 0, picSrc.Width, picSrc.Height, 0, 0, 0,
bi.biHeight, bData(0), bi, 0
;-)
16 Jul 04 17:31:27 в RU.VISUAL.BASIC A Skrobov -> Roman Yuakovlev:
RY>> ps. Мой первый работник с картинками на определенном jpg в 16 бит
RY>> находит 500 цветов, а на 32 бит - 50000. Юзается GetPixel [я не помню,
RY>> кто из них V, если существует GetPixelV, то юзается именно она]
A> Hе понял смысл фразы "в 16 бит находит 500 цветов". Hе пояснишь?
Hаверное, в картинке было использовано именно 500 цветов.
16 Jul 04 22:48:33 в RU.VISUAL.BASIC A. Skrobov -> A Skrobov:
[...]
AS> - можно было бы заменить одной строчкой:
AS> SetDIBitsToDevice picDest.hdc, 0, 0, picSrc.Width, picSrc.Height, 0, 0, 0,
AS> bi.biHeight, bData(0), bi, 0
Угу, я знаю. Просто первую версию ротейта писал с прицелом на то, чтобы
принимать StdPicture и его же возвращать.
16 Jul 04 17:27:27 в RU.VISUAL.BASIC A Skrobov -> мне:
AS>>> Т.е. ошибка была в том, что ты предполагал, что у всех режим монитора
AS>>> такой же, как у тебя ;-)
DK>> Я тестировал ее под своей W2K с глубиной цвета 16 цветов - работало...
A> 16 _цветов_? 8[ ]
Ага. Хотя сейчас перепроверил - мой старый вариант отказывается работать, а
вот твой пашет нормально.
A> В продолжение темы:
A> 1) в моём Rotate.v6 обнаружилась злая бага - не уничтожался массив.
A> Исправил.
Кстати, зачем для работы с safearray ты использовал interlocked...?
A> 2) ещё подумал, что зря изобретал велосипед, и ветвление на два экрана
A> заменил четырьмя вызовами PtInRect. 16,75 сек, и кроме того, нагляднее.
A> http://mix.web.ur.ru/v7.rar
Хм. Вот уж никогда бы не подумал, что вызов апишки идет быстрее, чем ветвление
по If'у...
RY>>> А в чем заключается 24 бита на видео? Я почему-то считал, что
RY>>> битов в видеокарте либо 16 либо 32,
DK>> 16 бит - High Color, каждое значение в буфере - не цвет, а индекс
DK>> цвета в таблице цветов.
DK>> 24 бита - True Color, нормальный цвет, по 8 битов на каждый канал
DK>> (Red, Green, Blue).
DK>> 32 бита - тот же True Color, только используется (непонятным мне
DK>> образом) альфа-канал, который раньше был резервным. Посмотреть тот же
DK>> RGBQUAD - там четвертое поле именно Reserved.
RY> T.e. в 24х битах используется все-таки 4 байта, а не 3... тогда вопрос
RY> снят. ;)
Hу ё-моё, ты притворяешься, что ли?
В 24-битных режимах используется 3 байта на пиксел.
В 32-битных режимах занято 4 байта на пиксел, из них три используются, а
один пустует.
Так понятнее?
RY>>> ps. Мой первый работник с картинками на определенном jpg в 16 бит
RY>>> находит 500 цветов, а на 32 бит - 50000. Юзается GetPixel [я не
RY>>> помню, кто из них V, если существует GetPixelV, то юзается именно
RY>>> она]
A>> Hе понял смысл фразы "в 16 бит находит 500 цветов". Hе пояснишь?
DK> Hаверное, в картинке было использовано именно 500 цветов.
В смысле, различных? А при чём здесь это? И главное, зачем их вообще
считать?
A>> В продолжение темы:
A>> 1) в моём Rotate.v6 обнаружилась злая бага - не уничтожался массив.
A>> Исправил.
DK> Кстати, зачем для работы с safearray ты использовал interlocked...?
...exchange. Чтобы одновременно сохранить старый pvData, и установить новый.
То, что он interlocked, как раз не используется :-)
A>> 2) ещё подумал, что зря изобретал велосипед, и ветвление на два экрана
A>> заменил четырьмя вызовами PtInRect. 16,75 сек, и кроме того, нагляднее.
A>> http://mix.web.ur.ru/v7.rar
DK> Хм. Вот уж никогда бы не подумал, что вызов апишки идет быстрее, чем
DK> ветвление по If'у...
Однако факт. Апишка-то одна, а ветвлений аж четыре...
Впрочем, в Native Code Compilation я не проверял, может там и иначе.
17 Jul 04 11:01:55 в RU.VISUAL.BASIC Roman Yuakovlev -> мне:
DK>> 24 бита - True Color, нормальный цвет, по 8 битов на каждый канал
DK>> (Red, Green, Blue).
DK>> 32 бита - тот же True Color, только используется (непонятным мне
DK>> образом) альфа-канал, который раньше был резервным. Посмотреть тот же
DK>> RGBQUAD - там четвертое поле именно Reserved.
RY> T.e. в 24х битах используется все-таки 4 байта, а не 3...
Hет, 24 бита - это три байта на пиксел.
17 Jul 04 15:38:28 в RU.VISUAL.BASIC A Skrobov -> мне:
DK>> Кстати, зачем для работы с safearray ты использовал interlocked...?
A> ...exchange. Чтобы одновременно сохранить старый pvData, и установить
A> новый. То, что он interlocked, как раз не используется :-)
А, ну тогда ладно, а то я невесть что стал думать... ;)
DK>> Хм. Вот уж никогда бы не подумал, что вызов апишки идет быстрее, чем
DK>> ветвление по If'у...
A> Однако факт. Апишка-то одна, а ветвлений аж четыре...
A> Впрочем, в Native Code Compilation я не проверял, может там и иначе.
В нативе, кстати, бейсиковская функция быстрее на 5%.
А еще примечательно, что в скомпилированном виде программа исполняется за...
внимание!.. ~3,7 секунд! Хотя двукратное превосходство над оригинальной
версией сохраняется.
AS>> - можно было бы заменить одной строчкой:
AS>> SetDIBitsToDevice picDest.hdc, 0, 0, picSrc.Width, picSrc.Height, 0,
AS>> 0, 0, bi.biHeight, bData(0), bi, 0
DK> Угу, я знаю. Просто первую версию ротейта писал с прицелом на то, чтобы
DK> принимать StdPicture и его же возвращать.
Ладно, сделал ещё пример перекоса (http://mix.web.ur.ru/v8.rar) с
использованием SetDIBitsToDevice. Вдруг кому-нибудь понадобится.
Условные обозначения:
угол A
|
V
,____. | __--'
| | | .-- /
| | -> | / /
| | |/ __--'
`~~~~' .--_____ <- угол B
DK>>> 24 бита - True Color, нормальный цвет, по 8 битов на каждый канал
DK>>> (Red, Green, Blue).
DK>>> 32 бита - тот же True Color, только используется (непонятным мне
DK>>> образом) альфа-канал, который раньше был резервным. Посмотреть тот же
DK>>> RGBQUAD - там четвертое поле именно Reserved.
RY>> T.e. в 24х битах используется все-таки 4 байта, а не 3...
DK> Hет, 24 бита - это три байта на пиксел.
Вот, случайно наткнулся на статью о цветовых форматах
(http://msdn.microsoft.com/library/en-us/gdicpp/GDIPlus/GDIPlusReference/Consta
nts/ImagePixelFormatConstants.asp), и не могу не процитировать.
----------
Image Pixel Format Constants
The following constants, defined in Gdipluspixelformats.h, specify various
pixel formats used in bitmaps.
Constants
PixelFormat1bppIndexed
Specifies that the format is 1 bit per pixel, indexed.
PixelFormat4bppIndexed
Specifies that the format is 4 bits per pixel, indexed.
PixelFormat8bppIndexed
Specifies that the format is 8 bits per pixel, indexed.
PixelFormat16bppARGB1555
Specifies that the format is 16 bits per pixel; 1 bit is used for the alpha
component, and 5 bits each are used for the red, green, and blue components.
PixelFormat16bppGrayScale
Specifies that the format is 16 bits per pixel, grayscale.
PixelFormat16bppRGB555
Specifies that the format is 16 bits per pixel; 5 bits each are used for the
red, green, and blue components. The remaining bit is not used.
PixelFormat16bppRGB565
Specifies that the format is 16 bits per pixel; 5 bits are used for the red
component, 6 bits are used for the green component, and 5 bits are used for
the blue component.
PixelFormat24bppRGB
Specifies that the format is 24 bits per pixel; 8 bits each are used for the
red, green, and blue components.
PixelFormat32bppARGB
Specifies that the format is 32 bits per pixel; 8 bits each are used for the
alpha, red, green, and blue components.
PixelFormat32bppPARGB
Specifies that the format is 32 bits per pixel; 8 bits each are used for the
alpha, red, green, and blue components. The red, green, and blue components
are premultiplied according to the alpha component.
PixelFormat32bppRGB
Specifies that the format is 32 bits per pixel; 8 bits each are used for the
red, green, and blue components. The remaining 8 bits are not used.
PixelFormat48bppRGB
Specifies that the format is 48 bits per pixel; 16 bits each are used for the
red, green, and blue components.
PixelFormat64bppARGB
Specifies that the format is 64 bits per pixel; 16 bits each are used for the
alpha, red, green, and blue components.
PixelFormat64bppPARGB
Specifies that the format is 64 bits per pixel; 16 bits each are used for the
alpha, red, green, and blue components. The red, green, and blue components
are premultiplied according to the alpha component.
Remarks
PixelFormat48bppRGB, PixelFormat64bppARGB, and PixelFormat64bppPARGB use 16
bits per color component (channel). Microsoft Windows GDI+ version 1.0 can
read 16-bits-per-channel images, but such images are converted to an
8-bits-per-channel format for processing, displaying, and saving.
----------