/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * filename: m-xtract.c * * * * UTIL C-source: Medical Image Conversion Utility * * * * purpose : extract specified images * * * * project : (X)MedCon by Erik Nolf * * * * Functions : MdcGetImagesToExtract() - Ask images to extract * * MdcExtractImages() - Extract/Reorder the images * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* $Id: m-xtract.c,v 1.34 2007/05/21 20:16:15 enlf Exp $ */ /* Copyright (C) 1997-2007 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 #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STRINGS_H #ifndef _WIN32 #include #endif #endif #include "medcon.h" /**************************************************************************** D E F I N E S ****************************************************************************/ MdcExtractInputStruct mdcextractinput; /**************************************************************************** F U N C T I O N S ****************************************************************************/ int MdcGetImagesToExtract(FILEINFO *fi, MdcExtractInputStruct *input) { Uint32 images=1; Uint32 *frames, *planes, *gates, *beds; Uint32 p,f,g,b; Uint32 it, bt; char *msg; /* initialize the extract input structure */ input->style = MDC_INPUT_NORM_STYLE; input->inrs = NULL; input->num_p = 1; input->num_f = 1; input->num_g = 1; input->num_b = 1; if (input->INTERACTIVE == MDC_YES) { MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("\tEXTRACT IMAGES\t\tFILE: %s\n",fi->ifname); MdcPrintLine('-',MDC_FULL_LENGTH); input->style = MdcGetSelectionType(); } if ( input->style == MDC_INPUT_ECAT_STYLE ) { /* ecat input type */ if (input->INTERACTIVE == MDC_NO) return(MDC_NO); MdcPrntScrn("\n\n\t"); MdcPrntScrn("Input notes: a) Any number must be one-based (0 = All)"); MdcPrntScrn("\n\t"); MdcPrntScrn(" b) Syntax of range : X...Y or X-Y"); MdcPrntScrn("\n\t"); MdcPrntScrn(" c) Syntax of interval: X:S:Y (S = step)"); MdcPrntScrn("\n\t"); MdcPrntScrn(" d) Just type for entire range\n"); MdcPrntScrn("\n\t"); MdcPrntScrn("Example : 1 3 5...10 12:2:20\n"); 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(planes); MdcFree(frames); 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(planes); MdcFree(frames); 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) { MdcFree(planes); MdcFree(frames); MdcFree(gates); MdcFree(beds); MdcPrntWarn(msg); return(MDC_BAD_CODE); } 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) { MdcFree(planes); MdcFree(frames); MdcFree(gates); MdcFree(beds); MdcPrntWarn(msg); return(MDC_BAD_CODE); } 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) { MdcFree(planes); MdcFree(frames); MdcFree(gates); MdcFree(beds); MdcPrntWarn(msg); return(MDC_BAD_CODE); } 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) { MdcFree(planes); MdcFree(frames); MdcFree(gates); MdcFree(beds); MdcPrntWarn(msg); return(MDC_BAD_CODE); } images*=planes[0]*frames[0]*gates[0]*beds[0]; input->num_p = planes[0]; input->num_f = frames[0]; input->num_g = gates[0]; input->num_b = beds[0]; if ((input->inrs=(Uint32 *)malloc((images+1)*sizeof(Uint32)))==NULL) { MdcFree(planes); MdcFree(frames); MdcFree(gates); MdcFree(beds); MdcPrntWarn("Couldn't malloc images number buffer"); return(MDC_BAD_ALLOC); } /* get sequential image numbers (like normal selection) */ it = 1; 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]) { images = p + /* the image number */ fi->dim[3]*( (f-1) + fi->dim[4]*( (g-1) + fi->dim[5]*( (b-1) ) ) ); input->inrs[it++]=images; } MdcFree(planes); MdcFree(frames); MdcFree(gates); MdcFree(beds); }else{ /* normal input type */ if ((input->inrs=(Uint32 *)malloc(MDC_BUF_ITMS*sizeof(Uint32)))==NULL) { MdcPrntWarn("Couldn't allocate images number buffer"); return(MDC_BAD_ALLOC); } if (input->INTERACTIVE == MDC_YES) { MdcPrntScrn("\n\t"); MdcPrntScrn("Input notes: a) Any number must be one-based "); MdcPrntScrn("(0 = All reversed)"); MdcPrntScrn("\n\t"); MdcPrntScrn(" b) Syntax of range : X...Y or X-Y"); MdcPrntScrn("\n\t"); MdcPrntScrn(" c) Syntax of interval: X:S:Y (S = step)"); MdcPrntScrn("\n\t"); MdcPrntScrn(" d) The list is sequence sensitive!"); MdcPrntScrn("\n\t"); MdcPrntScrn(" e) Just type for all reversed\n"); MdcPrntScrn("\n\t"); MdcPrntScrn("Example : 1 3 4:2:11 12...6\n"); MdcPrntScrn("\n\t"); MdcPrntScrn("Your input [1...%u]: ",fi->number); MdcGetStrInput(input->list,MDC_MAX_LIST); } it = 1; bt = 2; msg = MdcHandleNormList(input->list,&input->inrs,&it,&bt,fi->number); if (msg != NULL) { MdcFree(input->inrs); MdcPrntWarn(msg); return(MDC_BAD_CODE); } } input->inrs[0] = it - 1; if (input->INTERACTIVE == MDC_YES) MdcPrintLine('-',MDC_FULL_LENGTH); if (input->inrs[0] == 0) { MdcPrntWarn("No images specified!"); MdcFree(input->inrs); return(MDC_BAD_CODE); } return(MDC_YES); } char *MdcExtractImages(FILEINFO *fi) { MdcExtractInputStruct *input = &mdcextractinput; Uint32 i, j, bytes; char *msg=NULL; IMG_DATA id_tmp, *new_image; IMG_DATA *id_src, *id_dest; int error; if (MDC_FILE_STDIN == MDC_YES) return(NULL); /* stdin already in use */ /* in GUI skip command-line questions */ if (XMDC_GUI == MDC_NO) { error=MdcGetImagesToExtract(fi,input); if (error != MDC_YES) return("Failure retrieving images to extract"); } /* free obsolete data structs */ MdcFreeODs(fi); /* handle image extractions */ if (input->inrs[1] == 0) { /* * reverse images */ for (i=0; i < (fi->number/2); i++) { memcpy(&id_tmp,&fi->image[i],sizeof(IMG_DATA)); memcpy(&fi->image[i],&fi->image[fi->number-1-i],sizeof(IMG_DATA)); memcpy(&fi->image[fi->number-1-i],&id_tmp,sizeof(IMG_DATA)); } }else{ /* * extract/reorder images */ /* handle new IMG_DATA structs */ new_image = (IMG_DATA *)malloc(input->inrs[0]*sizeof(IMG_DATA)); if (new_image == NULL) { MdcFree(input->inrs); return("Couldn't alloc new IMG_DATA array"); } for (i=1; i<=input->inrs[0]; i++) { if (MDC_PROGRESS) MdcProgress(MDC_PROGRESS_INCR,1./(float)input->inrs[0],NULL); id_dest = &new_image[i-1]; id_src = &fi->image[input->inrs[i]-1]; bytes = id_src->width * id_src->height * MdcType2Bytes(id_src->type); /* copy IMG_DATA struct */ memcpy((Uint8 *)id_dest,(Uint8 *)id_src,sizeof(IMG_DATA)); /* copy fresh image buffer */ id_dest->buf = MdcGetImgBuffer(bytes); if (id_dest->buf == NULL) { /* free up previous allocated resources */ for (j=0; j < i-1; j++) MdcFree(new_image[j].buf); MdcFree(new_image); MdcFree(input->inrs); return("Couldn't alloc new image buffer"); }else{ memcpy(id_dest->buf,id_src->buf,bytes); } } /* remove all previous images */ for (i=0; inumber; i++) MdcFree(fi->image[i].buf); /* re-init FI */ MdcFree(fi->image); fi->number = input->inrs[0]; if (input->style == MDC_INPUT_ECAT_STYLE) { /* preserve ECAT style image */ fi->dim[0] = 6; fi->dim[3] = input->num_p; fi->dim[4] = input->num_f; fi->dim[5] = input->num_g; fi->dim[6] = input->num_b; }else{ fi->dim[0] = 3; fi->dim[3] = fi->number; for (i=4; i < MDC_MAX_DIMS; i++) fi->dim[i] = 1; } fi->image = new_image; if (fi->acquisition_type == MDC_ACQUISITION_DYNAMIC) { if (fi->dim[4] > 1) { fi->acquisition_type = MDC_ACQUISITION_DYNAMIC; }else{ fi->acquisition_type = MDC_ACQUISITION_TOMO; } } fi->endian = MDC_FILE_ENDIAN = MDC_HOST_ENDIAN; msg=MdcImagesPixelFiddle(fi); } MdcFree(input->inrs); if (msg != NULL) return(msg); return(NULL); }