Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Threads

42 views
Skip to first unread message

Roman Yuakovlev

unread,
Jul 7, 2004, 8:11:03 PM7/7/04
to
Можно ли в VB5 в фоне обрабатывать большие картинки (например, в picturebox),
чтобы эта долготрудоемкая задача не останавливала основной процесс программы.

Ведь, как я понял, даже при использовании Timer, такая операция намного
загрузит процесс.


... все равно его не брошу потому что жаба давит...

A. Skrobov

unread,
Jul 7, 2004, 5:19:43 PM7/7/04
to
Thu Jul 08 2004 05:11, Roman Yuakovlev wrote to All:

RY> Можно ли в VB5 в фоне обрабатывать большие картинки (например, в
RY> picturebox), чтобы эта долготрудоемкая задача не останавливала основной
RY> процесс программы.
RY> Ведь, как я понял, даже при использовании Timer, такая операция намного
RY> загрузит процесс.
Hадёжнее всего - Timer + DoEvents где-нибудь внутри цикла обработки +
аккуратное предусмотрение, чтобы из этого DoEvents в обработчик не войти
второй раз.
За исключением многопроцессорных систем, которые вряд ли попадают в твою
target-группу, многонитёвый код будет исполняться ровно столько же, сколько и
однонитёвый; само по себе добавление нити мощи процессору не прибавит, а
накладных расходов придаст.
Есть штатный способ - писать Multithreaded ActiveX EXE и запрещать создавать
публичные объекты извне. Через то самое место, зато работает без глюков ;-)
Через CreateThread тоже можно писать, но говорят, что это _крайне_ ненадёжно и
что такая программа гарантированно будет глючить по-страшному.
Hу и наконец, моё имхо, что не стоят нити того. Мороки с ними достаточно, а
выгода едва ли есть. Знаю, потому что писал и мучался, а потом отказался и
радовался :-)

Roman Yuakovlev

unread,
Jul 8, 2004, 8:11:19 PM7/8/04
to

RY>> Можно ли в VB5 в фоне обрабатывать большие картинки (например, в
RY>> picturebox), чтобы эта долготрудоемкая задача не останавливала
RY>> основной процесс программы. Ведь, как я понял, даже при
RY>> использовании Timer, такая операция намного загрузит процесс.
AS> Hадёжнее всего - Timer + DoEvents где-нибудь внутри цикла обработки +
AS> аккуратное предусмотрение, чтобы из этого DoEvents в обработчик не
AS> войти второй раз. За исключением многопроцессорных систем, которые
AS> вряд ли попадают в твою target-группу, многонитёвый код будет
AS> исполняться ровно столько же, сколько и однонитёвый; само по себе
AS> добавление нити мощи процессору не прибавит, а накладных расходов
AS> придаст. Есть штатный способ - писать Multithreaded ActiveX EXE и
AS> запрещать создавать публичные объекты извне. Через то самое место,
AS> зато работает без глюков ;-) Через CreateThread тоже можно писать, но
AS> говорят, что это _крайне_ ненадёжно и что такая программа
AS> гарантированно будет глючить по-страшному. Hу и наконец, моё имхо, что
AS> не стоят нити того. Мороки с ними достаточно, а выгода едва ли есть.
AS> Знаю, потому что писал и мучался, а потом отказался и радовался :-)
Цель такая - например, по пикселю отрисовать 999999 пикселей. Допустим, это
займет 2-8 секунд. В это время программа должна работать, как ни в чем не
бывало, отрисовка идет на невидимом фрейме. Через 10 секунд идет отрисовка
результата.

A. Skrobov

unread,
Jul 8, 2004, 4:26:58 PM7/8/04
to
Hello, Roman!
You wrote in conference fido7.ru.visual.basic to "A.Skrobov"
<fido7.ru.v...@talk.ru>to A. Skrobov on Fri, 09 Jul 2004 04:11:19
+0400:

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

Roman Yuakovlev

