Certain members in the BITMAPHANDLE structure mentioned below are intended for internal use, including pLUT
/pLUT16
, PaintHighBit
and PaintLowBit
.
These members are used when window-leveling. More information can be found in the LTKRN.H header file, which describes the entire structure.
12-/16-bit bitmaps can use a lookup table (LUT) for displaying images or performing image processing. However, using LUT is optional (it can be NULL). If the LUT is not NULL, it can be used for 'displaying' or for 'displaying and performing image processing'. The LUT data is created by window-leveling (L_ApplyLinearVOILUT, L_WindowLevel) or by loading a DICOM or TIFF file with window-leveling information.
There are 3 cases:
The LUT data is stored in the BITMAPHANDLE using the following fields:
Pointer to an array of L_RGBQUAD
values containing the corresponding color for each LUT entry. Usually, the L_RGBQUAD
entries contain grayscale colors.
But sometimes, the L_RGBQUAD
entries contain non-grayscale colors. The number of entries is determined by Flags.UseLUT
, LowBit
, HighBit
, PaintLowBit
and PaintHighBit
entries in the BITMAPHANDLE structure.
If pLUT
is NULL and pLUT16
is NULL, then there is no LUT (case '1' above).
Just like pLUT
, except that the array contains L_RGBQUAD16
values and each color value is 16-bit. 16-bit values provide extra precision compared to 8-bit values.
If TRUE, the LUT data is used for displaying and performing image processing (case '3' above). In this case, the number of LUT entries is determined by LowBit
and HighBit
:
LUT Length = 1 << (HighBit – LowBit + 1)
If FALSE, the LUT is used only for display. In this case, the number of LUT entries is determined by PaintLowBit
and PaintHighBit
:
LUT Length = 1 << (PaintHighBit – PaintLowBit + 1)
pLUT
and pLUT16
are synchronized (that is, they contain the same information). If pLUT == NULL
and pLUT16 != NULL
, then there is a LUT. Conversely, if pLUT != NULL
and pLUT16 == NULL
, there is a LUT.
If pLUT != NULL
and pLUT16 != NULL
, there is a LUT and both arrays will point to the same colors and have the same length.
PaintLowBit/PaintHighBit
can be different from LowBit/HighBit
, but usually they are the same.
Here are the 3 cases again:
pLUT == NULL
pLUT != NULL
and Flags.UseLUT == FALSE
(or 0)pLUT != NULL
and Flags.UseLUT == TRUE
(or 1)In cases '1' and '2', image processing will be performed on image data.
In case '3', image processing is performed and there is a LUT. The image can look completely different after image processing, so it is best to regenerate the LUT data to make sure you see all the details in the new bitmap. Regenerate the LUT by doing something like this:
L_GetMinMaxVal(pBitmap, MinVal, MaxVal);
L_ApplyLinearVOILUT(pBitmap, (MinVal + MaxVal / 2), (MaxVal – MinVal) / 2, 0);
In case '3', the image processing would typically take the LUT colors into account.
There are several types of image processing functions and the output will vary, producing one of these results:
Image processing does not change the size, and the output of each pixel depends only on the color of the original pixel (for example, when inverting the colors or changing the brightness). In this case, image processing will be performed on the LUT colors only and the data will be unchanged.
Image processing changes the size of the image. In this case, image processing is performed on the image data and the LUT entries are taken into account, if appropriate.
Flags.UseLUT
to FALSE before the image processing operation,
then they may restore it after. Users who are interested in the image processing function and applying it on an image as they see it in the viewer with LUT, they need to convert their 12- or
16-bit grayscale image to an 8-bit grayscale or a 24-bit RGB bitmap using L_WindowLevelBitmap
, then perform image processing on the converted image.
In some instances image processing performs well when using LUT, while in other cases it is better if the LUT is ignored. You can choose whichever mode is more appropriate for your application. Here is how you can get to each mode:
L_WindowLevel(pBitmap, pBitmap->LowBit, pBitmap->HighBit, NULL, 0, WINDOWLEVEL_PAINT)
(pBitmap, lowbit, highbit, pLUT, LUTLength, WINDOWLEVEL_PAINT)
(…, WINDOWLEVEL_PAINT_AND_PROCESSING)
or L_ApplyLinearVOILUT.You can also switch between '2' and '3' by switching the pBitmap->Flags.UseLUT
flag between 0 and 1. But when doing so, make sure PaintLowBit == LowBit
and PaintHighBit == HighBit
.
The above L_WindowLevel calls can also be replaced with L_WindowLevelExt function calls in order to use 16-bit entries for the LUT.
Help Collections
Raster .NET | C API | C++ Class Library | HTML5 JavaScript
Document .NET | C API | C++ Class Library | HTML5 JavaScript
Medical .NET | C API | C++ Class Library | HTML5 JavaScript
Medical Web Viewer .NET
Multimedia
Direct Show .NET | C API | Filters
Media Foundation .NET | C API | Transforms
Supported Platforms
.NET, Java, Android, and iOS/macOS Assemblies
Imaging, Medical, and Document
C API/C++ Class Libraries
Imaging, Medical, and Document
HTML5 JavaScript Libraries
Imaging, Medical, and Document