FreeBasic
Главная
Вход
Регистрация
Пятница, 23.01.2026, 02:11Приветствую Вас Гость | RSS
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Загрузка BMP. Модуль на тест.
DarkDemonДата: Воскресенье, 26.10.2025, 18:55 | Сообщение # 1
Генерал-майор
Группа: Друзья
Сообщений: 280
Репутация: -1
Статус: Offline
Собственно суть в названии темы. Задача была отвязаться от FB-шного загрузчика.
Этот модуль будет частью 2D\3D библиотеки, над которой сейчас работаю(простая замена GL2D).
Поэтому потестить надо перед тем как всё собирать воедино.
Тут не реализован только 15 битный формат и из 16 битных там только один - сейчас не посчитал это нужным.
Остальное есть, сжатие не поддерживается, переназначение каналов - поддерживается(но надо тестить,
чую где-то лажа). Формализовать пока некогда, всё фигарю очень быстро - лишь бы написать.
Рефакторить и вылизывать тоже буду потом. Модуль не для тюфиков, т.е. TakePix без клиппинга.
Сделать клиппинг это два JA на асме, мне не трудно - но не хочу, ибо оно нафиг не надо, когда
всё загружено правильно и считывается по пикселям корректно.

Код
'
'
'   [ BMModule.BAS ]
'
'   Модуль для загрузки BMP.
'   Не использует встроенный в FB функционал.
'   Работает только с форматами без сжатия.
'
'   > Quiet Snow <  2025
'   Совместимость: FBC 0.23.0
'                  FBC 1.10.1
'

NAMESPACE BMP

'    Тип заголовка *.BMP

TYPE BMFile   FIELD = 1
    BmID AS SHORT = 19778
    FileSize AS ULONG
    Reserved AS LONG
    BmOFFSET AS ULONG = 54
END TYPE

'    Старый заголовок( 40 байт )
TYPE BMHead   FIELD = 1
    HeadSize AS ULONG = 40
    BmpSizeX AS ULONG
    BmpSizeY AS ULONG
    BmSlices AS USHORT = 1
    BitDepth AS USHORT = 32
    Compress AS LONG
    DataSize AS ULONG
    BmHorRes AS ULONG
    BmVerRes AS ULONG
    UseColor AS ULONG
    SignColr AS ULONG
END TYPE

'    Новый заголовок( 56 байт )
TYPE BMHeadv5   FIELD = 1
    HeadSize AS ULONG = 40
    BmpSizeX AS ULONG
    BmpSizeY AS ULONG
    BmSlices AS USHORT = 1
    BitDepth AS USHORT = 32
    Compress AS LONG
    DataSize AS ULONG
    BmHorRes AS ULONG
    BmVerRes AS ULONG
    UseColor AS ULONG
    SignColr AS ULONG
    RedMask  AS ULONG
    GrnMask  AS ULONG
    BlueMask AS ULONG
    AlphMask AS ULONG
END TYPE

'    Дополненный новый заголовок (Не реализован)
'TYPE CIEXYZ   FIELD = 1
'   ciexyzX AS ULONG
'   ciexyzY AS ULONG
'   ciexyzZ AS ULONG
'END TYPE

'TYPE CIEXYZTRIPLE    FIELD = 1
'   ciexyzRed AS CIEXYZ  
'   ciexyzGreen AS CIEXYZ
'   ciexyzBlue AS CIEXYZ
'END TYPE

'TYPE BMHeadv5Add
'   CSType   AS ULONG
'   bV5Endpoints AS CIEXYZTRIPLE
'   GammaRed AS ULONG
'   GammaGrn AS ULONG
'   GammaBlu AS ULONG
'   Intent   AS ULONG
'   PrflData AS ULONG
'   ProfSize AS ULONG
'   Reserved AS ULONG
'END TYPE

   '  Заголовки
DIM FHead AS BMFile, BMPHead AS BMHead
DIM BMPHeadv5 AS BMHeadv5

'    Прототипы

DECLARE SUB  Load  (FName AS STRING)
DECLARE SUB  Save  (FName AS STRING)
DECLARE SUB  TakePix (x AS INTEGER, y AS INTEGER)
DECLARE FUNCTION TakePointer () AS ANY PTR
DECLARE SUB  ClosePic ()