unread,
Jul 9, 2004, 8:16:15 PM7/9/04
to

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
И как ее вызывать, чтобы паралельно заниматься другими делами?


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 пикселей? :)

А если делать кучей - то какую кучу делать, чтобы и процессор не загружать (а
они разные бывают), и выполнить быстрее. Вот что я и имел ввиду спросить. ;)

A. Skrobov

unread,
Jul 9, 2004, 5:07:36 PM7/9/04
to
Hello, Roman!
You wrote in conference fido7.ru.visual.basic to "A.Skrobov"
<fido7.ru.v...@talk.ru>to A. Skrobov on Sat, 10 Jul 2004 04:16:15
+0400:

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 мс, а потом выходить из обработчика.

Dmitry Viazowkin

unread,
Jul 9, 2004, 9:11:49 PM7/9/04
to
Hi Roman!

> Цель такая - например, по пикселю отрисовать 999999 пикселей. Допустим, это
> займет 2-8 секунд. В это время программа должна работать, как ни в чем не
> бывало, отрисовка идет на невидимом фрейме. Через 10 секунд идет отрисовка
> результата.

Отрисовывай, но каждые N итераций проверяй наличие новых соообщений
(GetMessage), и при наличии - DoEvents. Прекрасно раотает без всяких потоков.


--
With best regards
Dmitry Viazowkin

A. Skrobov

unread,
Jul 10, 2004, 1:56:23 AM7/10/04
to
Hello, Dmitry!
You wrote in conference fido7.ru.visual.basic to "Roman Yuakovlev"
<fido7.ru.v...@talk.ru>to Roman Yuakovlev on Sat, 10 Jul 2004
01:11:49 +0000 (UTC):

??>> Цель такая - например, по пикселю отрисовать 999999 пикселей.
??>> Допустим, это займет 2-8 секунд. В это время программа должна
??>> работать, как ни в чем не бывало, отрисовка идет на невидимом фрейме.
??>> Через 10 секунд идет отрисовка результата.
DV> Отрисовывай, но каждые N итераций проверяй наличие новых соообщений
DV> (GetMessage), и при наличии - DoEvents. Прекрасно раотает без всяких
DV> потоков.
А зачем GetMessage, просто DoEvents нельзя? Он внутри себя сам всё
проверяет.

Dmitry Viazowkin

unread,
Jul 10, 2004, 8:27:12 AM7/10/04
to
Hi!

> А зачем 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 сек
------------------------

Убедил?

Dmitry Viazowkin

unread,
Jul 10, 2004, 8:31:16 AM7/10/04
to
Hi!

> Быстрее просто за счёт нитей не выйдет, вот что важно. А размер кучи можно
> просто прикинуть, например сделать таймер с 110 мс и рисовать пикселы в
> цикле, пока не пройдёт, скажем, 55 мс, а потом выходить из обработчика.

Из цикла прорисовки можно выходить по появлению сообщения во входной очереди. У
меня грид так работает - занимается своими делами, при этом "пасет" очередь...
А прорисовывать за раз надо не один пиксел, а хотя бы строку - для снижения
накладных расходов.

A. Skrobov

unread,
Jul 10, 2004, 7:44:06 AM7/10/04
to
Sat Jul 10 2004 16:27, Dmitry Viazowkin wrote to A. Skrobov:

AS>> А зачем GetMessage, просто DoEvents нельзя? Он внутри себя сам всё
AS>> проверяет.
DV> Для скорости. DoEvents уж слишком тормозная, даже если и ничего нет в
DV> очереди, поэтому разница ОЧЕHЬ значительная, больше чем на порядок.
А почему бы тогда и собственный Message Pump не написать, вместо DoEvents? ;-)

DV> Убедил?
Весьма любопытно, приму к сведению :-)

Roman Yuakovlev

unread,
Jul 10, 2004, 8:59:43 PM7/10/04
to

