Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "autopos.h"
Toshihiro Shimizu 890ddd
#include "cleanupcommon.h"
Toshihiro Shimizu 890ddd
tomosu eea0ac
#include <sstream></sstream>
Shinya Kitaoka 9eb50d
Toshihiro Shimizu 890ddd
using namespace CleanupTypes;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
guardare DAFARE
Toshihiro Shimizu 890ddd
guardare assumo
Shinya Kitaoka 120a6e
autoalign rgb ->ora viene chiamata con un buffer rgbm ! modificare
Shinya Kitaoka 120a6e
opportunamente
Toshihiro Shimizu 890ddd
tomosu eea0ac
fare resize e realloc size dello stack a 65000 unita'
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Campbell Barton 107701
#if defined(MACOSX) || defined(LINUX)
Toshihiro Shimizu 890ddd
#define TRUE 1
Toshihiro Shimizu 890ddd
#define FALSE 0
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define SECURITY_MARGIN_MM 4.0
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static int Debug_flag = FALSE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*===========================================================================*/
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
tomosu eea0ac
     AUTOALIGNMENT
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define AUTOAL_BLACK_COLS 2
Toshihiro Shimizu 890ddd
#define AUTOAL_WHITE_COLS 2
Toshihiro Shimizu 890ddd
#define AUTOAL_THRESHOLD 160
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static int autoalign_gr8(UCHAR *buffer_gr8, int wrap, int lx, int ly,
Shinya Kitaoka 120a6e
                         int pix_origin, int dpix_dx, int dpix_dy,
Shinya Kitaoka 120a6e
                         int strip_width) {
Shinya Kitaoka 120a6e
  int first_x[2], dx_dcol[2], target[2];
Shinya Kitaoka 120a6e
  int i, x, y, cols;
Shinya Kitaoka 120a6e
  int col_value, threshold;
Shinya Kitaoka 120a6e
  int consec_black_cols, consec_white_cols, black_strip_edge;
Shinya Kitaoka 120a6e
  UCHAR *pix, *origin;
Shinya Kitaoka 120a6e
  int delta_x, delta_pix;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  origin = buffer_gr8 + pix_origin;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  first_x[0] = 0;
Shinya Kitaoka 120a6e
  dx_dcol[0] = 1;
Shinya Kitaoka 120a6e
  target[0]  = strip_width / 2;
Shinya Kitaoka 120a6e
  first_x[1] = lx - 1;
Shinya Kitaoka 120a6e
  dx_dcol[1] = -1;
Shinya Kitaoka 120a6e
  target[1]  = lx - 1 - strip_width / 2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  threshold = AUTOAL_THRESHOLD * ly;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (i = 0; i < 2; i++) {
Shinya Kitaoka 120a6e
    consec_black_cols = 0;
Shinya Kitaoka 120a6e
    consec_white_cols = 0;
Shinya Kitaoka 120a6e
    black_strip_edge  = 0;
Shinya Kitaoka 120a6e
    for (x = first_x[i], cols = 0; cols < strip_width;
Shinya Kitaoka 120a6e
         x += dx_dcol[i], cols++) {
Shinya Kitaoka 120a6e
      col_value = 0;
Shinya Kitaoka 120a6e
      pix       = origin + x * dpix_dx;
Shinya Kitaoka 120a6e
      for (y = 0; y < ly; y++) {
Shinya Kitaoka 120a6e
        col_value += *pix;
Shinya Kitaoka 120a6e
        pix += dpix_dy;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (col_value < threshold) {
Shinya Kitaoka 120a6e
        consec_white_cols = 0;
Shinya Kitaoka 120a6e
        consec_black_cols++;
Shinya Kitaoka 120a6e
        if (consec_black_cols >= AUTOAL_BLACK_COLS) black_strip_edge = x;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        consec_black_cols = 0;
Shinya Kitaoka 120a6e
        consec_white_cols++;
Shinya Kitaoka 120a6e
        if (consec_white_cols >= AUTOAL_WHITE_COLS && black_strip_edge)
Shinya Kitaoka 120a6e
          goto found;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return FALSE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
found:
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (x = first_x[i], cols = 0; cols < strip_width; x += dx_dcol[i], cols++) {
Shinya Kitaoka 120a6e
    pix = origin + x * dpix_dx;
Shinya Kitaoka 120a6e
    for (y = 0; y < ly; y++) {
Shinya Kitaoka 120a6e
      *pix = 255;
Shinya Kitaoka 120a6e
      pix += dpix_dy;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  delta_x   = target[i] - black_strip_edge;
Shinya Kitaoka 120a6e
  delta_pix = delta_x * dpix_dx;
Shinya Kitaoka 120a6e
  if (delta_x > 0) {
Shinya Kitaoka 120a6e
    for (x = lx - 1 - delta_x; x >= 0; x--) {
Shinya Kitaoka 120a6e
      pix = origin + x * dpix_dx;
Shinya Kitaoka 120a6e
      for (y = 0; y < ly; y++) {
Shinya Kitaoka 120a6e
        *(pix + delta_pix) = *pix;
Shinya Kitaoka 120a6e
        pix += dpix_dy;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    for (x = lx - delta_x; x < lx; x++) {
Shinya Kitaoka 120a6e
      pix = origin + x * dpix_dx;
Shinya Kitaoka 120a6e
      for (y = 0; y < ly; y++) {
Shinya Kitaoka 120a6e
        *pix = 255;
Shinya Kitaoka 120a6e
        pix += dpix_dy;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else if (delta_x < 0) {
Shinya Kitaoka 120a6e
    for (x = -delta_x; x < lx; x++) {
Shinya Kitaoka 120a6e
      pix = origin + x * dpix_dx;
Shinya Kitaoka 120a6e
      for (y = 0; y < ly; y++) {
Shinya Kitaoka 120a6e
        *(pix + delta_pix) = *pix;
Shinya Kitaoka 120a6e
        pix += dpix_dy;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    for (x = 0; x < -delta_x; x++) {
Shinya Kitaoka 120a6e
      pix = origin + x * dpix_dx;
Shinya Kitaoka 120a6e
      for (y = 0; y < ly; y++) {
Shinya Kitaoka 120a6e
        *pix = 255;
Shinya Kitaoka 120a6e
        pix += dpix_dy;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return TRUE;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static int autoalign_rgb(TPixel32 *buffer_rgb, int wrap, int lx, int ly,
Shinya Kitaoka 120a6e
                         int pix_origin, int dpix_dx, int dpix_dy,
Shinya Kitaoka 120a6e
                         int strip_width) {
Shinya Kitaoka 120a6e
  int first_x[2], dx_dcol[2], target[2];
Shinya Kitaoka 120a6e
  int i, x, y, cols;
Shinya Kitaoka 120a6e
  int col_value, threshold;
Shinya Kitaoka 120a6e
  int consec_black_cols, consec_white_cols, black_strip_edge;
Shinya Kitaoka 120a6e
  TPixel32 *pix, *origin;
Shinya Kitaoka 120a6e
  int delta_x, delta_pix;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  origin = buffer_rgb + pix_origin;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  first_x[0] = 0;
Shinya Kitaoka 120a6e
  dx_dcol[0] = 1;
Shinya Kitaoka 120a6e
  target[0]  = strip_width / 2;
Shinya Kitaoka 120a6e
  first_x[1] = lx - 1;
Shinya Kitaoka 120a6e
  dx_dcol[1] = -1;
Shinya Kitaoka 120a6e
  target[1]  = lx - 1 - strip_width / 2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  threshold = AUTOAL_THRESHOLD * ly;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (i = 0; i < 2; i++) {
Shinya Kitaoka 120a6e
    consec_black_cols = 0;
Shinya Kitaoka 120a6e
    consec_white_cols = 0;
Shinya Kitaoka 120a6e
    black_strip_edge  = 0;
Shinya Kitaoka 120a6e
    for (x = first_x[i], cols = 0; cols < strip_width;
Shinya Kitaoka 120a6e
         x += dx_dcol[i], cols++) {
Shinya Kitaoka 120a6e
      col_value = 0;
Shinya Kitaoka 120a6e
      pix       = origin + x * dpix_dx;
Shinya Kitaoka 120a6e
      for (y = 0; y < ly; y++) {
Shinya Kitaoka 120a6e
        col_value += (pix->r * 2 + pix->g * 5 + pix->b) >> 3;
Shinya Kitaoka 120a6e
        pix += dpix_dy;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (col_value < threshold) {
Shinya Kitaoka 120a6e
        consec_white_cols = 0;
Shinya Kitaoka 120a6e
        consec_black_cols++;
Shinya Kitaoka 120a6e
        if (consec_black_cols >= AUTOAL_BLACK_COLS) black_strip_edge = x;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        consec_black_cols = 0;
Shinya Kitaoka 120a6e
        consec_white_cols++;
Shinya Kitaoka 120a6e
        if (consec_white_cols >= AUTOAL_WHITE_COLS && black_strip_edge)
Shinya Kitaoka 120a6e
          goto found;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return FALSE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
found:
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (x = first_x[i], cols = 0; cols < strip_width; x += dx_dcol[i], cols++) {
Shinya Kitaoka 120a6e
    pix = origin + x * dpix_dx;
Shinya Kitaoka 120a6e
    for (y = 0; y < ly; y++) {
Shinya Kitaoka 120a6e
      pix->r = pix->g = pix->b = 255;
Shinya Kitaoka 120a6e
      pix += dpix_dy;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  delta_x   = target[i] - black_strip_edge;
Shinya Kitaoka 120a6e
  delta_pix = delta_x * dpix_dx;
Shinya Kitaoka 120a6e
  if (delta_x > 0) {
Shinya Kitaoka 120a6e
    for (x = lx - 1 - delta_x; x >= 0; x--) {
Shinya Kitaoka 120a6e
      pix = origin + x * dpix_dx;
Shinya Kitaoka 120a6e
      for (y = 0; y < ly; y++) {
Shinya Kitaoka 120a6e
        (pix + delta_pix)->r = pix->r;
Shinya Kitaoka 120a6e
        (pix + delta_pix)->g = pix->g;
Shinya Kitaoka 120a6e
        (pix + delta_pix)->b = pix->b;
Shinya Kitaoka 120a6e
        pix += dpix_dy;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    for (x = lx - delta_x; x < lx; x++) {
Shinya Kitaoka 120a6e
      pix = origin + x * dpix_dx;
Shinya Kitaoka 120a6e
      for (y = 0; y < ly; y++) {
Shinya Kitaoka 120a6e
        pix->r = pix->g = pix->b = 255;
Shinya Kitaoka 120a6e
        pix += dpix_dy;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else if (delta_x < 0) {
Shinya Kitaoka 120a6e
    for (x = -delta_x; x < lx; x++) {
Shinya Kitaoka 120a6e
      pix = origin + x * dpix_dx;
Shinya Kitaoka 120a6e
      for (y = 0; y < ly; y++) {
Shinya Kitaoka 120a6e
        (pix + delta_pix)->r = pix->r;
Shinya Kitaoka 120a6e
        (pix + delta_pix)->g = pix->g;
Shinya Kitaoka 120a6e
        (pix + delta_pix)->b = pix->b;
Shinya Kitaoka 120a6e
        pix += dpix_dy;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    for (x = 0; x < -delta_x; x++) {
Shinya Kitaoka 120a6e
      pix = origin + x * dpix_dx;
Shinya Kitaoka 120a6e
      for (y = 0; y < ly; y++) {
Shinya Kitaoka 120a6e
        pix->r = pix->g = pix->b = 255;
Shinya Kitaoka 120a6e
        pix += dpix_dy;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return TRUE;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int do_autoalign(const TRasterImageP &image) {
Shinya Kitaoka 120a6e
  int wrap, lx, ly, mx, my;
Shinya Kitaoka 120a6e
  int pix_origin, dpix_dx, dpix_dy;
Shinya Kitaoka 120a6e
  int strip_width;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // assumo che sia sempre orientata nel modo corretto
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRasterP ras = image->getRaster();
Shinya Kitaoka 120a6e
  wrap         = ras->getWrap();
Shinya Kitaoka 120a6e
  assert(TRaster32P(ras) ||
Shinya Kitaoka 120a6e
         TRasterGR8P(ras));  // per ricordare di gestire le img bw!
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // assumo TOR_BOTLEFT:__OR TOR_BOTRIGHT:__OR TOR_TOPLEFT:__OR TOR_TOPRIGHT:
Shinya Kitaoka 120a6e
  double dpix, dpiy;
Shinya Kitaoka 120a6e
  image->getDpi(dpix, dpiy);
Shinya Kitaoka 120a6e
  strip_width = (int)mmToPixel(5.0, dpix);
Shinya Kitaoka 120a6e
  lx          = ras->getLx();
Shinya Kitaoka 120a6e
  ly          = ras->getLy();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  mx = lx - 1;
Shinya Kitaoka 120a6e
  my = ly - 1;
Shinya Kitaoka d4642c
Shinya Kitaoka 120a6e
  // assumo  CASE TOR_BOTLEFT:
Shinya Kitaoka 120a6e
  pix_origin = 0;
Shinya Kitaoka 120a6e
  dpix_dx    = 1;
Shinya Kitaoka 120a6e
  dpix_dy    = wrap;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRasterGR8P ras8(ras);
Shinya Kitaoka 120a6e
  TRaster32P ras32(ras);
Shinya Kitaoka 120a6e
  ras->lock();
Shinya Kitaoka 120a6e
  int ret = FALSE;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (ras8)
Shinya Kitaoka 120a6e
    ret = autoalign_gr8(ras8->getRawData(), wrap, lx, ly, pix_origin, dpix_dx,
Shinya Kitaoka 120a6e
                        dpix_dy, strip_width);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  else if (ras32)
Shinya Kitaoka 120a6e
    ret = autoalign_rgb(ras32->pixels(), wrap, lx, ly, pix_origin, dpix_dx,
Shinya Kitaoka 120a6e
                        dpix_dy, strip_width);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    assert(!"Unsupported pixel type");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ras->unlock();
Shinya Kitaoka d4642c
Shinya Kitaoka 120a6e
  return FALSE;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*===========================================================================*/
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
     AUTOCENTERING
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
/*
tomosu eea0ac
 * Calcoli in millimetri per questa funzione che alla fine restituisce un
Toshihiro Shimizu 890ddd
 * valore per la striscia di ricerca direttamente in pixel
Toshihiro Shimizu 890ddd
 */
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int compute_strip_pixel(FDG_INFO *fdg, double dpi) {
Shinya Kitaoka 120a6e
  int i, strip_size_pix;
Shinya Kitaoka 120a6e
  double half_size, max_half_size, strip_size_mm;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  max_half_size = -1.0;
Shinya Kitaoka 120a6e
  for (i = 0; i < (int)fdg->dots.size(); i++) {
Shinya Kitaoka 120a6e
    half_size = (double)fdg->dots[i].lx * 0.5;
Shinya Kitaoka 120a6e
    if (max_half_size < half_size) max_half_size = half_size;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  strip_size_mm =
Shinya Kitaoka 120a6e
      fdg->dist_ctr_hole_to_edge + max_half_size + SECURITY_MARGIN_MM;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  strip_size_pix = (int)mmToPixel(strip_size_mm, dpi);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (Debug_flag)
Shinya Kitaoka 120a6e
    printf("Controllo una striscia larga %g mm e %d pixels\n", strip_size_mm,
Shinya Kitaoka 120a6e
           strip_size_pix);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return strip_size_pix;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#define SQMM_TO_SQPIXEL(area, x_res, y_res)                                    \
Shinya Kitaoka 120a6e
  ((double)((x_res) * (y_res)) * (double)(area) * ((1.0 / 25.4) * (1.0 / 25.4)))
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Shinya Kitaoka 120a6e
void convert_dots_mm_to_pixel(DOT *dots, int nd, double x_res, double y_res) {
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (i = 0; i < nd; i++) {
Shinya Kitaoka 120a6e
    dots[i].x1   = troundp(mmToPixel(dots[i].x1, x_res));
Shinya Kitaoka 120a6e
    dots[i].y1   = troundp(mmToPixel(dots[i].y1, y_res));
Shinya Kitaoka 120a6e
    dots[i].x2   = troundp(mmToPixel(dots[i].x2, x_res));
Shinya Kitaoka 120a6e
    dots[i].y2   = troundp(mmToPixel(dots[i].y2, y_res));
Shinya Kitaoka 120a6e
    dots[i].x    = (float)mmToPixel(dots[i].x, x_res);
Shinya Kitaoka 120a6e
    dots[i].y    = (float)mmToPixel(dots[i].y, y_res);
Shinya Kitaoka 120a6e
    dots[i].lx   = troundp(mmToPixel(dots[i].lx, x_res));
Shinya Kitaoka 120a6e
    dots[i].ly   = troundp(mmToPixel(dots[i].ly, y_res));
Shinya Kitaoka 120a6e
    dots[i].area = troundp(SQMM_TO_SQPIXEL(dots[i].area, x_res, y_res));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static char *Done       = 0;
Toshihiro Shimizu 890ddd
static int Done_rowsize = 0;
Toshihiro Shimizu 890ddd
static int Done_colsize = 0;
Toshihiro Shimizu 890ddd
#define DONE_MASK(I, J) (1 << (((I) + (J)*Done_rowsize) & 7))
Toshihiro Shimizu 890ddd
#define DONE_BYTE(I, J) (((I) + (J)*Done_rowsize) >> 3)
Toshihiro Shimizu 890ddd
#define SET_DONE(I, J) (Done[DONE_BYTE(I, J)] |= DONE_MASK(I, J))
Toshihiro Shimizu 890ddd
#define NOT_DONE(I, J) (!(Done[DONE_BYTE(I, J)] & DONE_MASK(I, J)))
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static int Pix_ystep = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
typedef struct big { unsigned lo, hi; } BIG;
Toshihiro Shimizu 890ddd
#define CLEARBIG(B) ((B).lo = 0, (B).hi = 0, (B))
Shinya Kitaoka 120a6e
#define ADDBIG(B, X)                                                           \
Shinya Kitaoka 120a6e
  ((B).lo += (unsigned)(X), (B).hi += (B).lo >> 30, (B).lo &= 0x3fffffff, (B))
Toshihiro Shimizu 890ddd
#define BIG_TO_DOUBLE(B) ((double)(B).hi * (double)0x40000000 + (double)(B).lo)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define IS_BLACK_GR8(PIX) (*(PIX) < 110)
Toshihiro Shimizu 890ddd
#define IS_VERY_BLACK_GR8(PIX) (*(PIX) < 30)
Toshihiro Shimizu 890ddd
#define BLACK_WEIGHT_GR8(PIX) (256 - *(PIX))
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define RGBR(PIX) ((PIX)->r << 1)
Toshihiro Shimizu 890ddd
#define RGBG(PIX) ((PIX)->g << 2)
Toshihiro Shimizu 890ddd
#define RGBB(PIX) ((PIX)->b)
Toshihiro Shimizu 890ddd
#define RGBVAL(PIX) (RGBR(PIX) + RGBG(PIX) + RGBB(PIX))
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define IS_BLACK_RGB(PIX) (RGBVAL(PIX) < 110 * 7)
Toshihiro Shimizu 890ddd
#define IS_VERY_BLACK_RGB(PIX) (RGBVAL(PIX) < 30 * 7)
Toshihiro Shimizu 890ddd
#define BLACK_WEIGHT_RGB(PIX) ((256 * 7 - RGBVAL(PIX)) >> 3)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static BIG Xsum, Ysum, Weightsum;
Toshihiro Shimizu 890ddd
static int Xmin, Xmax, Ymin, Ymax, Npix;
Toshihiro Shimizu 890ddd
#ifdef RECURSIVE_VERSION
Toshihiro Shimizu 890ddd
static int Level, Max_level;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
static int Very_black_found;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef DAFARE
Toshihiro Shimizu 890ddd
#ifdef RECURSIVE_VERSION
Toshihiro Shimizu 890ddd
static int Black_pixel = 0;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef DAFARE
Shinya Kitaoka 120a6e
static int find_dots_bw(const TRasterP &img, int strip_width,
Shinya Kitaoka 120a6e
                        PEGS_SIDE pegs_side, DOT dotarray[], int dotarray_size,
Shinya Kitaoka 120a6e
                        int max_area);
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
static int find_dots_gr8(const TRasterGR8P &img, int strip_width,
Shinya Kitaoka 120a6e
                         PEGS_SIDE pegs_side, DOT dotarray[], int dotarray_size,
Shinya Kitaoka 120a6e
                         int max_area);
Shinya Kitaoka 120a6e
static int find_dots_rgb(const TRaster32P &img, int strip_width,
Shinya Kitaoka 120a6e
                         PEGS_SIDE pegs_side, DOT dotarray[], int dotarray_size,
Shinya Kitaoka 120a6e
                         int max_area);
Toshihiro Shimizu 890ddd
static void
Toshihiro Shimizu 890ddd
#ifdef DAFARE
Toshihiro Shimizu 890ddd
visit_bw(int i, int j, int x, int y, int bit, UCHAR *byte),
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
    visit_gr8(int i, int j, int x, int y, UCHAR *pix),
Shinya Kitaoka 120a6e
    visit_rgb(int i, int j, int x, int y, TPixel32 *pix),
Shinya Kitaoka 120a6e
    stampa_dot(DOT const *dot);
Toshihiro Shimizu 890ddd
JosefMeixner e932c2
//! \brief Find the best matching pegs
JosefMeixner e932c2
//!
Shinya Kitaoka 120a6e
//! The found pegs are in array dots. The function checks, which of those best
Shinya Kitaoka 120a6e
//! fits the reference in
JosefMeixner e932c2
//! reference. The three best matching dots are returned in parameters i, j, k.
Shinya Kitaoka 120a6e
static int compare_dots(DOT const dots[], int ndots, DOT reference[],
Shinya Kitaoka 120a6e
                        int ref_dot, int &i, int &j, int &k);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
#define REVERSE(byte, bit)                                                     \
Shinya Kitaoka 120a6e
  {                                                                            \
Shinya Kitaoka 120a6e
    unsigned char mask;                                                        \
Shinya Kitaoka 120a6e
    mask = 1 << (bit);                                                         \
Shinya Kitaoka 120a6e
    *(byte) ^= mask;                                                           \
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
typedef struct {
Shinya Kitaoka 120a6e
  short ret, bit;
Shinya Kitaoka 120a6e
  int x, y, i, j;
Shinya Kitaoka 120a6e
  void *ptr;
Toshihiro Shimizu 890ddd
} STACK_INFO;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static STACK_INFO *Stack    = 0;
Toshihiro Shimizu 890ddd
static int Stack_alloc_size = 0;
Shinya Kitaoka 120a6e
static int Stack_size       = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
#define CREATE_STACK                                                           \
Shinya Kitaoka 120a6e
  {                                                                            \
Shinya Kitaoka 120a6e
    assert(!Stack);                                                            \
Shinya Kitaoka 120a6e
    Stack_alloc_size = 65500;                                                  \
Shinya Kitaoka 120a6e
    Stack_size       = 0;                                                      \
Shinya Kitaoka 120a6e
    Stack = (STACK_INFO *)malloc(Stack_alloc_size * sizeof(STACK_INFO));       \
Shinya Kitaoka 120a6e
    if (!Stack) return FALSE;                                                  \
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
#define DESTROY_STACK                                                          \
Shinya Kitaoka 120a6e
  {                                                                            \
Shinya Kitaoka 120a6e
    Stack_alloc_size = 0;                                                      \
Shinya Kitaoka 120a6e
    Stack_size       = 0;                                                      \
Shinya Kitaoka 120a6e
    free(Stack);                                                               \
Shinya Kitaoka 120a6e
    Stack = 0;                                                                 \
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define STACK_IS_EMPTY (!Stack_size)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#define PUSH_ONTO_STACK(RET, X, Y, I, J, BIT, PTR)                             \
Shinya Kitaoka 120a6e
  {                                                                            \
Shinya Kitaoka 120a6e
    if (Stack_size >= Stack_alloc_size) {                                      \
Shinya Kitaoka 120a6e
      Stack_alloc_size += 65500;                                               \
Shinya Kitaoka 120a6e
      Stack =                                                                  \
Shinya Kitaoka 120a6e
          (STACK_INFO *)realloc(Stack, Stack_alloc_size * sizeof(STACK_INFO)); \
Shinya Kitaoka 120a6e
      if (!Stack) return;                                                      \
Shinya Kitaoka 120a6e
    }                                                                          \
Shinya Kitaoka 120a6e
    Stack[Stack_size].ret = (RET);                                             \
Shinya Kitaoka 120a6e
    Stack[Stack_size].x   = (X);                                               \
Shinya Kitaoka 120a6e
    Stack[Stack_size].y   = (Y);                                               \
Shinya Kitaoka 120a6e
    Stack[Stack_size].i   = (I);                                               \
Shinya Kitaoka 120a6e
    Stack[Stack_size].j   = (J);                                               \
Shinya Kitaoka 120a6e
    Stack[Stack_size].bit = (BIT);                                             \
Shinya Kitaoka 120a6e
    Stack[Stack_size].ptr = (PTR);                                             \
Shinya Kitaoka 120a6e
    Stack_size++;                                                              \
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
#define POP_FROM_STACK_U(RET, X, Y, I, J, BIT, PTR)                            \
Shinya Kitaoka 120a6e
  {                                                                            \
Shinya Kitaoka 120a6e
    Stack_size--;                                                              \
Shinya Kitaoka 120a6e
    (RET) = Stack[Stack_size].ret;                                             \
Shinya Kitaoka 120a6e
    (X)   = Stack[Stack_size].x;                                               \
Shinya Kitaoka 120a6e
    (Y)   = Stack[Stack_size].y;                                               \
Shinya Kitaoka 120a6e
    (I)   = Stack[Stack_size].i;                                               \
Shinya Kitaoka 120a6e
    (J)   = Stack[Stack_size].j;                                               \
Shinya Kitaoka 120a6e
    (BIT) = Stack[Stack_size].bit;                                             \
Shinya Kitaoka 120a6e
    (PTR) = (UCHAR *)Stack[Stack_size].ptr;                                    \
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
#define POP_FROM_STACK_TPIXEL32(RET, X, Y, I, J, BIT, PTR)                     \
Shinya Kitaoka 120a6e
  {                                                                            \
Shinya Kitaoka 120a6e
    Stack_size--;                                                              \
Shinya Kitaoka 120a6e
    (RET) = Stack[Stack_size].ret;                                             \
Shinya Kitaoka 120a6e
    (X)   = Stack[Stack_size].x;                                               \
Shinya Kitaoka 120a6e
    (Y)   = Stack[Stack_size].y;                                               \
Shinya Kitaoka 120a6e
    (I)   = Stack[Stack_size].i;                                               \
Shinya Kitaoka 120a6e
    (J)   = Stack[Stack_size].j;                                               \
Shinya Kitaoka 120a6e
    (BIT) = Stack[Stack_size].bit;                                             \
Shinya Kitaoka 120a6e
    (PTR) = (TPixel32 *)Stack[Stack_size].ptr;                                 \
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static int find_dots(const TRasterP &img, int strip_width, PEGS_SIDE pegs_side,
Shinya Kitaoka 120a6e
                     DOT dotarray[], int dotarray_size, int max_area) {
Shinya Kitaoka 120a6e
  TRaster32P ras32(img);
Shinya Kitaoka 120a6e
  if (ras32)
Shinya Kitaoka 120a6e
    return find_dots_rgb(ras32, strip_width, pegs_side, dotarray, dotarray_size,
Shinya Kitaoka 120a6e
                         max_area);
Shinya Kitaoka 120a6e
  TRasterGR8P ras8(img);
Shinya Kitaoka 120a6e
  if (ras8)
Shinya Kitaoka 120a6e
    return find_dots_gr8(ras8, strip_width, pegs_side, dotarray, dotarray_size,
Shinya Kitaoka 120a6e
                         max_area);
Shinya Kitaoka 120a6e
  assert(!"Unsupported pixel type");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
#ifdef DAFARE
Shinya Kitaoka 120a6e
static int find_dots_bw(const TRasterP &img, int strip_width,
Shinya Kitaoka 120a6e
                        PEGS_SIDE pegs_side, DOT dotarray[], int dotarray_size,
Shinya Kitaoka 120a6e
                        int max_area) {
Shinya Kitaoka 120a6e
  int n_dots, ins, shift;
Shinya Kitaoka 120a6e
  int x, y;  // coords in img coord system
Shinya Kitaoka 120a6e
  int i, j;  // coords in done coord system
Shinya Kitaoka 120a6e
  int x0, y0, xsize, ysize, xlast, ylast, bit;
Shinya Kitaoka 120a6e
  UCHAR *byte, *buffer;
Shinya Kitaoka 120a6e
  int dot_lx, dot_ly;
Shinya Kitaoka 120a6e
  float dot_x, dot_y;
Shinya Kitaoka 120a6e
  int vertical;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (img->type == RAS_WB)
Shinya Kitaoka 120a6e
    Black_pixel = 1;
Shinya Kitaoka 120a6e
  else if (img->type == RAS_BW)
Shinya Kitaoka 120a6e
    Black_pixel = 0;
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    TERROR("find dots error: bad image type");
Shinya Kitaoka 120a6e
    return 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  switch (pegs_side) {
Shinya Kitaoka 120a6e
  case PEGS_BOTTOM:
Shinya Kitaoka 120a6e
  case PEGS_TOP:
Shinya Kitaoka 120a6e
    x0       = 0;
Shinya Kitaoka 120a6e
    y0       = pegs_side == PEGS_BOTTOM ? 0 : img->ly - strip_width;
Shinya Kitaoka 120a6e
    xsize    = img->lx;
Shinya Kitaoka 120a6e
    ysize    = strip_width;
Shinya Kitaoka 120a6e
    vertical = FALSE;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  case PEGS_LEFT:
Shinya Kitaoka 120a6e
  case PEGS_RIGHT:
Shinya Kitaoka 120a6e
    x0       = pegs_side == PEGS_LEFT ? 0 : img->lx - strip_width;
Shinya Kitaoka 120a6e
    y0       = 0;
Shinya Kitaoka 120a6e
    xsize    = strip_width;
Shinya Kitaoka 120a6e
    ysize    = img->ly;
Shinya Kitaoka 120a6e
    vertical = TRUE;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  default: {
Shinya Kitaoka 120a6e
    std::ostringstream os;
Shinya Kitaoka 120a6e
    os << "find dots internal error: pegs_side = " << std::hex << pegs_side
Shinya Kitaoka 120a6e
       << '\0';
Shinya Kitaoka 120a6e
    throw TCleanupException(os.str().c_str());
Shinya Kitaoka 120a6e
    x0 = y0 = xsize = ysize = vertical = 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  xlast        = x0 + xsize - 1;
Shinya Kitaoka 120a6e
  ylast        = y0 + ysize - 1;
Shinya Kitaoka 120a6e
  n_dots       = 0;
Shinya Kitaoka 120a6e
  Done_rowsize = xsize + 2;
Shinya Kitaoka 120a6e
  Done_colsize = ysize + 2;
Shinya Kitaoka 120a6e
  Done = (char *)calloc((size_t)((Done_rowsize * Done_colsize + 7) >> 3),
Shinya Kitaoka 120a6e
                        sizeof(char));
Shinya Kitaoka 120a6e
  if (!Done) {
Shinya Kitaoka 120a6e
    throw TCleanupException("find_dots: out of memory");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (i = 0; i < Done_rowsize; i++) {
Shinya Kitaoka 120a6e
    SET_DONE(i, 0);
Shinya Kitaoka 120a6e
    SET_DONE(i, Done_colsize - 1);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (j = 0; j < Done_colsize; j++) {
Shinya Kitaoka 120a6e
    SET_DONE(0, j);
Shinya Kitaoka 120a6e
    SET_DONE(Done_rowsize - 1, j);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  buffer    = (UCHAR *)img->buffer;
Shinya Kitaoka 120a6e
  Pix_ystep = (img->wrap + 7) >> 3;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (Debug_flag) {
Shinya Kitaoka 120a6e
    printf("Zona di scansione: (%d,%d) -- (%d,%d)\n", x0, y0, xlast, ylast);
Shinya Kitaoka 120a6e
    printf("wrap: %d\n", img->wrap);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef RECURSIVE_VERSION
Shinya Kitaoka 120a6e
  Max_level = max_area * 6 / 5;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  CREATE_STACK
Shinya Kitaoka 120a6e
  for (j = 1, y = y0; y <= ylast; j++, y++) {
Shinya Kitaoka 120a6e
    bit  = 7 - (x0 & 7);
Shinya Kitaoka 120a6e
    byte = buffer + (x0 >> 3) + y * Pix_ystep;
Shinya Kitaoka 120a6e
    for (i = 1, x = x0; x <= xlast; i++, x++) {
Shinya Kitaoka 120a6e
      if (NOT_DONE(i, j) && ((*byte >> bit) & 1) == Black_pixel) {
Shinya Kitaoka 120a6e
        CLEARBIG(Xsum);
Shinya Kitaoka 120a6e
        CLEARBIG(Ysum);
Shinya Kitaoka 120a6e
        CLEARBIG(Weightsum);
Shinya Kitaoka 120a6e
        Xmin = Xmax = x;
Shinya Kitaoka 120a6e
        Ymin = Ymax = y;
Shinya Kitaoka 120a6e
        Npix        = 0;
Toshihiro Shimizu 890ddd
#ifdef RECURSIVE_VERSION
Shinya Kitaoka 120a6e
        Level = 0;
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
        visit_bw(i, j, x, y, bit, byte);
Shinya Kitaoka 120a6e
        dot_lx = Xmax - Xmin + 1;
Shinya Kitaoka 120a6e
        dot_ly = Ymax - Ymin + 1;
Shinya Kitaoka 120a6e
        if (Npix < max_area * 3 / 2 && dot_lx > 3 && dot_lx < (xsize >> 1) &&
Shinya Kitaoka 120a6e
            dot_ly > 3 && dot_ly < (ysize >> 1) && Xmin > x0 && Xmax < xlast &&
Shinya Kitaoka 120a6e
            Ymin > y0 && Ymax < ylast) {
Shinya Kitaoka 120a6e
          dot_x = BIG_TO_DOUBLE(Xsum) / BIG_TO_DOUBLE(Weightsum);
Shinya Kitaoka 120a6e
          dot_y = BIG_TO_DOUBLE(Ysum) / BIG_TO_DOUBLE(Weightsum);
Shinya Kitaoka 120a6e
          if (vertical) {
Shinya Kitaoka 120a6e
            for (ins = 0; ins < n_dots; ins++)
Shinya Kitaoka 120a6e
              if (dotarray[ins].y > dot_y) break;
Shinya Kitaoka 120a6e
          } else {
Shinya Kitaoka 120a6e
            for (ins = 0; ins < n_dots; ins++)
Shinya Kitaoka 120a6e
              if (dotarray[ins].x > dot_x) break;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
          for (shift            = n_dots - 1; shift >= ins; shift--)
Shinya Kitaoka 120a6e
            dotarray[shift + 1] = dotarray[shift];
Shinya Kitaoka 120a6e
          n_dots++;
Shinya Kitaoka 120a6e
          dotarray[ins].x1   = Xmin;
Shinya Kitaoka 120a6e
          dotarray[ins].x2   = Xmax;
Shinya Kitaoka 120a6e
          dotarray[ins].y1   = Ymin;
Shinya Kitaoka 120a6e
          dotarray[ins].y2   = Ymax;
Shinya Kitaoka 120a6e
          dotarray[ins].lx   = dot_lx;
Shinya Kitaoka 120a6e
          dotarray[ins].ly   = dot_ly;
Shinya Kitaoka 120a6e
          dotarray[ins].area = Npix;
Shinya Kitaoka 120a6e
          dotarray[ins].x    = dot_x;
Shinya Kitaoka 120a6e
          dotarray[ins].y    = dot_y;
Shinya Kitaoka 120a6e
          if (n_dots >= dotarray_size) goto end_loop;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (bit == 0) {
Shinya Kitaoka 120a6e
        bit = 7;
Shinya Kitaoka 120a6e
        byte++;
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        bit--;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
end_loop:
Shinya Kitaoka 120a6e
  DESTROY_STACK
Shinya Kitaoka 120a6e
  free(Done);
Shinya Kitaoka 120a6e
  Done = NIL;
Shinya Kitaoka 120a6e
  return n_dots;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static int find_dots_gr8(const TRasterGR8P &img, int strip_width,
Shinya Kitaoka 120a6e
                         PEGS_SIDE pegs_side, DOT dotarray[], int dotarray_size,
Shinya Kitaoka 120a6e
                         int max_area) {
Shinya Kitaoka 120a6e
  int n_dots, ins, shift;
Shinya Kitaoka 120a6e
  int x, y; /* coords in img coord system */
Shinya Kitaoka 120a6e
  int i, j; /* coords in done coord system */
Shinya Kitaoka 120a6e
  int x0, y0, xsize, ysize, xlast, ylast;
Shinya Kitaoka 120a6e
  UCHAR *pix, *buffer;
Shinya Kitaoka 120a6e
  int dot_lx, dot_ly;
Shinya Kitaoka 120a6e
  float dot_x, dot_y;
Shinya Kitaoka 120a6e
  int vertical;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  switch (pegs_side) {
Shinya Kitaoka 120a6e
  case PEGS_BOTTOM:
Shinya Kitaoka 120a6e
  case PEGS_TOP:
Shinya Kitaoka 120a6e
    x0       = 0;
Shinya Kitaoka 120a6e
    y0       = pegs_side == PEGS_BOTTOM ? 0 : img->getLy() - strip_width;
Shinya Kitaoka 120a6e
    xsize    = img->getLx();
Shinya Kitaoka 120a6e
    ysize    = strip_width;
Shinya Kitaoka 120a6e
    vertical = FALSE;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case PEGS_LEFT:
Shinya Kitaoka 120a6e
  case PEGS_RIGHT:
Shinya Kitaoka 120a6e
    x0       = pegs_side == PEGS_LEFT ? 0 : img->getLx() - strip_width;
Shinya Kitaoka 120a6e
    y0       = 0;
Shinya Kitaoka 120a6e
    xsize    = strip_width;
Shinya Kitaoka 120a6e
    ysize    = img->getLy();
Shinya Kitaoka 120a6e
    vertical = TRUE;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  default: {
Shinya Kitaoka 120a6e
    std::ostringstream os;
Shinya Kitaoka 120a6e
    os << "find dots internal error: pegs_side = " << std::hex << pegs_side
Shinya Kitaoka 120a6e
       << '\0';
Shinya Kitaoka 120a6e
    throw TCleanupException(os.str().c_str());
Shinya Kitaoka 120a6e
    x0 = y0 = xsize = ysize = vertical = 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  xlast        = x0 + xsize - 1;
Shinya Kitaoka 120a6e
  ylast        = y0 + ysize - 1;
Shinya Kitaoka 120a6e
  n_dots       = 0;
Shinya Kitaoka 120a6e
  Done_rowsize = xsize + 2;
Shinya Kitaoka 120a6e
  Done_colsize = ysize + 2;
Shinya Kitaoka 120a6e
  Done = (char *)calloc((size_t)((Done_rowsize * Done_colsize + 7) >> 3),
Shinya Kitaoka 120a6e
                        sizeof(char));
Shinya Kitaoka 120a6e
  if (!Done) {
Shinya Kitaoka 120a6e
    throw TCleanupException("find_dots: out of memory");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (i = 0; i < Done_rowsize; i++) {
Shinya Kitaoka 120a6e
    SET_DONE(i, 0);
Shinya Kitaoka 120a6e
    SET_DONE(i, Done_colsize - 1);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (j = 0; j < Done_colsize; j++) {
Shinya Kitaoka 120a6e
    SET_DONE(0, j);
Shinya Kitaoka 120a6e
    SET_DONE(Done_rowsize - 1, j);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Pix_ystep = img->getWrap();
Shinya Kitaoka 120a6e
  if (Debug_flag) {
Shinya Kitaoka 120a6e
    printf("Zona di scansione: (%d,%d) -- (%d,%d)\n", x0, y0, xlast, ylast);
Shinya Kitaoka 120a6e
    printf("wrap: %d\n", img->getWrap());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
#ifdef RECURSIVE_VERSION
Shinya Kitaoka 120a6e
  Max_level = max_area * 6 / 5;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  img->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  buffer = (UCHAR *)img->getRawData();
Shinya Kitaoka 120a6e
  CREATE_STACK
Shinya Kitaoka 120a6e
  for (j = 1, y = y0; y <= ylast; j++, y++)
Shinya Kitaoka 120a6e
    for (i = 1, x = x0, pix = buffer + x0 + y * Pix_ystep; x <= xlast;
Shinya Kitaoka 120a6e
         i++, x++, pix++)
Shinya Kitaoka 120a6e
      if (NOT_DONE(i, j) && IS_BLACK_GR8(pix)) {
Shinya Kitaoka 120a6e
        CLEARBIG(Xsum);
Shinya Kitaoka 120a6e
        CLEARBIG(Ysum);
Shinya Kitaoka 120a6e
        CLEARBIG(Weightsum);
Shinya Kitaoka 120a6e
        Xmin = Xmax = x;
Shinya Kitaoka 120a6e
        Ymin = Ymax = y;
Shinya Kitaoka 120a6e
        Npix        = 0;
Toshihiro Shimizu 890ddd
#ifdef RECURSIVE_VERSION
Shinya Kitaoka 120a6e
        Level = 0;
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
        visit_gr8(i, j, x, y, pix);
Shinya Kitaoka 120a6e
        dot_lx = Xmax - Xmin + 1;
Shinya Kitaoka 120a6e
        dot_ly = Ymax - Ymin + 1;
Shinya Kitaoka 120a6e
        if (Npix < max_area * 3 / 2 && dot_lx > 3 && dot_lx < (xsize >> 1) &&
Shinya Kitaoka 120a6e
            dot_ly > 3 && dot_ly < (ysize >> 1) && Xmin > x0 && Xmax < xlast &&
Shinya Kitaoka 120a6e
            Ymin > y0 && Ymax < ylast) {
Shinya Kitaoka 120a6e
          dot_x = (float)(BIG_TO_DOUBLE(Xsum) / BIG_TO_DOUBLE(Weightsum));
Shinya Kitaoka 120a6e
          dot_y = (float)(BIG_TO_DOUBLE(Ysum) / BIG_TO_DOUBLE(Weightsum));
Shinya Kitaoka 120a6e
          if (vertical) {
Shinya Kitaoka 120a6e
            for (ins = 0; ins < n_dots; ins++)
Shinya Kitaoka 120a6e
              if (dotarray[ins].y > dot_y) break;
Shinya Kitaoka 120a6e
          } else {
Shinya Kitaoka 120a6e
            for (ins = 0; ins < n_dots; ins++)
Shinya Kitaoka 120a6e
              if (dotarray[ins].x > dot_x) break;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
          for (shift            = n_dots - 1; shift >= ins; shift--)
Shinya Kitaoka 120a6e
            dotarray[shift + 1] = dotarray[shift];
Shinya Kitaoka 120a6e
          n_dots++;
Shinya Kitaoka 120a6e
          dotarray[ins].x1   = Xmin;
Shinya Kitaoka 120a6e
          dotarray[ins].x2   = Xmax;
Shinya Kitaoka 120a6e
          dotarray[ins].y1   = Ymin;
Shinya Kitaoka 120a6e
          dotarray[ins].y2   = Ymax;
Shinya Kitaoka 120a6e
          dotarray[ins].lx   = dot_lx;
Shinya Kitaoka 120a6e
          dotarray[ins].ly   = dot_ly;
Shinya Kitaoka 120a6e
          dotarray[ins].area = Npix;
Shinya Kitaoka 120a6e
          dotarray[ins].x    = dot_x;
Shinya Kitaoka 120a6e
          dotarray[ins].y    = dot_y;
Shinya Kitaoka 120a6e
          if (n_dots >= dotarray_size) goto end_loop;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Toshihiro Shimizu 890ddd
end_loop:
Shinya Kitaoka 120a6e
  DESTROY_STACK
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  free(Done);
Shinya Kitaoka 120a6e
  Done = 0;
Shinya Kitaoka 120a6e
  img->unlock();
Shinya Kitaoka 120a6e
  return n_dots;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static int find_dots_rgb(const TRaster32P &img, int strip_width,
Shinya Kitaoka 120a6e
                         PEGS_SIDE pegs_side, DOT dotarray[], int dotarray_size,
Shinya Kitaoka 120a6e
                         int max_area) {
Shinya Kitaoka 120a6e
  int n_dots, ins, shift;
Shinya Kitaoka 120a6e
  int x, y; /* coords in img coord system */
Shinya Kitaoka 120a6e
  int i, j; /* coords in done coord system */
Shinya Kitaoka 120a6e
  int x0, y0, xsize, ysize, xlast, ylast;
Shinya Kitaoka 120a6e
  TPixel32 *pix, *buffer;
Shinya Kitaoka 120a6e
  int dot_lx, dot_ly;
Shinya Kitaoka 120a6e
  float dot_x, dot_y;
Shinya Kitaoka 120a6e
  int vertical;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(img->getPixelSize() ==
Shinya Kitaoka 120a6e
         4); /*questo e' per ricordare che l'algo e' per RGB*/
Shinya Kitaoka 120a6e
  switch (pegs_side) {
Shinya Kitaoka 120a6e
  case PEGS_BOTTOM:
Shinya Kitaoka 120a6e
  case PEGS_TOP:
Shinya Kitaoka 120a6e
    x0       = 0;
Shinya Kitaoka 120a6e
    y0       = pegs_side == PEGS_BOTTOM ? 0 : img->getLy() - strip_width;
Shinya Kitaoka 120a6e
    xsize    = img->getLx();
Shinya Kitaoka 120a6e
    ysize    = strip_width;
Shinya Kitaoka 120a6e
    vertical = FALSE;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case PEGS_LEFT:
Shinya Kitaoka 120a6e
  case PEGS_RIGHT:
Shinya Kitaoka 120a6e
    x0       = pegs_side == PEGS_LEFT ? 0 : img->getLx() - strip_width;
Shinya Kitaoka 120a6e
    y0       = 0;
Shinya Kitaoka 120a6e
    xsize    = strip_width;
Shinya Kitaoka 120a6e
    ysize    = img->getLy();
Shinya Kitaoka 120a6e
    vertical = TRUE;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  default: {
Shinya Kitaoka 120a6e
    std::ostringstream os;
Shinya Kitaoka 120a6e
    os << "find dots internal error: pegs_side = " << std::hex << pegs_side
Shinya Kitaoka 120a6e
       << '\0';
Shinya Kitaoka 120a6e
    throw TCleanupException(os.str().c_str());
Shinya Kitaoka 120a6e
    x0 = y0 = xsize = ysize = vertical = 0;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  xlast        = x0 + xsize - 1;
Shinya Kitaoka 120a6e
  ylast        = y0 + ysize - 1;
Shinya Kitaoka 120a6e
  n_dots       = 0;
Shinya Kitaoka 120a6e
  Done_rowsize = xsize + 2;
Shinya Kitaoka 120a6e
  Done_colsize = ysize + 2;
Shinya Kitaoka 120a6e
  Done = (char *)calloc((size_t)((Done_rowsize * Done_colsize + 7) >> 3),
Shinya Kitaoka 120a6e
                        sizeof(char));
Shinya Kitaoka 120a6e
  if (!Done) {
Shinya Kitaoka 120a6e
    throw TCleanupException("find_dots: out of memory");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (i = 0; i < Done_rowsize; i++) {
Shinya Kitaoka 120a6e
    SET_DONE(i, 0);
Shinya Kitaoka 120a6e
    SET_DONE(i, Done_colsize - 1);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (j = 0; j < Done_colsize; j++) {
Shinya Kitaoka 120a6e
    SET_DONE(0, j);
Shinya Kitaoka 120a6e
    SET_DONE(Done_rowsize - 1, j);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  buffer    = img->pixels();
Shinya Kitaoka 120a6e
  Pix_ystep = img->getWrap();
Shinya Kitaoka 120a6e
  if (Debug_flag) {
Shinya Kitaoka 120a6e
    printf("Zona di scansione: (%d,%d) -- (%d,%d)\n", x0, y0, xlast, ylast);
Shinya Kitaoka 120a6e
    printf("wrap: %d\n", img->getWrap());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
#ifdef RECURSIVE_VERSION
Shinya Kitaoka 120a6e
  Max_level = max_area * 6 / 5;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  CREATE_STACK
Shinya Kitaoka 120a6e
  for (j = 1, y = y0; y <= ylast; j++, y++)
Shinya Kitaoka 120a6e
    for (i = 1, x = x0, pix = buffer + x0 + y * Pix_ystep; x <= xlast;
Shinya Kitaoka 120a6e
         i++, x++, pix++)
Shinya Kitaoka 120a6e
      if (NOT_DONE(i, j) && IS_BLACK_RGB(pix)) {
Shinya Kitaoka 120a6e
        CLEARBIG(Xsum);
Shinya Kitaoka 120a6e
        CLEARBIG(Ysum);
Shinya Kitaoka 120a6e
        CLEARBIG(Weightsum);
Shinya Kitaoka 120a6e
        Xmin = Xmax = x;
Shinya Kitaoka 120a6e
        Ymin = Ymax = y;
Shinya Kitaoka 120a6e
        Npix        = 0;
Toshihiro Shimizu 890ddd
#ifdef RECURSIVE_VERSION
Shinya Kitaoka 120a6e
        Level = 0;
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
        visit_rgb(i, j, x, y, pix);
Shinya Kitaoka 120a6e
        dot_lx = Xmax - Xmin + 1;
Shinya Kitaoka 120a6e
        dot_ly = Ymax - Ymin + 1;
Shinya Kitaoka 120a6e
        if (Npix < max_area * 3 / 2 && dot_lx > 3 && dot_lx < (xsize >> 1) &&
Shinya Kitaoka 120a6e
            dot_ly > 3 && dot_ly < (ysize >> 1) && Xmin > x0 && Xmax <= xlast &&
Shinya Kitaoka 120a6e
            Ymin > y0 && Ymax <= ylast) {
Shinya Kitaoka 120a6e
          dot_x = (float)(BIG_TO_DOUBLE(Xsum) / BIG_TO_DOUBLE(Weightsum));
Shinya Kitaoka 120a6e
          dot_y = (float)(BIG_TO_DOUBLE(Ysum) / BIG_TO_DOUBLE(Weightsum));
Shinya Kitaoka 120a6e
          if (vertical) {
Shinya Kitaoka 120a6e
            for (ins = 0; ins < n_dots; ins++)
Shinya Kitaoka 120a6e
              if (dotarray[ins].y > dot_y) break;
Shinya Kitaoka 120a6e
          } else {
Shinya Kitaoka 120a6e
            for (ins = 0; ins < n_dots; ins++)
Shinya Kitaoka 120a6e
              if (dotarray[ins].x > dot_x) break;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
          for (shift            = n_dots - 1; shift >= ins; shift--)
Shinya Kitaoka 120a6e
            dotarray[shift + 1] = dotarray[shift];
Shinya Kitaoka 120a6e
          n_dots++;
Shinya Kitaoka 120a6e
          dotarray[ins].x1   = Xmin;
Shinya Kitaoka 120a6e
          dotarray[ins].x2   = Xmax;
Shinya Kitaoka 120a6e
          dotarray[ins].y1   = Ymin;
Shinya Kitaoka 120a6e
          dotarray[ins].y2   = Ymax;
Shinya Kitaoka 120a6e
          dotarray[ins].lx   = dot_lx;
Shinya Kitaoka 120a6e
          dotarray[ins].ly   = dot_ly;
Shinya Kitaoka 120a6e
          dotarray[ins].area = Npix;
Shinya Kitaoka 120a6e
          dotarray[ins].x    = dot_x;
Shinya Kitaoka 120a6e
          dotarray[ins].y    = dot_y;
Shinya Kitaoka 120a6e
          if (n_dots >= dotarray_size) goto end_loop;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Toshihiro Shimizu 890ddd
end_loop:
Shinya Kitaoka 120a6e
  DESTROY_STACK
Shinya Kitaoka 120a6e
  free(Done);
Shinya Kitaoka 120a6e
  Done = 0;
Shinya Kitaoka 120a6e
  return n_dots;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
#ifdef DAFARE
Shinya Kitaoka 120a6e
static void visit_bw(int i, int j, int x, int y, int bit, UCHAR *byte) {
Shinya Kitaoka 120a6e
  int ret, next_bit, prev_bit;
Shinya Kitaoka 120a6e
  UCHAR *next_byte, *prev_byte;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
start:
Shinya Kitaoka 120a6e
  ADDBIG(Xsum, x);
Shinya Kitaoka 120a6e
  ADDBIG(Ysum, y);
Shinya Kitaoka 120a6e
  ADDBIG(Weightsum, 1);
Shinya Kitaoka 120a6e
  if (x < Xmin) Xmin = x;
Shinya Kitaoka 120a6e
  if (x > Xmax) Xmax = x;
Shinya Kitaoka 120a6e
  if (y < Ymin) Ymin = y;
Shinya Kitaoka 120a6e
  if (y > Ymax) Ymax = y;
Shinya Kitaoka 120a6e
  Npix++;
Shinya Kitaoka 120a6e
  SET_DONE(i, j);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  next_bit = bit - 1;
Shinya Kitaoka 120a6e
  if (next_bit < 0) {
Shinya Kitaoka 120a6e
    next_bit  = 7;
Shinya Kitaoka 120a6e
    next_byte = byte + 1;
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    next_byte = byte;
Shinya Kitaoka 120a6e
  if (NOT_DONE(i + 1, j) && ((*next_byte >> next_bit) & 1) == Black_pixel) {
Shinya Kitaoka 120a6e
    PUSH_ONTO_STACK(1, x, y, i, j, bit, byte)
Shinya Kitaoka 120a6e
    i++;
Shinya Kitaoka 120a6e
    x++;
Shinya Kitaoka 120a6e
    bit  = next_bit;
Shinya Kitaoka 120a6e
    byte = next_byte;
Shinya Kitaoka 120a6e
    goto start;
Shinya Kitaoka 120a6e
  return_1:;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  prev_bit = bit + 1;
Shinya Kitaoka 120a6e
  if (prev_bit > 7) {
Shinya Kitaoka 120a6e
    prev_bit  = 0;
Shinya Kitaoka 120a6e
    prev_byte = byte - 1;
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    prev_byte = byte;
Shinya Kitaoka 120a6e
  if (NOT_DONE(i - 1, j) && ((*prev_byte >> prev_bit) & 1) == Black_pixel) {
Shinya Kitaoka 120a6e
    PUSH_ONTO_STACK(2, x, y, i, j, bit, byte)
Shinya Kitaoka 120a6e
    i--;
Shinya Kitaoka 120a6e
    x--;
Shinya Kitaoka 120a6e
    bit  = prev_bit;
Shinya Kitaoka 120a6e
    byte = prev_byte;
Shinya Kitaoka 120a6e
    goto start;
Shinya Kitaoka 120a6e
  return_2:;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (NOT_DONE(i, j + 1) && ((*(byte + Pix_ystep) >> bit) & 1) == Black_pixel) {
Shinya Kitaoka 120a6e
    PUSH_ONTO_STACK(3, x, y, i, j, bit, byte)
Shinya Kitaoka 120a6e
    j++;
Shinya Kitaoka 120a6e
    y++;
Shinya Kitaoka 120a6e
    byte += Pix_ystep;
Shinya Kitaoka 120a6e
    goto start;
Shinya Kitaoka 120a6e
  return_3:;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (NOT_DONE(i, j - 1) && ((*(byte - Pix_ystep) >> bit) & 1) == Black_pixel) {
Shinya Kitaoka 120a6e
    PUSH_ONTO_STACK(4, x, y, i, j, bit, byte)
Shinya Kitaoka 120a6e
    j--;
Shinya Kitaoka 120a6e
    y--;
Shinya Kitaoka 120a6e
    byte -= Pix_ystep;
Shinya Kitaoka 120a6e
    goto start;
Shinya Kitaoka 120a6e
  return_4:;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (!STACK_IS_EMPTY) {
Shinya Kitaoka 120a6e
    POP_FROM_STACK_U(ret, x, y, i, j, bit, byte);
Shinya Kitaoka 120a6e
    switch (ret) {
Shinya Kitaoka 120a6e
    case 1:
Shinya Kitaoka 120a6e
      goto return_1;
Shinya Kitaoka 120a6e
    case 2:
Shinya Kitaoka 120a6e
      goto return_2;
Shinya Kitaoka 120a6e
    case 3:
Shinya Kitaoka 120a6e
      goto return_3;
Shinya Kitaoka 120a6e
    case 4:
Shinya Kitaoka 120a6e
      goto return_4;
Shinya Kitaoka 120a6e
    default:
Shinya Kitaoka 120a6e
      abort();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef RECURSIVE_VERSION
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static void visit_bw(int i, int j, int x, int y, int bit, UCHAR *byte) {
Shinya Kitaoka 120a6e
  int next_bit, prev_bit;
Shinya Kitaoka 120a6e
  UCHAR *next_byte, *prev_byte;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (Level >= Max_level)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    Level++;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ADDBIG(Xsum, x);
Shinya Kitaoka 120a6e
  ADDBIG(Ysum, y);
Shinya Kitaoka 120a6e
  ADDBIG(Weightsum, 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (x < Xmin) Xmin = x;
Shinya Kitaoka 120a6e
  if (x > Xmax) Xmax = x;
Shinya Kitaoka 120a6e
  if (y < Ymin) Ymin = y;
Shinya Kitaoka 120a6e
  if (y > Ymax) Ymax = y;
Shinya Kitaoka 120a6e
  Npix++;
Shinya Kitaoka 120a6e
  SET_DONE(i, j);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  next_bit = bit - 1;
Shinya Kitaoka 120a6e
  if (next_bit < 0) {
Shinya Kitaoka 120a6e
    next_byte = byte + 1;
Shinya Kitaoka 120a6e
    next_bit  = 7;
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    next_byte = byte;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  prev_bit = bit + 1;
Shinya Kitaoka 120a6e
  if (prev_bit > 7) {
Shinya Kitaoka 120a6e
    prev_byte = byte - 1;
Shinya Kitaoka 120a6e
    prev_bit  = 0;
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    prev_byte = byte;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (NOT_DONE(i + 1, j) && ((*next_byte >> next_bit) & 1) == Black_pixel)
Shinya Kitaoka 120a6e
    visit_bw(i + 1, j, x + 1, y, next_bit, next_byte);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (NOT_DONE(i - 1, j) && ((*prev_byte >> prev_bit) & 1) == Black_pixel)
Shinya Kitaoka 120a6e
    visit_bw(i - 1, j, x - 1, y, prev_bit, prev_byte);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (NOT_DONE(i, j + 1) && ((*(byte + Pix_ystep) >> bit) & 1) == Black_pixel)
Shinya Kitaoka 120a6e
    visit_bw(i, j + 1, x, y + 1, bit, byte + Pix_ystep);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (NOT_DONE(i, j - 1) && ((*(byte - Pix_ystep) >> bit) & 1) == Black_pixel)
Shinya Kitaoka 120a6e
    visit_bw(i, j - 1, x, y - 1, bit, byte - Pix_ystep);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Level--;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static void visit_gr8(int i, int j, int x, int y, UCHAR *pix) {
Shinya Kitaoka 120a6e
  int weight, ret, dummy;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
start:
Shinya Kitaoka 120a6e
  weight = BLACK_WEIGHT_GR8(pix);
Shinya Kitaoka 120a6e
  ADDBIG(Xsum, x * weight);
Shinya Kitaoka 120a6e
  ADDBIG(Ysum, y * weight);
Shinya Kitaoka 120a6e
  ADDBIG(Weightsum, weight);
Shinya Kitaoka 120a6e
  if (IS_VERY_BLACK_GR8(pix)) Very_black_found = TRUE;
Shinya Kitaoka 120a6e
  if (x < Xmin) Xmin                           = x;
Shinya Kitaoka 120a6e
  if (x > Xmax) Xmax                           = x;
Shinya Kitaoka 120a6e
  if (y < Ymin) Ymin                           = y;
Shinya Kitaoka 120a6e
  if (y > Ymax) Ymax                           = y;
Shinya Kitaoka 120a6e
  Npix++;
Shinya Kitaoka 120a6e
  SET_DONE(i, j);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (NOT_DONE(i + 1, j) && IS_BLACK_GR8(pix + 1)) {
Shinya Kitaoka 120a6e
    PUSH_ONTO_STACK(1, x, y, i, j, 0, pix)
Shinya Kitaoka 120a6e
    i++;
Shinya Kitaoka 120a6e
    x++;
Shinya Kitaoka 120a6e
    pix++;
Shinya Kitaoka 120a6e
    goto start;
Shinya Kitaoka 120a6e
  return_1:;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (NOT_DONE(i - 1, j) && IS_BLACK_GR8(pix - 1)) {
Shinya Kitaoka 120a6e
    PUSH_ONTO_STACK(2, x, y, i, j, 0, pix)
Shinya Kitaoka 120a6e
    i--;
Shinya Kitaoka 120a6e
    x--;
Shinya Kitaoka 120a6e
    pix--;
Shinya Kitaoka 120a6e
    goto start;
Shinya Kitaoka 120a6e
  return_2:;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (NOT_DONE(i, j + 1) && IS_BLACK_GR8(pix + Pix_ystep)) {
Shinya Kitaoka 120a6e
    PUSH_ONTO_STACK(3, x, y, i, j, 0, pix)
Shinya Kitaoka 120a6e
    j++;
Shinya Kitaoka 120a6e
    y++;
Shinya Kitaoka 120a6e
    pix += Pix_ystep;
Shinya Kitaoka 120a6e
    goto start;
Shinya Kitaoka 120a6e
  return_3:;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (NOT_DONE(i, j - 1) && IS_BLACK_GR8(pix - Pix_ystep)) {
Shinya Kitaoka 120a6e
    PUSH_ONTO_STACK(4, x, y, i, j, 0, pix)
Shinya Kitaoka 120a6e
    j--;
Shinya Kitaoka 120a6e
    y--;
Shinya Kitaoka 120a6e
    pix -= Pix_ystep;
Shinya Kitaoka 120a6e
    goto start;
Shinya Kitaoka 120a6e
  return_4:;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (!STACK_IS_EMPTY) {
Shinya Kitaoka 120a6e
    POP_FROM_STACK_U(ret, x, y, i, j, dummy, pix);
Shinya Kitaoka 120a6e
    switch (ret) {
Shinya Kitaoka 120a6e
    case 1:
Shinya Kitaoka 120a6e
      goto return_1;
Shinya Kitaoka 120a6e
    case 2:
Shinya Kitaoka 120a6e
      goto return_2;
Shinya Kitaoka 120a6e
    case 3:
Shinya Kitaoka 120a6e
      goto return_3;
Shinya Kitaoka 120a6e
    case 4:
Shinya Kitaoka 120a6e
      goto return_4;
Shinya Kitaoka 120a6e
    default:
Shinya Kitaoka 120a6e
      abort();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef RECURSIVE_VERSION
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static void visit_gr8(int i, int j, int x, int y, UCHAR *pix) {
Shinya Kitaoka 120a6e
  int weight;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (Level >= Max_level)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    Level++;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  weight = BLACK_WEIGHT_GR8(pix);
Shinya Kitaoka 120a6e
  ADDBIG(Xsum, x * weight);
Shinya Kitaoka 120a6e
  ADDBIG(Ysum, y * weight);
Shinya Kitaoka 120a6e
  ADDBIG(Weightsum, weight);
Shinya Kitaoka 120a6e
  if (IS_VERY_BLACK_GR8(pix)) Very_black_found = TRUE;
Shinya Kitaoka 120a6e
  if (x < Xmin) Xmin                           = x;
Shinya Kitaoka 120a6e
  if (x > Xmax) Xmax                           = x;
Shinya Kitaoka 120a6e
  if (y < Ymin) Ymin                           = y;
Shinya Kitaoka 120a6e
  if (y > Ymax) Ymax                           = y;
Shinya Kitaoka 120a6e
  Npix++;
Shinya Kitaoka 120a6e
  SET_DONE(i, j);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (NOT_DONE(i + 1, j) && IS_BLACK_GR8(pix + 1))
Shinya Kitaoka 120a6e
    visit_gr8(i + 1, j, x + 1, y, pix + 1);
Shinya Kitaoka 120a6e
  if (NOT_DONE(i - 1, j) && IS_BLACK_GR8(pix - 1))
Shinya Kitaoka 120a6e
    visit_gr8(i - 1, j, x - 1, y, pix - 1);
Shinya Kitaoka 120a6e
  if (NOT_DONE(i, j + 1) && IS_BLACK_GR8(pix + Pix_ystep))
Shinya Kitaoka 120a6e
    visit_gr8(i, j + 1, x, y + 1, pix + Pix_ystep);
Shinya Kitaoka 120a6e
  if (NOT_DONE(i, j - 1) && IS_BLACK_GR8(pix - Pix_ystep))
Shinya Kitaoka 120a6e
    visit_gr8(i, j - 1, x, y - 1, pix - Pix_ystep);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Level--;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static void visit_rgb(int i, int j, int x, int y, TPixel32 *pix) {
Shinya Kitaoka 120a6e
  int weight, ret, dummy;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
start:
Shinya Kitaoka 120a6e
  weight = BLACK_WEIGHT_RGB(pix);
Shinya Kitaoka 120a6e
  ADDBIG(Xsum, x * weight);
Shinya Kitaoka 120a6e
  ADDBIG(Ysum, y * weight);
Shinya Kitaoka 120a6e
  ADDBIG(Weightsum, weight);
Shinya Kitaoka 120a6e
  if (IS_VERY_BLACK_RGB(pix)) Very_black_found = TRUE;
Shinya Kitaoka 120a6e
  if (x < Xmin) Xmin                           = x;
Shinya Kitaoka 120a6e
  if (x > Xmax) Xmax                           = x;
Shinya Kitaoka 120a6e
  if (y < Ymin) Ymin                           = y;
Shinya Kitaoka 120a6e
  if (y > Ymax) Ymax                           = y;
Shinya Kitaoka 120a6e
  Npix++;
Shinya Kitaoka 120a6e
  SET_DONE(i, j);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (NOT_DONE(i + 1, j) && IS_BLACK_RGB(pix + 1)) {
Shinya Kitaoka 120a6e
    PUSH_ONTO_STACK(1, x, y, i, j, 0, pix)
Shinya Kitaoka 120a6e
    i++;
Shinya Kitaoka 120a6e
    x++;
Shinya Kitaoka 120a6e
    pix += 1;
Shinya Kitaoka 120a6e
    goto start;
Shinya Kitaoka 120a6e
  return_1:;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (NOT_DONE(i - 1, j) && IS_BLACK_RGB(pix - 1)) {
Shinya Kitaoka 120a6e
    PUSH_ONTO_STACK(2, x, y, i, j, 0, pix)
Shinya Kitaoka 120a6e
    i--;
Shinya Kitaoka 120a6e
    x--;
Shinya Kitaoka 120a6e
    pix -= 1;
Shinya Kitaoka 120a6e
    goto start;
Shinya Kitaoka 120a6e
  return_2:;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (NOT_DONE(i, j + 1) && IS_BLACK_RGB(pix + Pix_ystep)) {
Shinya Kitaoka 120a6e
    PUSH_ONTO_STACK(3, x, y, i, j, 0, pix)
Shinya Kitaoka 120a6e
    j++;
Shinya Kitaoka 120a6e
    y++;
Shinya Kitaoka 120a6e
    pix += Pix_ystep;
Shinya Kitaoka 120a6e
    goto start;
Shinya Kitaoka 120a6e
  return_3:;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (NOT_DONE(i, j - 1) && IS_BLACK_RGB(pix - Pix_ystep)) {
Shinya Kitaoka 120a6e
    PUSH_ONTO_STACK(4, x, y, i, j, 0, pix)
Shinya Kitaoka 120a6e
    j--;
Shinya Kitaoka 120a6e
    y--;
Shinya Kitaoka 120a6e
    pix -= Pix_ystep;
Shinya Kitaoka 120a6e
    goto start;
Shinya Kitaoka 120a6e
  return_4:;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (!STACK_IS_EMPTY) {
Shinya Kitaoka 120a6e
    POP_FROM_STACK_TPIXEL32(ret, x, y, i, j, dummy, pix);
Shinya Kitaoka 120a6e
    switch (ret) {
Shinya Kitaoka 120a6e
    case 1:
Shinya Kitaoka 120a6e
      goto return_1;
Shinya Kitaoka 120a6e
    case 2:
Shinya Kitaoka 120a6e
      goto return_2;
Shinya Kitaoka 120a6e
    case 3:
Shinya Kitaoka 120a6e
      goto return_3;
Shinya Kitaoka 120a6e
    case 4:
Shinya Kitaoka 120a6e
      goto return_4;
Shinya Kitaoka 120a6e
    default:
Shinya Kitaoka 120a6e
      abort();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef RECURSIVE_VERSION
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static void visit_rgb(int i, int j, int x, int y, TPixel32 *pix) {
Shinya Kitaoka 120a6e
  int weight;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (Level >= Max_level)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    Level++;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  weight = BLACK_WEIGHT_RGB(pix);
Shinya Kitaoka 120a6e
  ADDBIG(Xsum, x * weight);
Shinya Kitaoka 120a6e
  ADDBIG(Ysum, y * weight);
Shinya Kitaoka 120a6e
  ADDBIG(Weightsum, weight);
Shinya Kitaoka 120a6e
  if (IS_VERY_BLACK_RGB(pix)) Very_black_found = TRUE;
Shinya Kitaoka 120a6e
  if (x < Xmin) Xmin                           = x;
Shinya Kitaoka 120a6e
  if (x > Xmax) Xmax                           = x;
Shinya Kitaoka 120a6e
  if (y < Ymin) Ymin                           = y;
Shinya Kitaoka 120a6e
  if (y > Ymax) Ymax                           = y;
Shinya Kitaoka 120a6e
  Npix++;
Shinya Kitaoka 120a6e
  SET_DONE(i, j);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (NOT_DONE(i + 1, j) && IS_BLACK_RGB(pix + 1))
Shinya Kitaoka 120a6e
    visit_rgb(i + 1, j, x + 1, y, pix + 1);
Shinya Kitaoka 120a6e
  if (NOT_DONE(i - 1, j) && IS_BLACK_RGB(pix - 1))
Shinya Kitaoka 120a6e
    visit_rgb(i - 1, j, x - 1, y, pix - 1);
Shinya Kitaoka 120a6e
  if (NOT_DONE(i, j + 1) && IS_BLACK_RGB(pix + Pix_ystep))
Shinya Kitaoka 120a6e
    visit_rgb(i, j + 1, x, y + 1, pix + Pix_ystep);
Shinya Kitaoka 120a6e
  if (NOT_DONE(i, j - 1) && IS_BLACK_RGB(pix - Pix_ystep))
Shinya Kitaoka 120a6e
    visit_rgb(i, j - 1, x, y - 1, pix - Pix_ystep);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Level--;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
JosefMeixner e932c2
#define PERCENT (40.0 / 100.0)
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
 * Attenzione: tutti i controlli e i calcoli vengono fatti in pixel.
Toshihiro Shimizu 890ddd
 * Quindi bisogna convertire tutti i valori in pixel prima di arrivare a
Toshihiro Shimizu 890ddd
 * questo livello.
Toshihiro Shimizu 890ddd
 * Inoltre: la pegs_side si riferisce alle coordinate di raster.
Toshihiro Shimizu 890ddd
 */
Toshihiro Shimizu 890ddd
int get_image_rotation_and_center(const TRasterP &img, int strip_width,
Shinya Kitaoka 120a6e
                                  PEGS_SIDE pegs_side, double *p_ang,
Shinya Kitaoka 120a6e
                                  double *cx, double *cy, DOT ref[],
Shinya Kitaoka 120a6e
                                  int ref_dot) {
Shinya Kitaoka 120a6e
  double angle;
Shinya Kitaoka 120a6e
  int found, i;
Shinya Kitaoka 120a6e
  float dx, dy;
Shinya Kitaoka 120a6e
  DOT _dotarray[MAX_DOT];
Shinya Kitaoka 120a6e
  DOT *dotarray = _dotarray;
Shinya Kitaoka 120a6e
  int ndot;
Shinya Kitaoka 120a6e
  int max_area, min_area;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  *p_ang = 0.0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (Debug_flag) {
Shinya Kitaoka 120a6e
    for (i = 0; i < ref_dot; i++) {
Shinya Kitaoka 120a6e
      printf("Reference dot <%d>\n", i);
Shinya Kitaoka 120a6e
      stampa_dot(ref + i);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  max_area = 0;
Shinya Kitaoka 120a6e
  if (ref_dot > 0) {
Shinya Kitaoka 120a6e
    min_area = ref[0].area;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (i = 0; i < ref_dot; i++) {
Shinya Kitaoka 120a6e
    if (ref[i].area > max_area) {
Shinya Kitaoka 120a6e
      max_area = ref[i].area;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (ref[i].area < min_area) {
Shinya Kitaoka 120a6e
      min_area = ref[i].area;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ndot = find_dots(img, strip_width, pegs_side, dotarray, MAX_DOT, max_area);
Shinya Kitaoka 120a6e
  if (Debug_flag) printf(">>>> %d dots found\n", ndot);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  i = 0;
Shinya Kitaoka 120a6e
  while (i < ndot)  // elimino i dots troppo piccoli
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    if (dotarray[i].area < min_area * PERCENT) {
Shinya Kitaoka 120a6e
      for (int j = i; j < ndot - 1; j++) dotarray[j] = dotarray[j + 1];
Shinya Kitaoka 120a6e
      ndot--;
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      i++;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* controllo il pattern delle perforazioni  */
Shinya Kitaoka 120a6e
  if (ndot <= 1) {
Shinya Kitaoka 120a6e
    return FALSE;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int indexArray[3] = {0, 1, 2};
Shinya Kitaoka 120a6e
  found             = compare_dots(dotarray, ndot, ref, ref_dot, indexArray[0],
Shinya Kitaoka 120a6e
                       indexArray[1], indexArray[2]);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (Debug_flag)
Shinya Kitaoka 120a6e
    for (i = 0; i < ndot; i++) {
Shinya Kitaoka 120a6e
      printf("**** Dot[%d]\n", i);
Shinya Kitaoka 120a6e
      stampa_dot(dotarray + i);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!found) return FALSE;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  angle = 0;
Shinya Kitaoka 120a6e
  for (i = 0; i < 2; i++) {
Shinya Kitaoka 120a6e
    dx = dotarray[indexArray[i + 1]].x - dotarray[indexArray[i]].x;
Shinya Kitaoka 120a6e
    dy = dotarray[indexArray[i + 1]].y - dotarray[indexArray[i]].y;
Shinya Kitaoka 120a6e
    switch (pegs_side) {
Shinya Kitaoka 120a6e
    case PEGS_LEFT:
Shinya Kitaoka 120a6e
    case PEGS_RIGHT:
Shinya Kitaoka 120a6e
      angle += dy == 0.0 ? M_PI_2 : atan(dx / dy);
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    default:
Shinya Kitaoka 120a6e
      angle -= dx == 0.0 ? M_PI_2 : atan(dy / dx);
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  *p_ang = angle / 2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Now calculate the center, we have to get the offset of the center for the
Shinya Kitaoka 120a6e
  // dot at point indexArray[1]
Shinya Kitaoka 120a6e
  // from the reference and then use the angle to calculate the offsets for the
Shinya Kitaoka 120a6e
  // center.
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  // It is assumed, that the holes are all on one line.
Shinya Kitaoka 120a6e
  float pegWidth =
Shinya Kitaoka 120a6e
      sqrt((ref[ref_dot - 1].x - ref[0].x) * (ref[ref_dot - 1].x - ref[0].x) +
Shinya Kitaoka 120a6e
           (ref[ref_dot - 1].y - ref[0].y) * (ref[ref_dot - 1].y - ref[0].y));
Shinya Kitaoka 120a6e
  float refPegOffset = sqrt(
Shinya Kitaoka 120a6e
      (ref[indexArray[1]].x - ref[0].x) * (ref[indexArray[1]].x - ref[0].x) +
Shinya Kitaoka 120a6e
      (ref[indexArray[1]].y - ref[0].y) * (ref[indexArray[1]].y - ref[0].y));
Shinya Kitaoka 120a6e
  *cx = dotarray[indexArray[1]].x +
Shinya Kitaoka 120a6e
        cos(*p_ang) * (pegWidth / 2.0f - refPegOffset);
Shinya Kitaoka 120a6e
  *cy = dotarray[indexArray[1]].y +
Shinya Kitaoka 120a6e
        sin(*p_ang) * (pegWidth / 2.0f - refPegOffset);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (Debug_flag) {
Shinya Kitaoka 120a6e
    printf("\nang: %g\ncx : %g\ncy : %g\n\n", *p_ang, *cx, *cy);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return TRUE;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
#define MIN_V 100.0
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static int compare_dots(DOT const dots[], int ndots, DOT reference[],
Shinya Kitaoka 120a6e
                        int ref_dot, int &i_ok, int &j_ok, int &k_ok) {
Shinya Kitaoka 120a6e
  int found;
Shinya Kitaoka 120a6e
  int toll;
Shinya Kitaoka 120a6e
  float tolld;
Shinya Kitaoka 120a6e
  int i, j, k;
Shinya Kitaoka 120a6e
  bool *dot_ok   = 0;
Shinya Kitaoka 120a6e
  float *ref_dis = 0, dx, dy;
Shinya Kitaoka 120a6e
  float vmin, v, dist_i_j, dist_i_k, dist_j_k, del1, del2;
Shinya Kitaoka 120a6e
  float ref_dis_0_1, ref_dis_1_2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  i_ok = 0;
Shinya Kitaoka 120a6e
  j_ok = 0;
Shinya Kitaoka 120a6e
  k_ok = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* questa funz e' indipendente da posizione e orientamento dei dots */
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (ndots < 1 || ref_dot < 1) {
Shinya Kitaoka 120a6e
    goto error;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* controllo quanti dots sono realmente buoni per il confronto */
Shinya Kitaoka 120a6e
  dot_ok = (bool *)calloc(ndots, sizeof(bool));
Shinya Kitaoka 120a6e
  found  = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (i = 0; i < ndots; i++) {
Shinya Kitaoka 120a6e
    dot_ok[i] = false;
Shinya Kitaoka 120a6e
    for (j = 0; j < ref_dot; j++) {
Shinya Kitaoka 120a6e
      toll = (int)((float)reference[j].area * PERCENT);
Shinya Kitaoka 120a6e
      if (abs(dots[i].area - reference[j].area) < toll) {
Shinya Kitaoka 120a6e
        dot_ok[i] = true;
Shinya Kitaoka 120a6e
        found++;
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!found) {
Shinya Kitaoka 120a6e
    goto error;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ref_dis = (float *)calloc(ref_dot, sizeof(float));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /* calcolo le distanze di riferimento e la tolleranza stessa */
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  tolld                              = (float)reference[0].lx;
Shinya Kitaoka 120a6e
  if (tolld < reference[0].ly) tolld = (float)reference[0].ly;
Shinya Kitaoka 120a6e
  for (i = 1; i < ref_dot; i++) {
Shinya Kitaoka 120a6e
    dx                                 = reference[0].x - reference[i].x;
Shinya Kitaoka 120a6e
    dy                                 = reference[0].y - reference[i].y;
Shinya Kitaoka 120a6e
    ref_dis[i - 1]                     = sqrtf((dx * dx) + (dy * dy));
Shinya Kitaoka 120a6e
    if (tolld < reference[i].lx) tolld = (float)reference[i].lx;
Shinya Kitaoka 120a6e
    if (tolld < reference[i].ly) tolld = (float)reference[i].ly;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // I suspect that the following expects symmetry in the holes layout...
Shinya Kitaoka 120a6e
  // Besides, if the layout is not symmetric, the peg is supposed to be rotated
Shinya Kitaoka 120a6e
  // OR translated
Shinya Kitaoka 120a6e
  // switching from, say, top to bottom? (Daniele)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  i_ok = -1;
Shinya Kitaoka 120a6e
  v = vmin = 10000000.0;
Shinya Kitaoka 120a6e
  for (i = 0; i < ndots - 2; i++) {
Shinya Kitaoka 120a6e
    if (!dot_ok[i]) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (j = i + 1; j < ndots - 1; j++) {
Shinya Kitaoka 120a6e
      if (!dot_ok[j]) continue;
Shinya Kitaoka 120a6e
      for (k = j + 1; k < ndots; k++) {
Shinya Kitaoka 120a6e
        if (!dot_ok[k]) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // Build square discrepancies from the reference relative hole distances
Shinya Kitaoka 120a6e
        dx       = dots[i].x - dots[j].x;
Shinya Kitaoka 120a6e
        dy       = dots[i].y - dots[j].y;
Shinya Kitaoka 120a6e
        dist_i_j = sqrtf((dx * dx) + (dy * dy));
Shinya Kitaoka 120a6e
        dx       = dots[i].x - dots[k].x;
Shinya Kitaoka 120a6e
        dy       = dots[i].y - dots[k].y;
Shinya Kitaoka 120a6e
        dist_i_k = sqrtf((dx * dx) + (dy * dy));
Shinya Kitaoka 120a6e
        del1     = (dist_i_j - ref_dis[0]);
Shinya Kitaoka 120a6e
        del2     = (dist_i_k - ref_dis[1]);
Shinya Kitaoka 120a6e
        v        = ((del1 * del1) + (del2 * del2));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // Furthermore, add discrepancies from the reference hole areas
Shinya Kitaoka 120a6e
        v += abs(dots[i].area -
Shinya Kitaoka 120a6e
                 reference[0].area);  // fabs since areas are already squared
Shinya Kitaoka 120a6e
        v += abs(dots[j].area - reference[1].area);
Shinya Kitaoka 120a6e
        v += abs(dots[k].area - reference[2].area);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (v < vmin) {
Shinya Kitaoka 120a6e
          i_ok = i;
Shinya Kitaoka 120a6e
          j_ok = j;
Shinya Kitaoka 120a6e
          k_ok = k;
Shinya Kitaoka 120a6e
          vmin = v;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (Debug_flag) {
Shinya Kitaoka 120a6e
    printf("Ho trovato v = %f su %f per %d %d %d \n", v, vmin, i_ok, j_ok,
Shinya Kitaoka 120a6e
           k_ok);
Shinya Kitaoka 120a6e
    printf("----  Dot <%d>  ----\n", i_ok);
Shinya Kitaoka 120a6e
    stampa_dot(dots + i_ok);
Shinya Kitaoka 120a6e
    printf("----  Dot <%d>  ----\n", j_ok);
Shinya Kitaoka 120a6e
    stampa_dot(dots + j_ok);
Shinya Kitaoka 120a6e
    printf("----  Dot <%d>  ----\n", k_ok);
Shinya Kitaoka 120a6e
    stampa_dot(dots + k_ok);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (i_ok < 0)
Shinya Kitaoka 120a6e
    goto error;
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    dx       = dots[i_ok].x - dots[j_ok].x;
Shinya Kitaoka 120a6e
    dy       = dots[i_ok].y - dots[j_ok].y;
Shinya Kitaoka 120a6e
    dist_i_j = sqrtf((dx * dx) + (dy * dy));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    dx       = dots[k_ok].x - dots[j_ok].x;
Shinya Kitaoka 120a6e
    dy       = dots[k_ok].y - dots[j_ok].y;
Shinya Kitaoka 120a6e
    dist_j_k = sqrtf((dx * dx) + (dy * dy));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ref_dis_0_1 = ref_dis[0];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    dx          = reference[1].x - reference[2].x;
Shinya Kitaoka 120a6e
    dy          = reference[1].y - reference[2].y;
Shinya Kitaoka 120a6e
    ref_dis_1_2 = sqrtf((dx * dx) + (dy * dy));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (fabsf(dist_i_j - ref_dis_0_1) >= tolld ||
Shinya Kitaoka 120a6e
        fabsf(dist_j_k - ref_dis_1_2) >= tolld) {
Shinya Kitaoka 120a6e
      i_ok = 0;
Shinya Kitaoka 120a6e
      j_ok = 1;
Shinya Kitaoka 120a6e
      k_ok = 2;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (ref_dis) free(ref_dis);
Shinya Kitaoka 120a6e
  if (dot_ok) free(dot_ok);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return TRUE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
error:
Shinya Kitaoka 120a6e
  if (ref_dis) free(ref_dis);
Shinya Kitaoka 120a6e
  if (dot_ok) free(dot_ok);
Shinya Kitaoka 120a6e
  return FALSE;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*---------------------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static void stampa_dot(DOT const *dot) {
Shinya Kitaoka 120a6e
  printf("Dimensioni: %d,\t%d\n", dot->lx, dot->ly);
Shinya Kitaoka 120a6e
  printf("Start     : %d,\t%d\n", dot->x1, dot->y1);
Shinya Kitaoka 120a6e
  printf("End       : %d,\t%d\n", dot->x2, dot->y2);
Shinya Kitaoka 120a6e
  printf("Baricentro: %5.3f,\t%5.3f\n", dot->x, dot->y);
Shinya Kitaoka 120a6e
  printf("Area      : %d\n", dot->area);
Toshihiro Shimizu 890ddd
}