.\" Automatically generated by Pod::Man 4.10 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "debian::manpages::libpuzzle 3" .TH debian::manpages::libpuzzle 3 "" "" "" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "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 .SH "SYNOPSIS" .IX Header "SYNOPSIS" #include .PP int puzzle_init_context(PuzzleContext *\fIcontext\fR); .PP int puzzle_free_context(PuzzleContext *\fIcontext\fR); .PP int puzzle_init_cvec(PuzzleContext *\fIcontext\fR, PuzzleCvec *\fIcvec\fR); .PP int puzzle_init_dvec(PuzzleContext *\fIcontext\fR, PuzzleDvec *\fIcvec\fR); .PP void puzzle_fill_dvec_from_file(PuzzleContext *\fIcontext\fR, PuzzleDvec *\fIdvec\fR, const char *\fIfile\fR); .PP void puzzle_fill_cvec_from_file(PuzzleContext *\fIcontext\fR, PuzzleCvec *\fIcvec\fR, const char *\fIfile\fR); .PP void puzzle_fill_cvec_from_dvec(PuzzleContext *\fIcontext\fR, PuzzleCvec *\fIcvec\fR, const PuzzleDvec *\fIdvec\fR); .PP void puzzle_free_cvec(PuzzleContext *\fIcontext\fR, PuzzleCvec *\fIcvec\fR); .PP void puzzle_free_dvec(PuzzleContext *\fIcontext\fR, PuzzleDvec *\fIcvec\fR); .PP void puzzle_init_compressed_cvec(PuzzleContext *\fIcontext\fR, PuzzleCompressedCvec *\fIcompressed_cvec\fR); .PP void puzzle_free_compressed_cvec(PuzzleContext *\fIcontext\fR, PuzzleCompressedCvec *\fIcompressed_cvec\fR); .PP int puzzle_compress_cvec(PuzzleContext *\fIcontext\fR, PuzzleCompressedCvec *\fIcompressed_cvec\fR, const PuzzleCvec *\fIcvec\fR); .PP int puzzle_uncompress_cvec(PuzzleContext *\fIcontext\fR, PuzzleCompressedCvec *\fIcompressed_cvec\fR, PuzzleCvec *\fIconst cvec\fR); .PP double puzzle_vector_normalized_distance(PuzzleContext *\fIcontext\fR, const PuzzleCvec *\fIcvec1\fR, const PuzzleCvec *\fIcvec2\fR, const int \fIfix_for_texts\fR); .SH "DESCRIPTION" .IX Header "DESCRIPTION" The Puzzle library computes a signature out of a bitmap picture. Signatures are comparable and similar pictures have similar signatures. .PP After a picture has been loaded and uncompressed, featureless parts of the image are skipped (autocrop), unless that step has been explicitly disabled, see \fBpuzzle_set\fR\|(3) .SH "LIBPUZZLE CONTEXT" .IX Header "LIBPUZZLE CONTEXT" Every public function requires a \fIPuzzleContext\fR object, that stores every required tunables. .PP Any application using libpuzzle should initialize a \fIPuzzleContext\fR object with \fB\fBpuzzle_init_context()\fB\fR and free it after use with \fB\fBpuzzle_free_context()\fB\fR .Sp .Vb 1 \& PuzzleContext context; \& \& puzzle_init_context(&context); \& [...] \& puzzle_free_context(&context); .Ve .SH "DVEC AND CVEC VECTORS" .IX Header "DVEC AND CVEC VECTORS" The next step is to divide the cropped image into a grid and to compute the average intensity of soft-edged pixels in every block. The result is a \fIPuzzleDvec\fR object. .PP \&\fIPuzzleDvec\fR objects should be initialized before use, with \fB\fBpuzzle_init_dvec()\fB\fR and freed after use with \fB\fBpuzzle_free_dvec()\fB\fR. .PP The \fIPuzzleDvec\fR structure has two important fields: \fIvec\fR is the pointer to the first element of the array containing the average intensities, and \fIsizeof_compressed_vec\fR is the number of elements. .PP \&\fIPuzzleDvec\fR objects are not comparable, so what you usually want is to transform these objects into \fIPuzzleCvec\fR objects. .PP A \fIPuzzleCvec\fR object is a vector with relationships between adjacent blocks from a \fIPuzzleDvec\fR object. .PP The \fB\fBpuzzle_fill_cvec_from_dvec()\fB\fR fills a \fIPuzzleCvec\fR object from a \fIPuzzleDvec\fR object. .PP But just like the other structure, \fIPuzzleCvec\fR objects must be initialized and freed with \fB\fBpuzzle_init_cvec()\fB\fR and \fB\fBpuzzle_free_cvec()\fB\fR. .PP \&\fIPuzzleCvec\fR objects have a vector whoose first element is in the \fIvec\fR field, and the number of elements is in the \fIsizeof_vec\fR field. .SH "LOADING PICTURES" .IX Header "LOADING PICTURES" \&\fIPuzzleDvec\fR and \fIPuzzleCvec\fR objects can be computed from a bitmap picture file, with \fB\fBpuzzle_fill_dvec_from_file()\fB\fR and \fB\fBpuzzle_fill_cvec_from_file()\fB\fR. .PP \&\fI\s-1GIF\s0\fR, \fI\s-1PNG\s0\fR and \fI\s-1JPEG\s0\fR files formats are currently supported and automatically recognized. .PP Here's a simple example that creates a \fIPuzzleCvec\fR objects out of a file. .Sp .Vb 2 \& 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); .Ve .SH "COMPARING VECTORS" .IX Header "COMPARING VECTORS" In order to check whether two pictures are similar, you need to compare their \fIPuzzleCvec\fR signatures, using \fB\fBpuzzle_vector_normalized_distance()\fB\fR. .PP That function returns a distance, between 0.0 and 1.0. The lesser, the nearer. .PP Tests on common pictures show that a normalized distance of 0.6 (also defined as \fI\s-1PUZZLE_CVEC_SIMILARITY_THRESHOLD\s0\fR) means that both pictures are visually similar. .PP If that threshold is not right for your set of pictures, you can experiment with \fI\s-1PUZZLE_CVEC_SIMILARITY_HIGH_THRESHOLD\s0\fR, \fI\s-1PUZZLE_CVEC_SIMILARITY_LOW_THRESHOLD\s0\fR and \fI\s-1PUZZLE_CVEC_SIMILARITY_LOWER_THRESHOLD\s0\fR or with your own value. .PP If the \fIfix_for_texts\fR of \fB\fBpuzzle_vector_normalized_distance()\fB\fR is 1, a fix is applied to the computation in order to deal with bitmap pictures that contain text. That fix is recommended, as it allows using the same threshold for that kind of picture as for generic pictures. .PP If \fIfix_for_texts\fR is \fI0\fR, that special way of computing the normalized distance is disabled. .Sp .Vb 3 \& 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); .Ve .SH "CVEC COMPRESSION" .IX Header "CVEC COMPRESSION" In order to reduce storage needs, \fIPuzzleCvec\fR objects can be compressed to 1/3 of their original size. .PP \&\fIPuzzleCompressedCvec\fR structures hold the compressed data. Before and after use, these structures have to be passed to \fB\fBpuzzle_init_compressed_cvec()\fB\fR and \fB\fBpuzzle_free_compressed_cvec()\fB\fR. .PP \&\fB\fBpuzzle_compress_cvec()\fB\fR compresses a \fIPuzzleCvec\fR object into a \fIPuzzleCompressedCvec\fR object. .PP And \fB\fBpuzzle_uncompress_cvec()\fB\fR uncompresses a \fIPuzzleCompressedCvec\fR object into a \fIPuzzleCvec\fR object. .Sp .Vb 8 \& 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); .Ve .PP The \fIPuzzleCompressedCvec\fR structure has two important fields: \fIvec\fR that is a pointer to the first element of the compressed data, and \fIsizeof_compressed_vec\fR that contains the number of elements. .SH "RETURN VALUE" .IX Header "RETURN VALUE" Functions return \fI0\fR on success, and \fI\-1\fR if something went wrong. .SH "AUTHORS" .IX Header "AUTHORS" Frank \s-1DENIS\s0 libpuzzle at pureftpd dot org .SH "ACKNOWLEDGMENTS" .IX Header "ACKNOWLEDGMENTS" Xerox Research Center H. \s-1CHI WONG\s0 Marschall \s-1BERN\s0 David \s-1GOLDBERG\s0 Sameh \s-1SCHAFIK\s0 .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fBpuzzle_set\fR\|(3), \fBpuzzle\-diff\fR\|(8)