'    Массивы

   DIM RAWMem AS BYTE PTR                       '    Память под файл целиком
   DIM BMMem AS BYTE PTR, BMLoaded AS SHORT     '    Указатель на загр. BMP и флаг того, что он загружен

   DIM BMSzX AS LONG, BMSzY AS LONG             '    Размер изображения
   DIM SvBMF AS INTEGER                         '    Свободный дескриптор
   
   DIM YMuls() AS BYTE PTR                      '    Предрасчитанный адрес для GetPix

   DIM PixCV AS ULONG                           '    Полученный GetPix-ом пиксель цвета

   DIM PalR(255) AS ULONG                       '    Палитра для 256 цветного BMP
   DIM PalG(255) AS ULONG
   DIM PalB(255) AS ULONG
   DIM Cv256(255) AS ULONG                      '    Готовый цвет из палитры

'
'    Загрузка *.BMP*
'

SUB Load (FName AS STRING)

   DIM  xp  AS INTEGER, yp    AS INTEGER
   DIM  Adr AS BYTE PTR, Adr2 AS BYTE PTR, PalAdr AS BYTE PTR
   DIM  OneLine AS INTEGER, TwoLine AS INTEGER
   DIM  Cv  AS ULONG, RCmp AS UBYTE, GCmp AS UBYTE, BCmp AS UBYTE, ACmp AS UBYTE

   DIM CvZam(3) AS INTEGER
   DIM RPosit AS INTEGER, GPosit AS INTEGER, BPosit AS INTEGER, APosit AS INTEGER

   DIM  Plus   AS INTEGER

   DIM  BMFLn AS UINTEGER                        '  Длина файла
   DIM  MaxColors AS USHORT

  '   Если уже загружен, то освободим память
   IF BMLoaded THEN ClosePic ()

  '   Откроем файл
   SvBMF = FREEFILE
   IF OPEN(FName, FOR BINARY, ACCESS READ, AS #SvBMF) THEN EXIT SUB

  '   Получим длину файла
   BMFLn = LOF(SvBMF)
   IF BMFLn = 0 THEN CLOSE SvBMF : EXIT SUB      '  Если файл пуст - выход

   GET #SvBMF, , FHead                           '  Загрузим заголовок

   IF FHead.BmID <> 19778 THEN CLOSE SvBMF : EXIT SUB   '  Если это не BMP файл - выход

   GET #SvBMF, , BMPHead                         '  Следующий заголовок ( 40 байт )

   '  Если новый заголовок v5 - тогда читаем его
   IF BMPHead.HeadSize >= 56 THEN
     SEEK #SvBMF, SEEK(SvBMF) - 40
     GET #SvBMF, , BMPHeadv5
      BMPHead.HeadSize = BMPHeadv5.HeadSize
      BMPHead.BmpSizeX = BMPHeadv5.BmpSizeX
      BMPHead.BmpSizeY = BMPHeadv5.BmpSizeY
      BMPHead.BmSlices = BMPHeadv5.BmSlices
      BMPHead.BitDepth = BMPHeadv5.BitDepth
      BMPHead.Compress = BMPHeadv5.Compress
      BMPHead.DataSize = BMPHeadv5.DataSize
      BMPHead.BmHorRes = BMPHeadv5.BmHorRes
      BMPHead.BmVerRes = BMPHeadv5.BmVerRes
      BMPHead.UseColor = BMPHeadv5.UseColor
      BMPHead.SignColr = BMPHeadv5.SignColr

      '   Определяем позиции каналов по маскам каналов
      FOR i AS INTEGER = 0 TO 3
         IF ((BMPHeadv5.RedMask AND 255) = 255) THEN
           RPosit = i            
         END IF
         BMPHeadv5.RedMask = BMPHeadv5.RedMask SHR 8
      NEXT

      FOR i AS INTEGER = 0 TO 3
         IF ((BMPHeadv5.GrnMask AND 255) = 255) THEN
           GPosit = i            
         END IF
         BMPHeadv5.GrnMask = BMPHeadv5.GrnMask SHR 8
      NEXT

      FOR i AS INTEGER = 0 TO 3
         IF ((BMPHeadv5.BlueMask AND 255) = 255) THEN
           BPosit = i            
         END IF
         BMPHeadv5.BlueMask = BMPHeadv5.BlueMask SHR 8
      NEXT

      FOR i AS INTEGER = 0 TO 3
         IF ((BMPHeadv5.AlphMask AND 255) = 255) THEN
           APosit = i            
         END IF
         BMPHeadv5.AlphMask = BMPHeadv5.AlphMask SHR 8
      NEXT

   END IF

  '   Получим размерность картинки
   BMSzX = BMPHead.BmpSizeX:   BMSzY = BMPHead.BmpSizeY

  '   Если размеры изображения нулевые, значит не будем грузить
   IF (BMSzX = 0) OR (BMSzY = 0) THEN CLOSE SvBMF : EXIT SUB

       '  Переходим в начало файла
         SEEK #SvBMF, 1

       '  Заводим память
         RAWMem = ALLOCATE(BMFLn)

       '  Грузим весь файл в память
         GET #SvBMF, , *RAWMem, BMFLn

  '   Закроем файл т.к. уже загрузили его
   CLOSE #SvBMF

  '   Теперь нужно распарсить файл в памяти    

  '   Посчитаем пропуск байт на строку
  Plus = BMSzX AND 3
  Adr = RAWMem + FHead.BmOFFSET' + 1

  '   Заводим память под 32 битное изображение
  BMMem  = ALLOCATE(BMSzX * BMSzY * 4)
  OneLine = BMSzX * 4
  TwoLine = OneLine SHL 1

  '   Перезаводим массив предрасчитанных Y для TakePix
  REDIM YMuls(BMSzY)
  '   Заполняем
  FOR yp = 0 TO BMSzY - 1
      YMuls(yp) = BMMem + (yp * OneLine)
  NEXT

  Adr2 = CINT(BMMem) + CINT(BMSzX * BMSzY * 4) - OneLine ' - 100

  ' __________________________________________
  '
  '     Обрабатываем согласно битности
  ' __________________________________________

   SELECT CASE  BMPHead.BitDepth

  '    8 БИТ
    CASE 8
    'PRINT "----------8 BIT------------"

    '   Сколько цветов в 256-цветной палитре
     MaxColors = BMPHead.UseColor
     IF BMPHead.SignColr > MaxColors THEN MaxColors = BMPHead.SignColr
     PalAdr =  RAWMem + BMPHead.HeadSize + 14

      FOR QPal AS INTEGER = 0 TO MaxColors       '  Читаем палитру
         PalB(QPal) = PEEK(UBYTE, PalAdr)
         PalG(QPal) = PEEK(UBYTE, PalAdr + 1)
         PalR(QPal) = PEEK(UBYTE, PalAdr + 2)
         Cv256(QPal) = RGB(PalR(QPal), PalG(QPal), PalB(QPal))
         PalAdr += 4
      NEXT

     '   Идём в цикле по Y
     FOR yp = 0 TO BMSzY - 1

        '   Идём в цикле по X
        FOR xp = 0 TO BMSzX - 1
           '  Считываем цвет
           Cv = PEEK(UBYTE, Adr)
           POKE ULONG, Adr2, Cv256(Cv)' SHL 5' OR &HFF000000
           Adr += 1
           Adr2 += 4
        NEXT
        Adr += Plus
        Adr2 -= TwoLine
     NEXT

  '   15 БИТ
    CASE 15
    PRINT "----------15 BIT------------"

  '   16 БИТ
    CASE 16

     FOR yp = 0 TO BMSzY - 1

        FOR xp = 0 TO BMSzX - 1
           #IFNDEF __FB_64BIT__
            ASM
               MOV ESI,                   [Adr]'   AX = 16 Bit Color   RRRRRGGG GGGBBBBB
               LODSW

               MOV EBX, EAX                    '   BX = AX         RRRRRGGG GGGBBBBB
               AND EAX, &B1111100000011111     '   EAX =           RRRRR000 000BBBBB
               SHL BX, 5                       '   EBX =           GGGGGGBB BBB00000
               SHL EAX, 8                      '   EAX =  RRRRR000 000BBBBB 00000000
               AND BX, &B1111110000000000      '   EBX =  00000000 GGGGGG00 00000000
               SHR AX, 5                       '   EAX =  RRRRR000 00000000 BBBBB000
               OR  EAX, EBX
               MOV DWORD PTR[Cv], EAX
                     
            END ASM
           #ELSE
            ASM
               MOV RSI,                   [Adr]'   AX = 16 Bit Color   RRRRRGGG GGGBBBBB
               LODSW

               MOV EBX, EAX                    '   BX = AX         RRRRRGGG GGGBBBBB
               AND EAX, &B1111100000011111     '   EAX =           RRRRR000 000BBBBB
               SHL BX, 5                       '   EBX =           GGGGGGBB BBB00000
               SHL EAX, 8                      '   EAX =  RRRRR000 000BBBBB 00000000
               AND BX, &B1111110000000000      '   EBX =  00000000 GGGGGG00 00000000
               SHR AX, 5                       '   EAX =  RRRRR000 00000000 BBBBB000
               OR  EAX, EBX
               MOV DWORD PTR[Cv], EAX
                     
            END ASM           
           #ENDIF

           POKE ULONG, Adr2, Cv

           Adr += 2
           Adr2 += 4
        NEXT
        Adr += Plus
        Adr2 -= TwoLine
     NEXT

  '   24 БИТ
    CASE 24

     '   Идём в цикле по Y
     FOR yp = 0 TO BMSzY - 1

        '   Идём в цикле по X
        FOR xp = 0 TO BMSzX - 1
           '  Считываем цвет
           Cv = PEEK(ULONG, Adr) AND &H00FFFFFF
           POKE ULONG, Adr2, Cv OR &HFF000000
           Adr += 3
           Adr2 += 4
        NEXT
        Adr += Plus
        Adr2 -= TwoLine
     NEXT

  '   32 БИТ
    CASE 32

     IF BMPHead.HeadSize = 40 THEN

       '   Идём в цикле по Y
       FOR yp = 0 TO BMSzY - 1

          '   Идём в цикле по X
          FOR xp = 0 TO BMSzX - 1
             Cv = PEEK(ULONG, Adr)     '  Считываем цвет
             POKE ULONG, Adr2, Cv      '  В память его
             Adr += 4
             Adr2 += 4
          NEXT
          Adr += Plus
          Adr2 -= TwoLine
       NEXT
       
     ELSEIF BMPHead.HeadSize >= 56 THEN

       '   Идём в цикле по Y
       FOR yp = 0 TO BMSzY - 1

          '   Идём в цикле по X
          FOR xp = 0 TO BMSzX - 1

             '  Считываем компоненты
             RCmp = PEEK(UBYTE, Adr + RPosit)
             GCmp = PEEK(UBYTE, Adr + GPosit)
             BCmp = PEEK(UBYTE, Adr + BPosit)
             ACmp = PEEK(UBYTE, Adr + APosit)

             '  Складываем в память
             POKE ULONG, Adr2, RGBA(RCmp, GCmp, BCmp, ACmp)             
             Adr += 4
             Adr2 += 4
          NEXT
          Adr += Plus
          Adr2 -= TwoLine
       NEXT

     END IF

   END SELECT
   BMLoaded = -1
   DEALLOCATE (RAWMem)
  ' __________________________________________
  '
  '     Конец обработки битностей
  ' __________________________________________

END SUB

'
'    Взять пиксель с загруженного в память *.BMP*
'

SUB TakePix (x AS INTEGER, y AS INTEGER)
     
    PixCV = PEEK (ULONG, (x SHL 2 + YMuls(y) ) )
     
END SUB

'
'    Получить указатель на пиксели картинки
'

FUNCTION TakePointer () AS ANY PTR
     
    TakePointer = BMMem
     
END FUNCTION

'
'   Выгрузить *.BMP* из памяти.
'

SUB ClosePic ()
    IF BMLoaded = 0 THEN EXIT SUB
    DEALLOCATE (BMMem)
    BMMem = 0
    BMLoaded = 0
END SUB

END NAMESPACE
 
haavДата: Воскресенье, 26.10.2025, 19:40 | Сообщение # 2
Генералиссимус
Группа: Администраторы
Сообщений: 1448
Репутация: 50
Статус: Offline
Быстро глянул код.

Если загружаются более одной картинки , что делать? Буфер у тебя один , значит всегда затирается последним загруженным. Я прав?

232 строка (warning при компиляции). Не критично конечно же.

251 строка: ошибка: Aborting due to runtime error 6 (out of bounds array access) at line 251


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
DarkDemonДата: Воскресенье, 26.10.2025, 20:01 | Сообщение # 3
Генерал-майор
Группа: Друзья
Сообщений: 280
Репутация: -1
Статус: Offline
Цитата
Если загружаются более одной картинки , что делать? Буфер у тебя один , значит всегда затирается последним загруженным. Я прав?

Да, одно считал. Если загружаешь следующее, то загруженное утилизируется и загружается новое.
Т.е. слот всего один. Загрузил, пользуешься текущим, снова загрузил, снова пользуешься текущим.
Довольно удобный принцип. Но я понял к чему ты это спросил. Так вышло, что пару дней назад дописал
прослойку к FBSound-у на старый компиль 0.23.0, в принципе она пойдёт под любой компиль, просто
привязана к старому FBSound, так вот там организована списочная(через массивы) работа с группами
файлов, цель была сделать групповую организацию и основной функционал воспроизвести случайный
файл из группы без повторов(имхо для игрушек - маст хев). Эту штуку возможно тоже выложу.

Тут же всё иначе. Сделано чтобы максимально просто получить доступ к пикселям в памяти.
Ну мало ли, альфа канал нужен или часть картинки. Но я тебя понял и вероятно функционал будет расти,
но чуть позже. Сейчас главное выловить все самые жестокие баги)))

