/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * filename: m-pixels.c                                                    *
 *                                                                         *
 * UTIL C-source: Medical Image Conversion Utility                         *
 *                                                                         *
 * purpose      : Ask & display pixel values                               *
 *                                                                         *
 * project      : (X)MedCon by Erik Nolf                                   *
 *                                                                         *
 * Functions    : MdcDisplayPixels()    - Display pixel values             *
 *                MdcAskPixels()        - Ask for pixels                   *
 *                MdcGetPixels()        - Get specified pixels             *
 *                MdcGetOnePixel()      - Get one pixel value              *
 *                MdcPrintPixel()       - Print pixel value                *
 *                                                                         *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
 */

/*
   Copyright (C) 1997-2026 by Erik Nolf

   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 2, or (at your option) any later
   version.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
   Public License for more details.

   You should have received a copy of the GNU General Public License along
   with this program; if not, write to the Free Software Foundation, Inc.,
   59 Place - Suite 330, Boston, MA 02111-1307, USA.  */

/****************************************************************************
                              H E A D E R S
****************************************************************************/

#include "m-depend.h"

#include <stdio.h>
#ifdef LIBMDC_HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef LIBMDC_HAVE_STRING_H
#include <string.h>
#endif
#ifdef LIBMDC_HAVE_STRINGS_H
#ifndef _WIN32
#include <strings.h>
#endif
#endif

#include "medcon.h"

/****************************************************************************
                            F U N C T I O N S
****************************************************************************/

void MdcDisplayPixels(FILEINFO *fi)
{
   Uint32 *images=NULL;
   Uint32 *cols=NULL;
   Uint32 *rows=NULL;

   if (MDC_FILE_STDIN == MDC_YES) return; /* stdin already in use */

   if (fi->type == COLRGB) {
     MdcPrntWarn("Print values of true color files unsupported");
     return;
   }

   MdcPrintLine('-',MDC_FULL_LENGTH);
   MdcPrntScrn("\tPIXEL DISPLAY\t\tFILE: %s\n",fi->ifname);
   MdcPrintLine('-',MDC_FULL_LENGTH);

   if (MdcAskPixels(fi,&images,&cols,&rows) == MDC_YES) {
     MdcGetPixels(fi,images,cols,rows);
   }

   MdcPrintLine('-',MDC_FULL_LENGTH);

   MdcFree(images);
   MdcFree(cols);
   MdcFree(rows);

}

