FreeBASIC マニュアルのトップに戻る

FreeBASIC GIF アニメーション(動画)を表示

目次→フォーラム→FreeBASIC→補足Accessing GIF Frames and Displaying GIF Images/Animations←オリジナル・サイト

GIF アニメーション(動画)を表示 左にメニュー・フレームが表示されていない場合は、ここをクリックして下さい

←リンク元に戻る プログラム開発関連に戻る

画像ファイル GIF には、動画を表示できる アニメーションGIF があります。
ここでは、FreeBASIC フォーラムで UEZ さんに作成してもらったプログラムを紹介します。
画像表示に GDI+(GdiPlus)を使っています。

参考1:GDI+入門

参考2:UEZ さんの描画関連プログラム集
FreeBasic Graphical Examples build 2019-05-08
https://www.autoitscript.com/forum/topic/185024-freebasic-graphical-examples-build-2019-05-08/
参考3:UEZ さんの描画関連プログラム集:美しさ-数学の魔法
https://www.freebasic.net/forum/viewtopic.php?f=7&t=29021
https://www.mediafire.com/file/64z8zpob2jirec4/The_beauty_-_magic_of_math_Vol._I_-_VII_build_2021-10-07.7z/file

プログラムと画像ファイルをダウンロードできます。→AdditionUsing2DicesAnimation.zip

注意:このコードのソースは、IDE-poseidonFB などを使って、Unicode(UTF16LE)で、表示・編集して下さい。

注:FreeBASIC 1.08〜 で、SetEnviron を追加しなくても、日本語環境で描画画面が表示されるように改善されました。
さいころを振る
'//------------------------------------//
'作成 2019/07/14、更新 2020/10/07
'プログラミングの考え方:さいころを 2つ使って足し算の問題を自動生成してみる
'注意: このソースは、ユニコードで、表示・編集して下さい。
'//------------------------------------//

'coded by UEZ build  2019-07-12
'https://www.freebasic.net/forum/viewtopic.php?t=23934
'Add Screencontrol 2020-06-15

#Ifdef __Fb_64bit__
    #Inclib "gdiplus"
    #Include "win/gdiplus-c.bi"
#Else
    #Include "win/gdiplus.bi"
    Using gdiplus
#Endif

#Include "fbgfx.bi"

' Sets the graphics method GDI
' 描画方法を GDI に設定
SetEnviron("fbgfx=GDI")

Using FB 

Dim Shared gdipToken As ULONG_PTR
Dim Shared GDIp As GdiplusStartupInput 

'アニメーションGIFをデコードして、フレームを選択
Function _GDIPlus_GIFAnimGetFrameDimensionsCount(Byval hImage As Any Ptr) As Ulong
   Dim As Ulong iFrameDimCount
   GdipImageGetFrameDimensionsCount(hImage, @iFrameDimCount)
   Return iFrameDimCount
End Function

Function _GDIPlus_GIFAnimGetFrameDimensionsList(Byval hImage As Any Ptr, Byval iFrameDimCount As Ulong) As GUID
   Dim As GUID FrameDimList
   GdipImageGetFrameDimensionsList(hImage, @FrameDimList, iFrameDimCount)
   Return FrameDimList
End Function

Function _GDIPlus_GIFAnimGetFrameCount(Byval hImage As Any Ptr, Byval tFrameDimList As GUID) As Ulong
   Dim As Ulong iFrameCount
   GdipImageGetFrameCount(hImage, @tFrameDimList, @iFrameCount)
   Return iFrameCount
End Function

Sub _GDIPlus_GIFAnimSelectActiveFrame(Byval hImage As Any Ptr, Byval tFrameDimList As GUID, Byval iCurrentFrame As Ulong)
   GdipImageSelectActiveFrame(hImage, @tFrameDimList, iCurrentFrame)
End Sub

Function _GDIPlus_ImageGetPropertyItem(Byval hImage As Any Ptr, Byval iPropID As PROPID) As PropertyItem Ptr
   Dim As Ulong iSize
   GdipGetPropertyItemSize(hImage, iPropID, @iSize)
   Dim As PropertyItem Ptr buffer
   buffer = Allocate(iSize * SizeOf(PropertyItem))
   GdipGetPropertyItem(hImage, iPropID, iSize, @buffer[0])
   Return buffer
End Function

