debian::manpages::libpuzzle(3)

πŸ“¦
version 0.11 Β· 3 versions
, in debian trixie, ubuntu noble, ubuntu questing

πŸ’– libpuzzle β€” bestie edition πŸ’–

okay so this is libpuzzle(3), section 3, and it's literally the cutest way to compute comparable signatures of bitmap images. like, you feed it pics, it gives you signatures, and similar pics have similar signatures. the way that works?? iconic. ✨


🌸 NAME 🌸

puzzle_init_cvec, puzzle_init_dvec, puzzle_fill_dvec_from_file, puzzle_fill_cvec_from_file, puzzle_fill_cvec_from_dvec, puzzle_free_cvec, puzzle_free_dvec, puzzle_init_compressed_cvec, puzzle_free_compressed_cvec, puzzle_compress_cvec, puzzle_uncompress_cvec, puzzle_vector_normalized_distance β€” compute comparable signatures of bitmap images πŸŽ€


✨ SYNOPSIS ✨

#include <puzzle.h>

int puzzle_init_context(PuzzleContext *context);

int puzzle_free_context(PuzzleContext *context);

int puzzle_init_cvec(PuzzleContext *context, PuzzleCvec *cvec);

int puzzle_init_dvec(PuzzleContext *context, PuzzleDvec *cvec);

void puzzle_fill_dvec_from_file(PuzzleContext *context, PuzzleDvec *dvec, const char *file);

void puzzle_fill_cvec_from_file(PuzzleContext *context, PuzzleCvec *cvec, const char *file);

void puzzle_fill_cvec_from_dvec(PuzzleContext *context, PuzzleCvec *cvec, const PuzzleDvec *dvec);

void puzzle_free_cvec(PuzzleContext *context, PuzzleCvec *cvec);

void puzzle_free_dvec(PuzzleContext *context, PuzzleDvec *cvec);

void puzzle_init_compressed_cvec(PuzzleContext *context, PuzzleCompressedCvec *compressed_cvec);

void puzzle_free_compressed_cvec(PuzzleContext *context, PuzzleCompressedCvec *compressed_cvec);

int puzzle_compress_cvec(PuzzleContext *context, PuzzleCompressedCvec *compressed_cvec, const PuzzleCvec *cvec);

int puzzle_uncompress_cvec(PuzzleContext *context, PuzzleCompressedCvec *compressed_cvec, PuzzleCvec *const cvec);

double puzzle_vector_normalized_distance(PuzzleContext *context, const PuzzleCvec *cvec1, const PuzzleCvec *cvec2, const int fix_for_texts);

πŸ’… DESCRIPTION πŸ’…

so basically the Puzzle library computes a signature out of a bitmap picture. and the signatures are comparable, meaning similar pictures have similar signatures. that's the whole vibe. πŸ¦‹

