/*====================================================================*
 -  Copyright (C) 2001 Leptonica.  All rights reserved.
 -
 -  Redistribution and use in source and binary forms, with or without
 -  modification, are permitted provided that the following conditions
 -  are met:
 -  1. Redistributions of source code must retain the above copyright
 -     notice, this list of conditions and the following disclaimer.
 -  2. Redistributions in binary form must reproduce the above
 -     copyright notice, this list of conditions and the following
 -     disclaimer in the documentation and/or other materials
 -     provided with the distribution.
 -
 -  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 -  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 -  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 -  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ANY
 -  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 -  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 -  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 -  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 -  OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 -  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 -  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *====================================================================*/
/*
 *  histoduptest.c
 *
 *  This demonstrates two things:
 *  (1) Histogram method of comparing two grayscale images for similarity.
 *      High score (> 0.5) means they're likely to be the same image
 *  (2) The morphological method, based on horizontal lines, for
 *      deciding if a grayscale image is text or non-text.
 */

#ifdef HAVE_CONFIG_H
#include <config_auto.h>
#endif  /* HAVE_CONFIG_H */

#include "string.h"
#include "allheaders.h"


#define  TEST1   1
#define  TEST2   1
#define  TEST3   1
#define  TEST4   1
#define  TEST5   1

l_int32 main(int    argc,
             char **argv)
{
l_uint8     *bytea1, *bytea2;
l_int32      i, j, n, maxi, maxj, istext, w1, h1, w2, h2;
l_int32      debug;
size_t       size1, size2;
l_float32    score, maxscore;
l_float32   *scores;
BOX         *box1, *box2;
NUMA        *nai;
NUMAA       *naa1, *naa2, *naa3, *naa4;
PIX         *pix1, *pix2;
PIXA        *pixa1, *pixa2, *pixa3;
PIXAC       *pac;

    if (argc != 1) {
        fprintf(stderr, "Syntax: histoduptest\n");
        return 1;
    }

        /* Set to 1 for more output from tests 1 and 2 */
    debug = 0;

    setLeptDebugOK(1);
    lept_mkdir("lept/comp");
    pac = pixacompRead("dinos.pac");  /* resolution = 75 ppi */

#if TEST1
    /* -------------------------------------------------------------- *
     *                  Test comparison with rotation                 *
     * -------------------------------------------------------------- */
        /* Make a second set that is rotated; combine with the input set. */
    pixa1 = pixaCreateFromPixacomp(pac, L_COPY);
    pixa2 = pixaScaleBySampling(pixa1, 2.0, 2.0);  /* to resolution 150 ppi */
    n = pixaGetCount(pixa2);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixa2, i, L_CLONE);
        pix2 = pixRotate(pix1, 0.06, L_ROTATE_SAMPLING, L_BRING_IN_WHITE,
                         0, 0);
        pixaAddPix(pixa2, pix2, L_INSERT);
        pixDestroy(&pix1);
    }

        /* Compare between every pair of images;
         * can also use n = 2, simthresh = 0.50.  */
    pixaComparePhotoRegionsByHisto(pixa2, 0.85, 1.3, 1, 3, 0.20,
                                   &nai, &scores, &pix1, debug);
    lept_free(scores);

        /* Show the similarity classes. */
    numaWriteStream(stderr, nai);
    pixWrite("/tmp/lept/comp/photoclass1.jpg", pix1, IFF_JFIF_JPEG);
    fprintf(stderr, "Writing photo classes: /tmp/lept/comp/photoclass1.jpg\n");
    numaDestroy(&nai);
    pixDestroy(&pix1);

        /* Show the scores between images as a 2d array */
    pix2 = pixRead("/tmp/lept/comp/scorearray.png");
    pixDisplay(pix2, 100, 100);
    pixDestroy(&pix2);
    pixaDestroy(&pixa1);
    pixaDestroy(&pixa2);
#endif

#if TEST2
    /* -------------------------------------------------------------- *
     *                      Test translation                          *
     * -------------------------------------------------------------- */
        /* Make a second set that is translated; combine with the input set. */
    pixa1 = pixaCreateFromPixacomp(pac, L_COPY);
    pixa2 = pixaScaleBySampling(pixa1, 2.0, 2.0);  /* to resolution 150 ppi */
    pixa3 = pixaTranslate(pixa2, 15, -21, L_BRING_IN_WHITE);
    pixaJoin(pixa2, pixa3, 0, -1);

        /* Compare between every pair of images. */
    pixaComparePhotoRegionsByHisto(pixa2, 0.85, 1.3, 1, 3, 0.20,
                                   &nai, &scores, &pix1, debug);
    lept_free(scores);

        /* Show the similarity classes. */
    numaWriteStream(stderr, nai);
    pixWrite("/tmp/lept/comp/photoclass2.jpg", pix1, IFF_JFIF_JPEG);
    fprintf(stderr, "Writing photo classes: /tmp/lept/comp/photoclass2.jpg\n");
    numaDestroy(&nai);
    pixDestroy(&pix1);

        /* Show the scores between images as a 2d array */
    pix2 = pixRead("/tmp/lept/comp/scorearray.png");
    pixDisplay(pix2, 100, 100);
    pixDestroy(&pix2);
    pixaDestroy(&pixa1);
    pixaDestroy(&pixa2);
    pixaDestroy(&pixa3);
#endif

