Blog. Just Blog

Работа с файлами AVIF на Ассемблере

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Работа с файлами AVIF на Ассемблере
Работа с файлами AVIF на Ассемблере

Графический формат AVIF, основанный на видеокодеке AV1, набирает популярность в интернете за счет эффективности сжатия, а также сохранения мелких деталей, меньшего количества артефактов и отсутствия растекания цвета вокруг резких границ объектов на изображении. AVIF неплохо поддерживается браузерами, а некоторые сайты, например, AliExpress, используют изображения в формате AVIF как основные. В связи с этим встает вопрос о поддержке файлов формата AVIF в приложениях. Это может быть просто просмотр изображений или конвертирование в другие форматы.

Сперва напомню шуточную пословицу: "На Ассемблере можно написать что угодно, но жизнь коротка". Это я к тому, что сегодня не будет никаких парсеров, ручного декодирования и прочего. Я воспользуюсь готовой библиотекой libavif, хоть за удобство придется заплатить монстрячими размерами файлов, которые придется таскать за собой. Обладатели прямых рук и соответствующих навыков могут собрать библиотеку своими силами и, наверное, даже уменьшить ее размер за счет отключения ненужного функционала. Ну а я буду пользоваться тем, что есть. Также для работы мне понадобится стандартная библиотека GDI+ и пачка структур с константами, которых нет в FASM.
  1. ; Структуры для работы с AVIF
  2. struct avifDecoder
  3.         codecChoice          dd ?
  4.         maxThreads           dd ?
  5.         requestedSource      dd ?
  6.         allowProgressive     dd ?
  7.         allowIncremental     dd ?
  8.         ignoreExif           dd ?
  9.         ignoreXMP            dd ?
  10.         imageSizeLimit       dd ?
  11.         imageCountLimit      dd ?
  12.         strictFlags          dd ?
  13.         image                dd ?
  14.         imageIndex           dd ?
  15.         imageCount           dd ?
  16.         progressiveState     dd ?
  17.         imageTiming          dd ?
  18.         timescale            dd ?
  19.         duration             dd ?
  20.         durationInTimescales dd ?
  21.         alphaPresent         dd ?
  22.         ioStats              dd ?
  23.         diag                 dd ?
  24.         io                   dd ?
  25.         data                 dd ?
  26. ends
  27.  
  28. struct avifRWData
  29.         Data dd ?
  30.         size dd ?
  31. ends
  32.  
  33. struct avifImage
  34.         Width                   dd ?
  35.         height                  dd ?
  36.         depth                   dd ?
  37.         yuvFormat               dd ?
  38.         yuvRange                dd ?
  39.         yuvChromaSamplePosition dd ?
  40.         yuvPlanes               rd 3
  41.         yuvRowBytes             rd 3
  42.         imageOwnsYUVPlanes      dd ?
  43.         alphaPlane              dd ?
  44.         alphaRowBytes           dd ?
  45.         imageOwnsAlphaPlane     dd ?
  46.         alphaPremultiplied      dd ?
  47.         icc                     dd ?
  48.         colorPrimaries          dd ?
  49.         transferCharacteristics dd ?
  50.         matrixCoefficients      dd ?
  51.         transformFlags          dd ?
  52.         pasp                    dd ?
  53.         clap                    dd ?
  54.         irot                    dd ?
  55.         imir                    dd ?
  56.         exif                    avifRWData
  57.         xmp                     avifRWData
  58. ends
  59.  
  60. struct avifRGBImage
  61.         Width              dd ?
  62.         height             dd ?
  63.         depth              dd ?
  64.         format             dd ?
  65.         chromaUpsampling   dd ?
  66.         ignoreAlpha        dd ?
  67.         alphaPremultiplied dd ?
  68.         isFloat            dd ?
  69.         pixels             dd ?
  70.         rowBytes           dd ?
  71. ends
  72.  
  73. struct BitmapData
  74.         Width       dd ?
  75.         Height      dd ?
  76.         Stride      dd ?
  77.         PixelFormat dd ?
  78.         Scan0       dd ?
  79.         Reserved    dd ?
  80. ends
  81.  
  82. AVIF_STRICT_DISABLED = 0
  83. AVIF_RESULT_OK = 0
  84. PixelFormat32bppARGB = 26200Ah
  85. ImageLockModeWrite = 0x0002
