Re: XForms: Creating Pixmaps on the fly

Steve Lamont (spl@szechuan.ucsd.edu)
Tue, 23 Jun 98 11:07:03 PDT

# To subscribers of the xforms list from spl@szechuan.ucsd.edu (Steve Lamont) :

> ... I think If I read the data
> into a pixmap first, and then show the pixmap I can keep track
> of the pixels that the plane is over and redraw them, and also
> have a scrollable view area. ...

Creating a Pixmap is somewhat involved -- especially if you can't know
in advance what sort of Visual class in which your application will
run. You'll at least have to be able to handle TrueColor and
PseudoColor visuals.

The following code generates a Pixmap in TrueColor -- it's extracted
from a specific application, so there are a few splisms but they shold
be pretty obvious:

static Pixmap convert_truecolor( HdumlP hduml_ptr, ImageP image_ptr )

{

Pixmap pixmap = 0;
int width = __get_image_width( image_ptr );
int height = __get_image_height( image_ptr );
FL_STATE *forms_state = &fl_state[fl_get_vclass()];
XImage *ximage;
unsigned char ***rgb = __get_image_rgb( image_ptr );
int pixel_bytes;
int scanline_pad;
int scanline_bytes;
unsigned char *image_data;
int i;
int j;
int red_bits;
int red_shift;
int green_bits;
int green_shift;
int blue_bits;
int blue_shift;

match_pixmap_to_visual( width,
&pixel_bytes, &scanline_pad, &scanline_bytes );

find_shift_bits( forms_state->xvinfo->red_mask,
&red_shift, &red_bits );
find_shift_bits( forms_state->xvinfo->green_mask,
&green_shift, &green_bits );
find_shift_bits( forms_state->xvinfo->blue_mask,
&blue_shift, &blue_bits );

image_data = ( unsigned char *) alloca( scanline_bytes * height );

ximage = XCreateImage( fl_get_display(),
forms_state->xvinfo->visual,
forms_state->depth,
ZPixmap,
0,
image_data,
width,
height,
scanline_pad,
0 );

if ( ximage ) {

Colormap colormap = forms_state->colormap;

memset( image_data, 0, scanline_bytes * height );

for ( j = 0; j < height; j++ )
for ( i = 0; i < width; i++ ) {

register unsigned long pixel =
S_RED( rgb, i, j, red_shift, red_bits ) |
S_GREEN( rgb, i, j, green_shift, green_bits ) |
S_BLUE( rgb, i, j, blue_shift, blue_bits );

XPutPixel( ximage, i, j, pixel );

}

pixmap = XCreatePixmap( fl_get_display(),
forms_state->trailblazer,
width,
height,
forms_state->depth );
XSetFunction( fl_get_display(),
forms_state->gc[8],
GXcopy );
XPutImage( fl_get_display(),
pixmap,
forms_state->gc[8],
ximage,
0, 0,
0, 0,
width, height );

ximage->data = NULL;
XDestroyImage( ximage );

}

return pixmap;

}

static void find_shift_bits( unsigned long mask,
int *shift_ptr,
int *bits_ptr )

{

int shift = 0;
int bits = 0;

while ( !( 0x01 & ( mask >> shift ) ) )
shift++;
*shift_ptr = shift;

while ( 0x01 & ( mask >> ( shift + bits ) ) )
bits++;
*bits_ptr = bits;

}

static void match_pixmap_to_visual( int width,
int *pixel_bytes_ptr,
int *scanline_pad_ptr,
int *scanline_bytes_ptr )

{

FL_STATE *forms_state = &fl_state[fl_get_vclass()];
int n_format_values;
XPixmapFormatValues *format_values =
XListPixmapFormats( fl_get_display(), &n_format_values );
int fmt;
int scanline_quantum;

for ( fmt = 0; fmt < n_format_values; fmt++ )
if ( format_values[fmt].depth == forms_state->depth )
break;

scanline_quantum =
( *scanline_pad_ptr = format_values[fmt].scanline_pad ) / CHAR_BIT;

*pixel_bytes_ptr = format_values[fmt].bits_per_pixel / CHAR_BIT;
*scanline_bytes_ptr =
( ( ( width * *pixel_bytes_ptr ) + ( scanline_quantum - 1 ) ) /
scanline_quantum ) * scanline_quantum;

XFree( format_values );

}

and the code below handles PseudoColor Visual classes. It's a little
more involved since the RGB image must be quantized and a lookup table
created to convert between RGB pixels and the Colormap indices. (I've
written a library (libquantize) for myself which does octree
quantization as outline in one of the _Graphics Gems_ series. That's
what all the Quantize business is.)

static Pixmap convert_pseudocolor( HdumlP hduml_ptr, ImageP image_ptr )

{

Pixmap pixmap = 0;
int width = __get_image_width( image_ptr );
int height = __get_image_height( image_ptr );
FL_STATE *forms_state = &fl_state[fl_get_vclass()];
int scanline_pad;
int pixel_bytes;
int scanline_bytes;
unsigned char *image;
XImage *ximage;

match_pixmap_to_visual( width,
&pixel_bytes, &scanline_pad, &scanline_bytes );

image = ( unsigned char *) alloca( scanline_bytes * height );

ximage = XCreateImage( fl_get_display(),
forms_state->xvinfo->visual,
forms_state->depth,
ZPixmap,
0,
image,
width,
height,
scanline_pad,
0 );
if ( ximage ) {

register QuantizeDatabaseP quantize_database_ptr =
__get_hduml_quantize_database( hduml_ptr );
register unsigned long *color_cross_index =
__get_hduml_color_cross_index( hduml_ptr );
unsigned char ***rgb = __get_image_rgb( image_ptr );
register int i;
register int j;
Colormap colormap = forms_state->colormap;

for ( j = 0; j < height; j++ )
for ( i = 0; i < width; i++ ) {

register unsigned long index =
QuantizeFindIndex( quantize_database_ptr,
I_RED( rgb, i, j ),
I_GREEN( rgb, i, j ),
I_BLUE( rgb, i, j ) );

XPutPixel( ximage, i, j, color_cross_index[index] );

}

pixmap = XCreatePixmap( fl_get_display(),
forms_state->trailblazer,
width,
height,
forms_state->depth );
XSetFunction( fl_get_display(),
forms_state->gc[8],
GXcopy );
XPutImage( fl_get_display(),
pixmap,
forms_state->gc[8],
ximage,
0, 0,
0, 0,
width, height );

ximage->data = NULL;
XDestroyImage( ximage );

}

return pixmap;

}

> Any help in pointing me in the right direction to learn about
> creating a pixmap on the fly, and doing things like scrollbars
> would be greatly appricieted.

Scrollbars are pretty straightforward but it depends upon how you're
using your Pixmaps.

What I'd do is to create a Canvas object and then create a child
Window to the Canvas, create the Pixmap and attach it to the child
Window as a background Pixmap, then use the scrollbars to set the
origin of the child Window relative to the Canvas.

spl
_________________________________________________
To unsubscribe, send the message "unsubscribe" to
xforms-request@bob.usuf2.usuhs.mil or see
http://bob.usuf2.usuhs.mil/mailserv/xforms.html
XForms Home Page: http://bragg.phys.uwm.edu/xforms
List Archive: http://bob.usuf2.usuhs.mil/mailserv/list-archives/