如何使用PowerShell(或PowerShell)从Windows 10中的jpeg文件中提取“压缩”属性?

5cg8jx4n  于 5个月前  发布在  Shell
关注(0)|答案(6)|浏览(86)

我试图从几千个jpeg文件中提取压缩属性。


的数据
我如何使用Excel Excel或PowerShell(或其他方法)来实现这一点?
一些用户没有使用正确的技术将tiff或png文件转换为jpeg。他们只是直接在资源管理器中编辑文件扩展名,而不是使用Photoshop等应用程序来正确更改文件格式。这会在下游过程中造成麻烦。
在检查了几个文件后,有问题的文件在该字段中显示为“未压缩”.
注意This answer没有提供我需要的解决方案,Compression属性不在该方法输出的308个属性列表中。

lvjbypge

lvjbypge1#

从我前面的评论-如果你的目标是真的识别 * 实际 * 文件类型(与依赖于文件扩展名)

Sub Tester()

    Const fldr As String = "C:\Temp\pics\"
    
    Debug.Print FileTypeId(fldr & "photo.jpg")
    Debug.Print FileTypeId(fldr & "unlock.gif")
    Debug.Print FileTypeId(fldr & "unlock2.png")
    Debug.Print FileTypeId(fldr & "sample.tiff")

End Sub

Function FileTypeId(fPath As String) As String

    Dim bytes() As Byte, ff As Integer, i As Long
    
    'read the file into an array of bytes
    ff = FreeFile
    Open fPath For Binary Access Read As ff
    ReDim bytes(0 To LOF(ff) - 1) 'maybe don't need to read more than the first 10 bytes or so...
    Get ff, , bytes
    Close ff

    'Does the file match any of our "known" types?
    '  File signatures are taken from:
    '  https://www.garykessler.net/library/file_sigs.html
    Select Case True
        Case ByteMatch(bytes, Array(&HFF, &HD8))
            FileTypeId = "JPEG"
        Case ByteMatch(bytes, Array(&H47, &H49, &H46, &H38, &H37, &H61)), _
             ByteMatch(bytes, Array(&H47, &H49, &H46, &H38, &H39, &H61))
             FileTypeId = "GIF"
        Case ByteMatch(bytes, Array(&H89, &H50, &H4E, &H47, &HD, &HA, &H1A, &HA))
            FileTypeId = "PNG"
        Case ByteMatch(bytes, Array(&H49, &H49, &H2A, &H0))
            FileTypeId = "TIFF"
        Case Else
            FileTypeId = "unknown"
    End Select
    
'    Debug.Print fPath
'    Debug.Print FileTypeId
'    For i = LBound(bytes) To 6
'        Debug.Print Hex(bytes(i))
'    Next i
End Function

'do the first elements in `bytes` match `sig` ? 
Function ByteMatch(bytes, sig) As Boolean
    Dim i As Long
    For i = LBound(sig) To UBound(sig)
        If bytes(i) <> sig(i) Then
           ByteMatch = False
           Exit Function
        End If
    Next i
    ByteMatch = True
End Function

字符串

jtw3ybtb

jtw3ybtb2#

一个实用的解决方案是使用功能强大的ExifTool CLI,它可以安装在用户级别(不需要管理员凭据)。
下面是一个PowerShell解决方案,通过winget.exe实现无人值守的按需安装:

# Install ExifTool.exe on demand
if (-not (Get-Command -ErrorAction Ignore ExifTool.exe)) {
  Write-Verbose 'Installing OliverBetz.ExifTool on demand...'
  winget install OliverBetz.ExifTool --silent >$null
  if ($LASTEXITCODE) { throw }
  Write-Verbose 'Refreshing $env:PATH...'
  $env:PATH = [Environment]::GetEnvironmentVariable('Path', 'Machine'),
              [Environment]::GetEnvironmentVariable('Path', 'User') -join ';'
}

# Get the compression info from the specified image files in the current dir.
# as JSON, and parse the output into objects via Convert-FromJson
$imageCompressionInfo = 
  exiftool -j -Compression *.png *.bmp *.jpg *.tiff |
  ConvertFrom-Json

# Output only those that are uncompressed
$imageCompressionInfo | Where-Object Compression -eq None

字符串

daolsyd0

daolsyd03#

为了您的目的,通过查找应该位于真正的经典JPEG文件(即0xffd8)开头的SOI标记,可能足以将包含其他类型图像格式的受损文件与JPEG区分开来。出现“JFIF”作为几个字节的文本也是JPEG的一个很好的指示(但不能保证). MS位图文件大多以“BM”开头开始,但也有其他possibilities。PNG以0x89504E47开头,其中包括字母PNG。ISTR GIF文件以“GIF”开头。最后TIFF将以“II”或“MM”开头开始.然后将文件扩展名设置回与文件内容一致,您应该可以开始了。这应该足够简单,打开文件读取第一个单词以检查文件数据中实际包含的内容(对于其他深奥的图像格式,可能需要额外的语法分析)。
你也可以尝试用棒球棒重新教育你的用户。
最简单的常用工具是保存每种格式的一个小图片到一个临时目录中,然后使用更多的图片来查看第一个块。显然,在MySQL中,你会打开文件进行二进制读取,并获得前两个字节。我不确定stackOverflow对高位字符集的React如何,所以这个示例输出可能不会像预期的那样表现。