Код
251 строка: ошибка: Aborting due to runtime error 6 (out of bounds array access) at line 251

Ого, где-то у меня значит жопа. Буду тогда внимательно смотреть и проверять границы...
Блин вечно какая-то задница с этими указателями)))

А что за файл ты пробовал загрузить? 251 это загрузка палитры 8-ми битной картинки.

Добавлено (26.10.2025, 20:09)
---------------------------------------------
А понял, жопа не страшная. Это банальный бажок.
Надо делать до MaxColors - 1. Т.к. в качестве параметров в файле это значение считается от единицы(фактическое кол-во),
а я итерирую от нуля. Спасибо за тестинг. Быстро кодил - не заметил.

Добавлено (26.10.2025, 20:25)
---------------------------------------------
Варнинги сейчас тоже стараюсь убирать. Забавно, если CINT-ы убрать и варнинга нет. Ой намудрил, забыл уже
там по кастингам, опять твой учебник надо перечитывать...
В целом, хорошо, продуктивно.

Сообщение отредактировал DarkDemon - Воскресенье, 26.10.2025, 20:02
 
haavДата: Воскресенье, 26.10.2025, 20:29 | Сообщение # 4
Генералиссимус
Группа: Администраторы
Сообщений: 1448
Репутация: 50
Статус: Offline
Ты хоть пример какой сюда напиши для визуального восприятия. Ты ведь как-то тестировал.

Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
DarkDemonДата: Воскресенье, 26.10.2025, 21:00 | Сообщение # 5
Генерал-майор
Группа: Друзья
Сообщений: 280
Репутация: -1
Статус: Offline
Тестирование было после модуля, но я его удалил. Ща заново напишу, 2 сек.