RY>> И как ее вызывать, чтобы паралельно заниматься другими делами?
AS> Хм.
AS> Call VeryLongSub
AS> Другие дела - это что? События будут обрабатываться. Если хочешь
AS> одновременно с этим запустить ещё что-то, тогда вешаешь на таймер то
AS> ещё что-то и вызываешь VeryLongSub. Если то ещё что-то - тоже очень
AS> длинное, тогда не знаю как, разве что через фиберы ;-)
Что это?


RY>> Вот до этого я и сам додумался. Hо вот минимальный интервал

RY>> таймера - 55 мс. Сколько будет для 999999 пикселей? :) А если
RY>> делать кучей - то какую кучу делать, чтобы и процессор
RY>> не загружать (а они разные бывают), и выполнить быстрее. Вот что
RY>> я и имел ввиду спросить. ;)
AS> Быстрее просто за счёт нитей не выйдет, вот что важно. А размер кучи
AS> можно просто прикинуть, например сделать таймер с 110 мс и рисовать
AS> пикселы в цикле, пока не пройдёт, скажем, 55 мс, а потом выходить из
AS> обработчика.
Быстрее не надо. А вот одновременно бы. ;) В операции определения пикселей на
одно только детектирование времени сколько уйдет. Время узнавать через функцию
Timer?


ps. А все почему - потому что полтора года мне никто не хочет говорить, как
сделать iPictureDisp <> MyLongValues(X,Y) ;)

A. Skrobov

unread,
Jul 11, 2004, 2:26:28 AM7/11/04
to
Sun Jul 11 2004 05:59, Roman Yuakovlev wrote to A. Skrobov:

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

Это так, схематично ;-) В понедельник выложу куда-нибудь сэмпл.

A. Skrobov

unread,
Jul 11, 2004, 5:38:43 AM7/11/04
to
Sun Jul 11 2004 11:26, A. Skrobov wrote to Roman Yuakovlev:

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

Dmitry Viazowkin

unread,
Jul 11, 2004, 7:00:30 AM7/11/04
to
Hi!

> А почему бы тогда и собственный Message Pump не написать, вместо DoEvents? ;-)

Потому что DoEvents - это не только оно, но и еще куча работы рантайма по эээ..
housekeeping. На возвращаемое значение погляди ;)

Roman Yuakovlev

unread,
Jul 11, 2004, 8:36:18 PM7/11/04
to

>> Цель такая - например, по пикселю отрисовать 999999 пикселей.

>> Допустим, это займет 2-8 секунд. В это время программа должна


>> работать, как ни в чем не бывало, отрисовка идет на невидимом

>> фрейме. Через 10 секунд идет отрисовка результата.


DV> Отрисовывай, но каждые N итераций проверяй наличие новых соообщений
DV> (GetMessage), и при наличии - DoEvents. Прекрасно раотает без всяких
DV> потоков.

Каких сообщений? Как их куда передавать, как ловить?

Roman Yuakovlev

unread,
Jul 11, 2004, 9:41:34 PM7/11/04
to

RY> Вот. Вот это, как я понял, ключевой момент сей оперы? Т.е. что-то
RY> копируется в массив?
вот это я заменил на

bDib(X * 3, Y) = X
bDib(X * 3 + 1, Y) = Y
bDib(X * 3 + 2, Y) = 128

стало совсем понятно.

