News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Viewing Animated GIF files

Started by bluedevil, May 18, 2017, 02:31:14 AM

Previous topic - Next topic

bluedevil

Hello people;
I have attached a project which loads an animated GIF using AniGIF library.
We should include the library
Include AniGIF.inc
IncludeLib AniGIF.lib
PUBLIC hInstance

Very important to declare hInstance as PUBLIC!!

Under Window procedure call two functions
PencereIslemi proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
invoke InitAniGIF ;Starts animation
mov eax,uMsg
.if eax==WM_INITDIALOG

              .
              .
              .
              .


.elseif eax==WM_COMMAND
              .
              .
              .
              .
.elseif eax==WM_CLOSE
              .
              .
.else
mov eax,FALSE
ret
.endif
invoke TerminateAniGIF ;HERE terminates animation
mov eax,TRUE
ret

PencereIslemi endp


Very important part :
#define logoGif 501
logoGif RCDATA    DISCARDABLE "Res/nelieltransform.gif"
  CONTROL "#501",aniLogo,"AniGIF",0x50000000,6,3,333,184,0x00000000

You have to write down "AniGIF" to Control section
And you have to define GIF as RCDATA


I want to ask is there any other options to achieve this goal without using these external -AniGIF- libraries?

@jj2007 you have included executables several times to forum. Bu you didnt share any source codes about this issue. Are you also using this libraries? If not can you share any sources with me?

Thanks for all =)

Because of the GIF file the zip file size  is ~700kb So here is a link to Github and Zippyshare
https://github.com/blue-devil/Assembly/tree/master/RadASM/Masm/Projects/GifView
http://www118.zippyshare.com/v/Nwse3uPN/file.html
..Dreams make the future
But the past never lies..
BlueDeviL // SCT
My Code Site:
BlueDeviL Github

jj2007

Quote from: blue_devil on May 18, 2017, 02:31:14 AM@jj2007 you have included executables several times to forum. Bu you didnt share any source codes about this issue. Are you also using this libraries? If not can you share any sources with me?

No, I use only the built-in Windows library GdiPlus. Here is a source:

guiTimerMs=50            ; more is slower
GuiParas equ "Simple GIF viewer", w240, h200
include \masm32\MasmBasic\Res\MbGui.asm      ; part of MasmBasic

Event Paint
  .if CL$(?)
      GuiImage CL$(), fit      ; drag an animated gif over the exe
  .else
      GuiImage 100, fit      ; or show tweetie from the resources
  .endif
GuiEnd


Full project attached, needs MasmBasic, of course.

\masm32\MasmBasic\Res\MbGui.asm is a public part of MasmBasic; the rest is closed source, but I could give you a personal exclusive license to disassemble the closed part, if you give me a good reason :bgrin:

For example, you could insert an int 3 into line 15572 of \Masm32\MasmBasic\MasmBasic.inc ;)

bluedevil

Quote from: jj2007 on May 18, 2017, 04:41:16 AM
Quote from: blue_devil on May 18, 2017, 02:31:14 AM@jj2007 you have included executables several times to forum. Bu you didnt share any source codes about this issue. Are you also using this libraries? If not can you share any sources with me?

No, I use only the built-in Windows library GdiPlus. Here is a source:

guiTimerMs=50            ; more is slower
GuiParas equ "Simple GIF viewer", w240, h200
include \masm32\MasmBasic\Res\MbGui.asm      ; part of MasmBasic

Event Paint
  .if CL$(?)
      GuiImage CL$(), fit      ; drag an animated gif over the exe
  .else
      GuiImage 100, fit      ; or show tweetie from the resources
  .endif
GuiEnd


Full project attached, needs MasmBasic, of course.

\masm32\MasmBasic\Res\MbGui.asm is a public part of MasmBasic; the rest is closed source, but I could give you a personal exclusive license to disassemble the closed part, if you give me a good reason :bgrin:

For example, you could insert an int 3 into line 15572 of \Masm32\MasmBasic\MasmBasic.inc ;)