Код

  #INCLUDE "BMModule.BAS"

 CONST GFX_NoSwch_NoFrm = 12

 DECLARE FUNCTION GetDispDt LIB "user32" ALIAS "EnumDisplaySettingsA"  (BYVAL AS ANY PTR, BYVAL AS ULONG,  BYVAL AS ANY PTR) AS LONG
  
  TYPE MyTip FIELD = 1
    NoUse AS ZSTRING * 36
    dmSize AS USHORT = 156
    NoUse2 AS ZSTRING * 66
    BitsPerPix AS ULONG
    PixWidth AS ULONG
    PixHeight AS ULONG
    DisplayFlags AS ULONG
    DisplayFreq AS ULONG
    NoUse3 AS ZSTRING * 32
  END TYPE
  DIM QInf AS MyTip
  
  GetDispDt (0, &HFFFFFFFF, @QInf)     '  Текущие настройки монитора
  
  SCREENRES QInf.PixWidth, QInf.PixHeight, 32, 1, GFX_NoSwch_NoFrm
  
  
  BMP.Load "1.bmp"                     '  Указать имя BMP файла
  
  '  Вывод попиксельно
  FOR iy AS INTEGER = 0 TO BMP.BMSzY - 1
     FOR ix AS INTEGER = 0 TO BMP.BMSzX - 1
        BMP.TakePix (ix, iy)
        PSET (ix, iy), BMP.PixCV
  NEXT ix, iy
  
  SLEEP
 