В общих чертах задача сводится к тому, чтобы преобразовать изображение из формата AVIF в обычный HBITMAP, а затем уже работать с ним привычными способами.
  1.         ; Инициализация GDI+
  2.         mov     [gdiplusSInput.GdiplusVersion],1
  3.         mov     [gdiplusSInput.DebugEventCallback],0
  4.         mov     [gdiplusSInput.SuppressBackgroundThread],0
  5.         mov     [gdiplusSInput.SuppressExternalCodecs],0
  6.         invoke  GdiplusStartup,gdiplusToken,gdiplusSInput,0
  7.  
  8.         ; Подготовить кодек AVIF
  9.         invoke  avifDecoderCreate
  10.         mov     [decoder],eax
  11.  
  12.         mov     ebx,[decoder]
  13.         mov     [ebx+avifDecoder.strictFlags],AVIF_STRICT_DISABLED
  14.         mov     [ebx+avifDecoder.maxThreads],2
  15.  
  16.         ; Загрузить данные из памяти
  17.         invoke  avifDecoderSetIOMemory,[decoder],fdata,file_size
  18.  
  19.         ; Декодировать первый кадр изображения
  20.         invoke  avifDecoderParse,[decoder]
  21.         invoke  avifDecoderNextImage,[decoder]
  22.         invoke  avifRGBImageSetDefaults,rgb,[ebx+avifDecoder.image]
  23.         invoke  avifRGBImageAllocatePixels,rgb
  24.         invoke  avifImageYUVToRGB,[ebx+avifDecoder.image],rgb
  25.  
  26.         mov     eax,[ebx+avifDecoder.image]
  27.  
  28.         ; Размеры полученного изображения
  29.         mov     [rcLock.top],0
  30.         mov     [rcLock.left],0
  31.         mov     esi,[ebx+avifDecoder.image]
  32.         mov     eax,[esi+avifRGBImage.Width]
  33.         mov     [dImageWidth],eax
  34.         mov     [rcLock.right],eax
  35.         mov     eax,[esi+avifRGBImage.height]
  36.         mov     [dImageHeight],eax
  37.         mov     [rcLock.bottom],eax
  38.  
  39.         ; Создать битмап
  40.         invoke  GdipCreateBitmapFromScan0,\
  41.                 [dImageWidth],[dImageHeight],0,\
  42.                 PixelFormat32bppARGB,0,xTmp
  43.         or      eax,eax
  44.         jnz     clear_gdi3
  45.  
  46.         invoke  GdipBitmapLockBits,[xTmp],rcLock,\
  47.                 ImageLockModeWrite,\
  48.                 PixelFormat32bppARGB, bmd
  49.  
  50.         ; Перенести изображение из кадра на битмап
  51.         xor     edx,edx
  52.         mov     eax,[dImageWidth]
  53.         mov     ecx,[dImageHeight]
  54.         imul    ecx
  55.         mov     ecx,eax
  56.         mov     esi,[rgb.pixels]
  57.         mov     edi,[bmd.Scan0]
  58. loc_loop:
  59.         ; Преобразовать точку в ABGR
  60.         lodsd
  61.         mov     edx,eax
  62.  
  63.         and     eax,0xFF000000
  64.  
  65.         mov     ebx,edx
  66.         and     ebx,0x000000FF
  67.         shl     ebx,16
  68.         or      eax,ebx
  69.  
  70.         mov     ebx,edx
  71.         and     ebx,0x0000FF00
  72.         or      eax,ebx
  73.  
  74.         mov     ebx,edx
  75.         and     ebx,0x00FF0000
  76.         shr     ebx,16
  77.         or      eax,ebx
  78.  
  79.         stosd
  80.         loop    loc_loop
  81.  
  82.         invoke  GdipBitmapUnlockBits,[xTmp], bmd
  83.  
  84.         ; Изображение корректное?
  85.         invoke  GdipGetImageWidth,[xTmp],tmp
  86.         cmp     [tmp],0
  87.         je      clear_gdi2
  88.         invoke  GdipGetImageHeight,[xTmp],tmp
  89.         cmp     [tmp],0
  90.         je      clear_gdi2
  91.  
  92.         ; Создать HBITMAP для установки на static
  93.         invoke  GdipCreateHBITMAPFromBitmap,[xTmp],\
  94.                 hBitmap,0x00FFFFFF
  95.         cmp     [hBitmap],0
  96.         jz      clear_gdi2
  97.  
  98.         ;------------------------------------------
  99.         ; [hBitmap] - хэндд битмапа
  100.         ;------------------------------------------
  101.  
  102.         ; Освободить графику
  103.         invoke  GdipDisposeImage,[xTmp]
  104. clear_gdi1:
  105.         invoke  DeleteObject,[hBitmap]
  106. clear_gdi2:
  107.         invoke  GdipDeleteGraphics,[hGraphics]
  108. clear_gdi3:
  109.         ; Выключение GDI+
  110.         invoke  GdiplusShutdown,[gdiplusToken]
  111.  
  112.         ; Освободить кодек AVIF
  113.         invoke  avifDecoderDestroy,[decoder]
В приведенном выше примере данные загружаются напрямую из памяти, за это отвечает функция avifDecoderSetIOMemory. Если надо загружать данные из файла на диске, то эта строчка изменится на
  1.         ; Загрузить данные из файла
  2.         invoke  avifDecoderSetIOFile,[decoder],fname
Получив хэндл HBITMAP, его можно сохранить в файл нужного формата, вывести на экран или сделать что-то другое, чего требует поставленная задача.

В приложении примеры программ с исходными текстами, которые масштабируют и выводят на форму изображение в формате AVIF из файла на диске и напрямую из памяти.

Примеры программ с исходными текстами (FASM)Примеры программ с исходными текстами (FASM)

AVIF.to.Form.Demo.zip (3,061,259 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 386 | Комментариев: 2

Комментарии

Отзывы посетителей сайта о статье
ManHunter (16.12.2024 в 15:23):
heic прекрасно поддерживается через WIC после установки кодеков.
https://www.manhunter.ru/softw...ovodnik.html
https://www.manhunter.ru/assem...hyu_wic.html
любитель (16.12.2024 в 15:10):
А для HEIC подобное будет?

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2025
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0033 сек.) / Память: 4.5 Mb
Наверх