【Excel VBA】GIF 화상 파일이 애니메이션 GIF인지 판별하는 툴의 작성 _그 ①(VBA의 기능만을 사용해 실장)

1. 이 기사에 관하여



이런 경우를 상정.
"GIF 이미지가 애니메이션 GIF인지 일반 GIF인지 판별하고 싶습니다"
<< 환경 제약으로 Office 소프트웨어의 VBA 만 사용할 수있을 때
(C#의 ImageAnimator.CanAnimate 메서드나 imagemagick 등의 뛰어난 외부 라이브러리를 사용할 수 없는 패턴을 상정),
VBA에서만 문제를 해결하고 싶다 >>
《객처의 요망 등으로 보수성의 관점에서 VBA만으로 구현해 주었으면 하는 경우》

2.하고 싶은 일과 참고로 한 자료



GIF 화상 파일의 구조에 대해서는 아래의 사이트를 참고로 했습니다.

GIF 형식 세부 정보 : http://www.tohoho-web.com/wwwgif.htm

그 중에 다음과 같은 설명이있었습니다.

일반적인 GIF 애니메이션은 GIF Header 뒤에 Application Extension이 있고 그 뒤에 Graphic Control Extension과 Image Block이 번갈아 연속한다.

Application Extension은 Netscape에 의해 확장된 Loop Control로 사용되며, Application Identifier에는 >"NETSCAPE", Application Authentication Code에는 "2.0"문자가 저장됩니다. Application Data로서 1바이트의 0x01 및 2바이트의 루프 회수(0~65535)가, 예를 들면 루프 회수가 5회의 경우는 0x01 0x05 0x00의 3바이트가 저장된다.

즉, 이미지 파일의 바이트 열에서 "NETSCAPE"라는 문자열의 바이트 열과 일치하는 부분이 있으면 애니메이션 GIF라는 것입니다.

따라서,
① 우선 「지정의 문자열을 바이트열로 변환하는 툴」을 작성해 NETSCAPE를 바이트열로 변환해,
②「①」에서 얻은 결과를 이용하여 애니메이션 GIF를 판별하는 툴을 작성한다
라고 하는 순서를 취했습니다.

3. 작성한 코드



(1)



우선 ①의 지정의 캐릭터 라인을 바이트열로 변환하는 툴로부터.

M_JudgeAnimationGif.bas
'******************************************************************************************
'*関数名    :convertByteArrayFromString
'*機能      :指定文字列をバイト列に変換し、指定セルにカンマ区切りで出力
'*引数(1)   :変換対象文字列格納セルオブジェクト
'*引数(2)   :出力先のセルオブジェクト
'******************************************************************************************
Public Sub convertByteArrayFromString(ByVal inputStrCell As Range, _
                                        ByRef outputCell As Range)

    '定数
    Const FUNC_NAME As String = "convertByteArrayFromString"

    '変数
    Dim inputStr As String               '対象文字列
    Dim outputByte() As Byte             '格納先バイト列
    Dim cnt As Long                      'ループカウンタ


    On Error GoTo ErrorHandler
    '---以下に処理を記述---

    '///出力先を初期化
    outputCell.Value = ""

    '///文字列を取得
    inputStr = StrConv(inputStrCell.Value, vbFromUnicode)

    '///バイト列に格納
    outputByte = inputStr

    '///出力処理
    With outputCell
        '出力
        For cnt = LBound(outputByte) To UBound(outputByte)
            .Value = .Value & outputByte(cnt)
            'カンマを付加
            If cnt <> UBound(outputByte) Then
                .Value = .Value & ","
            End If
        Next
    End With


ExitHandler:

    Exit Sub

ErrorHandler:

        MsgBox "エラーが発生しましたので終了します" & _
                vbLf & _
                "関数名:" & FUNC_NAME & _
                vbLf & _
                "エラー番号" & Err.Number & Chr(13) & Err.Description, vbCritical

        GoTo ExitHandler

End Sub

이것을 시트의 버튼에 설정해, 인수로서 적절한 셀 오브젝트를 준다면, 아래와 같이 되었습니다.



--------------------NETSCAPE에 대해 실행--------------------



(2)



그런 다음 78,69,84,83,67,65,80,69 바이트 열을 사용하여
애니메이션 GIF의 판별 코드를 작성합니다.

M_JudgeAnimationGif.bas
'******************************************************************************************
'*関数名    :isAnimationGifImage
'*機能      :指定のGIF画像ファイルがアニメーションであるかどうか判別する
'*引数(1)   :指定する画像ファイルのフルパス
'*引数(2)   :アニメーションであるかどうかの判定を出力するセルオブジェクト
'******************************************************************************************
Public Sub isAnimationGifImage(ByVal filePath As String, _
                                ByRef outputCell As Range)

    '定数
    Const FUNC_NAME As String = "isAnimationGifImage"

    '変数
    Dim fileExpression As String            'ファイル拡張子
    Dim picObject As Object                 '画像ファイル格納オブジェクト
    Dim byteData() As Byte                  'バイト列
    Dim fileNum As Long                     'ファイル番号
    Dim cnt As Long                         'ループタウンタ

    On Error GoTo ErrorHandler
    '---以下に処理を記述---

    '///拡張子取得
    fileExpression = Mid(filePath, InStrRev(filePath, ".") + 1)
    '拡張子がgifであるファイルのみ処理を続行
    If fileExpression <> "gif" Then
        outputCell.Value = "指定されたファイルはGIFファイルではありません。"
        GoTo ExitHandler
    End If

    '///画像ファイルのみ処理を続行
    On Error GoTo 0
    On Error Resume Next
    Set picObject = LoadPicture(filePath)
    On Error GoTo 0
    On Error GoTo ErrorHandler
    '正しくloadできていないならExitHandlerへ
    If picObject Is Nothing Then
        outputCell.Value = "指定されたファイルは画像ファイルではありません。"
        GoTo ExitHandler
    End If

    '///バイト列の格納処理
    '余っているファイル番号取得
    fileNum = FreeFile

    '指定されたファイルをバイナリモードで開く
    Open filePath For Binary As #fileNum
        'ファイルの長さで配列を初期化
        ReDim byteData(0 To LOF(fileNum))
        'ファイルをバイナリで読み込んでByte配列に格納
        Get fileNum, , byteData
    Close #fileNum

    '///gifアニメ判別処理
    'バイト列をループする
    For cnt = 0 To UBound(byteData) - 7
        'アニメーションGIFの識別文字列「NETSCAPE」のバイナリコードが見つかるまでループする
        If byteData(cnt) = 78 Then
            If byteData(cnt + 1) = 69 Then
                If byteData(cnt + 2) = 84 Then
                    If byteData(cnt + 3) = 83 Then
                        If byteData(cnt + 4) = 67 Then
                            If byteData(cnt + 5) = 65 Then
                                If byteData(cnt + 6) = 80 Then
                                    If byteData(cnt + 7) = 69 Then
                                        outputCell.Value = "TRUE:指定したファイルはアニメーションGIF画像ファイルです。"
                                        GoTo ExitHandler
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        End If
    Next

    '見つからなければ非アニメーションGIF
    outputCell.Value = "FALSE:指定したファイルはアニメーションGIF画像ファイルではありません。"


ExitHandler:

    Exit Sub

ErrorHandler:

        MsgBox "エラーが発生しましたので終了します" & _
                vbLf & _
                "関数名:" & FUNC_NAME & _
                vbLf & _
                "エラー番号" & Err.Number & Chr(13) & Err.Description, vbCritical

        GoTo ExitHandler

End Sub


이것을 시트의 버튼에 설정해, 인수로서 적절한 셀 오브젝트를 준다면, 아래와 같이 되었습니다.



4. 코드 해설



IF의 다중 중첩 정보



보기 좋지는 않지만 AND 연산자를 사용하는 것보다 처리가 빠릅니다 (VBA 사양에서 AND로 연결된 모든 것을 평가하기 위해)
참고 URL: VBScript의 And, Or에는 조심해~Java 익숙한 개발자의 헛된 함정 |

개선안:GOTO문을 사용해 의사 Continue 처리를 하면 가독성은 향상할지도 모르겠네요.

5. 끝에



※20191208
계속되는 기사를 썼습니다.
【Excel VBA】GIF 화상 파일이 애니메이션 GIF인지 판별하는 툴의 작성_그 ②「다른 방법으로 처리 속도를 비교」

이번에 만든 도구에 대해
Github에게 주었으므로 좋으면 참조하십시오.

Github



뭔가 보충이 있으면 댓글주세요.

좋은 웹페이지 즐겨찾기