/************************************************************************************/ /* * File name: MdispWindowLeveling.c * * Synopsis: This MIL program shows how to display a 10-bit monochrome Medical image * and applies a LUT to do interactive Window Leveling. */ #include #include #include /* Image file to load. */ #define IMAGE_FILE M_IMAGE_PATH MIL_TEXT("ArmsMono10bit.mim") /* Visible number of bits (8, 10, 12... or ImageSizeBit (for full range). */ #define IMAGE_NUMBER_OF_VISIBLE_BITS 10 /* Draw the LUT shape (if disabled reduces CPU usage). */ #define DRAW_LUT_SHAPE M_YES /* Utility functions. */ long MaxImageValue(MIL_ID MilImage, long NumberOfVisibleBits); void DrawLutShape(MIL_ID MilDisplay, MIL_ID MilOriginalImage, MIL_ID MilImage, long Start, long End, long InflexionIntensity, long ImageMaxValue, long DisplayMaxValue); void main(void) { MIL_ID MilApplication, /* Application identifier. */ MilSystem, /* System identifier. */ MilDisplay, /* Display identifier. */ MilImage, /* Image buffer identifier. */ MilOriginalImage = 0, /* Image buffer identifier. */ MilLut; /* Lut buffer identifier. */ long ImageSizeX, ImageSizeY, ImageMaxValue; long DisplaySizeBit, DisplayMaxValue; long Start, End, Step, InflectionLevel; unsigned char Ch; /* Allocate the MIL Application, System and Display. */ MappAllocDefault(M_SETUP, &MilApplication, &MilSystem, &MilDisplay, M_NULL, M_NULL); /* Restore target image from disk. */ MbufRestore(IMAGE_FILE, MilSystem, &MilImage); /* Set the maximum value of the image to indicate to MIL how to initialize the default display LUT. */ ImageMaxValue = MaxImageValue(MilImage, IMAGE_NUMBER_OF_VISIBLE_BITS); MbufControl(MilImage, M_MAX, ImageMaxValue); /* Display the image (to specify a user-defined window, use MdispSelectWindow()). */ MdispSelect(MilDisplay, MilImage); /* Determine the maximum displayable value of the current display. */ MdispInquire(MilDisplay, M_SIZE_BIT, &DisplaySizeBit); DisplayMaxValue = (1< to do interactive Window Leveling.\n\n"); getch(); /* Allocate a LUT buffer according to the image maximum value and display pixel depth. */ MbufAlloc1d(MilSystem, ImageMaxValue+1, ((DisplaySizeBit>8) ? 16 : 8)+M_UNSIGNED, M_LUT, &MilLut); /* Generate a LUT with a full range ramp and set its maximum value. */ MgenLutRamp(MilLut, 0, 0, ImageMaxValue, DisplayMaxValue); MbufControl(MilLut, M_MAX, DisplayMaxValue); /* Set the display LUT. */ MdispLut(MilDisplay, MilLut); /* Interactive Window Leveling using keyboard. */ printf("Position keys : Left=move Left, Right=move Right, Down=Narrow, Up=Wider.\n"); printf("Intensity keys: L=Lower, U=Upper, R=Reset.\n"); printf("Press to end.\n\n"); /* Modify LUT shape according to the arrow keys and update it. */ Ch = 0; Start = 0; End = ImageMaxValue; InflectionLevel = DisplayMaxValue; Step = (ImageMaxValue+1)/128; Step = max(Step,4); while (Ch != '\r') { switch (Ch) { /* Left arrow: Move region left. */ case 0x4B: { Start-=Step; End-=Step; break; } /* Right arrow: Move region right. */ case 0x4D: { Start+=Step; End+=Step; break; } /* Down arrow: Narrow region. */ case 0x50: { Start+=Step; End-=Step; break; } /* Up arrow: Widen region. */ case 0x48: { Start-=Step, End+=Step; break; } /* L key: Lower inflexion point. */ case 'L': case 'l': { InflectionLevel--; break; } /* U key: Upper inflexion point. */ case 'U': case 'u': { InflectionLevel++; break; } /* R key: Reset the LUT to full image range. */ case 'R': case 'r': { Start=0; End=ImageMaxValue; InflectionLevel=DisplayMaxValue; break; } } /* Saturate. */ End = min(End,ImageMaxValue); Start = min(Start,End); End = max(End,Start); Start = max(Start,0); End = max(End,0); InflectionLevel = max(InflectionLevel, 0); InflectionLevel = min(InflectionLevel, DisplayMaxValue); printf("Inflection points: Low=(%ld,0), High=(%ld,%ld). \r", Start, End, InflectionLevel); /* Generate a LUT with 3 slopes and saturated at both ends. */ MgenLutRamp(MilLut, 0, 0, Start, 0); MgenLutRamp(MilLut, Start, 0, End, InflectionLevel); MgenLutRamp(MilLut, End, InflectionLevel, ImageMaxValue, DisplayMaxValue); /* Update the display LUT. */ MdispLut(MilDisplay, MilLut); /* Draw the current LUT's shape in the image. Note: This simple annotation method requires significant update and CPU time. */ if (DRAW_LUT_SHAPE) { if (!MilOriginalImage) MbufRestore(IMAGE_FILE, MilSystem, &MilOriginalImage); DrawLutShape(MilDisplay, MilOriginalImage, MilImage, Start, End, InflectionLevel, ImageMaxValue, DisplayMaxValue); } /* If its an arrow key, get the second code. */ if ((Ch = getch()) == 0xE0) Ch = getch(); } printf("\n\n"); /* Free all allocations. */ MbufFree(MilLut); MbufFree(MilImage); if (MilOriginalImage) MbufFree(MilOriginalImage); MappFreeDefault(MilApplication, MilSystem, MilDisplay, M_NULL, M_NULL); } /* Function to calculate the maximum value of an image. */ long MaxImageValue(MIL_ID MilImage, long NumberOfVisibleBits) { MIL_ID MilExtremeResult = M_NULL; long ImageMaxValue, ImageSizeBit = 0; /* Determine and set the maximum value of the image. */ #if (M_MIL_LITE) { /* Relies on the number of bits of the user-specified image but saturates if necessary. */ MbufInquire(MilImage, M_SIZE_BIT, &ImageSizeBit); NumberOfVisibleBits = min(NumberOfVisibleBits, ImageSizeBit); ImageMaxValue = (1<