[[20240330113454]] 『指定フォルダー内のファイル(JPEG)のサイズを正普x(Muse) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) |

| 全文検索 | 過去ログ ]

 

『指定フォルダー内のファイル(JPEG)のサイズを正方形に変換して同名で保存』(Muse)

ExcelのVBAで指定フォルダー内のファイル(JPEG)のサイズ(横1x縦1)を正方形に変換して同名で保存したい。
正方形のサイズとは、(横1+縦1)/2と縦と横が同じサイズのことです。
(変更時にアスペクト比を維持する必要はありません。)

以下を試して見ましたが変化がありません。
(コードは、ネットを参考にしました。)

Option Explicit

Sub RESIZETEST()

    Dim folderPath As String
    Dim fileName As String
    Dim filePath As String
    Dim newWidth As Long
    Dim newHeight As Long

    ' 変換するフォルダーのパスを指定
    folderPath = "C:\Users\mido\"

    ' フォルダー内のJPEGファイルを処理
    fileName = Dir(folderPath & "*.jpg")
    While fileName <> ""
        filePath = folderPath & fileName

        ' 画像のサイズを取得
        Dim oImageFile As Object
        Set oImageFile = CreateObject("WIA.ImageFile")
        oImageFile.LoadFile filePath

        ' 正方形のサイズを計算
        newWidth = (oImageFile.Width + oImageFile.Height) \ 2
        newHeight = newWidth

        ' 画像を正方形にリサイズして保存
        Call WIA_ResizeImage(filePath, filePath, newWidth, newHeight, True, True)

        fileName = Dir()
    Wend
End Sub

Public Function WIA_ResizeImage(ByVal sInitialImage As String, _

                               ByVal sResizedImage As String, _
                               ByVal lMaximumWidth As Long, _
                               ByVal lMaximumHeight As Long, _
                               Optional ByVal bPreserveAspectRatio As Boolean = False, _
                               Optional ByVal bOverwrite As Boolean = False) As Boolean
End Function

< 使用 Excel:Excel2021、使用 OS:Windows11 >



 ちょっと勘違いした回答を書いてしまったので、消しました。
 すみません