1. As a MASM32 coder i cannot understand your way of codes. In my MASM directory i have a MasmBasic directory too. But it says:
Quote; The smallprint: this library is provided "as is", and the usual disclaimers apply.
; This help file refers to MasmBasic version 4 October 2012
; -----------------------------------------------------------------------
include \masm32\MasmBasic\MasmBasic.inc   ; this line substitutes include \masm32\include\masm32rt.inc
Is this old or very old version?
2. What is .ASC file doing exactly?
3. Generally hutch-- gives more pure assembly samples. But i always open to new knowledge. But here i have 2 issues.
3.a. I want to learn assembly, all syntaxes, rules, constants and everything. And in a very low-level way
3.b. I want to use RadASM as an IDE because i am the guy translated it in Turkish so i know every part of it.
4.When i see your code above i cannot implement that inside my own code :( Because i cannot understand what GuiImage does, what CL does and what $ does after CL?
5.At the end there must be a windows API but i still couldn't get there :(
..Dreams make the future
But the past never lies..
BlueDeviL // SCT
My Code Site:
BlueDeviL Github

jj2007

Quote from: blue_devil on May 18, 2017, 05:58:57 AM
1. As a MASM32 coder i cannot understand your way of codes. In my MASM directory i have a MasmBasic directory too. But it says:
Quote; The smallprint: this library is provided "as is", and the usual disclaimers apply.
; This help file refers to MasmBasic version 4 October 2012
; -----------------------------------------------------------------------
include \masm32\MasmBasic\MasmBasic.inc   ; this line substitutes include \masm32\include\masm32rt.inc
Is this old or very old version?

Almost five years old. Incredibly old. How old is your current smartphone? The current MasmBasic version is dated 12 May 2017. But caution, installing MasmBasic is incredibly complicated. Well, actually not that complicated, maybe installing GCC or VS Community can give you even more headaches ::)

Quote2. What is .ASC file doing exactly?

Assembler Source Code. Extract AnimatedGifViewer.asc and Tweetie.gif to any folder, then open the *.asc in \Masm32\MasmBasic\RichMasm.exe and hit the F6 key. The two files in the zip are the complete project.

Quote3. Generally hutch-- gives more pure assembly samples. But i always open to new knowledge. But here i have 2 issues.
3.a. I want to learn assembly, all syntaxes, rules, constants and everything. And in a very low-level way

Hutch is a very good at low level assembler, but he is equally good at writing macros and high-level library functions, see \masm32\help\masm32.chm

The question "is pure low level assembler better than using macros?" is very important in the early stages of learning. Later on, you will still be able to write low level assembler, but if you don't use macros, you will never go significantly beyond the hello world proggie stage. If you wonder what "significantly" means: The source of the RichMasm editor is currently close to 20,000 lines. That is a medium size program. Theoretically, one could write such a program in push push call style, have fun.

Quote3.b. I want to use RadASM as an IDE because i am the guy translated it in Turkish so i know every part of it.

It should be is possible*) to use MasmBasic from RadASM - after all, it's assembler, in the sense of: ML.exe can digest a MasmBasic source, from version 6.15 onwards. I haven't tested it, though (and I prefer HJWasm for building my stuff). Has anybody tested using MB in RadASM?

Quote4.When i see your code above i cannot implement that inside my own code :( Because i cannot understand what GuiImage does, what CL does and what $ does after CL?
5.At the end there must be a windows API but i still couldn't get there :(

There is a MasmBasic manual, and there is one for OllyDbg, too.

*) RadAsm assembles the source without problems, but convincing the IDE to add the resource and compile it is a major challenge :dazzled: In the end, I gave up with the *.rc file, instead I copied the rsrc.res from the MasmBasic folder and changed the linker's commandline by hand, adding rsrc.res. The full RadASM project is attached.

qWord

#4
blue_devil ,

a short demonstration using Gdiplus. See msdn for deatils of the used functions. Requires foo.gif in current dir and cmd option /Zp8
include \masm32\include\masm32rt.inc
include \masm32\include\gdiplus.inc
includelib \masm32\lib\gdiplus.lib
.686

.data?
    hInstance   HINSTANCE   ?
.code

WndProc proto hWnd:HWND,uMgs:UINT,wParam:WPARAM,lParam:LPARAM

main proc
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL gsi:GdiplusStartupInput
LOCAL gtkn:PULONG

    mov gsi.GdiplusVersion,1
    mov gsi.DebugEventCallback,0
    mov gsi.SuppressBackgroundThread,0
    mov gsi.SuppressExternalCodecs,0
    invoke GdiplusStartup,ADDR gtkn,ADDR gsi,0

    mov hInstance,rv(GetModuleHandle,0)
    mov wc.hInstance,eax
    mov wc.cbSize,SIZEOF wc
    mov wc.style,CS_HREDRAW or CS_VREDRAW or CS_SAVEBITS
    mov wc.lpfnWndProc,OFFSET WndProc
    mov wc.cbClsExtra,0
    mov wc.cbWndExtra,0
    mov wc.hIcon,rv(LoadIcon,0,IDI_APPLICATION)
    mov wc.hIconSm,eax
    mov wc.hCursor,rv(LoadCursor,0,IDC_ARROW)
    mov wc.lpszMenuName,0
    mov wc.hbrBackground,0
    mov wc.lpszClassName,chr$("Win32Wnd")
    invoke RegisterClassEx,ADDR wc
   
    mov ebx,ASM(mov edi,rv(GetSystemMetrics,SM_CXSCREEN))
    mov ecx,rv(GetSystemMetrics,SM_CYSCREEN)
    shr ebx,1
    shr eax,1
    shr edi,2
    shr ecx,2
    fnx esi = CreateWindowEx,0,wc.lpszClassName,"Foo32",WS_VISIBLE or WS_SYSMENU or WS_MAXIMIZEBOX or WS_MINIMIZEBOX or WS_SIZEBOX,edi,ecx,ebx,eax,0,0,hInstance,0
    invoke UpdateWindow,esi
   
    .while 1
        invoke GetMessage,ADDR msg,0,0,0
        .break .if !eax || eax == -1
        invoke TranslateMessage,ADDR msg
        invoke DispatchMessage,ADDR msg     
    .endw

    invoke GdiplusShutdown,gtkn
    invoke ExitProcess,msg.wParam
   