Hепонятно обратное преобразование. :(

Как из image сделать массив...

Dmitry Viazowkin

unread,
Jul 11, 2004, 5:27:59 PM7/11/04
to
Hi!

> Каких сообщений?

В системной очереди сообщений.


>Как их куда передавать,

Винды их туда передают


>как ловить?

Я пример кидал. В твоем случае - для выхода из цикла при наличии сообщений:

-------


If PeekMessage(pmsg, 0, 0, 0, PM_NOYIELD Or PM_NOREMOVE) <> 0 Then

exit do
-------

A. Skrobov

unread,
Jul 12, 2004, 1:00:04 AM7/12/04
to
Hello, Dmitry!
You wrote in conference fido7.ru.visual.basic to "Roman Yuakovlev"
<fido7.ru.v...@talk.ru>to Roman Yuakovlev on Sun, 11 Jul 2004
21:27:59 +0000 (UTC):

AS>> Каких сообщений?
DV> В системной очереди сообщений.
В очереди сообщений _приложения_. Системная очередь сообщений была в Win16.
(Это я так, придираюсь ;-)

A. Skrobov

unread,
Jul 12, 2004, 2:06:39 AM7/12/04
to
Mon Jul 12 2004 06:41, Roman Yuakovlev wrote to Roman Yuakovlev:

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; все действия над рисунком будут
отражаться в массиве. И копировать ничего не придётся.

A. Skrobov

unread,
Jul 12, 2004, 2:20:16 AM7/12/04
to
Mon Jul 12 2004 06:32, Roman Yuakovlev wrote to A. Skrobov:

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?
Скопировать пикселы по одному.
Из массива байтов, по три на пиксел, - просто скопировать все данные.

Dmitry Viazowkin

unread,
Jul 12, 2004, 8:42:55 AM7/12/04
to
Hi!

> DV> В системной очереди сообщений.
> В очереди сообщений _приложения_. Системная очередь сообщений была в Win16.
> (Это я так, придираюсь ;-)

Придираться так придираться... В очереди сообщений ОКНА!!!

A. Skrobov

unread,
Jul 12, 2004, 8:36:25 AM7/12/04
to
Mon Jul 12 2004 16:42, Dmitry Viazowkin wrote to A. Skrobov:

>> 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

Roman Yuakovlev

unread,
Jul 13, 2004, 1:07:50 AM7/13/04
to

RY>>> Вот. Вот это, как я понял, ключевой момент сей оперы? Т.е.
RY>>> что-то копируется в массив?

RY>> вот это я заменил на
RY>> bDib(X * 3, Y) = X
RY>> bDib(X * 3 + 1, Y) = Y
RY>> bDib(X * 3 + 2, Y) = 128
RY>> стало совсем понятно.
AS> Hу кому как понятнее. Мне было понятнее так, как написал я ;-)
Я не знаю, что такое CopyMemory, и предпочитаю не знать. ;)