zamabuvaraeuДата: Воскресенье, 26.10.2025, 22:11 | Сообщение # 6
Полковник
Группа: Друзья
Сообщений: 184
Репутация: 5
Статус: Offline
Попиксельно — это же очень медленно. Как сразу всю картину одним вызовом вывести?
 
DarkDemonДата: Воскресенье, 26.10.2025, 22:26 | Сообщение # 7
Генерал-майор
Группа: Друзья
Сообщений: 280
Репутация: -1
Статус: Offline
Цитата
Попиксельно — это же очень медленно. Как сразу всю картину одним вызовом вывести?

Основное назначение модуля:
1) Отвязаться от FbGfx в плане загрузки картинок. (мне это + на далёкое будущее)
2) Максимально упростить загрузку текстур для OpenGL. 2 функции (BMP.Load, BMP.TakePointer)
3) Предоставить простой доступ к пикселям по координатам. Возможно кто-то вообще захочет
загрузить пиксели в обычный 2-х мерный массив и поработать с ними.

Работать с точками, безусловно, медленно, однако загрузка с диска в разы более ресурсоёмкая операция,
на её фоне это мелочи.
Я бы рекомендовал вести обработку полинейно, взяв поинтеры строк через внутрянку модуля YMuls(y),
это даст обширные возможности встроенному оптимизатору FB(у меня флор маппер на табличных оптимизациях
выдавал под 1300 кадров, взаместо 300 без оптимизаций, можно смекнуть за профит).