main endp

getDelayProp proc image:PVOID
LOCAL propSize:UINT
LOCAL delayProp: ptr PropertyItem

    invoke GdipGetPropertyItemSize,image, PropertyTagFrameDelay, ADDR propSize
   
    mov delayProp,alloc(propSize)

    invoke GdipGetPropertyItem,image, PropertyTagFrameDelay, propSize, delayProp

    mov eax,delayProp
    ret
   
getDelayProp endp

getFrameCount proc image:PVOID, dimGuid: ptr GUID
LOCAL dimCount:DWORD
LOCAL dimensionIDs: ptr GUID
LOCAL count:DWORD
   
    invoke GdipImageGetFrameDimensionsCount,image, ADDR dimCount
   
    .if eax || dimCount != 1
        xor eax,eax
        ret
    .endif
   
    imul edx,dimCount,SIZEOF GUID
    mov dimensionIDs,alloc(edx)
     
    invoke GdipImageGetFrameDimensionsList,image,dimensionIDs, dimCount
   
    invoke GdipImageGetFrameCount,image,dimensionIDs,ADDR count
   
    invoke RtlMoveMemory,dimGuid,dimensionIDs,SIZEOF GUID

    free dimensionIDs
   
    mov eax,count
    ret
   
getFrameCount endp


getDelayForFrame proc delayProp:ptr PropertyItem, frameNo:DWORD
   
   
    mov edx,delayProp
    assume edx: ptr PropertyItem
   
    mov ecx,[edx]._length
    .if [edx].nType == PropertyTagTypeLong ||[edx].nType == PropertyTagTypeSLONG
        shr ecx,2
    .elseif [edx].nType == PropertyTagTypeShort
        shr ecx,1
    .elseif [edx].nType != PropertyTagTypeByte
        ; error case
        int 3
    .endif
   
    .if ecx < frameNo
        ; error case
        int 3
    .endif
   
    mov ecx,[edx].value
    mov eax,frameNo
    .if [edx].nType == PropertyTagTypeLong ||[edx].nType == PropertyTagTypeSLONG
        mov eax,DWORD ptr [ecx + DWORD*eax]
    .elseif [edx].nType == PropertyTagTypeShort
        movzx eax,WORD ptr [ecx + WORD*eax]
    .else
        movzx eax,BYTE ptr [ecx + eax]
    .endif
   
    assume edx: nothing
   
    imul eax,10 ; GIF delay unit is 1/100s => mul. with 10 to get milliseconds
   
    ret
   
getDelayForFrame endp