(´・ω・`) 2024/03/30(土) 12:24:19

その後、アドバイスが途切れていますし
私の方も手詰まりなので別のアプローチを考えて見ましたが
以下でエラーが出ます。
実行エラー:438 「オブジェクトは、このプロパティまたはメソッドをサポートしていません 」
.ApplyToFile OriginalFilePath, NewFilePath

こちらの手法も手詰まりです。

Sub ResizeJPEGFilesToSquare()

      Dim FolderPath As String
      Dim FileName As String
      Dim NewWidth As Double
      Dim NewHeight As Double
      Dim OriginalWidth As Double
      Dim OriginalHeight As Double
      Dim AspectRatio As Double
      Dim NewFilePath As String
      Dim OriginalFilePath As String
      Dim FileSystem As Object
      Dim FileObject As Object

      ' 指定フォルダーのパス
      FolderPath = "C:\Users\mido\"

      ' FileSystemオブジェクトを作成
      'VBEのツールから参照設定で、Microsoft Scripting Runtimeにチェックを入れてください。
      Set FileSystem = CreateObject("Scripting.FileSystemObject")

      ' 指定フォルダー内のファイルを処理
      For Each FileObject In FileSystem.GetFolder(FolderPath).Files
            If LCase(FileSystem.GetExtensionName(FileObject.Path)) = "jpg" Then
                  ' オリジナルファイルのパス
                  OriginalFilePath = FileObject.Path

                  ' 新しいファイル名(同名+_Squareで保存)
                  NewFilePath = FolderPath & FileSystem.GetBaseName(OriginalFilePath) & "_Square.jpg"

                  ' オリジナル画像のサイズを取得
                  With CreateObject("WIA.ImageFile")
                        .LoadFile OriginalFilePath
                        OriginalWidth = .Width
                        OriginalHeight = .Height
                  End With

                  ' 正方形のサイズを計算
                  AspectRatio = (OriginalWidth + OriginalHeight) / 2
                  NewWidth = AspectRatio
                  NewHeight = AspectRatio

                  ' 画像を正方形にリサイズして保存
                  '使う前の準備として、先にVBAエディタからツール⇒参照設定
                  '⇒Microsoft Windows Image Acquisition Libraly 2.0 にチェック入れてください
                  With CreateObject("WIA.ImageProcess")
                        .Filters.Add .FilterInfos("Scale").FilterID
                        .Filters(1).Properties("MaximumWidth") = NewWidth
                        .Filters(1).Properties("MaximumHeight") = NewHeight
                        .Filters(1).Properties("PreserveAspectRatio") = False
                        .ApplyToFile OriginalFilePath, NewFilePath
                  End With
            End If
      Next FileObject

      ' メッセージボックスを表示
      MsgBox "処理が完了しました。"
End Sub

(Muse) 2024/03/30(土) 16:14:38


 マジレスすべきなのかどうなのか悩ましい...  と思って傍観してました。^^;

 > 以下を試して見ましたが変化がありません。
  については、
  ホントに Function WIA_ResizeImage の中身が無い状態で試してるんなら、
  変化が無くて当然ですよね? (これで変化したらある意味ホラー...)

 たぶん最低限↓これくらいは書かないと何もならないでしょう。

    Public Function WIA_ResizeImage(ByVal sInitialImage As String, _
                                   ByVal sResizedImage As String, _
                                   ByVal lMaximumWidth As Long, _
                                   ByVal lMaximumHeight As Long, _
                                   Optional ByVal bPreserveAspectRatio As Boolean = False, _
                                   Optional ByVal bOverwrite As Boolean = False) As Boolean
        Dim oWIA                  As Object 'WIA.ImageFile
        Dim oIP                   As Object 'ImageProcess

        Set oWIA = CreateObject("WIA.ImageFile")
        Set oIP = CreateObject("WIA.ImageProcess")

        oIP.Filters.Add oIP.FilterInfos("Scale").FilterID
        oIP.Filters(1).Properties("MaximumWidth") = lMaximumWidth
        oIP.Filters(1).Properties("MaximumHeight") = lMaximumHeight
        oIP.Filters(1).Properties("PreserveAspectRatio") = bPreserveAspectRatio

        oWIA.LoadFile sInitialImage
        Set oWIA = oIP.Apply(oWIA)
        If bOverwrite Then
            On Error Resume Next
            Kill sResizedImage
            On Error GoTo 0
        End If
        oWIA.SaveFile sResizedImage
        WIA_ResizeImage = True
    End Function

 で、その上で、
 >       Call WIA_ResizeImage(filePath, filePath, newWidth, newHeight, True, True)
                                                                        ↑ココ
 名前付き引数の名前から察するに、この場合「False」だと思います。

(白茶) 2024/03/30(土) 16:50:07


白茶さん、ありがとうございます。

Function WIA_ResizeImageの中身が無いので何も処理しないでリターンしていたのですね。
ホラーだと言われて当然です。

Functionを変更してうまく処理できました。
(Call文のパラメーターもFALSEに書き換えました。)

(Muse) 2024/03/30(土) 17:54:26


 「別のアプローチ」の方もちょっと見てみました。

 Sub ResizeJPEGFilesToSquare()
      Dim FolderPath As String
      Dim FileName As String
      Dim NewWidth As Double
      Dim NewHeight As Double
      Dim OriginalWidth As Double
      Dim OriginalHeight As Double
      Dim AspectRatio As Double
      Dim NewFilePath As String
      Dim OriginalFilePath As String
      Dim FileSystem As Object
      Dim FileObject As Object
      Dim o As Object '◆追加
      ' 指定フォルダーのパス
      FolderPath = "C:\Users\mido\"
      ' FileSystemオブジェクトを作成
      'VBEのツールから参照設定で、Microsoft Scripting Runtimeにチェックを入れてください。
      Set FileSystem = CreateObject("Scripting.FileSystemObject")
      ' 指定フォルダー内のファイルを処理
      For Each FileObject In FileSystem.GetFolder(FolderPath).Files
            If LCase(FileSystem.GetExtensionName(FileObject.Path)) = "jpg" Then
                  ' オリジナルファイルのパス
                  OriginalFilePath = FileObject.Path
                  ' 新しいファイル名(同名+_Squareで保存)
                  NewFilePath = FolderPath & FileSystem.GetBaseName(OriginalFilePath) & "_Square.jpg"
                  ' オリジナル画像のサイズを取得
                  Set o = CreateObject("WIA.ImageFile") '◆追加
                  With o 'CreateObject("WIA.ImageFile") '■書替
                        .LoadFile OriginalFilePath
                        OriginalWidth = .Width
                        OriginalHeight = .Height
                  End With
                  ' 正方形のサイズを計算
                  AspectRatio = (OriginalWidth + OriginalHeight) / 2
                  NewWidth = AspectRatio
                  NewHeight = AspectRatio
                  ' 画像を正方形にリサイズして保存
                  '使う前の準備として、先にVBAエディタからツール⇒参照設定
                  '⇒Microsoft Windows Image Acquisition Libraly 2.0 にチェック入れてください
                  With CreateObject("WIA.ImageProcess")
                        .Filters.Add .FilterInfos("Scale").FilterID
                        .Filters(1).Properties("MaximumWidth") = NewWidth
                        .Filters(1).Properties("MaximumHeight") = NewHeight
                        .Filters(1).Properties("PreserveAspectRatio") = False
                        '.ApplyToFile OriginalFilePath, NewFilePath '■削除
                        .Apply(o).SaveFile NewFilePath              '◆追加
                  End With
            End If
      Next FileObject
      ' メッセージボックスを表示
      MsgBox "処理が完了しました。"
 End Sub

(白茶) 2024/03/30(土) 17:56:01


 ついでに。^^;

 私自身「Windows Image Acquisition」ってのは全く存じ上げなかったモノで今回初めて使ってみました。
 いい機会を与えて頂き勉強になりました。ありがとうございます。

 でまぁお礼というか
 ここ最近「GDI+ フラット API」について手探り勉強中で、自分的にタイムリーなネタだったので、ちょっと別案書いてみました。
 ネットのアチコチからコピってきてペッペして整えただけですけどね。ご笑納くださいwww

    Option Explicit
    #If False Then
    Dim InterpolationMode
    Const InterpolationModeInvalid = -1
    Const InterpolationModeDefault = 0&
    Const InterpolationModeLowQuality = 1&
    Const InterpolationModeHighQuality = 2&
    Const InterpolationModeBilinear = 3&
    Const InterpolationModeBicubic = 4&
    Const InterpolationModeNearestNeighbor = 5&
    Const InterpolationModeHighQualityBilinear = 6&
    Const InterpolationModeHighQualityBicubic = 7&
    #End If
    Private Type GdiplusStartupInput
        GdiplusVersion As Long
        DebugEventCallback As LongPtr
        SuppressBackgroundThread As Long
        SuppressExternalCodecs As Long
    End Type
    Private Declare PtrSafe Function GdiplusStartup Lib "gdiplus" (ByRef token As LongPtr, ByRef inputbuf As GdiplusStartupInput, Optional ByVal outputbuf As LongPtr = 0) As Long
    Private Declare PtrSafe Function GdiplusShutdown Lib "gdiplus" (ByVal token As LongPtr) As Long
    Private Declare PtrSafe Function GdipLoadImageFromFile Lib "gdiplus" (ByVal FileName As LongPtr, ByRef image As LongPtr) As Long
    Private Declare PtrSafe Function GdipDisposeImage Lib "gdiplus" (ByVal image As LongPtr) As Long
    Private Declare PtrSafe Function GdipGetImageHeight Lib "gdiplus" (ByVal image As LongPtr, ByRef Height As Long) As Long
    Private Declare PtrSafe Function GdipGetImageWidth Lib "gdiplus" (ByVal image As LongPtr, ByRef Width As Long) As Long
    Private Declare PtrSafe Function GdipGetImageGraphicsContext Lib "gdiplus" (ByVal image As LongPtr, graphics As LongPtr) As Long
    Private Declare PtrSafe Function GdipDrawImageRectI Lib "gdiplus.dll" (ByVal GpGraphics As LongPtr, ByVal GpImage As LongPtr, ByVal Left As Long, ByVal Top As Long, ByVal Width As Long, ByVal Height As Long) As Long
    Private Declare PtrSafe Function GdipDeleteGraphics Lib "gdiplus" (ByVal graphics As LongPtr) As Long
    Private Declare PtrSafe Function GdipCreateBitmapFromGraphics Lib "gdiplus" (ByVal Width As Long, ByVal Height As Long, ByVal graphics As LongPtr, bitmap As LongPtr) As Long
    Private Enum InterpolationMode                'イメージをスケーリングまたは回転するときに使用されるアルゴリズムを指定します
        InterpolationModeInvalid = -1             '内部的に使用される
        InterpolationModeDefault = 0&             '既定の補間モードを指定します。
        InterpolationModeLowQuality = 1&          '低品質モードを指定します。
        InterpolationModeHighQuality = 2&         '高品質モードを指定します。
        InterpolationModeBilinear = 3&            '双一次補間を指定します。 事前フィルター処理は実行されません。このモードは、イメージを元のサイズの 50% 以下にするような縮小処理には適していません。
        InterpolationModeBicubic = 4&             '双三次補間を指定します。 事前フィルター処理は実行されません。このモードは、イメージを元のサイズの 25% 以下にするような縮小処理には適していません。
        InterpolationModeNearestNeighbor = 5&     '最近傍補間を指定します。
        InterpolationModeHighQualityBilinear = 6& '高品質双一次補間を指定します。 事前フィルター処理が適用され、高品質の縮小処理が実行されます。
        InterpolationModeHighQualityBicubic = 7&  '高品質双三次補間を指定します。 事前フィルター処理が適用され、高品質の縮小処理が実行されます。 このモードを使用すると、変換後のイメージが高品質になります。
    End Enum
    Private Declare PtrSafe Function GdipSetInterpolationMode Lib "gdiplus" (ByVal graphics As LongPtr, ByVal nInterpolationMode As InterpolationMode) As Long
    Private Type GUID
        Data1 As Long
        Data2 As Integer
        Data3 As Integer
        Data4(7) As Byte
    End Type
    Private Type EncoderParameter
        GUID As GUID
        NumberOfValues As Long
        TypeAPI As Long
        Value As LongPtr
    End Type
    Private Type EncoderParameters
        Count As Long
        Parameter(0 To 15) As EncoderParameter
    End Type
    Private Declare PtrSafe Function CLSIDFromString Lib "ole32" (ByVal lpsz As Any, ByRef pCLSID As GUID) As Long
    Private Const CLSID_BMP As String = "{557CF400-1A04-11D3-9A73-0000F81EF32E}"
    Private Const CLSID_GIF As String = "{557CF402-1A04-11D3-9A73-0000F81EF32E}"
    Private Const CLSID_TIF As String = "{557CF405-1A04-11D3-9A73-0000F81EF32E}"
    Private Const CLSID_PNG As String = "{557CF406-1A04-11D3-9A73-0000F81EF32E}"
    Private Const CLSID_JPG As String = "{557CF401-1A04-11D3-9A73-0000F81EF32E}"
    Private Const QUALITY_PARAMS As String = "{1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB}"
    Private Declare PtrSafe Function GdipSaveImageToFile Lib "gdiplus" (ByVal image As LongPtr, ByVal FileName As LongPtr, ByRef clsidEncoder As GUID, encoderParams As Any) As Long
    Private Sub SaveToFile(hImg As LongPtr, FileName As String, Optional ByVal jpgQuarity As Long = 85)
        Dim fGUID As GUID, p As EncoderParameters
        Select Case UCase$(CreateObject("Scripting.FilesystemObject").GetExtensionName(FileName))
            Case "JPG"
                Call CLSIDFromString(StrPtr(CLSID_JPG), fGUID)
                If jpgQuarity > 100 Then jpgQuarity = 100
                If jpgQuarity < 1 Then jpgQuarity = 85
                p.Count = 1
                With p.Parameter(0)
                    Call CLSIDFromString(StrPtr(QUALITY_PARAMS), .GUID)
                    .TypeAPI = 4
                    .NumberOfValues = 1
                    .Value = VarPtr(jpgQuarity)
                End With
            Case "TIF": Call CLSIDFromString(StrPtr(CLSID_TIF), fGUID)
            Case "GIF": Call CLSIDFromString(StrPtr(CLSID_GIF), fGUID)
            Case "BMP": Call CLSIDFromString(StrPtr(CLSID_BMP), fGUID)
            Case Else:  Call CLSIDFromString(StrPtr(CLSID_PNG), fGUID)
        End Select
        If p.Count Then
            Call GdipSaveImageToFile(hImg, StrPtr(FileName), fGUID, p)
        Else
            Call GdipSaveImageToFile(hImg, StrPtr(FileName), fGUID, ByVal 0&)
        End If
    End Sub
    Private Function NumberedFilename(FileName As String, Optional Prefix As String, Optional Suffix As String) As String
        Dim i As Long, p As String, b As String, e As String, fn As String
        With CreateObject("Scripting.FilesystemObject")
            p = .GetParentFolderName(FileName)
            b = Prefix & .GetBaseName(FileName) & Suffix
            e = .GetExtensionName(FileName)
            fn = b & "." & e
            i = 1
            Do
                NumberedFilename = .BuildPath(p, fn)
                If Not .FileExists(NumberedFilename) Then Exit Do
                i = i + 1
                fn = b & Format$(i, " (0).") & e
            Loop
        End With
    End Function
    Private Function CreateResizedImage(hSrc As LongPtr, sizeW As Long, sizeH As Long) As LongPtr
        Dim w As Long, h As Long, rtn As Long, hGrap As LongPtr, hRes As LongPtr
        rtn = GdipGetImageWidth(hSrc, w)
        rtn = GdipGetImageHeight(hSrc, h)
        If w * h = 0 Then Exit Function
        rtn = GdipGetImageGraphicsContext(hSrc, hGrap)
        If rtn = 0 Then rtn = GdipCreateBitmapFromGraphics(sizeW, sizeH, hGrap, hRes)
        If rtn = 0 Then rtn = GdipDeleteGraphics(hGrap)
        If rtn = 0 Then rtn = GdipGetImageGraphicsContext(hRes, hGrap)
        If rtn = 0 Then rtn = GdipSetInterpolationMode(hGrap, InterpolationModeBicubic)
        If rtn = 0 Then rtn = GdipDrawImageRectI(hGrap, hSrc, 0, 0, sizeW, sizeH)
        If rtn = 0 Then CreateResizedImage = hRes
        If rtn = 0 Then rtn = GdipDeleteGraphics(hGrap)
    End Function

    Rem ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Sub RESIZETEST2()
        Dim FolderPath As String
        Dim FileName As String
        Dim filePath As String
        Dim NewWidth As Long
        Dim NewHeight As Long
        Dim tkn As LongPtr, gi As GdiplusStartupInput
        Dim hImg As LongPtr, hResized As LongPtr
        gi.GdiplusVersion = 1&
        Call GdiplusStartup(tkn, gi)

        FolderPath = "C:\Users\mido\"

        FileName = Dir(FolderPath & "*.jpg")
        While FileName <> ""
            filePath = FolderPath & FileName
            If GdipLoadImageFromFile(StrPtr(filePath), hImg) = 0 Then
                Call GdipGetImageWidth(hImg, NewWidth)
                Call GdipGetImageHeight(hImg, NewHeight)
                NewWidth = (NewWidth + NewHeight) \ 2
                hResized = CreateResizedImage(hImg, NewWidth, NewWidth)
                If hResized Then
                    Call SaveToFile(hResized, NumberedFilename(filePath, , "_Square"))
                    Call GdipDisposeImage(hResized)
                End If
                Call GdipDisposeImage(hImg)
            End If
            FileName = Dir()
        Wend
        Call GdiplusShutdown(tkn)
    End Sub

(白茶) 2024/03/30(土) 18:27:10


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.