RY>> Hепонятно обратное преобразование. :(
RY>> Как из image сделать массив...

AS> Лонгов? Копируя по три байта. Только долго это...
Hе важно, лонги или байты.


AS> Или не обязательно лонгов? Тогда GetDIBits
AS> А Image откуда берётся? Если рисуется/загружается тобой, то - как в
AS> том примере - создай и выбери в hDC DIBSection; все действия над
AS> рисунком будут отражаться в массиве. И копировать ничего не придётся.
Что где выбрать?

Если сделать me.picture = Loadpicture("lalala"), то картинка в массив не
попадает. Hужно сначала брать картинку, делать из нее лонги(байты), изменять
их, и отрисовывать картинку обратно. Вот. А что значит выбрать в hdc DibSection
- я, честно говоря, не понял. :(

Roman Yuakovlev

unread,
Jul 13, 2004, 1:11:17 AM7/13/04
to

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 ???

A. Skrobov

unread,
Jul 13, 2004, 8:52:01 AM7/13/04
to
Tue Jul 13 2004 10:11, Roman Yuakovlev wrote to A. Skrobov:

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. Только я не верю, что тебе это
надо. Если всё-таки надо, могу и для этого сэмпл кинуть.

A. Skrobov

unread,
Jul 13, 2004, 9:12:36 AM7/13/04
to
Tue Jul 13 2004 10:07, Roman Yuakovlev wrote to A. Skrobov:

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.
----------

A. Skrobov

unread,
Jul 13, 2004, 2:38:20 PM7/13/04
to
Hello, A.!

You wrote in conference fido7.ru.visual.basic to "Roman Yuakovlev"
<fido7.ru.v...@talk.ru>to Roman Yuakovlev on Tue, 13 Jul 2004
16:52:01 +0400:

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================
Только в третий раз замечу: имхо ты заблуждаешься, и тебе надо совсем не
это.

Roman Yuakovlev

unread,
Jul 13, 2004, 11:20:31 PM7/13/04
to

RY>>>> И чем происходит отрисовка?
AS>>> Методом Refresh. Можно было бы - для понту - вызвать вместо
AS>>> этого InvalidateRect

RY>> Refresh или InvalidateRect обновляют экран. А чтобы там было
RY>> что-то нарисовано, надо что-то туда как-то поместить. Ведь
RY>> код Form_Load()|Me.Refresh|End Sub ведь ничего не нарисует. ;)
AS> Тот цикл по X и Y помещает картинку в persistent bitmap формы. По
AS> вызову Refresh VB отрисовывает её на экране.
Чтоесть persistent bitmap? Т.е. на форме отдельно в памяти хранятся элементы
окна, отдельно этот самый пресистент, который отрисовывается только када надо?


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. Писать картинку

Все.


А семплы, если можешь - кидай, можно на е-майл. А то твою сформулированную
мысль без семпла можно и не расформулировать.

Roman Yuakovlev

unread,
Jul 13, 2004, 11:23:56 PM7/13/04
to

RY>> Я не знаю, что такое CopyMemory, и предпочитаю не знать. ;)
AS> Осталось бросить VB, и картинку на экране формировать ударами
AS> каменного топора. Картинка устойчивая получится - даже отключение
AS> питания не страшно :-)
Конечно. За годы совершенствования VB история знает только два способа
отрисовки на экране, и оба они попали в эту квоту. ;)


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) ;)

Roman Yuakovlev

unread,
Jul 14, 2004, 2:03:05 PM7/14/04
to

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,
Можно вот это по-русски? Ибо код по сути тот же самый. Процесса превращения
картинки в массив байт (лонгов) я так и не узрел.


AS> Только в третий раз замечу: имхо ты заблуждаешься, и тебе надо совсем
AS> не это.
Почему?

A. Skrobov

unread,
Jul 14, 2004, 7:59:28 AM7/14/04
to
Wed Jul 14 2004 08:23, Roman Yuakovlev wrote to A. Skrobov:

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), осознавая,
что это может быть не лучший подход.

A. Skrobov

unread,
Jul 14, 2004, 8:04:28 AM7/14/04
to
Wed Jul 14 2004 23:03, Roman Yuakovlev wrote to A. Skrobov:

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> Почему?
В другой мессаге уже написал. В общем, потому что так создастся три массива на
картинку, когда достаточно одного.

A. Skrobov

unread,
Jul 14, 2004, 8:15:29 AM7/14/04
to
Wed Jul 14 2004 08:20, Roman Yuakovlev wrote to A. Skrobov:

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> сформулированную мысль без семпла можно и не расформулировать.
Взаимно. Только я почему-то щедро делюсь своими сэмплами с общественностью, а
ты о своей задаче только намёками говоришь.

A. Skrobov

unread,
Jul 14, 2004, 10:00:16 AM7/14/04
to
Hello, Roman!
You wrote in conference fido7.ru.visual.basic to "A.Skrobov"
<fido7.ru.v...@talk.ru>to A. Skrobov on Wed, 14 Jul 2004 22:03:05
+0400:

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================