Добавлено (26.10.2025, 22:56)
---------------------------------------------

Цитата
Как сразу всю картину одним вызовом вывести?

Для этого и пишется модуль на OpenGL, для полной отвязки от FBGfx. Там ещё дофига работы,
недели две возиться до первых прототипов(и то не факт). То что показывал видео, это 1ый модуль,
примерно на 1700 строк, там просто шерстил возможности(они такими же и останутся), там
не всё хорошо, а точнее много что хреново. Поэтому переписываю с переосмыслением.
Архитектурно то что есть сейчас - мне нравится главное не забросить и допилить эту штуку.
Целый месяц жёсткого кодинга сильно выматывает после многих лет не кодинга.
 
haavДата: Понедельник, 27.10.2025, 05:58 | Сообщение # 8
Генералиссимус
Группа: Администраторы
Сообщений: 1448
Репутация: 50
Статус: Offline
Попробуй загрузить битмап из архива. Мне кажется цвет фона не совпадает. Остальные битмапы вроде загружались без проблем. RLE конечно же не пробовал , раз оно не поддерживается.
Прикрепления: 1_bmp.zip (1.4 Kb)


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
DarkDemonДата: Понедельник, 27.10.2025, 10:54 | Сообщение # 9
Генерал-майор
Группа: Друзья
Сообщений: 280
Репутация: -1
Статус: Offline
Цитата
Попробуй загрузить битмап из архива. Мне кажется цвет фона не совпадает. Остальные битмапы вроде загружались без проблем. RLE конечно же не пробовал , раз оно не поддерживается.

Вот таких тестовых битмап мне не хватало. Спасибо Стас. Отличный тестинг.

Проблема банальна, это 15 битка, которую как раз обошёл стороной. Видимо оно всегда засовывается в 16 бит,
но надо всё проверить.
Что требуется для этого модуля чтобы он более менее пахал:
- Пофиксить 16 бит загрузчик (исходя из масок каналов, там всего 3 варианта, но альфа не в счёт)
- Дописать 4 бит загрузчик.
- Посмотреть что там с RLE хотя бы на 8 битах.

Короче всё ясно, буду ковырять потихоньку.

Добавлено (03.11.2025, 09:25)
---------------------------------------------
Короче начал переписывать эту шляпу заново, т.к. отталкивался от размера заголовка, а надо было всего лишь
найти вот эти несколько строчек:

The compression types supported by BMP are listed below :
  • 0 - no compression
  • 1 - 8 bit run length encoding
  • 2 - 4 bit run length encoding
  • 3 - RGB bitmap with mask


Архитектурно было сделано ПЛОХО. Надо теперь весь детект заголовков переписывать. Вот жеж, а. Столько времени слил.
По сути основной заголовок 40 байт так и является основным, не надо его менять, надо просто дочитывать маски и всё.
И ещё, если кто-то будет повторять этот путь - бдите: 1 бит и 4 бит - выравнивание 4 байта, в большую, разумеется, сторону.
И да, 16 бит R5G6B5 - без альфы, R5G5B5 - может быть с 1 бит альфой. 24 бит - без альфы, 32 бит - там где альфа маска 0 - без альфы.
Маски для 16 бит - битовые, для 32 бит - байтовые. Т.е. для 16 бит используем сдвиговые операнды, а для 32-х смотрим
байтовую позицию. В битовых режимах старшие биты\полубайты идут в виде пикселей раньше.
Там где ассемблерный код он полностью дублируется для x32, за исключением размера регистров для указателей, параметры
процедур при этом лучше делать фиксированные.