WndProc proc uses ebx esi hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
LOCAL rect:RECT
LOCAL ps:PAINTSTRUCT
LOCAL graphics:PVOID

    .data?
        gifImage PVOID ?
        delayProp  PVOID ? ; ptr PropertyItem
        frameCount SDWORD ?
        frameDimGuid GUID <>
        frameNumber SDWORD ?
    .code

    .if uMsg == WM_CLOSE
        invoke PostQuitMessage,0
    .elseif uMsg == WM_DESTROY
   
        invoke GdipDisposeImage, gifImage
       
        free delayProp
       
    .elseif uMsg == WM_CREATE
       
        fnx GdipLoadImageFromFile,L"foo.gif", ADDR gifImage
       
        fnx delayProp = getDelayProp,gifImage
               
        fnx frameCount = getFrameCount,gifImage,ADDR frameDimGuid
       
        .if frameCount > 1
           
            add frameNumber,1
           
            invoke getDelayForFrame,delayProp,frameNumber
            invoke SetTimer,hWnd,123,eax,NULL
           
        .endif
       
       
    .elseif uMsg == WM_TIMER && wParam == 123
       
        invoke KillTimer,hWnd,123
       
        invoke GdipImageSelectActiveFrame,gifImage, ADDR frameDimGuid, frameNumber

        mov eax,frameNumber
        add eax,1
        .if eax == frameCount
            xor eax,eax
        .endif
        mov frameNumber,eax
       
        invoke getDelayForFrame,delayProp,eax
        invoke SetTimer,hWnd,123,eax,NULL
       
        invoke InvalidateRect,hWnd,NULL,FALSE
       
    .elseif uMsg == WM_PAINT
   
        invoke BeginPaint,hWnd,ADDR ps
       
        invoke GetClientRect,hWnd,ADDR rect
       
        fnx ebx = CreateCompatibleDC,ps.hdc
        invoke CreateCompatibleBitmap,ps.hdc,rect.right,rect.bottom
        fnx esi = SelectObject,ebx,eax
       
        invoke GdipCreateFromHDC,ebx, ADDR graphics

        invoke GdipGraphicsClear,graphics,-1
       
        invoke GdipDrawImageI,graphics, gifImage,0,0
       
        invoke BitBlt,ps.hdc,0,0,rect.right,rect.bottom,ebx,0,0,SRCCOPY
       
        invoke DeleteObject,rv(SelectObject,ebx,esi)
        invoke DeleteDC,ebx
        invoke GdipDeleteGraphics,graphics
        invoke EndPaint,hWnd,ADDR ps
       
    .else
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam
        ret
    .endif
   
    xor eax,eax
    ret
   
WndProc endp
end main


BTW: What has happen to this forum? "Use masmbasic" is now the accepted default answer to any upcoming question?
MREAL macros - when you need floating point arithmetic while assembling!

newrobert

i remember there was static gif lib, no ani gif lib.

jj2007

Quote from: qWord on May 18, 2017, 11:35:28 AMBTW: What has happen to this forum? "Use masmbasic" is now the accepted default answer to any upcoming question?

OP asked explicitly how I did it. Apart from this post, I made a quick check and found out that my last 28 posts had nothing to do with MasmBasic. So your remark proves that you are German and nothing else. Btw you should try MasmBasic, much faster than C and (no) [ugly] {brackets} or se;mi;co;lons;  8)

fearless

Quote from: qWord on May 18, 2017, 11:35:28 AM
and cmd option /Zp8

Hi qWord, thanks for the example, just wondering why the /Zp8 is required? is it some alignment with data structures or for the gif file. Thanks in advance

HSE

Hi qWord!

Without /Zp I have a crash in:        mov eax,DWORD ptr [ecx + DWORD*eax]
in theory is a 4 bytes problem. And work perfect with /Zp4  :t


Equations in Assembly: SmplMath

hutch--

qword,

I am not sure why but after building it with the /Zp8 option and placing an animated gif in the same directory, it builds with no errors but will not run. Ends up in memory but nothing shows.

qWord

Quote from: fearless on May 18, 2017, 10:45:04 PMjust wondering why the /Zp8 is required?
It the default structure member alignment in Win32 and should be always used to avoid strange errors. For most structures it has no effect because of their layout. In the above example it is the PropertyItem structure that has a WORD-sized member breaking the alignment of the following pointer (and yes, for this structure also Zp4 works, because there are no 64 bit width members in it)

Quote from: jj2007 on May 18, 2017, 04:40:11 PM
OP asked explicitly how I did it.
He explicit ask how do it with plain WinAPI.

Quote from: jj2007 on May 18, 2017, 04:40:11 PMApart from this post, I made a quick check and found out that my last 28 posts had nothing to do with MasmBasic.
just ignoring the several thousand other post you did with more or less "advertising".

Quote from: jj2007 on May 18, 2017, 04:40:11 PMSo your remark proves that you are German and nothing else
Yes Mr. "I know the answer, but I won't give it to you"
MREAL macros - when you need floating point arithmetic while assembling!

qWord

Quote from: hutch-- on May 19, 2017, 12:30:09 AM
I am not sure why but after building it with the /Zp8 option and placing an animated gif in the same directory, it builds with no errors but will not run. Ends up in memory but nothing shows.
strange - can you upload the EXE?
MREAL macros - when you need floating point arithmetic while assembling!

qWord

MREAL macros - when you need floating point arithmetic while assembling!

hutch--

Just tried your build, will not run on my Win10 64 bit.

I have attached the source and how I built it and used your GIF file.

I could not get your window to start so I put all of your GDIP code in another window but it was looking for code that was not available. Are you using a special GDI plus include file ?

qWord

Your build works fine on win7x64

I guess there is some incompatibility in my code - would require to analyze the return values of the GDIP functions. I will try it later with a Win10 dev VM.

Quote from: hutch-- on May 19, 2017, 01:12:37 AMAre you using a special GDI plus include file ?
Actual not.
MREAL macros - when you need floating point arithmetic while assembling!