2014-01-30 2 views
1
public byte[] HashImage(string fileName) 
{ 
    using (var image = new Bitmap(fileName)) 
    { 
     var sha256 = SHA256.Create(); 

     var rect = new Rectangle(0, 0, image.Width, image.Height); 
     var data = image.LockBits(rect, ImageLockMode.ReadOnly, image.PixelFormat); 

     var dataPtr = data.Scan0; 

     var totalBytes = (int)Math.Abs(data.Stride) * data.Height; 
     var rawData = new byte[totalBytes]; 
     System.Runtime.InteropServices.Marshal.Copy(dataPtr, rawData, 0, totalBytes); 

     image.UnlockBits(data); 

     return sha256.ComputeHash(rawData); 
    } 
} 

private Tuple<int, string> GetIndexedImage(string fileName) 
{ 
    var baseFileName = Path.GetFileNameWithoutExtension(fileName); 
    int index; 
    if (int.TryParse(baseFileName, out index)) 
    { 
     return Tuple.Create(index, fileName); 
    } 
    return null; 
} 

private string HashToString(byte[] hash) 
{ 
    var builder = new StringBuilder(); 
    foreach (var b in hash) 
    { 
     builder.AppendFormat("{0:x2}", b); 
    } 
    return builder.ToString(); 
} 

HashImage() получает SHA256 Хэш изображения в виде байтов. GetFileIndex() возвращает кортеж индекса и имени файла. HashToString() - построитель строк, который преобразует хеши в строку.Как сгруппировать мои повторяющиеся хэши?

private void button1_Click(object sender, EventArgs e) 
{ 
    string original = @"C:\Users\user\Documents\CaptchaCollection\"; 

    var equivalentImages = Directory.GetFiles(original) 
            .Select(f => GetIndexedImage(f)) // build tuples (index, fileName) or null if parsing failed 
            .Where(t => t != null)   // ignore all invalid ones 
            .OrderBy(t => t.Item1)   // order by index 
            .Select(t => Tuple.Create(HashImage(t.Item2), t.Item2)) // create new tuple (hash, fileName) 
            .GroupBy(t => t.Item1);   // group by Hash 

    // print groups 
    foreach (var group in equivalentImages) 
    { 
     Console.WriteLine("All images with hash: {0}", HashToString(group.Key)); 
     foreach (var t in group) 
     { 
      Console.WriteLine("\t{0}", t.Item2); 
     } 
    } 

} 

Теперь это похоже на основной метод, когда я нажимаю кнопку «Я начинаю получать хэши файлов изображений».

Однако в настоящее время основная проблема заключается в том, что кажется, что, когда я собираю файлы из хэшей output, они не группируются, а вместо этого печатаются по порядку. Вместо этого они разбросаны по всему выходному файлу.

Как сгруппировать любую группу и дублированные элементы с одинаковыми хэшами как друг друга?

+0

Ваше использование LINQ и функциональной композиции очень приятно. – usr

+0

@usr Весь код LINQ не мой. Я редко знаю об этом, если честно – puretppc

+0

GetIndexedImage можно вызвать как группу методов. – Magus

ответ

0

Вы группируете byte[]. К сожалению, коллекции .NET не поддерживают равенство и хеширование. Это означает, что вы получаете сравнение ссылок по умолчанию. (Мое мнение: это недостаток дизайна в платформе .NET. Не должно быть равенства по умолчанию. В таких случаях должно быть указано сообщение об ошибке.)

Напишите себе IEqualityComparer<byte[]>.

Кроме того, вы заказываете перед группировкой. Группирование не упорядочивает заказ. Документы не гарантируют, что на это нельзя положиться. И на самом деле это не выполняется на практике.

+0

Просто потому, что информированное решение другой стороны не соответствует вашим личным ожиданиям, не делает его ошибкой дизайна. Это просто, ваше мнение. – Magus

+0

@ Magus Я согласен. Я сделал это ясно сейчас. – usr

+0

Я считаю, что ему нужно написать 'IEqualityComparer >' вместо 'IEqualityComparer '. Если бы вы захотели использовать 'IEqualityComparer ', вы могли бы, но я бы рекомендовал изменить последние два оператора LINQ на один' .GroupBy (t => HashImage (t.Item2), t => t, new YourComparer()) '(Это приводит к тому, что' GroupBy' возвращает исходный кортеж как значения хэшированного ключа, поэтому вы можете использовать старый индекс для сортировки в foreach 'foreach (var t in group.OrderBy (t => t.Item1))') –

Смежные вопросы