INTERNAL/REVIEW: Making Bitmap-Style WIDGET_BUTTONs Cross-Platform
Help Article Update 2
Anonym
[Needs to be reviewed for Compliance and IP issues (i.e. .pro file included)]
WIDGET_BUTTON has an the option of displaying bitmap images in place of labels when its /BITMAP keyword is set. The most common way to capture the bitmap image is by setting WIDGET_BUTTON's VALUE keyword to the path to the .bmp holding the button's image. Unexpectedly, if the bitmap file is storing a 24-bit True Color image, this file argument is handled differently by UNIX/Motif widgets compared to Windows Widgets. This Tech Tip explains the difference, and provides a code workaround that will make WIDGET_BUTTON, /BITMAP calls behave identically cross-platform.
The .bmp standard designed originally for use with Microsoft O.S.'s stores 24-bit True Color bitmap colors in BGR ordering. The WIDGET_BUTTON /BITMAP keyword on Windows anticipates this and displays the colors correctly. Classic Macintosh and UNIX Motif have had a tradition of defaulting to creating and reading bitmap files as RGB color-ordered. IDL for UNIX and Mac thus implemented WIDGET_BUTTON /BITMAP, so that it would read bitmap files on those platforms, as if they were RGB-ordered. That means that IDL widget programs using Windows-generated button bitmaps will, by default, show a Red-Blue reversing of the button image colors, when displayed in an IDL for UNIX or MAC widget program.
The example code below shows how a cross-platform IDL Widget Program can work around this inconsistent behavior. The key to the workaround is that the VALUE keyword of a /BITMAP-style WIDGET_BUTTON can accept either a filepath or an image array. The image array is expected to be RGB-ordered, not BGR-ordered. By reading the Windows-style bitmap into an RGB image (and changing its interleave ordering), the contents of the file can be correctly re-ordered to display properly on a UNIX or Macintosh host.
Note that 8-bit "pseudocolor" bitmaps behave the same cross-platform without any special handling as discussed in this Tech Tip.
The below example code and the requisite bitmap resource file can be downloaded at this link: red_button.tar.gz
; File: red_button.pro
; Syntax: RED_BUTTON
; Purpose: Demonstrate portable code for using a bitmap file created on
; Windows on either MS Windows or X Windows platforms.
; Output: This code creates a widget-base with one single 89 x 61 pixel
; red-colored button. No events are handled.
; Preconditions: The file 'red_color.bmp' must be in the same directory
; as this source code. The bitmap file must have been created on Windows
; with its default BGR color channel ordering.
PRO red_button
tlb = widget_base()
; Find this source code's directory and the critical bitmap file
sourceDirInfo = routine_info('RED_BUTTON', /source)
sourceDir = file_dirname(sourceDirInfo.path)
file = filepath('red_color.bmp', root=sourceDir)
; Check if the Bitmap is 8-bit or 24-bit color
void = query_bmp(file, info)
; Case of bitmap file is 8-bit or the host is Windows. In this case
; WIDGET_BUTTON can take the file as its VALUE argument.
if info.channels eq 1 $ ; 8-bit works the same on UNIX and WIN...
or !version.os_family eq 'Windows' $ ; and WIN needs no special handling
then begin
my_bitmap = file
endif $
; Case of Bitmap is a True-Color Windows-formatted file. In this case
; the bitmap file needs to be opened as an image and be "massaged"
; before its data is passed to WIDGET_BUTTON
else begin
unix_bitmap = read_bmp(file, /rgb) ; reads in RGB ordering
; READ_BMP returns a width x height x color_channel array.
; WIDGET_BUTTON needs a color_channel x width x height array.
my_bitmap = transpose(unix_bitmap,[1,2,0])
endelse
button = widget_button(tlb, /bitmap, value=my_bitmap)
widget_control, tlb, /realize
END