10
votes

Comment utiliser uniquement des données d'image dans un fichier JPG avec DotNet?

J'ai une ~ 20000 images JPG, dont certaines sont des doublons. Malheureusement, certains fichiers ont été étiquetés avec des métadonnées Exif, de sorte qu'un simple fichier de fichier ne peut pas identifier le dupliqué.

Je tente de créer un script PowerShell pour les traiter, mais ne peut trouver aucun moyen d'extraire uniquement les données bitmap.

Le système.Drawing.bitmap ne peut renvoyer qu'un objet bitmap, pas des octets. Il y a une fonction gethash (), mais elle agit apparemment dans l'ensemble du fichier.

Comment puis-je hacher ces fichiers d'une manière que les informations exif sont exclues? Je préférerais éviter les dépendances externes si possible.


0 commentaires

5 Réponses :


5
votes

Vous pouvez charger le JPEG dans un système.Drawing.image et utiliser la méthode gethashcode xxx

pour obtenir les octets que vous pouvez xxx < / p>


1 commentaires

Votre première approche ne fonctionne pas. Il renvoie différents hashcodes pour la même image (différentes métadonnées). La deuxième approche fonctionne et est à peu près ce que tout le monde fait pour faire varier les niveaux de complétude dans le script PowerShell. :-)



0
votes

Traduire en PowerShell, je reçois cela -

[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$provider = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider

foreach ($location in $args)
{
    $files=get-childitem $location | where{$_.Extension -match "jpg|jpeg"}
    foreach ($f in $files)
        {
        $bitmap = New-Object -TypeName System.Drawing.Bitmap -ArgumentList $f.FullName
        $stream = New-Object -TypeName System.IO.MemoryStream
        $bitmap.Save($stream)

        $hashbytes = $provider.ComputeHash($stream.ToArray())
        $hashstring = ""
        foreach ($byte in $hashbytes) 
            {$hashstring += $byte.tostring("x2")}  
        $f.FullName
        $hashstring
        echo ""
        }
} 


0 commentaires

9
votes

Ceci est une implémentation avancée de la fonction avancée PowerShell V2.0. C'est un peu long mais j'ai vérifié qu'il donne le même hashcode (généré à partir des pixels bitmap) sur la même image, mais avec différentes métadonnées et tailles de fichiers. Il s'agit d'une version capable de pipeline qui accepte également des caractères génériques et des chemins littéraux: xxx


0 commentaires

5
votes

Voici un script PowerShell qui produit un hachage SHA256 sur uniquement les octets de l'image comme extrait à l'aide de verrous. Cela devrait produire un hasch unique pour chaque fichier différent. Veuillez noter que je n'avais pas inclus le code itération de fichiers, mais il devrait s'agir d'une tâche relativement simple pour remplacer le code C: \ test.bmp Actuellement avec un itérateur de répertoires. La variable $ finale contient la chaîne HEX-ASCII du hachage final.

private static String ImageDataHash(FileInfo imgFile)
{
    using (Bitmap bmp = (Bitmap)Bitmap.FromFile(imgFile.FullName))
    {                
        BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);
        IntPtr dataPointer = bmpData.Scan0;
        int totalBytes = bmpData.Stride * bmp.Height;
        byte[] values = new byte[totalBytes];                
        System.Runtime.InteropServices.Marshal.Copy(dataPointer, values, 0, totalBytes);                
        bmp.UnlockBits(bmpData);
        SHA256 sha = new SHA256Managed();
        byte[] hash = sha.ComputeHash(values);
        return BitConverter.ToString(hash).Replace("-", "");                
    }
}


1 commentaires

Bitconverter.tostring () - Nice!



0
votes

Il s'agit d'une méthode plus rapide pour enregistrer sur un MemorMemReam:

$ms = New-Object System.IO.MemoryStream
$bmp.Save($ms, [System.Drawing.Imaging.ImageFormat]::Bmp)
[void]$ms.Seek(0,'Begin')


0 commentaires