hashing.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #include "global-state.h"
  2. #include "hashing.h"
  3. #include "data-structure.h"
  4. #include "raylib.h"
  5. #include <stdio.h>
  6. const unsigned ResizedSide64 = 8;
  7. const unsigned ResizedSq64 = ResizedSide64 * ResizedSide64;
  8. const unsigned ResizedSide256 = 16;
  9. const unsigned ResizedSq256 = ResizedSide256 * ResizedSide256;
  10. extern ProcessingOptions ProcOptions;
  11. void
  12. PUHS_Compare_Hashes_256bit ( Imagefile * im1, Imagefile * im2 )
  13. {
  14. if ( im1 == NULL || im2 == NULL )
  15. {
  16. fprintf( stderr, "ERROR, IMAGE IN ELEMENT IS NULL!\n" );
  17. return;
  18. }
  19. if ( im1->hash == NULL || im2->hash == NULL )
  20. return;
  21. if ( im1->group != NULL && im2->group != NULL )
  22. return;
  23. HASH64BIT similarity_hash[4];
  24. for ( unsigned i = 0; i < ResizedSq256; ++i )
  25. similarity_hash[i / 64] = im1->hash[i / 64] ^ im2->hash[i / 64];
  26. unsigned similar_bits = ResizedSq256;
  27. for ( unsigned i = 0; i < ResizedSq256 / 64; ++i )
  28. while ( similarity_hash[i] != 0 )
  29. {
  30. similar_bits--;
  31. similarity_hash[i] &= similarity_hash[i] - 1;
  32. }
  33. if ( similar_bits / (float)ResizedSq256 >= ProcOptions.threshold )
  34. {
  35. if ( im1->group == NULL && im2->group == NULL )
  36. PUDS_Create_group( im1, im2, sizeof(HASH64BIT) );
  37. else
  38. {
  39. if ( im1->group == NULL )
  40. PUDS_Add_to_group( im1, im2->group );
  41. else
  42. PUDS_Add_to_group( im2, im1->group );
  43. }
  44. }
  45. }
  46. void
  47. PUHS_Compare_Hashes_64bit ( Imagefile * im1, Imagefile * im2 )
  48. {
  49. if ( im1 == NULL || im2 == NULL )
  50. {
  51. fprintf( stderr, "ERROR, IMAGE IN ELEMENT IS NULL!\n" );
  52. return;
  53. }
  54. if ( im1->hash == NULL || im2->hash == NULL )
  55. return;
  56. if ( im1->group != NULL && im2->group != NULL )
  57. return;
  58. HASH64BIT similarity_hash = im1->hash[0] ^ im2->hash[0];
  59. unsigned similar_bits = ResizedSq64;
  60. while ( similarity_hash != 0 )
  61. {
  62. similar_bits--;
  63. similarity_hash &= similarity_hash - 1;
  64. }
  65. if ( similar_bits / (float)ResizedSq64 >= ProcOptions.threshold )
  66. {
  67. if ( im1->group == NULL && im2->group == NULL )
  68. PUDS_Create_group( im1, im2, sizeof(HASH64BIT) );
  69. else
  70. {
  71. if ( im1->group == NULL )
  72. PUDS_Add_to_group( im1, im2->group );
  73. else
  74. PUDS_Add_to_group( im2, im1->group );
  75. }
  76. }
  77. }
  78. void
  79. PUHS_Hash_Dhash_256bit ( Imagefile * im )
  80. {
  81. if ( im->hash != NULL )
  82. free(im->hash);
  83. if ( !FileExists(im->path->s) )
  84. {
  85. fprintf( stderr, "File %s is suddenly missing!\n", im->path->s );
  86. im->hashed = false;
  87. return;
  88. }
  89. Image img = LoadImage( im->path->s );
  90. if ( img.data == NULL )
  91. {
  92. fprintf( stderr, "Failed to load image %s\n", im->path->s );
  93. im->hashed = false;
  94. return;
  95. }
  96. ImageResize( &img, ResizedSide256 + 1, ResizedSide256 );
  97. ImageColorGrayscale(&img);
  98. im->hash = calloc( 4, sizeof(HASH64BIT) );
  99. uint8_t * data = img.data;
  100. for ( unsigned u = 0, i = 0, bt = 0; u < ResizedSide256; ++u )
  101. {
  102. for ( unsigned v = 0; v < ResizedSide256; ++v, ++i, ++bt )
  103. im->hash[bt / 64] |= (HASH64BIT)( (unsigned)( data[i] - data[i + 1] ) >> ( sizeof(int) * 8 - 1 ) ) << ( bt % 64 );
  104. i++;
  105. }
  106. UnloadImage(img);
  107. im->hashed = true;
  108. }
  109. void
  110. PUHS_Hash_Dhash_64bit ( Imagefile * im )
  111. {
  112. if ( im->hash != NULL )
  113. free(im->hash);
  114. if ( !FileExists(im->path->s) )
  115. {
  116. fprintf( stderr, "File %s is suddenly missing!\n", im->path->s );
  117. im->hashed = false;
  118. return;
  119. }
  120. Image img = LoadImage( im->path->s );
  121. if ( img.data == NULL )
  122. {
  123. fprintf( stderr, "Failed to load image %s\n", im->path->s );
  124. im->hashed = false;
  125. return;
  126. }
  127. ImageResize( &img, ResizedSide64 + 1, ResizedSide64 );
  128. ImageColorGrayscale(&img);
  129. im->hash = calloc( 1, sizeof(HASH64BIT) );
  130. uint8_t * data = img.data;
  131. for ( unsigned u = 0, i = 0, bt = 0; u < ResizedSide64; ++u )
  132. {
  133. for ( unsigned v = 0; v < ResizedSide64; ++v, ++i, ++bt )
  134. im->hash[0] |= (HASH64BIT)( (unsigned)( data[i] - data[i + 1] ) >> ( sizeof(int) * 8 - 1 ) ) << bt;
  135. i++;
  136. }
  137. UnloadImage(img);
  138. im->hashed = true;
  139. }