int MdcAskPixels(FILEINFO *fi, Uint32 *img[], Uint32 *col[], Uint32 *row[])
{
   Int32 a1;
   Uint32 images=1, bt, it, f, p, g, b;
   Uint32  *frames, *planes, *gates, *beds;
   Uint32 *itmp, *ctmp, *rtmp;
   char *msg=NULL;

   if (MDC_PIXELS_PRINT_ALL == MDC_YES) {
     itmp = (Uint32 *)malloc(2*sizeof(Uint32));
     ctmp = (Uint32 *)malloc(2*sizeof(Uint32));
     rtmp = (Uint32 *)malloc(2*sizeof(Uint32));

     if ((itmp == NULL) || (ctmp == NULL) || (rtmp == NULL)) {
       MdcPrntWarn("Failure to malloc index buffers");
       MdcFree(itmp); MdcFree(ctmp); MdcFree(rtmp);
       return(MDC_NO);
     }

     /* all images */
     itmp[0]=1;  itmp[1]=0;
     /* one pixel coord: 0,0 = all */
     ctmp[0]=1; ctmp[1]=0;
     rtmp[0]=1; rtmp[1]=0;

     *img = itmp;
     *col = ctmp;
     *row = rtmp;

     return(MDC_YES);
   }


   a1 = MdcGetSelectionType();

   MdcPrntScrn("\n");
   MdcPrntScrn("\n\tInput notes: a) Any number must be one-based (0 = All)");
   MdcPrntScrn("\n\t             b) Syntax of range   : X...Y or X-Y");
   MdcPrntScrn("\n\t             c) Syntax of interval: X:S:Y    (S = step)");
   MdcPrntScrn("\n\t             d) Just type <enter> for the entire range\n");

   if ( a1 == MDC_INPUT_ECAT_STYLE ) { /* ecat   */
     if ( (planes=(Uint32 *)malloc((fi->dim[3]+1)*sizeof(Uint32))) == NULL ){
       MdcPrntWarn("Couldn't allocate planes buffer");
       return(MDC_NO);
     }
     memset(planes,0,(fi->dim[3]+1)*sizeof(Uint32));
     if ( (frames=(Uint32 *)malloc((fi->dim[4]+1)*sizeof(Uint32))) == NULL ){
       MdcPrntWarn("Couldn't allocate frames buffer");
       MdcFree(planes);
       return(MDC_NO);
     }
     memset(frames,0,(fi->dim[4]+1)*sizeof(Uint32));
     if ( (gates=(Uint32 *)malloc((fi->dim[5]+1)*sizeof(Uint32))) == NULL ) {
       MdcPrntWarn("Couldn't allocate gates buffer");
        MdcFree(frames);
        MdcFree(planes);
        return(MDC_NO);
     }
     memset(gates,0,(fi->dim[5]+1)*sizeof(Uint32));
     if ( (beds=(Uint32 *)malloc((fi->dim[6]+1)*sizeof(Uint32))) == NULL ) {
       MdcPrntWarn("Couldn't allocate beds buffer");
       MdcFree(frames);
       MdcFree(planes);
       MdcFree(gates);
       return(MDC_NO);
     }
     memset(beds,0,(fi->dim[6]+1)*sizeof(Uint32));

     MdcPrntScrn("\n\tGive planes list [1...%u]: ",fi->dim[3]);
     MdcGetStrInput(mdcbufr,MDC_2KB_OFFSET);

     if ((msg=MdcHandleEcatList(mdcbufr,&planes,(Uint32)fi->dim[3])) != NULL) {
       MdcPrntWarn(msg);
       MdcFree(frames); MdcFree(planes); MdcFree(gates); MdcFree(beds);
       return(MDC_NO);
     }

     MdcPrntScrn("\n\tGive frames list [1...%u]: ",fi->dim[4]);
     MdcGetStrInput(mdcbufr,MDC_2KB_OFFSET);

     if ((msg=MdcHandleEcatList(mdcbufr,&frames,(Uint32)fi->dim[4])) != NULL) {
       MdcPrntWarn(msg);
       MdcFree(frames); MdcFree(planes); MdcFree(gates); MdcFree(beds);
       return(MDC_NO);
     }

     MdcPrntScrn("\n\tGive gates  list [1...%u]: ",fi->dim[5]);
     MdcGetStrInput(mdcbufr,MDC_2KB_OFFSET);

     if ((msg=MdcHandleEcatList(mdcbufr,&gates,(Uint32)fi->dim[5])) != NULL) {
       MdcPrntWarn(msg);
       MdcFree(frames); MdcFree(planes); MdcFree(gates); MdcFree(beds);
       return(MDC_NO);
     }

     MdcPrntScrn("\n\tGive beds   list [1...%u]: ",fi->dim[6]);
     MdcGetStrInput(mdcbufr,MDC_2KB_OFFSET);

     if ((msg=MdcHandleEcatList(mdcbufr,&beds,(Uint32)fi->dim[6])) != NULL) {
       MdcPrntWarn(msg);
       MdcFree(frames); MdcFree(planes); MdcFree(gates); MdcFree(beds);
       return(MDC_NO);
     }

     images*=(planes[0]*frames[0]*gates[0]*beds[0]);

     if (images == 0 ) {
       MdcPrntWarn("No valuable images specified!");
       MdcFree(frames); MdcFree(planes); MdcFree(gates); MdcFree(beds);
       return(MDC_NO);
     }

     itmp=(Uint32 *)malloc((images+1)*sizeof(Uint32));
     if (itmp == NULL) {
       MdcPrntWarn("Couldn't allocate images number buffer");
       MdcFree(frames); MdcFree(planes); MdcFree(gates); MdcFree(beds);
       return(MDC_NO);
     }

     itmp[0]=images;

     /* get sequential image numbers (like normal selection) */
     it = 1; bt = 2;
     for (b=1; b<=fi->dim[6]; b++) if (beds[b])
     for (g=1; g<=fi->dim[5]; g++) if (gates[g])
     for (f=1; f<=fi->dim[4]; f++) if (frames[f])
     for (p=1; p<=fi->dim[3]; p++) if (planes[p]) {

       itmp[it++]= p +
                   fi->dim[3]*( (f-1) +
                   fi->dim[4]*( (g-1) +
                   fi->dim[5]*( (b-1) ) ) );

     }

     if ((it-1) != images) {
       MdcPrntErr(MDC_BAD_CODE,"Internal Error ## Improper list handling");
     }

     MdcFree(planes); MdcFree(frames); MdcFree(gates); MdcFree(beds);

   }else{           /* normal */

     if ( (itmp=(Uint32 *)malloc(MDC_BUF_ITMS*sizeof(Uint32))) == NULL ) {
       MdcPrntWarn("Couldn't allocate image numbers buffer");
       return(MDC_NO);
     }

     itmp[0] = 0;

     MdcPrntScrn("\n\tGive a list of image numbers:     ex. 1 7...31 84");
     MdcPrntScrn("\n\tYour input [1...%u]: ",fi->number);
     MdcGetStrInput(mdcbufr,MDC_2KB_OFFSET);

     it = 1; bt = 2;

     if ((msg=MdcHandleNormList(mdcbufr,&itmp,&it,&bt,fi->number)) != NULL){
       MdcPrntWarn(msg);
       if (itmp != NULL) MdcFree(itmp);
       return(MDC_NO);
     }

   }

   if (itmp[1] == 0) { /* all images selected, special case */
     itmp[0]=fi->number;
     it = fi->number;
   }else{
     itmp[0] = it - 1;
   }

   if (itmp[0] == 0) {
     MdcPrntWarn("No images specified!");
     MdcFree(itmp);
     return(MDC_NO);
   }

   if ( (ctmp=(Uint32 *)malloc(MDC_BUF_ITMS*sizeof(Uint32))) == NULL ) {
     MdcPrntWarn("Couldn't allocate pixels column buffer");
     MdcFree(itmp);
     return(MDC_NO);
   }
   if ( (rtmp=(Uint32 *)malloc(MDC_BUF_ITMS*sizeof(Uint32))) == NULL ) {
     MdcPrntWarn("Couldn't allocate pixels row buffer");
     MdcFree(itmp); MdcFree(ctmp);
     return(MDC_NO);
   }

   it=1; bt=2;

   MdcPrntScrn("\n\n\tGive a list of pixels x,y :       ex. 1,1 12,0");
   MdcPrntScrn("\n\tYour input [%u,%u]: ",fi->mwidth,fi->mheight);
   MdcGetStrInput(mdcbufr,MDC_2KB_OFFSET);

   MdcPrntScrn("\n");

   if ((msg=MdcHandlePixelList(mdcbufr,&ctmp,&rtmp,&it,&bt)) != NULL) {
     MdcPrntWarn(msg);
     MdcFree(itmp); MdcFree(ctmp); MdcFree(rtmp);
     return(MDC_NO);
   }

   ctmp[0] = it - 1;  rtmp[0] = it - 1;

   if ((ctmp[0] == 0) || (rtmp[0] == 0)) {
     MdcPrntWarn("No valid pixel specified!");
     MdcFree(itmp); MdcFree(ctmp); MdcFree(rtmp);
     return(MDC_NO);
   }

   *img = itmp;
   *col = ctmp;
   *row = rtmp;

   return(MDC_YES);
}