Sub _GDIPlus_GIFAnimGetFrameDelays(Byval hImage As Any Ptr, Byval iAnimFrameCount As Ulong, aFrameDelay() As Ulong)
   Dim As PropertyItem Ptr PropItem = _GDIPlus_ImageGetPropertyItem(hImage, PROPERTYTAGFRAMEDELAY)
   Select Case PropItem->type
      Case 1
         Dim As Ubyte Ptr delay = PropItem->value
         For i As Ulong = 0 To Ubound(aFrameDelay)
            aFrameDelay(i) = delay[i] * 10
         Next
      Case 3
         Dim As Ushort Ptr delay = PropItem->value
         For i As Ulong = 0 To Ubound(aFrameDelay)
            aFrameDelay(i) = delay[i] * 10
         Next
      Case 4
         Dim As Ulong Ptr delay = PropItem->value
         For i As Ulong = 0 To Ubound(aFrameDelay)
            aFrameDelay(i) = delay[i] * 10
         Next
   End Select
End Sub
'GDIPlus GIFセクションを終了

Function _GDIPlus_Startup() As Bool
   GDIp.GdiplusVersion = 1
   If GdiplusStartup(@gdipToken, @GDIp, NULL) <> 0 Then
      Error 1
      Return False
   Endif
   Return True
End Function

Sub _GDIPlus_Shutdown()
   GdiplusShutdown(gdipToken)
End Sub

Function _GDIPlus_ImageLoadFromFile(Byval sFilename As String) As Any Ptr
   Dim GDIpImage As Any Ptr
   If (GdipLoadImageFromFile(Wstr(sFilename), @GDIpImage) <> 0) Then
      Error 1
      Return 0
   End If
   Return GDIpImage
End Function

Sub RollDices()
   'GDIPlus 初期化
   If _GDIPlus_Startup() = False Then End -1

   
   Dim As String sFile = "tenor2.gif" '<------- ここで GIF アニメのファイル名を指定
   
   
   Dim As Any Ptr hGIFAnim = _GDIPlus_ImageLoadFromFile(sFile) 'GIG アニメファイルを読み込む
   
   Dim As Single iW, iH
   
   GdipGetImageDimension(hGIFAnim, @iW, @iH)   'GIF アニメの寸法を取得
   
   If iW = 0 Then 
      GdiplusShutdown(gdipToken)
      Messagebox(0, "Something went wrong to load the GIF animation!", "ERROR", 16)
      End -2
   End If
   
   'アニメを表示する FB GUIを作成する
	iW =640 : iH =480
   Screencontrol SET_DRIVER_NAME, "GDI"
   Screenres iW, iH, 32, 1, GFX_HIGH_PRIORITY Or GFX_NO_SWITCH 
   'Dim As String sWinTitle = "GDIPlus GIF Anim Player by UEZ"
   Dim As String sWinTitle = "足し算の問題を自動生成   "
   
   Dim As Integer iDW, iDH
   Screencontrol GET_DESKTOP_SIZE, iDW, iDH
   Dim tWorkingArea As RECT
   SystemParametersInfo(SPI_GETWORKAREA, null, @tWorkingArea, null)
   Screencontrol SET_WINDOW_POS, (iDW - iW) \ 2, ((tWorkingArea.Bottom - iH) - (iDH - tWorkingArea.Bottom)) \ 2
   
   
   Dim As HWND hHWND
   Screencontrol(GET_WINDOW_HANDLE, Cast(Integer, hHWND)) 'GDI+ 描画ハンドルを表示するための FB GUIハンドルを取得
   
   'GIF アニメを表示するバッファ付きGDIデバイスを作成する
   Dim As Any Ptr    hCanvas, _
               hDC = GetDC(hHWND), _
               hHBitmap = CreateCompatibleBitmap(hDC, iW, iH), _
               hDC_backbuffer = CreateCompatibleDC(hDC), _
               hDC_obj = SelectObject(hDC_backbuffer, hHBitmap)
   GdipCreateFromHDC(hDC_backbuffer, @hCanvas)   
   
   'GDI+ で GIF アニメーションを設定する
   Dim As Ulong iFrame = 0, iFrameDimCount = _GDIPlus_GIFAnimGetFrameDimensionsCount(hGIFAnim)
   Dim As GUID tFrameDimList = _GDIPlus_GIFAnimGetFrameDimensionsList(hGIFAnim, iFrameDimCount)
   Dim As Ulong iFrames = _GDIPlus_GIFAnimGetFrameCount(hGIFAnim, tFrameDimList)
   Dim As Ulong aFrameDelays(0 To iFrames - 1)
   _GDIPlus_GIFAnimGetFrameDelays(hGIFAnim, iFrames, aFrameDelays())
   
   'フレーム遅延を含めてリアルタイムでGUI でアニメーションをループせずに再生
   Do
      _GDIPlus_GIFAnimSelectActiveFrame(hGIFAnim, tFrameDimList, iFrame) 'フレーム抽出
      GdipDrawImageRect(hCanvas, hGIFAnim, 0, 0, iW, iH) 'GDI キャンバスにフレームをコピー
      BitBlt(hDC, 0, 0, iW, iH, hDC_backbuffer, 0, 0, SRCCOPY) 'GUI にブリットフレーム
      Sleep aFrameDelays(iFrame)
      Windowtitle sWinTitle & " * Frame: " & iFrame + 1 & " / " & iFrames
      iFrame += 1
   Loop Until iFrame = iFrames
   
   'Sleep
   
   'GDI / GDI+ リソースを解放
   SelectObject(hDC_backbuffer, hDC_obj)
   DeleteDC(hDC_backbuffer)
   DeleteObject(hHBitmap)
   ReleaseDC(hHWND, hDC)
   GdipDeleteGraphics(hCanvas)
   GdipDisposeImage(hGIFAnim)
   _GDIPlus_Shutdown()
   
   'End 0
