#! /bin/bash
# Last edited on 2023-09-25 09:07:11 by stolfi

# Computes adjusted feature point coordinates in the full images
# by applying the adjustments entered by hand.

echo "entering ${0##*/} ..." 1>&2

tmp="/tmp/$$" # Prefix for temporary files.
echo "tmp = ${tmp}" 1>&2

img_in_dir="images/full"  # Directory with full original images.
pts_in_dir="align/raw"    # Directory with ".pts"/".ipts"  files of manually-picked feature coordinate.
adj_in_dir="align/adj"    # Directory with manual adjustments to the mapped ".ipts" files.

adj_out_dir="align/adj/out"  # Directory for all output files.
pts_out_dir="${adj_out_dir}" # Directory for adjusted versions of image ".ipts" files.

img_out_dir="${adj_out_dir}" # Directory for re-rectified images.
nhood_out_dir="${img_out_dir}/nhood" # Directory for feature neighborhood clips of the same.

deltas_in_file="${adj_in_dir}/deltas_by_hand.txt"   # File with manual fine adjustments to feature coords.
opts_ump_in_file="${opts_ref_in_file}"           # File with output point coords to be mapped back to input image.

oUnit=0.500 # Output pixels per user unit.

sides=( a b )

img_in_files_all=( ${pts_in_dir}/ref{a,b}.jpg ${img_in_dir}/[a-z][a-z][0-9][0-9][0-9][a-z].jpg )
img_in_files_some=( ${pts_in_dir}/ref{a,b}.jpg ${img_in_dir}/nt03{{0,1,2}a,3b}.jpg )

