/**********************************************************************
 * File:        matmatch.cpp  (Formerly matrix_match.c)
 * Description: matrix matching routines for Tessedit
 * Author:      Chris Newton
 * Created:     Wed Nov 24 15:57:41 GMT 1993
 *
 * (C) Copyright 1993, Hewlett-Packard Ltd.
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
 ** You may obtain a copy of the License at
 ** http://www.apache.org/licenses/LICENSE-2.0
 ** Unless required by applicable law or agreed to in writing, software
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 *
 **********************************************************************/

#include "mfcpch.h"
#include          <stdlib.h>
#include          <math.h>
#include          <string.h>
#include          <ctype.h>
#include          <assert.h>
#include          "tessvars.h"
#include          "stderr.h"
#include          "img.h"
#include          "hosthplb.h"
#include          "adaptions.h"
#include          "matmatch.h"
#include          "secname.h"

#define EXTERN

EXTERN BOOL_VAR (tessedit_display_mm, FALSE, "Display matrix matches");
EXTERN BOOL_VAR (tessedit_mm_debug, FALSE,
"Print debug information for matrix matcher");
EXTERN INT_VAR (tessedit_mm_prototype_min_size, 3,
"Smallest number of samples in a cluster for a prototype to be used");

// Colours for displaying the match
#define BB_COLOUR 0
#define BW_COLOUR 1
#define WB_COLOUR 3
#define UB_COLOUR 5
#define BU_COLOUR 7
#define UU_COLOUR 9
#define WU_COLOUR 11
#define UW_COLOUR 13
#define WW_COLOUR 15

#define BINIM_BLACK 0
#define BINIM_WHITE 1

float matrix_match(  // returns match score
                   IMAGE *image1,
                   IMAGE *image2) {
  ASSERT_HOST (image1->get_bpp () == 1 && image2->get_bpp () == 1);

  if (image1->get_xsize () >= image2->get_xsize ())
    return match1 (image1, image2);
  else
    return match1 (image2, image1);
}