End Sub

'//------------------------------------//
'作成 2019/07/14
'プログラミングの考え方:さいころを 2つ使って足し算の問題を自動生成してみる
'注意: このソースは、ユニコードで、表示・編集して下さい。
'//------------------------------------//

#Include Once "xfont.bi"

Dim A As Integer
Dim B As Integer
Dim S As Integer
Dim Dice1 As Any Ptr
Dim Dice2 As Any Ptr
Dim FileName1 As String
Dim FileName2 As String
Dim KeyMoji As String

Dim x As Integer
Dim y As Integer
Dim Japanese As WString * 20
Dim Shared As xfont.interface font
font.loadfont("MsGothic.xf", 1) 'FontIndex 1 に、登録します
font.fontindex = 1 'フォントを使います


Print "サイコロを使って、足し算の問題を自動生成します。"
Print "何かキー入力で回答を表示します。そして次の問題を生成してます。"
Print "問題生成のくり返えしは、[Esc]キーで抜けます。"
Print

Screen 18, 32

Dice1 = ImageCreate(170,170)  '画像のために、記憶装置を、割り当てて、初期化します。
Dice2 = ImageCreate(170,170)  '画像のために、記憶装置を、割り当てて、初期化します。

Randomize

Do

   ScreenRes 640, 480, 32
   A = Rnd * 6 + 0.5
   B = Rnd * 6 + 0.5
   S = A+B
   
   RollDices  'GIF アニメを再生

   Cls
   FileName1 = "dice" & Str(A) & ".bmp"
   FileName2 = "dice" & Str(B) & ".bmp"
   BLoad FileName1, Dice1
   BLoad FileName2, Dice2
   
   Put (70,200),Dice1
   Put (360,200),Dice2
   
   Print
   Print
   Print
   Print
   Print Using "  ## + ## = "; A; B;
   Sleep
   
   Japanese =" " & Str(S) & "   [Esc]キーで抜ける"
   x = 70
   y = 100
   font.drawstring ( , Japanese , x, y,4,4) '文字の大きさ 4倍 size
   

   KeyMoji=InKey                      'キーボード・バッファで、キー入力を待って、最初のキーの文字を返します。

   Sleep(2000)
   KeyMoji=InKey                      'キーボード・バッファで、キー入力を待って、最初のキーの文字を返します。

Loop Until KeyMoji=Chr(27)  ' [27]=[Esc] キー入力するまで、繰返す

ImageDestroy(Dice1)     '画像のための記憶装置を破棄して、割り当てを解除します。
ImageDestroy(Dice2)
 
補足 に戻る
←リンク元に戻る プログラム開発関連に戻る
日本語著作:WATANABE Makoto

ホームページのトップに戻る

表示-非営利-継承