for side in ${sides[@]} ; do
  
  echo "### processing images of side  ${side} ###" 1>&2

  opts_ref_in_file="${pts_in_dir}/ref${side}.pts" # Name of file with their coords on {ofile}.
  if [[ ! ( -s ${opts_ref_in_file} ) ]]; then
    echo "** ${opts_ref_in_file} not found" 1>&2; exit 1
  fi
  
  # Edit the next line as appropriate:
  img_in_files=( `ls "${img_in_files_all[@]}" | egrep -e "${side}[.]" | sort` )
  
  # Decide if will show each image as computed:
  if [[ ${#img_in_files[@]} -le 12 ]]; then show=1; else show=0; fi

  for img_in_file in "${img_in_files[@]}" ; do 

    iname="${img_in_file##*/}"; iname="${iname/.*}" # Filename of input image, sans the directory and extension.
    echo "=== ${iname} ===" 1>&2

    img_out_file="${img_out_dir}/${iname}.png"  # Filename of image re-rectified with adjusted ref points.
    nhood_pref="${img_out_dir}/nhood/${iname}"  # Filename prefix for neighborhood clips.
    ipts_ref_in_file="${pts_in_dir}/${iname}.ipts"   # Name of file with coords of key features on {img_in_file}.
    if [[ ! ( -s ${ipts_ref_in_file} ) ]]; then
      echo "** ${ipts_ref_in_file} not found" 1>&2; exit 1
    fi
    mpts_ump_out_file="${pts_out_dir}/${iname}.mpts"  # Name of file with all ref feature points mapped back to input image.

    ipts_ref_adj_out_file="${pts_out_dir}/${iname}.ipts"   # Name of file with adjuted input coords of key features.
    rm -f ${ipts_ref_adj_out_file}

    if [[ ( "/${iname}" == "/ref${side}" ) || ( "/${iname}" == "/ref${side}-mask" ) ]]; then
      # Reference image. The ref points are not adjusted by defintion.
      echo "!! skipping adjustment of reference image feature points" 1>&2
      ( cd ${pts_out_dir} && ln -s ../${iname}.pts ${iname}.pts )
      ( cd ${pts_out_dir} && ln -s ../${iname}.pts ${iname}.ipts )
      ipts_ref_adj_out_file=${ipts_ref_in_file}
    else
      # Not a ref image. apply the manual adjustments:
      
      rm -f ${mpts_ump_out_file} ${img_out_file} ${nhood_pref}-*.png

      # Get the pixel coord adjustments for image ${iname}:
      adjs=( `egrep -e "^${iname}\\\b" ${deltas_in_file} | tr ' ' '\012'` )
      echo "output pixel coord adjustments = ${adjs[*]}" 1>&2
      if [[ "/${adjs[0]}" != "/${iname}" ]]; then echo "** bug iname" 1>&2; exit 1; fi
      tagPref="${adjs[1]}"
      echo "tagPref = ${tagPref}" 1>&2
      if [[ ( "/${tagPref}" != "/P" ) && ( "/${tagPref}" != "/Q" ) ]]; then
        echo "** bug ${iname}: tag prefix = \"${tagPref}\" not [PQ]" 1>&2; exit 1
      fi

      echo "applying adjustments to coords of ${opts_ref_in_file} ..." 1>&2 
      opts_adj_out_file="${tmp}-adj.opts"  # File with adjusted output user coordinates of ref pts.
      cat ${opts_ref_in_file} \
        | adjust_image_out_ref_pts.gawk \
            -v oUnit=${oUnit} \
            -v tagPref="${tagPref}" \
            -v deltas="${adjs[*]:2}" \
        > ${opts_adj_out_file}

      echo "mapping the adjusted user output points back to input image coords ..." 1>&2
      mpts_adj_out_file="${tmp}-adj.mpts" # File with adjusted in/out user/pixel coord.
      persp_rectify.sh \
          ${img_in_file} \
          ${ipts_ref_in_file} ${opts_ref_in_file} \
          ${oUnit} \
          NONE \
          ${opts_adj_out_file} ${mpts_adj_out_file} \
          NONE

      echo "joining old and new user input coords of ref points ..." 1>&2
      ipts_old_file="${tmp}-old.ipts"
      cat ${ipts_ref_in_file} | sed -e 's:^ *::g' | egrep -e '^[PQ][0-9]\b' | sort > ${ipts_old_file}
      mpts_new_file="${tmp}-new.mpts"
      cat ${mpts_adj_out_file} | sed -e 's:^ *::g' | egrep -e '^[PQ][0-9]\b' | sort > ${mpts_new_file}
      jpts_file="${tmp}-join.jpts"
      join -j 1 -o 0,1.2,1.3,2.2,2.3 ${ipts_old_file} ${mpts_new_file} | head -n 4 > ${jpts_file}
      cat ${jpts_file} 1>&2

      echo "creating adjusted feature user input coords ${ipts_ref_adj_out_file}, with '*_old' versions ..." 1>&2
      cat ${jpts_file} \
        | gawk \
            -v cmd="${0##*/}" \
            ' BEGIN{
                printf "# Generated by %s - do not edit!\n", cmd;
                printf "\n"
              }
              /^[PQ][0-9][ ]/ {
                tag = $1; xi_old = $2; yi_old = $3; xi_adj = $4; yi_adj = $5;
                printf "%-6s %6.1f %6.1f\n", tag, xi_adj, yi_adj;
                printf "%-6s %6.1f %6.1f\n", (tag "_old"), xi_old, yi_old;
                next;
              }
              // { printf "** bug\n" > "/dev/stderr"; exit(1); }
            ' \
        > ${ipts_ref_adj_out_file}
      cat ${ipts_ref_adj_out_file} 1>&2
    fi
      
    echo "recreating the rectified images with adjusted input ref points ..." 1>&2
    if [[ ( "/${iname}" == "/ref${side}" ) || ( "/${iname}" == "/ref${side}-mask" ) ]]; then
      # Reference image. The rectified image is not affected by definition.
      ( cd ${img_out_dir} && ln -s ../${iname}.jpg ${iname}.jpg )
    else
      persp_rectify.sh \
          ${img_in_file} \
          ${ipts_ref_adj_out_file} ${opts_ref_in_file} \
          ${oUnit} \
          ${img_out_file} \
          ${opts_ref_in_file} ${mpts_ump_out_file} \
          ${nhood_pref}
    fi
    
    if [[ -s ${img_out_file} ]] ; then 
      if [[ ${show} -ne 0 ]]; then 
        display -title '%f' ${img_out_file}
        display -title '%f' ${nhood_pref}-*.png
      fi
    else
      echo "** ${img_out_file} not generated" 1>&2
    fi

  done
done
