Всё. Нашел косяк в init()
bi32BitInfo.bmiHeader.biHeight = -meHeight;
Вот тут минус пропустил.
Я еще бингу описал все это, он говорит мол, может у вас meHeight отрицательный??
Я проверил, нет положительный... а он ДОЛЖЕН быть отрицательный, оказывается.
У меня собственно и были подозрения, что где-то какой-то минус закрался или типа того, оказалось наоборот))
SilentPrayerCG
> может у вас meHeight отрицательный?
Я тоже подумал сразу об этом, но не стал писать, думал, как можно минус при конверсии из 32-х в 64 бита потерять.
Этот минус сделан для файлов, в которых применяется обратный порядок строк.
Хорошо, значит, проблема решена.
Mikle
Странно тогда, зеркалится даже созданный спрайт, а не из файла.
Ну я DPBM проверю еще как работает, да скину проект сюда.
Может еще попробую потом PTR на nint переделать.
вот это еще место странное
PTR = GCH.AddrOfPinnedObject().ToInt64();
можно тоинт64 убрать и работает. а если сделать каст в nint то скажет каст не нужен
хотя там где скан0 требовал nint пришлось кастить
В общем вот рабочий DBPM на х64 C#
https://mega.nz/file/WfJSFJ5Z#82XZOA6MSKTrJMh412vo_io-itS9OH6mXRnaUkvLsvw
FPS вроде такой-же или примерно такой-же как в VB.net
из проблем пока только Nullable Context
так как это новый какой-то подход, который включен по дефолту
он подчеркивает спрайты, которые зануляются в коде
и подчеркивает вот это ((Graphics)hDC.Wrapper).ReleaseHdc();
причем, я сейчас понял, что все что я кодил с ср2д) я этого не делал, я не занулял спрайты, и я не релизил хдц через какой-то лютый каст
про спрайты он гундит, потому что они объявлены не нуллабл и зануляются
причем если я объявлю их нулабл, то тогда в тех местах где они куда-то передаются, он начинает гундеть что "возможно этот объект нулл"
я так понимаю, они там везде тогда должны быть нуллабл, по всему коду
коду спрайта в том числе
в общем я тут как-бы всё, я не могу понять как нормально должно быть тогда, в вб забили болт на этот концепт его там нет
Mikle
если ты будешь делать новую версию на новом c# обрати внимание как теперь надо это делать
ps
на самом деле надо еще проверить работоспособность всего остального)) не исключено что гдето еще ошибки есть.
Пример скачал.
Как время выпадет, проверю на старом C# 2008.
SilentPrayerCG
> я не занулял спрайты, и я не релизил хдц через какой-то лютый каст
Спрайты ладно, по закрытию программы всё равно уничтожатся, а вот hDC релизить нужно (не в VB6, конечно, там и это не обязательно).
Mikle
А что будет если НЕ зарелизить?
Мне казалось если процесс мертв то он как-бы всё уже.
Просто девайс то это форма, а процесса уже закрыт, какая разница? Oo
На старом сишарпе этого нуллабл контекста нет. Но я обошел вроде эту проблему в классе спрайта.
А вот как я заткнул это дело сейчас в коде самой программы
релизилку заткнул так
(hDC.Wrapper as Graphics)!.ReleaseHdc();
кое как, методом тыка и подсказкой от бинга
! - по сути тупо игнорит варнинг, как я понял.
наверное его можно использовать и с спрайтами
но тут я воспользовался какой-то другой шнягой
SprNorm ?? new Sprite(0,0)
из того что я понял, если спрайт окажется нулл, то вместо него будет использоваться новый спрайт (поидее туда можно любой сделать, я написал 0 0 ну это тупо затычка тоже)
hDC я кстати не смог нулабл сделать, я его зарелизить так не смог.
Mikle привет.
Если я сделаю простой класс у которого будет проперти 1 спрайт ср2дшный, и несколько каких-нибудь интов или типа того.
Мне как-то надо ему какой-то деструктор прописывать, чтобы он занулял этот спрайт в конце или что-то такое? Или когда мой класс перестанет быть, сборщик мусора сам потом очистит спрайт который в пропертях у этого класса был?
Хотелось бы конечно вообще приделать iDisposable и к самому спрайту. Я пытался, но меня сбивает с толку, то что если я создам битмап, и сделаю dispose() то потом я не могу на него сослаться, он какбы null становится. А если я спрайту прикручиваю iDisposable интерфейс, всё по примеру, делаю ему GHC.free, он как-бы не становится нуллом. Я что-то не проверил, перестает ли он вообще работать после моего dispose, но ссылаться я все еще на него могу, по этому я не уверен что правильно все сделал и забил.
SilentPrayerCG
> Если я сделаю простой класс у которого будет проперти 1 спрайт ср2дшный, и
> несколько каких-нибудь интов или типа того.
> Мне как-то надо ему какой-то деструктор прописывать
По идее — не обязательно. Когда все ссылки на твой объект будут удалены, сборщик мусора уничтожит сам объект и все ссылки внутри него. Ну а спрайт, уничтожаясь, сам сделает dispose() всему внутри спрайта, чему требуется.
Видишь ли, на тех версиях, на которых я работал, этого iDisposable не было. Я не знаю, на что повлияет разница, возможно, даст возможность по dispose() удалять объект сразу, а не когда захочет сборщик мусора, на NET это может задерживаться, вот VB6 удалял сразу.
Этот вопрос надо изучать.
Mikle
Ну по идее должен сразу удалять. Меня смутило что если я грохну битмап или фонт или бруш, они нулл становятся, а рукописный класс почему-то нет.
Я правильно понимаю что у тебя там только цбуф pinned? Потому что в деструктуре он освобождается ручками через GCH.
Все остальные поля это тупо цифры, их диспозить или как-то занулять не нужно, как я понял.
PS
перепроверил - нефига они не становятся нулл, я похоже это придумал, сделав не верный вывод.
При dispose() некоторые проперти отваливаются, в частности у битмапа, очевидно они берутся из тех данных которые уничтожаются при dispose(), а в целом сам объект продолжает быть не нулл
у всяких фонтов там их цифры тоже продолжают существовать.
надо еще раз попробовать прикрутить iDisposable к спрайту и проверить
SilentPrayerCG
> если я грохну битмап или фонт или бруш, они нулл становятся, а рукописный класс почему-то нет
Потому, что это всё не NET объекты (в отличие от своего класса), обёрнутые в NET интерфейс.
SilentPrayerCG
> Я правильно понимаю что у тебя там только цбуф pinned?
Верно.
Mikle
я там обновил сообщение.
не прав я был похоже, хотя я раньше в вб все делал, может есть разница но не думаю.
очевидно, созданный условный битмап или бруш без конструктора, вот он нулл наверное будет
а если его задиспозить, то он сломанный получается просто
я так понимаю и какого-то предусмотренного метода проверить является ли объект задиспозенным - нет.
ловить экспекшен при обращение к пропертям и еще там какие-то лайвхаки используются, судя по тому что я нагуглил.
Но если главное это цбуф, можно по нему будет проверить, работает ли самодельный диспоз.
Попробовал. Сделал еще раз диспоз
там где должны чиститься unmanaged ресурсы разместил то что было в деструкторе,
if (GCH.IsAllocated)
{
GCH.Free();
Debugger.Break();
}
добавил брик чтобы чекнуть, что этот блок исполняется - исполняется
но картинка все еще рисуется)
В общем я поскармливал бингу всю эту инфу, вроде подозрений на галлюцинации нет, хотя хз.
Из того, что я понял, что, как ты сказал, bitmap типа .net объект, при диспозе, он освобождает некий внутренний gdi+ объект, и по этому bitmap становится не юзабельным, но якобы память все равно освобождается сборщиком мусора когда ему захочется.
Вот в этом я не уверен. По-моему где-то было написано, что диспоз форсится. Да и в целом, я вроде давно тестил, что если какое-то большое количество битмапов будет объявляться без диспоза в конце, это вызовет утечку, а если с диспозом то нет, хотя заявляется, что сборщик мусора, сам как-то решает. Может конечно такие штуки предусмотрены, если большое количество диспозится он быстрее высвобождает.
А вот то что GCH.Free, он мне сказал, что просто открепляется, но память освободится когда-то там.
Я так понимаю, если открепить, даже если он продолжает работать, в какой-то момент он может сломаться, если объект передвинется в памяти, и PTR уже будет указывать на что-то иное.
В таком случае не понятно, нужно ли реально диспоз делать, или оставить деструктор. Тогда этот null в конце спрайта не нужен видимо. Потому что с nullable контекстом, он тупо гундит что это unnecessary assignment (хотя я не проверял что он гундит без нуллабл контекста)
Я так понимаю, по логике, если cBuf был 10005000 размером, и спрайт занулить, он станет 0 размером, типа он начнет меньше занимать. Можно оставить диспоз наверное просто занулить в нем все поля. Хз даст это что-то или нет.
Mikle
Напомни
symbolSprite.MulAddS2X(symbolSprite, 0, 0, SR2D.ARGB(a, 128, 128, 128), SR2D.ARGB(128, 128, 128, 128));
первый цвет, ниже 128 уменьшает яркость, выше 128 увеличивает яркость компоненты
а второй цвет что делает?
второй это просто линейно повышает наверное яркость пикселей?
И это единственный способ покрутить яркость? Он получается просто всего половина от 255, в плане градации.
Есть какой-то быстрый метод там, чтобы 1 компонент (альфу к примеру) затемнить с плавность от 0 до 255?
Я думал может сделать blend с пустым спрайтом, но видимо blend не так работает? У меня не получилось.
SilentPrayerCG
Первый компонент - множитель, если это 128, то умножается на 1, то есть не меняется, если 255, то почти на 2, смысл понятен. То есть это и яркость , и контрастность.
Второй - добавление за вычетом 128, то есть яркость.
SilentPrayerCG
> Есть какой-то быстрый метод там, чтобы 1 компонент (альфу к примеру) затемнить с плавность от 0 до 255?
Не очень понял. Изначально в альфе есть изображение? Или однотонная заливка?
"от 0 до 255" — это, как бы, высветлить, а не затемнить.
Mikle
Ну вот допустим я хочу прибавить ко всем пикселям +N разом
ну т.е не попиксельно, а так-же через какую-нибудь функцию
Просто MullAddS2X он получается, если я убавляю яркость -1, то по сути это -2
Это по-моему как раз тоже самое что я все те годы назад спрашивал, и ты как раз MullAddS2X предложил)))) я опять к этому вернулся
изначально было нужно нарисовать спрайт с указанным % прозрачности
в принципе MullAddS2X работает, думал может можно еще как-то, чтобы можно было от 0 до 255 уменьшать, так чтобы было 255 254 253, а не 255, 253, 251 (так как аргумент ограничен байтом и там 128 + - 128)