void MdcGetPixels(FILEINFO *fi, Uint32 img[], Uint32 col[], Uint32 row[])
{

   Uint32 it, pt, ct, rt, number, itotal;
   IMG_DATA *id;

   MdcPrintLine('+',MDC_FULL_LENGTH);
   MdcPrntScrn("\
 : image: :     slope     : :   intercept   :   pixel  :     value\n");
   MdcPrintLine('+',MDC_FULL_LENGTH);

   if (img[1] == 0) { /* special: just all images selected */
     itotal = fi->number;
   }else{             /* normal : get selected images from first index */
     itotal = img[0];
   }

   for (it=1; it <= itotal; it++) {

      if (img[1] == 0) {  /* special: calc next image number */
        number = it-1;
      }else{              /* normal : get image number from next index */
        number = img[it] - 1;
      }

      id = &fi->image[number];

      for (pt=1; pt <= row[0]; pt++) {

         if (row[pt] == 0) { /* all pixels of the row */

           for (rt=0; rt < id->height; rt++) {

              if (col[pt] == 0) { /* all pixels of the column */

                for (ct=0; ct < id->width; ct++)

                   MdcPrintPixel(id,number,ct,rt);

              }else{

                   MdcPrintPixel(id,number,col[pt]-1,rt);
              }
           }
         }else{

           if (col[pt] == 0) { /* all pixels of the column */

             for (ct=0; ct < id->width; ct++)

                   MdcPrintPixel(id,number,ct,row[pt]-1);

           }else{

                   MdcPrintPixel(id,number,col[pt]-1,row[pt]-1);
           }
         }
      }

   }

   MdcPrintLine('+',MDC_FULL_LENGTH);

}