float match1(  /* returns match score */
             IMAGE *image_w,
             IMAGE *image_n) {
  inT32 x_offset;
  inT32 y_offset;
  inT32 x_size = image_w->get_xsize ();
  inT32 y_size;
  inT32 x_size2 = image_n->get_xsize ();
  inT32 y_size2;
  IMAGE match_image;
  IMAGELINE imline_w;
  IMAGELINE imline_n;
  IMAGELINE match_imline;
  inT32 x;
  inT32 y;
  float sum = 0.0;

  x_offset = (image_w->get_xsize () - image_n->get_xsize ()) / 2;

  ASSERT_HOST (x_offset >= 0);
  match_imline.init (x_size);

  sum = 0;

  if (image_w->get_ysize () < image_n->get_ysize ()) {
    y_size = image_n->get_ysize ();
    y_size2 = image_w->get_ysize ();
    y_offset = (y_size - y_size2) / 2;

    if (tessedit_display_mm && !tessedit_mm_use_prototypes)
      tprintf ("I1 (%d, %d), I2 (%d, %d), MI (%d, %d)\n", x_size,
        image_w->get_ysize (), x_size2, image_n->get_ysize (),
        x_size, y_size);

    match_image.create (x_size, y_size, 4);

    for (y = 0; y < y_offset; y++) {
      image_n->fast_get_line (0, y, x_size2, &imline_n);
      for (x = 0; x < x_size2; x++) {
        if (imline_n.pixels[x] == BINIM_BLACK) {
          sum += -1;
          match_imline.pixels[x] = UB_COLOUR;
        }
        else {
          match_imline.pixels[x] = UW_COLOUR;
        }
      }
      match_image.fast_put_line (x_offset, y, x_size2, &match_imline);
    }

    for (y = y_offset + y_size2; y < y_size; y++) {
      image_n->fast_get_line (0, y, x_size2, &imline_n);
      for (x = 0; x < x_size2; x++) {
        if (imline_n.pixels[x] == BINIM_BLACK) {
          sum += -1.0;
          match_imline.pixels[x] = UB_COLOUR;
        }
        else {
          match_imline.pixels[x] = UW_COLOUR;
        }
      }
      match_image.fast_put_line (x_offset, y, x_size2, &match_imline);
    }

    for (y = y_offset; y < y_offset + y_size2; y++) {
      image_w->fast_get_line (0, y - y_offset, x_size, &imline_w);
      image_n->fast_get_line (0, y, x_size2, &imline_n);
      for (x = 0; x < x_offset; x++) {
        if (imline_w.pixels[x] == BINIM_BLACK) {
          sum += -1.0;
          match_imline.pixels[x] = BU_COLOUR;
        }
        else {
          match_imline.pixels[x] = WU_COLOUR;
        }
      }

      for (x = x_offset + x_size2; x < x_size; x++) {
        if (imline_w.pixels[x] == BINIM_BLACK) {
          sum += -1.0;
          match_imline.pixels[x] = BU_COLOUR;
        }
        else {
          match_imline.pixels[x] = WU_COLOUR;
        }
      }

      for (x = x_offset; x < x_offset + x_size2; x++) {
        if (imline_n.pixels[x - x_offset] == imline_w.pixels[x]) {
          sum += 1.0;
          if (imline_w.pixels[x] == BINIM_BLACK)
            match_imline.pixels[x] = BB_COLOUR;
          else
            match_imline.pixels[x] = WW_COLOUR;
        }
        else {
          sum += -1.0;
          if (imline_w.pixels[x] == BINIM_BLACK)
            match_imline.pixels[x] = BW_COLOUR;
          else
            match_imline.pixels[x] = WB_COLOUR;
        }
      }

      match_image.fast_put_line (0, y, x_size, &match_imline);
    }
  }
  else {
    y_size = image_w->get_ysize ();
    y_size2 = image_n->get_ysize ();
    y_offset = (y_size - y_size2) / 2;

    if (tessedit_display_mm && !tessedit_mm_use_prototypes)
      tprintf ("I1 (%d, %d), I2 (%d, %d), MI (%d, %d)\n", x_size,
        image_w->get_ysize (), x_size2, image_n->get_ysize (),
        x_size, y_size);

    match_image.create (x_size, y_size, 4);

    for (y = 0; y < y_offset; y++) {
      image_w->fast_get_line (0, y, x_size, &imline_w);
      for (x = 0; x < x_size; x++) {
        if (imline_w.pixels[x] == BINIM_BLACK) {
          sum += -1;
          match_imline.pixels[x] = BU_COLOUR;
        }
        else {
          match_imline.pixels[x] = WU_COLOUR;
        }
      }
      match_image.fast_put_line (0, y, x_size, &match_imline);
    }

    for (y = y_offset + y_size2; y < y_size; y++) {
      image_w->fast_get_line (0, y, x_size, &imline_w);
      for (x = 0; x < x_size; x++) {
        if (imline_w.pixels[x] == BINIM_BLACK) {
          sum += -1;
          match_imline.pixels[x] = BU_COLOUR;
        }
        else {
          match_imline.pixels[x] = WU_COLOUR;
        }
      }
      match_image.fast_put_line (0, y, x_size, &match_imline);
    }

    for (y = y_offset; y < y_offset + y_size2; y++) {
      image_w->fast_get_line (0, y, x_size, &imline_w);
      image_n->fast_get_line (0, y - y_offset, x_size2, &imline_n);
      for (x = 0; x < x_offset; x++) {
        if (imline_w.pixels[x] == BINIM_BLACK) {
          sum += -1.0;
          match_imline.pixels[x] = BU_COLOUR;
        }
        else {
          match_imline.pixels[x] = WU_COLOUR;
        }
      }

      for (x = x_offset + x_size2; x < x_size; x++) {
        if (imline_w.pixels[x] == BINIM_BLACK) {
          sum += -1.0;
          match_imline.pixels[x] = BU_COLOUR;
        }
        else {
          match_imline.pixels[x] = WU_COLOUR;
        }
      }

      for (x = x_offset; x < x_offset + x_size2; x++) {
        if (imline_n.pixels[x - x_offset] == imline_w.pixels[x]) {
          sum += 1.0;
          if (imline_w.pixels[x] == BINIM_BLACK)
            match_imline.pixels[x] = BB_COLOUR;
          else
            match_imline.pixels[x] = WW_COLOUR;
        }
        else {
          sum += -1.0;
          if (imline_w.pixels[x] == BINIM_BLACK)
            match_imline.pixels[x] = BW_COLOUR;
          else
            match_imline.pixels[x] = WB_COLOUR;
        }
      }

      match_image.fast_put_line (0, y, x_size, &match_imline);
    }
  }
  if (tessedit_mm_debug)
    tprintf ("Match score %f\n", 1.0 - sum / (x_size * y_size));

  return (1.0 - sum / (x_size * y_size));
}
