diff --git a/Utilities/ipSegmentation/ipSegmentationClear.c b/Utilities/ipSegmentation/ipSegmentationClear.c index 148822b81b..1a85501250 100644 --- a/Utilities/ipSegmentation/ipSegmentationClear.c +++ b/Utilities/ipSegmentation/ipSegmentationClear.c @@ -1,81 +1,80 @@ -/*========================================================================= - -Program: Medical Imaging & Interaction Toolkit -Language: C++ -Date: $Date$ -Version: $Revision$ - -Copyright (c) German Cancer Research Center, Division of Medical and -Biological Informatics. All rights reserved. -See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. - -This software is distributed WITHOUT ANY WARRANTY; without even -the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include #include "empty.xpm" #include "ipSegmentationP.h" void ipMITKSegmentationClear (mitkIpPicDescriptor* segmentation) { ipMITKSegmentationTYPE *cur, *last; mitkIpPicTSV_t* tag; const char *src; mitkIpUInt1_t *dst; mitkIpUInt4_t i, j; assert (segmentation); if (ipMITKSegmentationUndoIsEnabled (segmentation)) { ipMITKSegmentationUndoSave (segmentation); } /* clear the image data */ cur = (ipMITKSegmentationTYPE *) segmentation->data; last = cur + _mitkIpPicElements (segmentation); while (cur < last) { *cur++ = 0; } /* create an 'empty' tag */ tag = mitkIpPicQueryTag (segmentation, tagSEGMENTATION_EMPTY); if (!tag) { tag = (mitkIpPicTSV_t *) malloc (sizeof (mitkIpPicTSV_t)); strcpy (tag->tag, tagSEGMENTATION_EMPTY); tag->type = mitkIpPicBool; tag->bpe = sizeof (mitkIpBool_t) / 8; tag->dim = 1; tag->n[0] = 1; tag->value = malloc (sizeof (mitkIpBool_t)); *((mitkIpBool_t *) tag->value) = mitkIpTrue; mitkIpPicAddTag (segmentation, tag); } /* create an `empty` icon */ tag = mitkIpPicQueryTag (segmentation, "ICON80x80"); if (!tag) { tag = (mitkIpPicTSV_t *) malloc (sizeof (mitkIpPicTSV_t)); tag->type = mitkIpPicUInt; tag->bpe = 8; tag->dim = 2; tag->n[0] = 80; tag->n[1] = 80; tag->value = malloc (tag->n[0] * tag->n[1] * sizeof (mitkIpUInt1_t)); strcpy (tag->tag, "ICON80x80"); mitkIpPicAddTag (segmentation, tag); } dst = (mitkIpUInt1_t *) tag->value; for (i = 0; i < 80; i++) { src = empty_xpm [3+i]; for (j = 0; j < 80; j++) { *dst = (*src == '.' ? 0 : 196); src++; dst++; } } } diff --git a/Utilities/ipSegmentation/ipSegmentationError.c b/Utilities/ipSegmentation/ipSegmentationError.c index 5592c8186b..4c2309b4ba 100644 --- a/Utilities/ipSegmentation/ipSegmentationError.c +++ b/Utilities/ipSegmentation/ipSegmentationError.c @@ -1,58 +1,57 @@ -/*========================================================================= - -Program: Medical Imaging & Interaction Toolkit -Language: C++ -Date: $Date$ -Version: $Revision$ - -Copyright (c) German Cancer Research Center, Division of Medical and -Biological Informatics. All rights reserved. -See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. - -This software is distributed WITHOUT ANY WARRANTY; without even -the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include #include "ipSegmentationP.h" static const char* messages [] = { "ok.", "sorry, out of memory.", "sorry, wrong data type of segmentation image.", "sorry, undo is disabled.", "sorry, PIC descriptor is null.", "sorry, unknown error occurred." }; void ipMITKSegmentationError (int error) { switch (error) { case ipMITKSegmentationOK: case ipMITKSegmentationOUT_OF_MEMORY: case ipMITKSegmentationWRONG_TYPE: case ipMITKSegmentationUNDO_DISABLED: printf ("ipMITKSegmentation: %s\n", messages [error]); break; default: printf ("ipMITKSegmentation: %s\n", messages [ipMITKSegmentationUNKNOWN_ERROR]); break; } if (error > 0) { exit (-1); } } void ipMITKSegmentationCheckImage (mitkIpPicDescriptor* segmentation) { if ((segmentation->type != ipMITKSegmentationTYPE_ID) || (segmentation->bpe != ipMITKSegmentationBPE)) { ipMITKSegmentationError (ipMITKSegmentationWRONG_TYPE); } if (!segmentation->data) { ipMITKSegmentationError (ipMITKSegmentationUNKNOWN_ERROR); } } diff --git a/Utilities/ipSegmentation/ipSegmentationFree.c b/Utilities/ipSegmentation/ipSegmentationFree.c index e8183c3b98..da3c74f992 100644 --- a/Utilities/ipSegmentation/ipSegmentationFree.c +++ b/Utilities/ipSegmentation/ipSegmentationFree.c @@ -1,27 +1,26 @@ -/*========================================================================= - -Program: Medical Imaging & Interaction Toolkit -Language: C++ -Date: $Date$ -Version: $Revision$ - -Copyright (c) German Cancer Research Center, Division of Medical and -Biological Informatics. All rights reserved. -See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. - -This software is distributed WITHOUT ANY WARRANTY; without even -the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include void ipMITKSegmentationFree (mitkIpPicDescriptor* segmentation) { if (!segmentation) return; mitkIpPicFree (segmentation); } diff --git a/Utilities/ipSegmentation/ipSegmentationInterpolate.c b/Utilities/ipSegmentation/ipSegmentationInterpolate.c index 4ad6ba2bef..a45534d683 100644 --- a/Utilities/ipSegmentation/ipSegmentationInterpolate.c +++ b/Utilities/ipSegmentation/ipSegmentationInterpolate.c @@ -1,324 +1,323 @@ -/*========================================================================= - -Program: Medical Imaging & Interaction Toolkit -Language: C++ -Date: $Date$ -Version: $Revision$ - -Copyright (c) German Cancer Research Center, Division of Medical and -Biological Informatics. All rights reserved. -See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. - -This software is distributed WITHOUT ANY WARRANTY; without even -the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include #include #include #include "ipSegmentationP.h" /*! The algorithm implements the shape-based interpolation technique. Further detailed information can be found in: G.T. Herman, J. Zheng, C.A. Bucholtz: "Shape-based interpolation" IEEE Computer Graphics & Applications, pp. 69-79,May 1992 */ #define MAX 2048 extern float truncf (float x); static mitkIpPicDescriptor* setup (mitkIpPicDescriptor* pic_old); static mitkIpInt2_t distance (const mitkIpInt2_t* const old_distance, const mitkIpInt2_t* mask_dist, const mitkIpInt2_t* mask_offset, const mitkIpUInt4_t mask_elements); // DON'T ever touch this code again - rather rewrite it! Then use ITK or some other library! // Works ONLY with 2D images. mitkIpPicDescriptor* ipMITKSegmentationPadBy1Pixel (mitkIpPicDescriptor* pic_in) { //prepare the images mitkIpPicDescriptor* pic_out; ipMITKSegmentationTYPE* out_pixel_pointer; ipMITKSegmentationTYPE* in_pixel_pointer; unsigned int x, y; pic_out = mitkIpPicCopyHeader(pic_in, NULL); if (pic_out == NULL) { ipMITKSegmentationError (ipMITKSegmentationPIC_NULL); } if ((pic_out->type != ipMITKSegmentationTYPE_ID) || (pic_out->bpe != ipMITKSegmentationBPE)) { ipMITKSegmentationError (ipMITKSegmentationWRONG_TYPE); } // pad by 1 pixel pic_out->n[0] += 4; pic_out->n[1] += 4; // allocate image data pic_out->data = malloc ( pic_out->n[0] * pic_out->n[1] * ((pic_out->bpe)/8) ); // copy pixel data out_pixel_pointer = (ipMITKSegmentationTYPE*) (pic_out->data); in_pixel_pointer = (ipMITKSegmentationTYPE*) (pic_in->data); for (y = 0; y < pic_out->n[1]; ++y) for (x = 0; x < pic_out->n[0]; ++x) { if ( x < 2 || y < 2 || (x > pic_out->n[0]-3) || (y > pic_out->n[1]-3) ) // set border pixels to 0 { *out_pixel_pointer = 0; } else { *out_pixel_pointer = *in_pixel_pointer; ++in_pixel_pointer; } ++out_pixel_pointer; } return pic_out; } // Works ONLY with 2D images. mitkIpPicDescriptor* ipMITKSegmentationShrinkBy1Pixel (mitkIpPicDescriptor* pic_in ) { mitkIpPicDescriptor* pic_out; ipMITKSegmentationTYPE* out_pixel_pointer; ipMITKSegmentationTYPE* in_pixel_pointer; unsigned int x, y; //prepare the images pic_out = mitkIpPicCopyHeader(pic_in, NULL); if (pic_out == NULL) { ipMITKSegmentationError (ipMITKSegmentationPIC_NULL); } if ((pic_out->type != ipMITKSegmentationTYPE_ID) || (pic_out->bpe != ipMITKSegmentationBPE)) { ipMITKSegmentationError (ipMITKSegmentationWRONG_TYPE); } // pad by 1 pixel pic_out->n[0] -= 4; pic_out->n[1] -= 4; // allocate image data pic_out->data = malloc ( pic_out->n[0] * pic_out->n[1] * (pic_out->bpe/8) ); // copy pixel data out_pixel_pointer = pic_out->data; in_pixel_pointer = pic_in->data; for (y = 0; y < pic_in->n[1]; ++y) for (x = 0; x < pic_in->n[0]; ++x) { if ( x < 2 || y < 2 || (x > pic_in->n[0]-3) || (y > pic_in->n[1]-3) ) // ignore border pixels { } else { *out_pixel_pointer = *in_pixel_pointer; ++out_pixel_pointer; } ++in_pixel_pointer; } return pic_out; } mitkIpPicDescriptor* ipMITKSegmentationInterpolate (mitkIpPicDescriptor* pPic1, mitkIpPicDescriptor* pPic2, const mitkIpFloat4_t ratio) { mitkIpPicDescriptor *pic_out, *pic[2]; /* pointer to image data */ mitkIpUInt4_t frame [_mitkIpPicNDIM]; /* pointer for definition of frame-size */ mitkIpInt4_t x, y; mitkIpUInt4_t i; /* loop counters */ mitkIpFloat4_t weight[] = {1.0f-ratio, ratio}; /* weights of the interpolants */ mitkIpInt2_t mask_width = 1; /* mask width from center to border */ mitkIpInt2_t mask_x[] = {0, -1, +1, 0, -1}; /* relativ position in x-axis of mask */ mitkIpInt2_t mask_y[] = {0, 0, -1, -1, -1}; /* relativ position in y-axis of mask */ mitkIpInt2_t mask_dist[] = {0, 10, 14, 10, 14};/* distance to central element */ mitkIpInt2_t mask_offset [5]; /* relative start position in given image */ mitkIpUInt4_t mask_elements = 5; /* elements in distance mask */ mitkIpInt2_t first_x, first_y; /* first pixel for distance calculation in enlarged image version */ mitkIpInt2_t last_x, last_y; /* last pixel for distance calculation in enlarged image version */ mitkIpInt2_t *pixel[2]; /* pointer to the current pixels */ ipMITKSegmentationTYPE* pixel_out; mitkIpPicDescriptor* returnImage; mitkIpPicDescriptor* pic1 = ipMITKSegmentationPadBy1Pixel( pPic1 ); mitkIpPicDescriptor* pic2 = ipMITKSegmentationPadBy1Pixel( pPic2 ); /* prepare the images */ pic_out = mitkIpPicCopyHeader(pic1, NULL); if (pic_out == NULL) { ipMITKSegmentationError (ipMITKSegmentationPIC_NULL); } if ((pic_out->type != ipMITKSegmentationTYPE_ID) || (pic_out->bpe != ipMITKSegmentationBPE)) { ipMITKSegmentationError (ipMITKSegmentationWRONG_TYPE); } pic_out->data = malloc (_mitkIpPicSize (pic_out)); for (i = 0; i < pic1->dim; i++) { frame [i] = 1; } pic[0] = setup (pic1); pic[1] = setup (pic2); /* apply the mask in both directions */ for (i=0; i< mask_elements; i++) { mask_offset [i] = mask_x[i] + mask_y[i]*pic[0]->n[0]; } first_x = mask_width; first_y = mask_width; last_x = pic[0]->n[0] - mask_width-1; last_y = pic[0]->n[1] - mask_width-1; /* top-left to bottom-right, borders are neglected */ for (y = first_y; y <= last_y; y++) { pixel [0] = (mitkIpInt2_t *) pic [0]->data + (first_x + y * pic [0]->n [0]); pixel [1] = (mitkIpInt2_t *) pic [1]->data + (first_x + y * pic [1]->n [0]); for (x = first_x; x <= last_x; x++) { *(pixel [0])++ = distance (pixel [0], mask_dist, mask_offset, mask_elements); *(pixel [1])++ = distance (pixel [1], mask_dist, mask_offset, mask_elements); } } /* bottom-right to top-left, borders are neglected */ for (i=0; i< mask_elements; i++) { mask_offset [i] = -mask_offset [i]; } pixel_out = (ipMITKSegmentationTYPE *) pic_out->data + _mitkIpPicElements(pic_out) - 1; for (y = last_y; y >= first_y; y--) { pixel [0] = (mitkIpInt2_t *) pic [0]->data + (last_x + y * pic [0]->n [0]); pixel [1] = (mitkIpInt2_t *) pic [1]->data + (last_x + y * pic [1]->n [0]); for (x = last_x; x >= first_x; x--) { *(pixel [0]) = distance (pixel [0], mask_dist, mask_offset, mask_elements); *(pixel [1]) = distance (pixel [1], mask_dist, mask_offset, mask_elements); *pixel_out-- = (weight [0] * *(pixel [0]) + weight [1] * *(pixel[1]) > 0 ? 1 : 0); pixel[0]--; pixel[1]--; } } mitkIpPicFree(pic [0]); mitkIpPicFree(pic [1]); mitkIpPicFree(pic1); mitkIpPicFree(pic2); returnImage = ipMITKSegmentationShrinkBy1Pixel( pic_out ); mitkIpPicFree(pic_out); return returnImage; } static mitkIpPicDescriptor* setup (mitkIpPicDescriptor* pic_old) { mitkIpPicDescriptor* pic; ipMITKSegmentationTYPE* src; mitkIpInt2_t* dst; mitkIpUInt4_t x, y; /* Allocate new image for distance transform */ pic = mitkIpPicCopyHeader (pic_old, NULL); pic->type = mitkIpPicInt; pic->bpe = 16; pic->n[0] += 2; pic->n[1] += 2; pic->data = malloc (_mitkIpPicSize (pic)); /* Set the frame to -1 */ dst = (mitkIpInt2_t *) pic->data; for (x = 0; x < pic->n[0]; x++) { *dst++ = -MAX; } dst = (mitkIpInt2_t *) pic->data + _mitkIpPicElements (pic) - pic->n[0]; for (x = 0; x < pic->n[0]; x++) { *dst++ = -MAX; } dst = (mitkIpInt2_t *) pic->data; for (y = 0; y < pic->n[1]; y++) { *dst = -MAX; dst += pic->n[0]; } dst = (mitkIpInt2_t *) pic->data + (pic->n[0] - 1); for (y = 0; y < pic->n[1]; y++) { *dst = -MAX; dst += pic->n[0]; } /* Set the image data to initial values */ src = (ipMITKSegmentationTYPE *) pic_old->data; dst = (mitkIpInt2_t *) pic->data + (1 + pic->n[0]); for (y = 0; y < pic_old->n[1]; y++) { for (x = 0; x < pic_old->n[0]; x++) { *dst++ = (*src++ > 0 ? MAX : -MAX); } dst += 2; } dst = (mitkIpInt2_t *) pic->data + (1 + pic->n[0]); for (y = 0; y < pic_old->n[1]; y++) { for (x = 0; x < pic_old->n[0]; x++) { if ((dst[0] < dst[1]) || (dst[0] < dst[pic->n[0]])) { *dst = -5; } else if ((dst[0] > dst[1]) || (dst[0] > dst[pic->n[0]])) { *dst = 5; } dst++; } dst += 2; } dst -= 2; for (y = 0; y < pic_old->n[1]; y++) { for (x = 0; x < pic_old->n[0]; x++) { dst--; if (abs (dst[0]) > 5) { if ((dst[0] < dst[-1]) || (dst[0] < dst[-(int)(pic->n[0])])) { *dst = -5; } else if ((dst[0] > dst[-1]) || (dst[0] > dst[-(int)(pic->n[0])])) { *dst = 5; } } } } return pic; } static mitkIpInt2_t distance (const mitkIpInt2_t* const old_distance, const mitkIpInt2_t* mask_dist, const mitkIpInt2_t* mask_offset, const mitkIpUInt4_t mask_elements) { mitkIpInt2_t cur_distance, new_distance; mitkIpUInt4_t i; cur_distance = old_distance [0]; if (abs (cur_distance) != 5) { if (cur_distance > 0) { for (i = 0; i < mask_elements; i++) { new_distance = *mask_dist + old_distance [*mask_offset]; if (new_distance < cur_distance) { cur_distance = new_distance; } mask_dist++; mask_offset++; } } else if (cur_distance < 0) { for (i = 0; i < mask_elements; i++) { new_distance = old_distance [*mask_offset] - *mask_dist; if (new_distance > cur_distance) { cur_distance = new_distance; } mask_dist++; mask_offset++; } } } return cur_distance; } diff --git a/Utilities/ipSegmentation/ipSegmentationNew.c b/Utilities/ipSegmentation/ipSegmentationNew.c index b9b5bead5d..23d84ad7c0 100644 --- a/Utilities/ipSegmentation/ipSegmentationNew.c +++ b/Utilities/ipSegmentation/ipSegmentationNew.c @@ -1,35 +1,34 @@ -/*========================================================================= - -Program: Medical Imaging & Interaction Toolkit -Language: C++ -Date: $Date$ -Version: $Revision$ - -Copyright (c) German Cancer Research Center, Division of Medical and -Biological Informatics. All rights reserved. -See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. - -This software is distributed WITHOUT ANY WARRANTY; without even -the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "ipSegmentationP.h" mitkIpPicDescriptor* ipMITKSegmentationNew (mitkIpPicDescriptor* image) { mitkIpPicDescriptor* s = NULL; if (image) { s = mitkIpPicNew (); s->type = ipMITKSegmentationTYPE_ID; s->bpe = ipMITKSegmentationBPE; s->dim = 2; s->n[0] = image->n[0]; s->n[1] = image->n[1]; s->data = malloc (_mitkIpPicSize (s)); } return s; } diff --git a/Utilities/ipSegmentation/ipSegmentationUndo.c b/Utilities/ipSegmentation/ipSegmentationUndo.c index 56594c44b8..3f72bb1604 100644 --- a/Utilities/ipSegmentation/ipSegmentationUndo.c +++ b/Utilities/ipSegmentation/ipSegmentationUndo.c @@ -1,245 +1,244 @@ -/*========================================================================= - -Program: Medical Imaging & Interaction Toolkit -Language: C++ -Date: $Date$ -Version: $Revision$ - -Copyright (c) German Cancer Research Center, Division of Medical and -Biological Informatics. All rights reserved. -See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. - -This software is distributed WITHOUT ANY WARRANTY; without even -the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include #include #include "ipSegmentationP.h" static char* tagUNDO = "SEGMENTATION_UNDO"; static char* tagUNDO_DATA = "DATA"; static char* tagUNDO_LEVEL = "LEVEL"; // Implemented in mitkIpPicDelT.c static mitkIpPicTSV_t *_mitkIpPicRemoveTag( _mitkIpPicTagsElement_t **head, _mitkIpPicTagsElement_t *which, char *tag ); void ipMITKSegmentationUndoEnable (mitkIpPicDescriptor* segmentation, const mitkIpUInt1_t level) { mitkIpPicTSV_t *undo, *data, *max; assert (segmentation); undo = mitkIpPicQueryTag (segmentation, tagUNDO); if (!undo) { undo = (mitkIpPicTSV_t *) malloc (sizeof (mitkIpPicTSV_t)); if (!undo) { ipMITKSegmentationError (ipMITKSegmentationOUT_OF_MEMORY); } strcpy (undo->tag, tagUNDO); undo->type = mitkIpPicTSV; undo->bpe = 32; undo->dim = 1; undo->n[0] = 0; undo->value = NULL; mitkIpPicAddTag (segmentation, undo); } data = mitkIpPicQuerySubTag (undo, tagUNDO_DATA); if (!data) { data = (mitkIpPicTSV_t *) malloc (sizeof (mitkIpPicTSV_t)); if (!data) { ipMITKSegmentationError (ipMITKSegmentationOUT_OF_MEMORY); } strcpy (data->tag, tagUNDO_DATA); data->type = mitkIpPicTSV; data->bpe = 32; data->dim = 1; data->n[0] = 0; data->value = NULL; mitkIpPicAddSubTag (undo, data); } if (data->n[0] > level) { /* remove levels which exceed the maximum */ mitkIpUInt1_t i; for (i = data->n[0] - level; i > 0; i--) { _mitkIpPicTagsElement_t *head = (_mitkIpPicTagsElement_t *) data->value; mitkIpPicTSV_t* tag = _mitkIpPicRemoveTag (&head, head, head->tsv->tag); data->value = head; data->n[0]--; mitkIpPicFreeTag (tag); } } max = mitkIpPicQuerySubTag (undo, tagUNDO_LEVEL); if (max) { /* change the maximum of levels */ mitkIpUInt1_t* value = (mitkIpUInt1_t *) max->value; *value = level; } else { mitkIpUInt1_t* value = (mitkIpUInt1_t *) malloc (sizeof (mitkIpUInt1_t)); if (!value) { ipMITKSegmentationError (ipMITKSegmentationOUT_OF_MEMORY); } *value = level; max = (mitkIpPicTSV_t *) malloc (sizeof (mitkIpPicTSV_t)); if (!max) { ipMITKSegmentationError (ipMITKSegmentationOUT_OF_MEMORY); } strcpy (max->tag, tagUNDO_LEVEL); max->type = mitkIpPicUInt; max->bpe = 8; max->dim = 1; max->n[0] = 1; max->value = value; mitkIpPicAddSubTag (undo, max); } } void ipMITKSegmentationUndoDisable (mitkIpPicDescriptor* segmentation) { mitkIpPicTSV_t *undo; assert (segmentation); undo = mitkIpPicDelTag (segmentation, tagUNDO); mitkIpPicFreeTag (undo); } mitkIpBool_t ipMITKSegmentationUndoIsEnabled (mitkIpPicDescriptor* segmentation) { mitkIpPicTSV_t *undo = NULL; if (segmentation) { undo = mitkIpPicQueryTag (segmentation, tagUNDO); } return (undo ? mitkIpTrue : mitkIpFalse); } void ipMITKSegmentationUndoSave (mitkIpPicDescriptor* segmentation) { mitkIpPicTSV_t *undo, *data, *level, *tag; assert (segmentation); undo = mitkIpPicQueryTag (segmentation, tagUNDO); if (!undo) { ipMITKSegmentationError (ipMITKSegmentationUNDO_DISABLED); } /* if no level is available ... */ data = mitkIpPicQuerySubTag (undo, tagUNDO_DATA); level = mitkIpPicQuerySubTag (undo, tagUNDO_LEVEL); if (*((mitkIpUInt1_t *) level->value) > 0) { if (data->n[0] == *((mitkIpUInt1_t *) level->value)) { /* ... remove the first one. */ _mitkIpPicTagsElement_t* head = (_mitkIpPicTagsElement_t *) data->value; mitkIpPicTSV_t* tag = _mitkIpPicRemoveTag (&head, head, head->tsv->tag); data->value = head; data->n[0]--; mitkIpPicFreeTag (tag); } /* build and store the level */ tag = (mitkIpPicTSV_t *) malloc (sizeof (mitkIpPicTSV_t)); if (!tag) { ipMITKSegmentationError (ipMITKSegmentationOUT_OF_MEMORY); } strcpy (tag->tag, "IMAGE"); tag->type = segmentation->type; tag->bpe = segmentation->bpe; tag->dim = segmentation->dim; tag->n[0] = segmentation->n[0]; tag->n[1] = segmentation->n[1]; tag->value = malloc (_mitkIpPicSize (segmentation)); memmove (tag->value, segmentation->data, _mitkIpPicSize (segmentation)); mitkIpPicAddSubTag (data, tag); } } void ipMITKSegmentationUndo (mitkIpPicDescriptor* segmentation) { mitkIpPicTSV_t *undo, *data; assert (segmentation); undo = mitkIpPicQueryTag (segmentation, tagUNDO); if (!undo) { ipMITKSegmentationError (ipMITKSegmentationUNDO_DISABLED); } /* if any level is stored ... */ data = mitkIpPicQuerySubTag (undo, tagUNDO_DATA); if (data->n[0]) { /* ... replace the image data and remove this level */ _mitkIpPicTagsElement_t* head = (_mitkIpPicTagsElement_t *) data->value; _mitkIpPicTagsElement_t* current = head; mitkIpPicTSV_t* tag; while( current->next != NULL ) { current = current->next; } tag = _mitkIpPicRemoveTag (&head, current, current->tsv->tag); data->value = head; data->n[0]--; memmove (segmentation->data, tag->value, _mitkIpPicSize (segmentation)); mitkIpPicFreeTag (tag); tag = mitkIpPicDelTag (segmentation, tagSEGMENTATION_EMPTY); if (tag) { mitkIpPicFreeTag (tag); } } } mitkIpBool_t ipMITKSegmentationUndoAvailable (mitkIpPicDescriptor* segmentation) { mitkIpPicTSV_t *undo, *data; assert (segmentation); undo = mitkIpPicQueryTag (segmentation, tagUNDO); if (!undo) { ipMITKSegmentationError (ipMITKSegmentationUNDO_DISABLED); } data = mitkIpPicQuerySubTag (undo, tagUNDO_DATA); return (data->n[0] ? mitkIpTrue : mitkIpFalse); } mitkIpPicTSV_t * _mitkIpPicRemoveTag( _mitkIpPicTagsElement_t **head, _mitkIpPicTagsElement_t *which, char *tag) { mitkIpPicTSV_t *tsv = NULL; if( which != NULL ) { tsv = which->tsv; if( which->prev == NULL ) /* which is the current head */ { *head = which->next; if( *head ) (*head)->prev = NULL; } else if( which->next == NULL ) /* which is the current tail */ { which->prev->next = NULL; } else /* which is somewhere if the list */ { which->prev->next = which->next; which->next->prev = which->prev; } free( which ); } return( tsv ); }