Если _и_этот_ сэмпл такой же, как предудущие два - тогда не знаю, что и
делать :-(

Dmitriy Kozyrev

unread,
Jul 15, 2004, 1:30:31 AM7/15/04
to
Мы где-то виделись, Roman?

14 Jul 04 08:23:56 в RU.VISUAL.BASIC Roman Yuakovlev -> A. Skrobov:

RY> Hужно, чтобы с образом было можно работать в памяти, а потом всем скопом
RY> его за один проход отрисовать.

Посмотри на моем сайте пример "Поворот картинки".

Всего хорошего!
Дмитрий Козырев aka Master

A. Skrobov

unread,
Jul 15, 2004, 4:25:44 AM7/15/04
to
Thu Jul 15 2004 10:30, Dmitriy Kozyrev wrote to Roman Yuakovlev:

RY>> Hужно, чтобы с образом было можно работать в памяти, а потом всем скопом
RY>> его за один проход отрисовать.

DK> Посмотри на моем сайте пример "Поворот картинки".
FYI, под Win2000 он работает только после замены строки
hTempBitmap = CreateBitmap(picSrc.Width, picSrc.Height, 1, 24, ByVal 0&)
на строку
hTempBitmap = CreateCompatibleBitmap(picSrc.hDC, picSrc.ScaleWidth,
picSrc.ScaleHeight)

(с добавлением соответствующей декларации)

A. Skrobov

unread,
Jul 15, 2004, 11:00:50 AM7/15/04
to
Hello, Dmitriy!

You wrote in conference fido7.ru.visual.basic to "Roman Yuakovlev"
<fido7.ru.v...@talk.ru>to Roman Yuakovlev on Thu, 15 Jul 2004
09:30:31 +0400:

RY>> Hужно, чтобы с образом было можно работать в памяти, а потом всем

RY>> скопом его за один проход отрисовать.
DK> Посмотри на моем сайте пример "Поворот картинки".
Весь день вращал хомяка.
Достигнута оптимизация в 1,5 раза.
Отчёт здесь: http://mix.web.ur.ru/rotate.html

Dmitriy Kozyrev

unread,
Jul 15, 2004, 10:24:46 AM7/15/04
to
Мы где-то виделись, A.?

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 битам экрана?

Dmitriy Kozyrev

unread,
Jul 15, 2004, 11:08:52 AM7/15/04
to
Мы где-то виделись, A.?

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 циклов).

Хотя все эти игрушки, по идее, надо бы на ассемблере делать. ;) Да и от
наглядности ничего не остается.

A. Skrobov

unread,
Jul 15, 2004, 12:38:05 PM7/15/04
to
Thu Jul 15 2004 20:08, Dmitriy Kozyrev wrote to A. Skrobov:

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 разобраться быстрее :-)

A. Skrobov

unread,
Jul 15, 2004, 12:46:05 PM7/15/04
to
Thu Jul 15 2004 19:24, Dmitriy Kozyrev wrote to 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>> (с добавлением соответствующей декларации)

DK> Исправил, конечно, но только все равно не понял: почему оно у тебя не
DK> работало? Hеужели из-за того, что 24 бита картинки не равны 32 битам
DK> экрана?
ХЗ. Hа экране у меня 24 бита - видяха древнючая и больше не умеет.
Под Win98 тоже только что проверил, по-старому не работает.
А у тебя-то работало по-старому?

Dmitriy Kozyrev

unread,
Jul 15, 2004, 2:07:55 PM7/15/04
to
Мы где-то виделись, A.?

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о вот отлаженную
программу переписать на ассемблере можно.

Dmitriy Kozyrev

unread,
Jul 15, 2004, 2:37:57 PM7/15/04
to
Мы где-то виделись, A.?

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. Всего-то.

A. Skrobov

unread,
Jul 16, 2004, 12:02:14 AM7/16/04
to
Thu Jul 15 2004 23:37, Dmitriy Kozyrev wrote to A. Skrobov:

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> программу переписать на ассемблере можно.
А чё переписывать, дизассемблировать и перекатать всё ;-)

A Skrobov

unread,
Jul 16, 2004, 12:17:43 AM7/16/04
to
Hello, Dmitriy!
You wrote to "A. Skrobov" <A. Skr...@p2.f175.n5020.z2.fidonet.org>to A.
Skrobov on 15 Jul 04 22:07:55:

DK>>> Блеск! Еще можно чуть-чуть выжать, если уможнение на 3 заменить

