Работа с файлами AVIF на Ассемблере
Работа с файлами AVIF на Ассемблере
Графический формат AVIF, основанный на видеокодеке AV1, набирает популярность в интернете за счет эффективности сжатия, а также сохранения мелких деталей, меньшего количества артефактов и отсутствия растекания цвета вокруг резких границ объектов на изображении. AVIF неплохо поддерживается браузерами, а некоторые сайты, например, AliExpress, используют изображения в формате AVIF как основные. В связи с этим встает вопрос о поддержке файлов формата AVIF в приложениях. Это может быть просто просмотр изображений или конвертирование в другие форматы.
Сперва напомню шуточную пословицу: "На Ассемблере можно написать что угодно, но жизнь коротка". Это я к тому, что сегодня не будет никаких парсеров, ручного декодирования и прочего. Я воспользуюсь готовой библиотекой libavif, хоть за удобство придется заплатить монстрячими размерами файлов, которые придется таскать за собой. Обладатели прямых рук и соответствующих навыков могут собрать библиотеку своими силами и, наверное, даже уменьшить ее размер за счет отключения ненужного функционала. Ну а я буду пользоваться тем, что есть. Также для работы мне понадобится стандартная библиотека GDI+ и пачка структур с константами, которых нет в FASM.
Code (Assembler) : Убрать нумерацию
- ; Структуры для работы с AVIF
- struct avifDecoder
- codecChoice dd ?
- maxThreads dd ?
- requestedSource dd ?
- allowProgressive dd ?
- allowIncremental dd ?
- ignoreExif dd ?
- ignoreXMP dd ?
- imageSizeLimit dd ?
- imageCountLimit dd ?
- strictFlags dd ?
- image dd ?
- imageIndex dd ?
- imageCount dd ?
- progressiveState dd ?
- imageTiming dd ?
- timescale dd ?
- duration dd ?
- durationInTimescales dd ?
- alphaPresent dd ?
- ioStats dd ?
- diag dd ?
- io dd ?
- data dd ?
- ends
- struct avifRWData
- Data dd ?
- size dd ?
- ends
- struct avifImage
- Width dd ?
- height dd ?
- depth dd ?
- yuvFormat dd ?
- yuvRange dd ?
- yuvChromaSamplePosition dd ?
- yuvPlanes rd 3
- yuvRowBytes rd 3
- imageOwnsYUVPlanes dd ?
- alphaPlane dd ?
- alphaRowBytes dd ?
- imageOwnsAlphaPlane dd ?
- alphaPremultiplied dd ?
- icc dd ?
- colorPrimaries dd ?
- transferCharacteristics dd ?
- matrixCoefficients dd ?
- transformFlags dd ?
- pasp dd ?
- clap dd ?
- irot dd ?
- imir dd ?
- exif avifRWData
- xmp avifRWData
- ends
- struct avifRGBImage
- Width dd ?
- height dd ?
- depth dd ?
- format dd ?
- chromaUpsampling dd ?
- ignoreAlpha dd ?
- alphaPremultiplied dd ?
- isFloat dd ?
- pixels dd ?
- rowBytes dd ?
- ends
- struct BitmapData
- Width dd ?
- Height dd ?
- Stride dd ?
- PixelFormat dd ?
- Scan0 dd ?
- Reserved dd ?
- ends
- AVIF_STRICT_DISABLED = 0
- AVIF_RESULT_OK = 0
- PixelFormat32bppARGB = 26200Ah
- ImageLockModeWrite = 0x0002
Code (Assembler) : Убрать нумерацию
- ; Инициализация GDI+
- mov [gdiplusSInput.GdiplusVersion],1
- mov [gdiplusSInput.DebugEventCallback],0
- mov [gdiplusSInput.SuppressBackgroundThread],0
- mov [gdiplusSInput.SuppressExternalCodecs],0
- invoke GdiplusStartup,gdiplusToken,gdiplusSInput,0
- ; Подготовить кодек AVIF
- invoke avifDecoderCreate
- mov [decoder],eax
- mov ebx,[decoder]
- mov [ebx+avifDecoder.strictFlags],AVIF_STRICT_DISABLED
- mov [ebx+avifDecoder.maxThreads],2
- ; Загрузить данные из памяти
- invoke avifDecoderSetIOMemory,[decoder],fdata,file_size
- ; Декодировать первый кадр изображения
- invoke avifDecoderParse,[decoder]
- invoke avifDecoderNextImage,[decoder]
- invoke avifRGBImageSetDefaults,rgb,[ebx+avifDecoder.image]
- invoke avifRGBImageAllocatePixels,rgb
- invoke avifImageYUVToRGB,[ebx+avifDecoder.image],rgb
- mov eax,[ebx+avifDecoder.image]
- ; Размеры полученного изображения
- mov [rcLock.top],0
- mov [rcLock.left],0
- mov esi,[ebx+avifDecoder.image]
- mov eax,[esi+avifRGBImage.Width]
- mov [dImageWidth],eax
- mov [rcLock.right],eax
- mov eax,[esi+avifRGBImage.height]
- mov [dImageHeight],eax
- mov [rcLock.bottom],eax
- ; Создать битмап
- invoke GdipCreateBitmapFromScan0,\
- [dImageWidth],[dImageHeight],0,\
- PixelFormat32bppARGB,0,xTmp
- or eax,eax
- jnz clear_gdi3
- invoke GdipBitmapLockBits,[xTmp],rcLock,\
- ImageLockModeWrite,\
- PixelFormat32bppARGB, bmd
- ; Перенести изображение из кадра на битмап
- xor edx,edx
- mov eax,[dImageWidth]
- mov ecx,[dImageHeight]
- imul ecx
- mov ecx,eax
- mov esi,[rgb.pixels]
- mov edi,[bmd.Scan0]
- loc_loop:
- ; Преобразовать точку в ABGR
- lodsd
- mov edx,eax
- and eax,0xFF000000
- mov ebx,edx
- and ebx,0x000000FF
- shl ebx,16
- or eax,ebx
- mov ebx,edx
- and ebx,0x0000FF00
- or eax,ebx
- mov ebx,edx
- and ebx,0x00FF0000
- shr ebx,16
- or eax,ebx
- stosd
- loop loc_loop
- invoke GdipBitmapUnlockBits,[xTmp], bmd
- ; Изображение корректное?
- invoke GdipGetImageWidth,[xTmp],tmp
- cmp [tmp],0
- je clear_gdi2
- invoke GdipGetImageHeight,[xTmp],tmp
- cmp [tmp],0
- je clear_gdi2
- ; Создать HBITMAP для установки на static
- invoke GdipCreateHBITMAPFromBitmap,[xTmp],\
- hBitmap,0x00FFFFFF
- cmp [hBitmap],0
- jz clear_gdi2
- ;------------------------------------------
- ; [hBitmap] - хэндд битмапа
- ;------------------------------------------
- ; Освободить графику
- invoke GdipDisposeImage,[xTmp]
- clear_gdi1:
- invoke DeleteObject,[hBitmap]
- clear_gdi2:
- invoke GdipDeleteGraphics,[hGraphics]
- clear_gdi3:
- ; Выключение GDI+
- invoke GdiplusShutdown,[gdiplusToken]
- ; Освободить кодек AVIF
- invoke avifDecoderDestroy,[decoder]
Code (Assembler) : Убрать нумерацию
- ; Загрузить данные из файла
- invoke avifDecoderSetIOFile,[decoder],fname
В приложении примеры программ с исходными текстами, которые масштабируют и выводят на форму изображение в формате AVIF из файла на диске и напрямую из памяти.
Просмотров: 386 | Комментариев: 2
Комментарии
Отзывы посетителей сайта о статье
любитель
(16.12.2024 в 15:10):
А для HEIC подобное будет?
Добавить комментарий
Заполните форму для добавления комментария
https://www.manhunter.ru/softw...ovodnik.html
https://www.manhunter.ru/assem...hyu_wic.html