В принципе та версия которая у меня была последняя грузила 16 битки и 1 битки, но там были какие-то проблемы с питчем
на 4 битках, поэтому чтобы всё это дерьмо устранить надо просто сесть и переписать заново. С остальными проблем не было.
Объём кода тоже был неоправданно большой, многие вещи делались шаблонно и неоптимально. Нужно больше ассемблера
во внутреннем цикле.

Думал напишу этот модуль быстрее. Но тут чтобы хорошо сделать прям дофига работы. А тестировать эту штуку - вообще ад.


Сообщение отредактировал DarkDemon - Понедельник, 03.11.2025, 09:28
 
DarkDemonДата: Вторник, 04.11.2025, 01:53 | Сообщение # 10
Генерал-майор
Группа: Друзья
Сообщений: 280
Репутация: -1
Статус: Offline




Итак, мужчины. Кажется поборол...

В общем релиз кандидат, на тест. Грузит решительно всё, но кроме RLE. Демо в комплекте.
Добавлено куча всего, клиппинг в TakePix, загрузка в FBGfx одной командой

Могут быть незначительные баги. Поэтому любой тестинг категорически приветствуется.

Файл загружу на форум, чтобы не потерялось. Код шапки темы больше не актуален.
Прикрепления: bmmodule_v0_9.zip (834.3 Kb)


Сообщение отредактировал DarkDemon - Вторник, 04.11.2025, 01:59
 
haavДата: Вторник, 04.11.2025, 08:29 | Сообщение # 11
Генералиссимус
Группа: Администраторы
Сообщений: 1448
Репутация: 50
Статус: Offline
На винде вроде все работает.

На Linux 64-bit не все:

1) 16Bit_Stas.bmp отображается черным квадратом (наверное не загружено)
2) 32BitAlf2.bmp не отображается вовсе , вместо их отображаются 32bit.bmp и правая все время моргает (типа подмигивает мне smile )

Теперь о пожеланиях:

1) В одном месте у тебя есть возможность исключить ASM код макросом. Однако в другой функции , такой возможности нет. Было бы неплохо иметь такую возможность и в другой функции (мало ли код понадобится портировать на платформу , отличную от x86)
2) У функций сделать коды ошибок. Скажем не загрузилось изображение , получить код ошибки и узнать из-за чего это (нет файла на диске , не поддерживается и пр.). И так для всех функций.
3) Пример сделать кроссплатформенный. Для простоты , на других платформах размеры дисплея задавать константами. Так же , чтобы не было проблем , имена в файлах на linux регистрозависимы (это я об fbgfx.bi)


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
DarkDemonДата: Вторник, 04.11.2025, 10:25 | Сообщение # 12
Генерал-майор
Группа: Друзья
Сообщений: 280
Репутация: -1
Статус: Offline
haav, спасибо за очередной тестовый прогон.

Цитата
1) 16Bit_Stas.bmp отображается черным квадратом (наверное не загружено)

16 битки протягиваются через ASM код, скорее всего это причина. Немного не хватило терпения добавить FB версию.
Приму к сведению.

Цитата haav ()
2) 32BitAlf2.bmp не отображается вовсе , вместо их отображаются 32bit.bmp и правая все время моргает (типа подмигивает мне )

Вот тут трудно сказать, что за фигня. Но редкий тиринг есть и на винде сразу при старте программы(и не только).
Похоже их двойной буфер очень коряв, потому и моргает, т.к. загруженное изображение выводится уже
FBGfx-ом. Возможно устранится через ScreenLock \ ScreenUnlock, но от них уже давно отказался, потому что
прям знатный рудимент, код так писать неудобно.

Цитата haav ()
1) В одном месте у тебя есть возможность исключить ASM код макросом. Однако в другой функции , такой возможности нет.

Думаю это будет. Планы на дубликаты ASM кода в виде FB и наоборот - есть. Пока не насытил код этими штуками.

Цитата haav ()
2) У функций сделать коды ошибок. Скажем не загрузилось изображение , получить код ошибки и узнать из-за чего это (нет файла на диске , не поддерживается и пр.). И так для всех функций.

