As the title says.
But there are some wrong-doings here.1. It doesn't really hash, that is, you don't get any kind of alphanumeric key… you get a 64-character code (comprised of 1s and 0s. :3).2. It's low quality, and would need some modification for more serious work, but this is Game Maker, after all.Anyway, lets go back in time, to last night…I came onto IRC, remembering someone talk of something they were working on, for comparing images, and I needed something like that for a project I'm working on, so I asked about, and Ling answered by telling me a bit about Perceptual Hashing, which creates similar hashes for similar images.I looked more into it, and began porting the basic theory.Now that I've done so (with a basic Hamming Distance-like thing as well), I've decided to release the code.It's two small scripts, pretty much fully commented.Licensed under CC-BY-SA. :3Please excuse my bad coding habits and overall bad coding. It works, at least.phash();Returns a 64-character string./***************************************************
Perceptual Hash in Game Maker
Script written by Nick Simmons using the basic
structure from [ <a rel="nofollow" href="http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html">http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html</a> ].
This code may be freely distributed and edited under
the Creative Commons BY-SA liscense.
Usage: phash(image);
***************************************************/
var temp_image work_surface work_surface2 average;
average = 0;
main_pixel[0,0] = 0;
output = "";
temp_image = argument0;
work_surface = surface_create(8,8); // Create a small surface to draw/read from.
surface_set_target(work_surface); // Set surface one as the draw target.
draw_sprite_stretched(temp_image,0,0,0,8,8); // Draw the image, stretched down to size.
// Here's the fun part (part one), use the colors to convert to grayscale.
for (j=0; j<8; j+=1;) { // All the way down the image.
for (i=0; i<8; i+=1;) { // All the way across.
_a = surface_getpixel(work_surface,i,j); // Get the color.
_b[0] = color_get_red(_a); // Separate the color out.
_b[1] = color_get_green(_a); // ^
_b[2] = color_get_blue(_a); // ^
_c = (_b[0]+_b[1]+_b[2])/765; // Add them all together, and average it out to make it 'grayscale'.
main_pixel[i,j] = _c; // Store that for now.
}
}
// Fun part (part two), average the grayscale.
for (j=0; j<8; j+=1;) { // All the way down the image.
for (i=0; i<8; i+=1;) { // All the way across.
average += main_pixel[i,j]; // Add the value to the overall average.
}
}
average = average/64; // Divide that by the amount of pixels (8x8 = 64).
// Fun part (part three), convert to one-bit using the average.
for (j=0; j<8; j+=1;) { // All the way down the image.
for (i=0; i<8; i+=1;) { // All the way across.
if main_pixel[i,j] > average { // Make the image 'one bit'.
main_pixel[i,j] = 1; // ^
} else { // ^
main_pixel[i,j] = 0; // ^
}
}
}
// More can be done here, but for now just make it a 64-character string.
for (j=0; j<8; j+=1;) { // All the way down the image.
for (i=0; i<8; i+=1;) { // All the way across.
output = output + string(main_pixel[i,j]);
}
}
// Then make it a 32-character string, from that.
//output = string_copy(output,0,32) + "#" + string_copy(output,32,32);
// Note: I have this here just because I personally used/use it this way, since the #
// is the same for all hashes, it doesn't throw it off by enough to be noticible.
// If you really have an issue with that, just leave it uncommented.
surface_reset_target(); // Fix drawing.
surface_free(work_surface); // Delete the surface.
return output;
/***************************************************
(Psuedo) Hamming Distance in Game Maker
Script written by Nick Simmons.
This code may be freely distributed and edited under
the Creative Commons BY-SA liscense.
Usage: hdistance(string1, string2);
Warning: This script was intended for use with phash();
other uses may require modification.
Also, in this case, the script currently gives a
percentage. (Or a -1 in case of failure.)
Requirements:
- Must be strings.
- Must be the same length.
***************************************************/
var input_a input_b threshold string_a string_b length output;
input_a = string(argument0);
input_b = string(argument1);
string_a[0] = "";
string_b[0] = "";
output = 0;
length = string_length(input_a); // Get the length.
if length != string_length(input_b) {return -1; break;} // If the lengths do not match, stop now.
for (i=0; i<length; i+=1;) { // For the entire length of both strings.
string_a[i] = string_copy(input_a,i,1); // Copy them into an array.
string_b[i] = string_copy(input_b,i,1); // ^
}
for (i=0; i<length; i+=1;) { // For the entire length of both strings.
if string_a[i] = string_b[i] {output += 1;}; // Check them against eachother, and add 1 to the output if they match.
}
output = output / length; // Divide by the length to get a percentage.
return output;
And here we have… a game I made. :DIt was for a health project (oh irony) on OCD.I made use of the above thing in the game.Techno-Jumper - Platformer5 levels. SFX made with SFXR. Music made with FL Studio.DOWNLOAD o.o
Pretty simple algorithm I see, but I'd like to see some test results… how well does this algorithm perform? I quickly glanced over your source material and noticed you are converting the source color to gray scale sort of wrong. Usually converting an RGB color to a gray one is done by 0.3*R+0.59*G+0.11*B. I am not sure what kind of effect this has on the algorithm, but you should try it out!
Furthermore, I became interested in perceptual hashing a few weeks back as well and found pHash. Try to implement THAT in GM :3 :3Well it was written simply and such so I probably did things wrong, but it performs pretty fast, considering the use of get pixel, but Game Maker is a bit iffy about scaling in that it's giving different results sometimes…
And I could certainly fix the greyscale, but I'm just lazy… XDAs far as pHash goes, no. I don't know much C and do not have any environment to work with so yeah… o.oNot sure of a use? lol
Well I have one, so I made it. XD Anyway, I guess it is a bit out of place, for making games, but here it is anyway. O.o
Updated.
WHY MUST MY BLOGS ALWAYS DIE!? </raeg>
Blogs are made to die.