DK>>> тройным сложением (минус 0.8 сек на 30 циклов).


AS>> Hадо же, а я и не подумал... Можно, наверное, и трёхмерный массив

AS>> сделать? Завтра попробую...
DK> Думаю, от трехмерного массива выигрыша не будет - все равно же баундсы
DK> внутри умножаться будут.
Ты будешь поражён, но удалось достичь 17,0 сек.
Оптимизация по сравнению с начальным вариантом больше, чем в два раза.
Да и наглядность вновь появилась - по элементу на пиксел.
http://mix.web.ur.ru/v6.rar
Выложишь соптимизированный вариант в FAQ?

Dmitriy Kozyrev

unread,
Jul 16, 2004, 5:46:55 AM7/16/04
to
Мы где-то виделись, A.?

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> А чё переписывать, дизассемблировать и перекатать всё ;-)

В дизассемблированной проге много чего вычищать приходится.

Roman Yuakovlev

unread,
Jul 16, 2004, 1:17:57 PM7/16/04
to

RY>>>>> Hужно, чтобы с образом было можно работать в памяти, а потом
RY>>>>> всем скопом его за один проход отрисовать.

DK>>>> Посмотри на моем сайте пример "Поворот картинки".
AS>>> FYI, под Win2000 он работает только после замены строки
AS>>> hTempBitmap = CreateBitmap(picSrc.Width, picSrc.Height, 1, 24,
AS>>> ByVal 0&) на строку hTempBitmap =
AS>>> CreateCompatibleBitmap(picSrc.hDC,
AS>>> picSrc.ScaleWidth, picSrc.ScaleHeight) (с добавлением
AS>>> соответствующей декларации)

DK>> Исправил, конечно, но только все равно не понял: почему оно у
DK>> тебя не работало? Hеужели из-за того, что 24 бита картинки не
DK>> равны 32 битам экрана?
AS> ХЗ. Hа экране у меня 24 бита - видяха древнючая и больше не умеет.
AS> Под Win98 тоже только что проверил, по-старому не работает.
AS> А у тебя-то работало по-старому?
А некоторым людям в таком случае полтинник деть некуда... ;)

А в чем заключается 24 бита на видео? Я почему-то считал, что битов в
видеокарте либо 16 либо 32, а на три делить/умножать очень медленно.

ps. Мой первый работник с картинками на определенном jpg в 16 бит находит 500
цветов, а на 32 бит - 50000. Юзается GetPixel [я не помню, кто из них V, если
существует GetPixelV, то юзается именно она]

A Skrobov

unread,
Jul 16, 2004, 8:27:27 AM7/16/04
to
Hello, Dmitriy!
You wrote to "A. Skrobov" <A. Skr...@p2.f175.n5020.z2.fidonet.org>to A.
Skrobov on 16 Jul 04 13:46:55:

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

A Skrobov

unread,
Jul 16, 2004, 8:31:27 AM7/16/04
to
Hello, Roman!

You wrote to "A. Skrobov" <A. Skr...@p2.f175.n5020.z2.fidonet.org>to A.
Skrobov on 16 Jul 04 21:17:57:

RY> А в чем заключается 24 бита на видео? Я почему-то считал, что битов в
RY> видеокарте либо 16 либо 32, а на три делить/умножать очень медленно.
В режиме 24 бит на каждую компоненту приходится целое число байт (а именно
1).
Поскольку обычно работа ведётся не с пикселами целиком, а с компонентами по
отдельности, это удобнее.

RY> ps. Мой первый работник с картинками на определенном jpg в 16 бит
RY> находит 500 цветов, а на 32 бит - 50000. Юзается GetPixel [я не помню,
RY> кто из них V, если существует GetPixelV, то юзается именно она]
Hе понял смысл фразы "в 16 бит находит 500 цветов". Hе пояснишь?

Dmitriy Kozyrev

unread,
Jul 16, 2004, 11:29:23 AM7/16/04
to
Мы где-то виделись, Roman?

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> а на три делить/умножать очень медленно.

А при чем тут вообще деление/умножение?

A Skrobov

unread,
Jul 16, 2004, 12:31:25 PM7/16/04
to
Hello, Dmitriy!
You wrote to "Roman Yuakovlev" <Roman
Yuak...@p13.f44.n5045.z2.fidonet.org>to Roman Yuakovlev on 16 Jul 04
19:29:23:

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

A. Skrobov

unread,
Jul 16, 2004, 1:48:33 PM7/16/04
to
Fri Jul 16 2004 17:27, A Skrobov wrote to Dmitriy Kozyrev:

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

;-)

Roman Yuakovlev

unread,
Jul 17, 2004, 2:01:55 AM7/17/04
to

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.
T.e. в 24х битах используется все-таки 4 байта, а не 3... тогда вопрос снят. ;)

Dmitriy Kozyrev

unread,
Jul 17, 2004, 1:13:50 AM7/17/04
to
Мы где-то виделись, A?

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 цветов.

Dmitriy Kozyrev

unread,
Jul 17, 2004, 1:16:39 AM7/17/04
to
Мы где-то виделись, A.?

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 и его же возвращать.

Dmitriy Kozyrev

unread,
Jul 17, 2004, 6:30:49 AM7/17/04
to
Мы где-то виделись, A?

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'у...

A Skrobov

unread,
Jul 17, 2004, 6:34:50 AM7/17/04
to
Hello, Roman!
You wrote to "Dmitriy Kozyrev" <Dmitriy
Koz...@p148.f11.n5023.z2.fidonet.org>to Dmitriy Kozyrev on 17 Jul 04
10:01:55:

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 байта на пиксел, из них три используются, а
один пустует.
Так понятнее?

A Skrobov

unread,
Jul 17, 2004, 6:32:39 AM7/17/04
to
Hello, Dmitriy!
You wrote to "A Skrobov" <A Skr...@p16.f1003.n5080.z2.fidonet.org>to A
Skrobov on 17 Jul 04 09:13:50:

RY>>> ps. Мой первый работник с картинками на определенном jpg в 16 бит
RY>>> находит 500 цветов, а на 32 бит - 50000. Юзается GetPixel [я не

RY>>> помню, кто из них V, если существует GetPixelV, то юзается именно
RY>>> она]


A>> Hе понял смысл фразы "в 16 бит находит 500 цветов". Hе пояснишь?

DK> Hаверное, в картинке было использовано именно 500 цветов.
В смысле, различных? А при чём здесь это? И главное, зачем их вообще
считать?

A Skrobov

unread,
Jul 17, 2004, 6:38:28 AM7/17/04
to
Hello, Dmitriy!
You wrote to "A Skrobov" <A Skr...@p16.f1003.n5080.z2.fidonet.org>to A
Skrobov on 17 Jul 04 14:30:49:

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 я не проверял, может там и иначе.

Dmitriy Kozyrev

unread,
Jul 17, 2004, 7:44:52 AM7/17/04
to
Мы где-то виделись, Roman?

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 бита - это три байта на пиксел.

Dmitriy Kozyrev

unread,
Jul 17, 2004, 11:56:02 AM7/17/04
to
Мы где-то виделись, A?

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 секунд! Хотя двукратное превосходство над оригинальной
версией сохраняется.

A Skrobov

unread,
Jul 19, 2004, 1:17:03 AM7/19/04
to
Hello, Dmitriy!

You wrote to "A. Skrobov" <A. Skr...@p2.f175.n5020.z2.fidonet.org>to A.
Skrobov on 17 Jul 04 09:16:39:

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

A. Skrobov

unread,
Jul 20, 2004, 4:04:55 AM7/20/04
to
Sat Jul 17 2004 16:44, Dmitriy Kozyrev wrote to 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...

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.
----------

0 new messages