#ifndef lint static char SccsId[] = "%W% %G%"; #endif /* Module: mainbffr.c (Main Buffers) * Purpose: Allocate or reallocate large buffers * Subroutine: init_imaging buffers() returns: void * Subroutine: init_display_buffers() returns: void * Subroutine: init_colorbarbuf() returns: void * Subroutine: init_panbuf() returns: void * Subroutine: init_dispbuf() returns: void * Subroutine: init_imagebuf() returns: int * Xlib calls: none * Copyright: 1989 Smithsonian Astrophysical Observatory * You may do anything you like with this file except remove * this copyright. The Smithsonian Astrophysical Observatory * makes no representations about the suitability of this * software for any purpose. It is provided "as is" without * express or implied warranty. * Modified: {0} Michael VanHilst initial version 25 May 1989 * {1} MVH fix in init_imagebuf to note square buf 4 April 1990 * {2} Doug Mink add initial zoom factor 2 Jan 1996 * {n} -- -- */ #include /* get stderr, NULL, etc */ #include /* X window stuff */ #include /* X window manager stuff */ #include "hfiles/define.h" /* define MIN, MAX, etc. */ #include "hfiles/struct.h" /* declare structure types */ #include "hfiles/extern.h" /* extern main parameter structures */ #include "hfiles/scale.h" /* define scaling constants */ /* * Subroutine: init_imaging_buffers * Purpose: Allocate major buffers used for imaging */ void init_imaging_buffers () { char *calloc_errchk(); int init_imagebuf(); buffer.scalemap = (unsigned char *) calloc_errchk(SCALEBUFSZ, sizeof(char), "scaling map"); buffer.histogram = (int *) calloc_errchk(SCALEBUFSZ, sizeof(int), "histogram table"); (void)init_imagebuf (); } /* * Subroutine: init_display_buffers * Purpose: Allocate buffers used for each window's display */ void init_display_buffers () { void init_panbuf(), init_dispbuf(); init_panbuf(); init_dispbuf(); } /* * Subroutine: init_panbuf * Purpose: Allocate or reallocate panbox display buffers */ void init_panbuf () { int buf_sz; char *calloc_errchk(); buf_sz = panbox.xwidth * panbox.yheight; /* test if the current buffers are adequate, else allocate or reallocate */ if( buf_sz > buffer.panbuf_sz ) { if( buffer.panbuf != NULL ) free( (char *)buffer.panbuf ); if( panbox.image.data != NULL ) { free( panbox.image.data ); panbox.image.data = NULL; panbox.data_size = 0; } /* reserve exact window sized buffer for the panbox short integer image */ buffer.panbuf = (short *) calloc_errchk(buf_sz, sizeof(short), "Panbox map"); buffer.panbuf_sz = buf_sz; /* reserve buffer for the panbox display image */ if( color.screen_depth <= 1 ) { /* if only bitmap will be used */ panbox.image.bytes_per_line = (panbox.xwidth + 7) / 8; buf_sz = panbox.image.bytes_per_line * panbox.yheight; } panbox.image.data = calloc_errchk(buf_sz, sizeof(char), "Panbox display"); panbox.data_size = buf_sz; } panbox.image.width = panbox.xwidth; panbox.image.height = panbox.yheight; } /* * Subroutine: init_dispbuf * Purpose: Allocate or reallocate dispbox display buffer */ void init_dispbuf () { int buf_sz; char *calloc_errchk(); void set_coordsys(), set_tdisp(); dispbox.image.width = dispbox.xwidth; dispbox.image.height = dispbox.yheight; if( color.screen_depth <= 1 ) { /* if only bitmap will be used */ dispbox.image.bytes_per_line = (dispbox.xwidth + 7) / 8; buf_sz = dispbox.image.bytes_per_line * dispbox.yheight; } else buf_sz = dispbox.xwidth * dispbox.yheight; /* test if the current buffer is adequate, else allocate or reallocate */ if( buf_sz > dispbox.data_size ) { if( dispbox.image.data != NULL ) free( dispbox.image.data ); dispbox.image.data = calloc_errchk(buf_sz, sizeof(char), "Display image"); dispbox.data_size = buf_sz; } /* set the display coord system and propose new display parameters */ set_coordsys(&coord.disp, 0.5, (int)dispbox.width, (int)dispbox.height, dispbox.xzero, dispbox.yzero, dispbox.xzero + dispbox.xwidth - 1, dispbox.yzero + dispbox.yheight - 1); /* complete tdi parameters, must already have center and zoom */ if (img.zoom > 0) coord.tid.zoom = img.zoom; set_tdisp(&coord); } /* * Subroutine: init_imagebuf * Purpose: Allocate or reallocate main image buffer to fit img or as * much as allowed. Also allocate file data buffer if data * cannot be read directly into i*2 buf. * Returns: 1 on success, else 0. * Post-state: buffer.load_filebuf set to 0 if alloc's failed. * Method: Try to allocate enough for entire given image subsection. * If the display is to be rotated, make the short buf square * or double (whichever is less). * Parameters: * buffer: i/o: record structure for imaging buffers * coord.img: i: coordinate system of image or image subsection * coord.buf: o: coordinate system of short integer image buffer */ static char imgbuf_error[] = "Unable to allocate sufficient memory for requested image.\n"; int init_imagebuf () { int width, height; int img_sz, buf_sz; int shortbuf_double = 0; int shortbuf_square = 0; int did_alloc = 0; char *calloc_errchk(); void set_coordsys(); /* calculate buffer size, use img if within limit, else use limit */ width = coord.img.width; height = coord.img.height; img_sz = width * height; /* if image is to be rotated 90% (aspect ratio changed) */ if( img.rotate_code & 1 ) { /* make short buffer square or double for rotation algorithm */ buf_sz = SQR(MAX(width, height)); if( buf_sz > (2 * img_sz) ) { buf_sz = 2 * img_sz; shortbuf_double = 1; } else shortbuf_square = 1; } else buf_sz = img_sz; /* buf_sz is in shorts, img_sz will now be in bytes (as is filebuf_sz) */ img_sz *= img.bytepix; /* free filebuf if unique and inadequate, or unneeded */ if( buffer.filebuf == (char *)buffer.shortbuf ) { buffer.filebuf = NULL; buffer.filebuf_sz = 0; } else if( (buffer.filebuf != NULL) && ((img.bytepix <= 2) || (img_sz > buffer.filebuf_sz)) ) { free( buffer.filebuf ); buffer.filebuf = NULL; buffer.filebuf_sz = 0; } /* check the adequacy of current short integer image buf */ if( buf_sz > buffer.shortbuf_sz ) { if( buffer.shortbuf != NULL ) free( (char *)buffer.shortbuf ); buffer.shortbuf = (short *)calloc_errchk(buf_sz, sizeof(short), NULL); if( buffer.shortbuf == 0 ) { /* if failed, clear the slate, report error, and continue */ buffer.shortbuf_sz = 0; if( buffer.filebuf != NULL ) { free( buffer.filebuf ); buffer.filebuf = NULL; buffer.filebuf_sz = 0; } (void)fprintf(stderr, imgbuf_error); buffer.load_filebuf = 0; return( 0 ); } buffer.shortbuf_sz = buf_sz; did_alloc = 1; } /* check on file data buf (if it still exists, it must be adequate) */ if( buffer.filebuf == NULL ) { if( img.bytepix > 2 ) { /* force worst case allignment */ buffer.filebuf = calloc_errchk((img_sz + 7) / 8, 8, NULL); if( buffer.filebuf == NULL ) { /* if failed, clear the slate, report error, and continue */ buffer.filebuf_sz = 0; free( (char *)buffer.shortbuf ); buffer.shortbuf = NULL; buffer.shortbuf_sz = 0; fputs (imgbuf_error, stderr); buffer.load_filebuf = 0; return( 0 ); } buffer.filebuf_sz = img_sz; did_alloc++; } else { /* no special input buffer needed */ buffer.filebuf = (char *)buffer.shortbuf; /* shortbuf_sz is shorts, filebuf_sz is bytes */ buffer.filebuf_sz = buffer.shortbuf_sz * sizeof(short); } } /* note rotation space status */ buffer.shortbuf_double = shortbuf_double; buffer.shortbuf_square = shortbuf_square; /* set basic buffer coord system parameters (fill buffer) */ set_coordsys(&coord.buf, 0.5, width, height, 0, 0, width - 1, height - 1); /* flag that buffer must be loaded */ coord.buferror = 1; buffer.load_filebuf = 1; /* report buffer size */ if( control.verbose && did_alloc ) { (void)printf("Reserved %d x %d image data buffer", width, height); if( did_alloc > 1 ) (void)printf("s.\n"); else (void)printf(".\n"); } return( 1 ); }