C:\temp>more test.bmp
BM6°%

C:\temp>more test.gif
GIF89aÇð¸

C:\temp>more test.jpg
 Ï Ó
JFIF

C:\temp>more test.png
ëPNG

C:\temp>more test.tif
II*

字符串
我没想到你手头上没有一个十六进制编辑器,这是一个最小的JavaScript代码,可以检查和显示任何文件的前两个字节。

Sub Test()
  Dim i As Integer
  Debug.Print "Graphics File Headers"
  testfile ("C:\temp\test.jpg")
  testfile ("C:\temp\test.png")
  testfile ("C:\temp\test.gif")
  testfile ("C:\temp\test.tif")
End Sub

Sub testfile(fname As String)
  Dim tag1 As Byte, tag2 As Byte
  Open fname For Binary Access Read As 1
  Get #1, , tag1
  Get #1, , tag2
  Debug.Print fname, Hex(tag1), Hex(tag2), Chr(tag1) & Chr(tag2)
  Close #1
End Sub

Output:
Graphics File Headers
C:\temp\test.jpg            FF            D8            ÿØ
C:\temp\test.png            89            50            ‰P
C:\temp\test.gif            47            49            GI
C:\temp\test.tif            49            49            II

jfewjypa

jfewjypa4#

您可以使用API GetFileAttributes获取。

Option Explicit
#If VBA7 Then
    Private Declare PtrSafe Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesA" (ByVal lpFileName As String) As Long
#Else
    Private Declare Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesA" (ByVal lpFileName As String) As Long
#End If
Private Const FILE_ATTRIBUTE_COMPRESSED As Long = &H800
Sub GetCompressionStatus()
    Dim filePath As String
    Dim fileAttributes As Long
    filePath = "d:\temp\my.jpg"
    fileAttributes = GetFileAttributes(filePath)
    Debug.Print fileAttributes ' for debug
    If (fileAttributes And FILE_ATTRIBUTE_COMPRESSED) = FILE_ATTRIBUTE_COMPRESSED Then
        MsgBox "COMPRESSED"
    Else
        MsgBox "NO COMPRESSED"
    End If
End Sub

字符串

vaj7vani

vaj7vani5#

在我看来,最简单的方法是通过WMIC,它是Windows原生的,可以通过CMD和Powershell使用。下面是命令及其输出的示例:

wmic datafile where "name='C:\\test.jpg'"
    AccessMask  Archive  Caption      Compressed  CompressionMethod  CreationClassName  CreationDate               CSCreationClassName   CSName           Description  Drive  EightDotThreeFileName  Encrypted  EncryptionMethod  Extension  FileName  FileSize  FileType    FSCreationClassName  FSName  Hidden  InstallDate                InUseCount  LastAccessed               LastModified               Manufacturer  Name         Path  Readable  Status  System  Version  Writeable
1507775     TRUE     C:\test.jpg  FALSE                          CIM_LogicalFile    20231128113827.761885-480  Win32_ComputerSystem  DESKTOP-XXXXXXX  C:\test.jpg  c:     c:\test.jpg            FALSE                        jpg        test      5440375   JPEG Image  Win32_FileSystem     NTFS    FALSE   20231128113827.761885-480              20231128114415.151472-480  20231108204657.602147-480                C:\test.jpg  \     TRUE      OK      FALSE            TRUE

字符串
这个输出也可以被调整、总结或隔离,就像这样:

PS C:\> wmic datafile where "name='C:\\test.jpg'" list brief
Compressed  Encrypted  FileSize  Hidden  Name         Readable  System  Version  Writeable
FALSE       FALSE      5440375   FALSE   C:\test.jpg  TRUE      FALSE            TRUE


在wmic帮助中查看更多:)

wmic /?


编辑:当然,我会添加确切的值返回,因为你只需要寻找压缩状态:

wmic datafile where "name='C:\\test.jpg'" get Compressed


回报率:

Compressed
FALSE


你可以在你的脚本中按照你喜欢的方式解析它。

wmtdaxz3

wmtdaxz36#

下面是一个PowerShell答案。请记住,WMI在PowerShell Core中不可用。请使用CIM。

(Get-CimInstance -ClassName CIM_DataFile -Filter "Name='C:\\Test.jpg'").Compressed

字符串
是否有单独的文件系统压缩和映像压缩?
下面是生成shell属性列表的代码。除了“video compression”之外,我没有看到任何关于压缩的内容,我不确定这是否是您想要的。

$shell = New-Object -COMObject Shell.Application
$shellfolder = $shell.Namespace($Env:USERPROFILE)
(1..325) | %{ '{0}, {1}' -f ($_,$shellfolder.GetDetailsOf($null, $_)) }

相关问题