double MdcGetOnePixel(IMG_DATA *id, Uint32 i, Uint32 x, Uint32 y)
{
  double value=0.0;
  Uint32 offset;

  if ((x < id->width) && (y < id->height)) {

      offset = (y * id->width) + x;

      switch (id->type) {
       case BIT8_U:
        {
           Uint8 *pix = (Uint8 *)id->buf;
           value = (double)pix[offset];
        }
        break;
       case BIT8_S:
        {
           Int8 *pix = (Int8 *)id->buf;
           value = (double)pix[offset];
        }
        break;
       case BIT16_U:
        {
           Uint16 *pix = (Uint16 *)id->buf;
           value = (double)pix[offset];
        }
        break;
       case BIT16_S:
        {
           Int16 *pix = (Int16 *)id->buf;
           value = (double)pix[offset];
        }
        break;
       case BIT32_U:
        {
           Uint32 *pix = (Uint32 *)id->buf;
           value = (double)pix[offset];
        }
        break;
       case BIT32_S:
        {
           Int32 *pix = (Int32 *)id->buf;
           value = (double)pix[offset];
        }
        break;
       case BIT64_U:
        {
           Uint64 *pix = (Uint64 *)id->buf;
           value = (double)pix[offset];
        }
        break;
       case BIT64_S:
        {
           Int64 *pix = (Int64 *)id->buf;
           value = (double)pix[offset];
        }
        break;
       case FLT32:
        {
           float *pix = (float *)id->buf;
           value = (double)pix[offset];
        }
        break;
       case FLT64:
        {
           double *pix = (double *)id->buf;
           value = pix[offset];
        }
        break;
      }

   }else{

      value = 0.0;

   }

   return(value);
}

void MdcPrintPixel(IMG_DATA *id, Uint32 i, Uint32 x, Uint32 y)
{
   double ppv; /* plain pixel value */

   if ((x < id->width) && (y < id->height)) {

     ppv = MdcGetOnePixel(id,i,x,y);  /* Plain Pixel Value */

     MdcPrntScrn("#: %4u :",i+1);
     MdcPrntScrn("S: %+e :",id->rescale_slope);
     MdcPrntScrn("I: %+e :",id->rescale_intercept);
     MdcPrntScrn("P(%3u,%3u): %+e\n",x+1,y+1,ppv);

   }else{

      MdcPrntWarn("Invalid pixel (%u,%u) for image #%u [%ux%u]"
                       ,x+1,y+1,i+1,id->width,id->height);

   }

}