В этом нет необходимости, код очень простой, любая проблема локализуется очень просто(функция Load, выкл. подфункции).
У меня была DEBUG версия, где всё принтами высвечивалось, вся инфа, по загружаемой картинке, но для релиза код подчистил.
Суть тут в том, что если где-то баг именно в алгоритме, эти сообщения мало что дадут. В работе над этой штукой
сталкивался в т.ч. с созависимыми багами, например, Gfx менял свой питч, а я думал - что я осёл и начинал править верный загрузчик.
Там это просто никак не помогло бы. Большинство правок делаются по факту анализа выводимой картинки(неверный питч
видно, даже его объём видно, порядок байт, артефакты). Именно по видимым косякам делается точное предположение
о причине, т.к. вариантов при правильной архитектуре - немного. А тут она более или менее адекватная.
Всегда можно код лучше и чище сделать, но пока и так нормально.
Вообще не сильно уверен за ASM вставки, т.к. асм на FB очень кривожопый и иногда приходится догадываться во что
он превращает код, поэтому не уверен за эти места, потому что уже было так что: в одном месте поставил ковычки,
на 64 битах - разницы ноль, на 32 - всё стало работать не так как надо, ковычки в любом нормальном ассемблере
означают получение значения из смещения, однако на FB хрен проссышь что они глобально означают и разница есть
только в 32 битном коде. Поэтому часть операций приходится прям по одной команде сверять, чтобы не лохануться.
А я это делаю без отладчика, местами больновато.


Цитата
3) Пример сделать кроссплатформенный. Для простоты , на других платформах размеры дисплея задавать константами. Так же , чтобы не было проблем , имена в файлах на linux регистрозависимы (это я об fbgfx.bi)

В теории - всё что написано на чистом FB должно быть кроссплатформенно. Поэтому сделать версию полностью
на FB - полагаю вполне реально. А с линуксом у меня сложные отношения, предпочёл бы туда не лезть ни в каком виде.

Касаемо дисплея - там есть встроенный кроссплатформенный функционал в виде SCREENLIST. Просто экспериментирую
с разными функциями WinAPI, чтобы понять что где и как детектит и где лучше работает. А как SCREENLIST на линуксе
не знаю, это надо проверять, по идее разницы быть не должно.

Добавлено (05.11.2025, 07:46)
---------------------------------------------

Цитата haav ()
правая все время моргает

Цитата DarkDemon ()
Похоже их двойной буфер очень коряв

Слова Лёхи про двойной буфер, забывшего поставить двойной буфер. Вашу мать... Воистину гениально)))
Это надо в цитаты форума. Короче втыкаем SCREENSET 1, 0 сразу после SCREENRES.

А тут про линукс)), куда мне рассеянной куропате в линукс.
 
zamabuvaraeuДата: Среда, 05.11.2025, 17:12 | Сообщение # 13
Полковник
Группа: Друзья
Сообщений: 184
Репутация: 5
Статус: Offline

Цитата
все время моргает
Так оно стирается и перерисовывается всё время каждые 25 миллисекунд.
Какой смысл.
Лучше всего нарисовать один раз в памяти; и потом выводить только по запросу через BitBlt внутри WM_PAINT.
 
DarkDemonДата: Среда, 05.11.2025, 19:34 | Сообщение # 14
Генерал-майор
Группа: Друзья
Сообщений: 280
Репутация: -1
Статус: Offline
Цитата zamabuvaraeu ()
Какой смысл.

Вроде написал, что забыл указать скринсет. Модуль с демо были написаны за 1,5 суток с хером. Подумай...


Сообщение отредактировал DarkDemon - Среда, 05.11.2025, 19:36
 
DarkDemonДата: Суббота, 08.11.2025, 08:53 | Сообщение # 15
Генерал-майор
Группа: Друзья
Сообщений: 280
Репутация: -1
Статус: Offline
Короче пофиксил баг в 16 бит загрузчике(стандартные файлы), оптимизировал и отвязал ASM в 16 битном загрузчике.
Добавил директивы для Linux(в демо в т.ч.) теперь есть вероятность что запустится и там. Пофиксил дабл буфер в демо.
Кое где поправил комментарии, убрал лишнее ненужное. На этом пока всё...
Прикрепления: bmmodule_v0_95.zip (839.0 Kb)
 
  • Страница 1 из 1
  • 1
Поиск: