Перевод с VB6 на NET, несколько вопросов.

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

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

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

Сообщение Nord777 » 30.05.2007 (Ср) 20:05

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

Нет. Хендл относится к контексту устройства, а массив к битмэпу (никакой взаимосвязи).
Представь ситуацию:

Form1.BackgroundImage = Bmp
Сборщик мусора в какое то время перемещает массив.
Ты делаешь какое либо действие, в результате которого форме посылается Refresh. Форма пытается обратиться к битмэпу по несуществующему адресу. Результат - исключение памяти.
Если ты не получаешь это исключение в данный момент, то не надейся, что ты не получишь его в будущем. Так что фиксировать массив в таких случаях крайне желательно.


Код: Выделить всё
SetDIBitsToDevice(Graphics.FromHwnd(Me.Handle.ToInt32).GetHdc, ....

так делать нежелательно.
На каждый вызов GetHdc надо делать вызов ReleaseHdc

2. Нужно ли заново получать хендл при изменении размера массива (формы)?

нет.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 03.06.2007 (Вс) 15:40

Nord777
Так ведь SetDIBits вообще можно выводить из массива, никак с битмэпом не связанного. Я просто из произвольного массива вывожу графику на форму. Что-то я не вник в смысл необходимости связывать при этом массив с битмэпом.
Ты делаешь какое либо действие, в результате которого форме посылается Refresh

Ну и что? Если я просто создал форму и вообще не делал никаких массивов и битмэпов, по Refresh не происходит никаких проблем. Так откуда они возьмутся, если я что-то нарисовал на форме при помощи SetDIBits?
И еще, никак не могу загрузить данные из битмэпа в массив, вообще минуя формы или PictureBoxы. GetDiBits дает нули, через GetPixel в цикле работает, но очень медленно. Не дашь примерчик, чтобы в модуле, вообще без всяких форм, создать битмэп, загрузить его FromFile, привести его к формату ARGB (видимо Clone, до сих пор у меня получилось). Дальше получить данные в свой массив, с которым можно работать.

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

Сообщение Nord777 » 03.06.2007 (Вс) 18:53

Так ведь SetDIBits вообще можно выводить из массива, никак с битмэпом не связанного. Я просто из произвольного массива вывожу графику на форму. Что-то я не вник в смысл необходимости связывать при этом массив с битмэпом.

В этом действительно нет необходимости. Просто иногда это бывает удобно. Например: Программе нужно выводить графику в смешанном режиме (т.е. рисовать сложные обьекты при помощи Graphics и иметь быстрый доступ к отдельным пикселям изображения). Представил? Я рисую на битмэпе нужное изображение и в коде пишу Ме.BackgroundImage = Bmp. При этом форма сама будет заботиться о перерисовке нужной части картинки (именно той, которая действительно нуждается в обновлении, а не все области).

создать битмэп, загрузить его FromFile, привести его к формату ARGB (видимо Clone, до сих пор у меня получилось). Дальше получить данные в свой массив, с которым можно работать.

Наверно как то так:

Код: Выделить всё
Imports System.Runtime.InteropServices

Public Class Form1
    Dim BmpArray(,) As Integer

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        'Исходное изображение 24bpp
        Dim BmpSource As Bitmap = Bitmap.FromFile("AnyFile24bpp.bmp")

        ReDim BmpArray(BmpSource.Width - 1, BmpSource.Height - 1)

        'Создать изображение-приёмник на 32bpp
        Dim BmpDest As New Bitmap(BmpSource.Width, BmpSource.Height, _
                BmpSource.Width * 4, _
                Imaging.PixelFormat.Format32bppArgb, _
                Marshal.UnsafeAddrOfPinnedArrayElement(BmpArray, 0))

        'Нарисуем на приёмеике исходное изображение
        Using G As Graphics = Graphics.FromImage(BmpDest)
            G.DrawImage(BmpSource, 0, 0)
        End Using

        'освободим ненужые обьекты
        BmpDest.Dispose()
        BmpSource.Dispose()

        ' В результате в массиве BmpArray(,) содержатся данные в формате 32bpp
    End Sub
End Class
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 06.06.2007 (Ср) 12:59

Nord777
Thanks! Работает.
Только пришлось использовать другой оверлоад для DrawImage, с явным указанием высоты и ширины, иначе, почему-то, картинка масштабируется (увеличивается) и, в результате, на приемник не лезет.
И еще, при загрузке из PNG файла с альфа каналом, в приемник попадает только альфа канал...

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

Сообщение Nord777 » 06.06.2007 (Ср) 21:14

С альфа каналом попробую на досуге разобраться. Есть одно предположение, но его надо проверить.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

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

Сообщение Nord777 » 08.06.2007 (Пт) 13:32

Только пришлось использовать другой оверлоад для DrawImage, с явным указанием высоты и ширины, иначе, почему-то, картинка масштабируется (увеличивается) и, в результате, на приемник не лезет

А это потому что у картинки не 96dpi, верно?

Зачем в png-файле ты используешь альфа-канал? Прозрачность работает и без него.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 09.06.2007 (Сб) 10:04

Nord777
"не 96dpi" - видимо так, не важно, главное теперь работает.
С PNG не совсем так, как я написал, в приемник попадает не только альфа, а и все остальные каналы, но уже умноженными на альфу, видимо так срабатывает DrawImage.
Зачем в png-файле ты используешь альфа-канал? Прозрачность работает и без него.

А полупрозрачность?

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

Сообщение Nord777 » 09.06.2007 (Сб) 11:16

и полупрозрачность тоже. (32bppARGB)
Можешь попробывать его на разном фоне.
Вложения
1.png
рисунок обрамлен черной рамкой.
На нем градиент от красного до прозрачного.
1.png (3.38 Кб) Просмотров: 4664
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 10.06.2007 (Вс) 8:55

Nord777
Да, если я его печатаю средствами NET, то все выглядит корректно, но если меня средства NET по разным причинам не устраивают (или я хочу не печатать, а сохранить данные в файл TGA), то мне нужно иметь неискаженные данные, какие они и находятся в BmpSrc, иначе бы оно правильно не отражалось. Но попытки перенести данные в массив с помощью DrawImage (а так же SetPixel(GetPixel(...)) вызывают автоматически просчет альфаканала (покомпонентное умножение всех цветовых каналов на альфу). То есть нужен какой-то более низкоуровневый метод.
Может у DrawImage есть какие-нибудь стили, или у битмэпа атрибуты, типа "не использовать альфа-канал"?

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

Сообщение Nord777 » 10.06.2007 (Вс) 9:57

Может у DrawImage есть какие-нибудь стили, или у битмэпа атрибуты, типа "не использовать альфа-канал"?

Такого к сожалению нет.
Но ничто не мешает тебе анализировать полученный массив.
Проходишь весь массив, веделяешь из интЕгера(ARGB) прозрачную составляющую(A) и записываешь это значение в другой массив (твой альфа-канал). Примерно как то так, если я конечно правильно тебя понял.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 10.06.2007 (Вс) 15:19

Nord777
Как раз с альфаканалом все в порядке, искажен RGB канал, в тех местах, где альфа равна нулю, и RGB полностью потерян.

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

Сообщение Nord777 » 10.06.2007 (Вс) 20:11

Скинь мне небольшую картинку с альфа-каналом. Посмотрим.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 11.06.2007 (Пн) 13:40

Вот PNG и четыре GIF-а, показывающих содержимое цветовых каналов. Мне желательно получить это же.

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

Сообщение Nord777 » 11.06.2007 (Пн) 21:58

Mikle, весь прикол в том, что в PNG-файлах ты не можешь сохранять альфа-каналы. Пробовал в фотошопе. Да, ты можешь смело создать альфа-канал, но при сохранении в .png он вырезается. После сохранения такого файла, попробуй его снова открыть - альфа канала ты не увидишь. Из понимаемых GDI+ форматов только .tif может сохранять альфу.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

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

Сообщение Nord777 » 12.06.2007 (Вт) 0:34

Пока сам не попробовал - не понял что за проблема.
Код не комментировал, разберешься.
Вложения
RGBA.rar
Проект RGBA
(24.24 Кб) Скачиваний: 195
Screenshot for ARGB.png
Скриншот
Screenshot for ARGB.png (26.79 Кб) Просмотров: 4549
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 12.06.2007 (Вт) 8:55

Nord777
Это проблемы современных фотошопов, для работы с PNG я пользуюсь четвертым, а с помощью DX8 это прекрасно читалось, но не импортировать же DX8 в NET приложение ради чтения PNG.
Пример качаю.

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

Сообщение Nord777 » 12.06.2007 (Вт) 11:40

Я пользуюсь девятым шопом. Соответственно альфа-канала в твоём файле я не увидел. Как поведет себя прога на .png файле c альфа-каналом не знаю.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 20.06.2007 (Ср) 12:49

Nord777
Спасибо, все вышло отлично.
Теперь, если я еще не надоел :) , еще вопросик. Как писать в битмэп произвольный текст? Graphics.DrawString я, естественно, нашел, но не могу выбрать произвольный цвет - там только набор готовых цветов. Еще хотелось бы сглаживать шрифты, как в VB6 Print выводит текст с учетом метода сглаживания, выбранного в панели управления. Если можно не использовать метод из панели управления, а задавать непосредственно - еще лучше.

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Сообщение Viper » 20.06.2007 (Ср) 12:55

Насчет цветов - метод Color.FromArgb
Насчет сглаживания - вроде есть метод в классе Graphics соответствующий
Весь мир матрица, а мы в нем потоки байтов!

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

Сообщение Nord777 » 20.06.2007 (Ср) 13:06

Насчет сглаживания - вроде есть метод в классе Graphics соответствующий

Свойство. TextRenderingHint.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 22.06.2007 (Пт) 9:59

Вот код:
Код: Выделить всё
Imports System.Runtime.InteropServices

Public Class Form1

  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    pic.Image = New Bitmap(pic.Size.Width, pic.Size.Height, Imaging.PixelFormat.Format32bppArgb)

    Dim BackColor As System.Drawing.Color = Color.FromArgb(&HFF405060)
    Dim ForeColor As System.Drawing.Color = Color.FromArgb(&HFFD0C0A0)

    Using G As Graphics = Graphics.FromImage(pic.Image)
      G.Clear(BackColor)
      G.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
      G.DrawString("testTEST", Button1.Font, Brushes.White, 0, 0)
    End Using
  End Sub

End Class

pic - это PictureBox на форме. TextRenderingHint свое дело делает, но как вместо Brushes.White применить ForeColor, я так и не понял.

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

Сообщение tyomitch » 22.06.2007 (Пт) 10:34

New SolidBrush(ForeColor)
Изображение

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 24.06.2007 (Вс) 9:51

Спасибо, кто бы мог подумать, что оно так называется :)
Я, все-таки, закончил перевод софт движка, а по ходу дела проникся (начал проникаться) идеей нового для меня языка. В результате стал переделывать с учетом того, чего мне не позволял сделать VB6. В классе спрайта так и осталось применение VarPtr, но только непосредственно перед вызовом ф-ций из DLL (не все ли равно, передавать "ByVal VarPtr(x)" или "ByRef x" в ассемблерную DLL? Или я не прав?). Перемещение класса Sprite внутрь модуля SR2D позволило сделать Private (скрыть от пользователя) некоторые, ранее не скрытые элементы, но...

Осталась нескрытой ф-ция DataPtr потому, что екземпляры класса Sprite вызывают ее при взаимном "общении". Вопрос, можно ли ее тоже как-нибудь скрыть?
Один из переведенных примеров, чтобы было понятнее, можно взять здесь:
http://tuapse-mikle.narod.ru/PAK.rar
Размер - 193 кБ.

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

Сообщение Nord777 » 24.06.2007 (Вс) 12:16

Mikle похоже сказались бессонные ночи за проектом :D
Функция DataPtr у тебя вызывается только из модуля (ты же ведь перенес класс Sprite). Теперь ничто не мешает тебе обьявить её как Private.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 25.06.2007 (Пн) 10:02

Nord777
Оп-па.
В NET Private методы класса видятся из ДРУГОГО экземпляра этого класса, на VB6 такого не было, я даже не подумал Private попробовать.

Пред.

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

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

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

    TopList