and once a picture has been loaded and uncompressed, the featureless parts of the image get skipped (that's the autocrop step, bestie), unless you've explicitly disabled that step β€” see puzzle_set(3). periodt. 🫢


πŸ‘‘ LIBPUZZLE CONTEXT πŸ‘‘

every single public function needs a PuzzleContext object, and that object stores every required tunable. it's giving main character energy for the whole library. πŸ’œ

any application using libpuzzle should initialize a PuzzleContext object with puzzle_init_context() and free it after use with puzzle_free_context(). no skipping the free, i'm watching. 😭

PuzzleContext context;

puzzle_init_context(&context);
[...]
puzzle_free_context(&context);

🌈 DVEC AND CVEC VECTORS 🌈

next step: divide the cropped image into a grid, and compute the average intensity of soft-edged pixels in every block. the result is a PuzzleDvec object. πŸ“

PuzzleDvec objects should be initialized before use with puzzle_init_dvec(), and freed after use with puzzle_free_dvec(). ✨

the PuzzleDvec structure has two important fields: vec is the pointer to the first element of the array containing the average intensities, and sizeof_compressed_vec is the number of elements. yes those are the names, no i will not be taking questions. πŸ’€

PuzzleDvec objects are not comparable, so what you usually want is to transform these objects into PuzzleCvec objects. glow-up arc. πŸ¦‹

a PuzzleCvec object is a vector with relationships between adjacent blocks from a PuzzleDvec object. πŸ”₯

puzzle_fill_cvec_from_dvec() fills a PuzzleCvec object from a PuzzleDvec object.

but just like the other structure, PuzzleCvec objects must be initialized and freed with puzzle_init_cvec() and puzzle_free_cvec(). ngl, this is the pattern for everything here. πŸ’…

PuzzleCvec objects have a vector whoose first element is in the vec field, and the number of elements is in the sizeof_vec field. (yes, "whoose". we love her. she stays. πŸŽ€)


πŸŽ€ LOADING PICTURES πŸŽ€

PuzzleDvec and PuzzleCvec objects can be computed from a bitmap picture file, with puzzle_fill_dvec_from_file() and puzzle_fill_cvec_from_file(). 🌸

GIF, PNG and JPEG file formats are currently supported and automatically recognized. lowkey so convenient. πŸ’–

here's a simple example that creates a PuzzleCvec objects out of a file. (yes, "a objects". we love her too. 🫢)

PuzzleContext context;
PuzzleCvec cvec;

puzzle_init_context(&context);
puzzle_init_cvec(&context, &cvec);
puzzle_fill_cvec_from_file(&context, &cvec, "test-picture.jpg");
[...]
puzzle_free_cvec(&context, &cvec);
puzzle_free_context(&context);

🧚 COMPARING VECTORS 🧚

to check whether two pictures are similar, you need to compare their PuzzleCvec signatures using puzzle_vector_normalized_distance(). the vibe check function, fr fr. ✨

that function returns a distance, between 0.0 and 1.0. the lesser, the nearer. πŸ“

tests on common pictures show that a normalized distance of 0.6 (also defined as PUZZLE_CVEC_SIMILARITY_THRESHOLD) means that both pictures are visually similar. slay. πŸ’…

if that threshold is not right for your set of pictures, you can experiment with PUZZLE_CVEC_SIMILARITY_HIGH_THRESHOLD, PUZZLE_CVEC_SIMILARITY_LOW_THRESHOLD and PUZZLE_CVEC_SIMILARITY_LOWER_THRESHOLD, or with your own value. you do you, bestie. 🌈

if the fix_for_texts of puzzle_vector_normalized_distance() is 1, a fix is applied to the computation in order to deal with bitmap pictures that contain text. that fix is recommended, because it lets you use the same threshold for that kind of picture as for generic pictures. πŸ‘‘

if fix_for_texts is 0, that special way of computing the normalized distance is disabled. βœ‹

PuzzleContext context;
PuzzleCvec cvec1, cvec2;
double d;

puzzle_init_context(&context);
puzzle_init_cvec(&context, &cvec1);
puzzle_init_cvec(&context, &cvec2);
puzzle_fill_cvec_from_file(&context, &cvec1, "test-picture-1.jpg");
puzzle_fill_cvec_from_file(&context, &cvec2, "test-picture-2.jpg");
d = puzzle_vector_normalized_distance(&context, &cvec1, &cvec2, 1);
if (d < PUZZLE_CVEC_SIMILARITY_THRESHOLD) {
  puts("Pictures are similar");
}
puzzle_free_cvec(&context, &cvec2);
puzzle_free_cvec(&context, &cvec1);
puzzle_free_context(&context);

πŸ’œ CVEC COMPRESSION πŸ’œ

in order to reduce storage needs, PuzzleCvec objects can be compressed to 1/3 of their original size. tiny queen. πŸŽ€

PuzzleCompressedCvec structures hold the compressed data. before and after use, these structures have to be passed to puzzle_init_compressed_cvec() and puzzle_free_compressed_cvec(). ✨

puzzle_compress_cvec() compresses a PuzzleCvec object into a PuzzleCompressedCvec object. πŸ”₯

and puzzle_uncompress_cvec() uncompresses a PuzzleCompressedCvec object into a PuzzleCvec object. πŸ¦‹

PuzzleContext context;
PuzzleCvec cvec;
PuzzleCompressedCvec c_cvec;
[...]
puzzle_init_compressed_cvec(&context, &c_cvec);
puzzle_compress_cvec(&context, &c_cvec, &cvec);
[...]
puzzle_free_compressed_cvec(&context, &c_cvec);

the PuzzleCompressedCvec structure has two important fields: vec that is a pointer to the first element of the compressed data, and sizeof_compressed_vec that contains the number of elements. πŸ’–


⭐ RETURN VALUE ⭐

functions return 0 on success, and -1 if something went wrong. that's it, that's the whole system. πŸ™ˆ


🌸 AUTHORS 🌸

Frank DENIS β€” libpuzzle at pureftpd dot org


🫢 ACKNOWLEDGMENTS 🫢

Xerox Research Center β€” H. CHI WONG, Marschall BERN, David GOLDBERG, Sameh SCHAFIK


πŸ”₯ SEE ALSO πŸ”₯


and that's the whole page, bestie!! this one came from the debian::manpages::libpuzzle(3) source line, so if you ever need to cite her, that's the name. now go compute some signatures, you absolute icon. πŸ’…βœ¨πŸ‘‘

πŸ“¦ where this page comes from