#if TEST3
    /* -------------------------------------------------------------- *
     *                 Compare two image regions                      *
     * -------------------------------------------------------------- */
        /* Do a comparison on a pair: dinos has (5,7) and (4,10) being
         * superficially similar.  But they are far apart by this test. */
    pixa1 = pixaCreateFromPixacomp(pac, L_COPY);
    pixa2 = pixaScaleBySampling(pixa1, 2.0, 2.0);  /* to resolution 150 ppi */
    pix1 = pixaGetPix(pixa2, 5, L_CLONE);
    box1 = pixaGetBox(pixa2, 5, L_COPY);
    pix2 = pixaGetPix(pixa2, 7, L_CLONE);
    box2 = pixaGetBox(pixa2, 7, L_COPY);
    pixGenPhotoHistos(pix1, box1, 1, 1.2, 3, &naa1, &w1, &h1, 5);
    pixGenPhotoHistos(pix2, box2, 1, 1.2, 3, &naa2, &w2, &h2, 7);
    pixaDestroy(&pixa1);
    pixaDestroy(&pixa2);
    if (!naa1 || !naa2) {
        fprintf(stderr, "Not both image; exiting\n");
        return 0;
    }
    bytea1 = l_compressGrayHistograms(naa1, w1, h1, &size1);
    bytea2 = l_compressGrayHistograms(naa2, w2, h2, &size2);
    naa3 = l_uncompressGrayHistograms(bytea1, size1, &w1, &h1);
    naa4 = l_uncompressGrayHistograms(bytea2, size2, &w2, &h2);
    fprintf(stderr, "*******  (%d, %d), (%d, %d)  *******\n", w1, h1, w2, h2);
    pixa1 = pixaCreate(0);
        /* Set @minratio very small to allow comparison for all pairs */
    compareTilesByHisto(naa3, naa4, 0.1, w1, h1, w2, h2, &score, pixa1);
    pixaDestroy(&pixa1);
    fprintf(stderr, "score = %5.3f\n", score);
    pixaDestroy(&pixa1);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    boxDestroy(&box1);
    boxDestroy(&box2);
    numaaDestroy(&naa1);
    numaaDestroy(&naa2);
    numaaDestroy(&naa3);
    numaaDestroy(&naa4);
    lept_free(bytea1);
    lept_free(bytea2);
#endif

#if TEST4
    /* -------------------------------------------------------------- *
     *                  Test comparison in detail                     *
     * -------------------------------------------------------------- */
    pixa1 = pixaCreateFromPixacomp(pac, L_COPY);
    n = pixaGetCount(pixa1);
    maxscore = 0.0;
    maxi = 0;
    maxj = 0;
    for (i = 0; i < n; i++) {
        fprintf(stderr, "i = %d\n", i);
        pix1 = pixaGetPix(pixa1, i, L_CLONE);
        box1 = pixaGetBox(pixa1, i, L_COPY);
        for (j = 0; j <= i; j++) {
            pix2 = pixaGetPix(pixa1, j, L_CLONE);
            box2 = pixaGetBox(pixa1, j, L_COPY);
            pixCompareGrayByHisto(pix1, pix2, box1, box2, 0.85, 230, 1, 3,
                                  &score, 0);
            fprintf(stderr, "Score[%d,%d] = %5.3f\n", i, j, score);
            if (i != j && score > maxscore) {
                maxscore = score;
                maxi = i;
                maxj = j;
            }
            pixDestroy(&pix2);
            boxDestroy(&box2);
        }
        pixDestroy(&pix1);
        boxDestroy(&box1);
    }
    pixaDestroy(&pixa1);
    fprintf(stderr, "max score [%d,%d] = %5.3f\n", maxi, maxj, maxscore);
#endif

#if TEST5
    /* -------------------------------------------------------------- *
     *              Text or photo determination in detail             *
     * -------------------------------------------------------------- */
        /* Are the images photo or text?  This is the morphological
         * method, which is more accurate than the variance of gray
         * histo method.  Output to /tmp/lept/comp/isphoto1.pdf.  */
    pixa1 = pixaCreateFromPixacomp(pac, L_COPY);
    n = pixaGetCount(pixa1);
    pixa2 = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pixa3 = pixaCreate(0);
        fprintf(stderr, "i = %d\n", i);
        pix1 = pixaGetPix(pixa1, i, L_CLONE);
        box1 = pixaGetBox(pixa1, i, L_COPY);
        fprintf(stderr, "w = %d, h = %d\n", pixGetWidth(pix1),
                pixGetHeight(pix1));
        pixDecideIfText(pix1, box1, &istext, pixa3);
        if (istext == 1) {
            fprintf(stderr, "This is text\n\n");
        } else if (istext == 0) {
            fprintf(stderr, "This is a photo\n\n");
        } else {  /*  istext == -1 */
            fprintf(stderr, "Not determined if text or photo\n\n");
        }
        if (istext == 0) {
            pix2 = pixaDisplayTiledInRows(pixa3, 32, 1000, 1.0, 0, 50, 2);
            pixDisplay(pix2, 100, 100);
            pixaAddPix(pixa2, pix2, L_INSERT);
            pixaDestroy(&pixa3);
        }
        pixDestroy(&pix1);
        boxDestroy(&box1);
    }
    fprintf(stderr, "Writing to: /tmp/lept/comp/isphoto1.pdf\n");
    pixaConvertToPdf(pixa2, 300, 1.0, L_FLATE_ENCODE, 0, NULL,
                         "/tmp/lept/comp/isphoto1.pdf");
    pixaDestroy(&pixa1);
    pixaDestroy(&pixa2);
#endif

    pixacompDestroy(&pac);
    return 0;
}

