home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Encyclopedia of Graphics File Formats Companion
/
GFF_CD.ISO
/
software
/
unix
/
saoimage
/
sao1_07.tar
/
crdset.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-04-20
|
12KB
|
361 lines
#ifndef lint
static char SccsId[] = "%W% %G%";
#endif
/* Module: crdset.c (Coordinate Set)
* Purpose: Set up coordinate system parameters and translation matrices
* Subroutine: set_coordsys() returns: void
* Subroutine: set_transform() returns: void
* Subroutine: set_imgtran() returns: void
* Subroutine: set_fbuftran() returns: void
* Subroutine: set_buftran() returns: void
* Subroutine: set_edges() returns: void
* Xlib calls: none
* Notes:
* the base coordinate system is the img
* coordinate conversions are computed by passing through the img
* the img has 0.0, 0.0 as its upper left corner
* files often have 0.5,0.5 at lower left corner (index from 1, ioff = 0.0)
* disp, buffer, and pan have 0.0,0.0 in upper left corner (ioff = 0.5)
* integer values refer to the center of the pixel in its coordinate system
* translations always produce a real (float) value output
* Copyright: 1988 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 1 September 1988
* {1} MVH support for file buffer coord sys 19 Feb 1990
* {n} <who> -- <does what> -- <when>
*/
#include "hfiles/coord.h" /* coord structs */
#include "hfiles/image.h" /* image struct */
/*
* Subroutine: set_coordsys
* Purpose: Set basic params for a coordinate system
*/
void set_coordsys ( csys, ioff, width, height, x1, y1, x2, y2 )
Coordsys *csys;
double ioff;
int width, height;
int x1, y1, x2, y2;
{
csys->width = width;
csys->height = height;
csys->ioff = ioff;
/* pixel coords of four sides (col or row just inside the edge) */
csys->X1i = x1;
csys->Y1i = y1;
csys->X2i = x2;
csys->Y2i = y2;
csys->Xwdth = 1 + x2 - x1;
csys->Yhght = 1 + y2 - y1;
/* put the center in the center of the pixel before the true center */
csys->cenX = (float)(x1 + ((csys->Xwdth - 1) / 2)) + ioff;
csys->cenY = (float)(y1 + ((csys->Yhght - 1) / 2)) + ioff;
/* determine real coords of outer edge using ... */
/* ... offset from integer coords to real coords */
if( ioff < 0.25 ) {
csys->X1 = (float)x1 - (float)0.5;
csys->Y1 = (float)y1 - (float)0.5;
csys->X2 = (float)x2 + (float)0.5;
csys->Y2 = (float)y2 + (float)0.5;
} else {
csys->X1 = (float)x1;
csys->Y1 = (float)y1;
csys->X2 = (float)(x2 + 1);
csys->Y2 = (float)(y2 + 1);
}
}
/*
* Subroutine: set_transform
* Purpose: Calculate transforms given where to put A on B
* Note: Forward transform is A to B
*/
void set_transform ( BAcenX, BAcenY, BAzoom, Asys, Bsys, AtoB, BtoA )
double BAcenX, BAcenY; /* i: B coords of center of A system */
double BAzoom; /* i: size of a B pixel in A units */
Coordsys *Asys, *Bsys;
Transform *AtoB, *BtoA;
{
float ABzoom;
void set_trans_speed(), invert_transform();
ABzoom = 1.0 / BAzoom;
AtoB->inx_outx = ABzoom;
AtoB->iny_outx = 0.0;
AtoB->add_outx = BAcenX - (Asys->cenX * ABzoom);
/* if given an integer parameter, its float value would be less by ioff */
AtoB->iadd_outx = BAcenX - ((Asys->cenX - Asys->ioff) * ABzoom);
AtoB->inx_outy = 0.0;
AtoB->iny_outy = ABzoom;
AtoB->add_outy = BAcenY - (Asys->cenY * ABzoom);
AtoB->iadd_outy = BAcenY - ((Asys->cenY - Asys->ioff) * ABzoom);
/* compute speedy integer computation parameters */
set_trans_speed(AtoB);
/* compute the inverse parameters (complete) */
invert_transform(BtoA, AtoB, Bsys->ioff);
}
/*
* Subroutine: set_imgtran
* Purpose: Set the img-to-file transform
*/
void set_imgtran ( image, img, file, imgtofile, filetoimg )
struct imageRec *image;
Coordsys *img, *file;
Transform *imgtofile, *filetoimg;
{
float if_zoom;
void rotate_transform(), set_trans_speed(), invert_transform();
if_zoom = 1.0 / image->fiblock;
imgtofile->inx_outx = if_zoom;
imgtofile->iny_outx = 0.0;
imgtofile->add_outx = image->ficenX - (img->cenX * if_zoom);
/* if given an integer parameter, its float value would be less by ioff */
imgtofile->iadd_outx = image->ficenX - ((img->cenX - img->ioff) * if_zoom);
imgtofile->inx_outy = 0.0;
imgtofile->iny_outy = if_zoom;
imgtofile->add_outy = image->ficenY - (img->cenY * if_zoom);
imgtofile->iadd_outy = image->ficenY - ((img->cenY - img->ioff) * if_zoom);
/* if rotation or y coordinate flipping is to be applied, do it new */
if( (image->rotate_code != 0) || (image->row_order != 0) ) {
rotate_transform(img, imgtofile, image->row_order, image->rotate_code);
}
/* compute speedy integer computation parameters */
set_trans_speed(imgtofile);
/* compute the inverse parameters (complete) */
invert_transform(filetoimg, imgtofile, file->ioff);
}
/*
* Subroutine: set_fbuftran
* Purpose: Set buffer-to-filebuffer transform, should the
* two buffers differ.
* Note: Two buffers have same dimensions (and are usually the same)
*/
void set_fbuftran ( image, buf, fbuf, buftofbuf )
struct imageRec *image;
Coordsys *buf, *fbuf; /* descriptions of short and file buffers */
Transform *buftofbuf;
{
void rotate_transform(), set_trans_speed();
buftofbuf->inx_outx = 1.0;
buftofbuf->iny_outx = 0.0;
buftofbuf->add_outx = 0.0;
buftofbuf->iadd_outx = 0.5;
buftofbuf->inx_outy = 0.0;
buftofbuf->iny_outy = 1.0;
buftofbuf->add_outy = 0.0;
buftofbuf->iadd_outy = 0.5;
/* if rotation or y coordinate flipping is to be applied, do it new */
if( (image->rotate_code != 0) || (image->row_order != 0) ) {
rotate_transform(buf, buftofbuf, image->row_order, image->rotate_code);
}
/* compute speedy integer computation parameters */
set_trans_speed(buftofbuf);
/* set the fbuf coordinate system parameters */
if( image->rotate_code & 1 ) {
/* rotated 90 or 270 degrees means switch X and Y axes */
fbuf->X1 = buf->Y1;
fbuf->X2 = buf->Y2;
fbuf->Y1 = buf->X1;
fbuf->Y2 = buf->X2;
fbuf->X1i = buf->Y1i;
fbuf->X2i = buf->Y2i;
fbuf->Y1i = buf->X1i;
fbuf->Y2i = buf->X2i;
fbuf->Xwdth = buf->Yhght;
fbuf->Yhght = buf->Xwdth;
fbuf->cenX = buf->cenY;
fbuf->cenY = buf->cenX;
fbuf->width = buf->height;
fbuf->height = buf->width;
fbuf->ioff = buf->ioff;
} else
bcopy((char *)buf, (char *)fbuf, sizeof(Coordsys));
}
/*
* Subroutine: set_buftran
* Purpose: Set buffer-to-img transform (& buf-to-file)
* Note: adjusts alignment so as not to waste buffer space
* Note: edges later used to check whether requested display is
* available
* Exception: assumes buf is not smaller than disp
*/
void set_buftran ( coord )
struct coordRec *coord;
{
void set_transform(), combine_transform(), set_edges(), invert_transform();
/* if buf and image are identical, just copy */
if( !coord->bufcheck ) {
set_transform(coord->img.cenX, coord->img.cenY, 1.0,
&coord->buf, &coord->img,
&coord->buftoimg, &coord->imgtobuf);
bcopy((char *)&(coord->imgtofile),
(char *)&(coord->buftofile), sizeof(Transform));
coord->ib.srcX1 = 0;
coord->ib.srcX2 = coord->img.width - 1;
coord->ib.srcY1 = 0;
coord->ib.srcY2 = coord->img.height - 1;
coord->ib.srcXwdth = coord->img.width;
coord->ib.srcYhght = coord->img.height;
coord->ib.cenX = coord->img.cenX;
coord->ib.cenY = coord->img.cenY;
coord->ib.zoom = 1.0;
coord->ib.block = 1;
} else {
float lX, tY, rX, bY, diff;
{
register double ibzoom;
/* if the buffer needs checking, calculate buffer to img zoom */
if( (coord->buf.width < ((double)coord->disp.width /
coord->id.zoom)) ||
(coord->buf.height < ((double)coord->disp.height /
coord->id.zoom)) ) {
/* use idzoom if zoom 1 won't work (check disp size in img coords) */
ibzoom = coord->id.zoom;
coord->ib.block = coord->id.block;
} else {
ibzoom = 1.0;
coord->ib.block = 1;
}
coord->ib.zoom = ibzoom;
/* calculate corners of display in img coords */
coord->ib.cenX = coord->id.cenX;
coord->ib.cenY = coord->id.cenY;
lX = coord->ib.cenX - (coord->buf.cenX * ibzoom);
rX = coord->ib.cenX +
(((double)coord->buf.width - coord->buf.cenX) * ibzoom);
tY = coord->ib.cenY - (coord->buf.cenY * ibzoom);
bY = coord->ib.cenY +
(((double)coord->buf.height - coord->buf.cenY) * ibzoom);
}
/* shift center if buffer extends beyond an edge */
if( lX < 0.0 ) {
diff = -lX;
lX = 0.0;
rX += diff;
coord->ib.cenX += diff;
} else if( rX > (double)coord->img.width ) {
diff = rX - (double)coord->img.width;
lX -= diff;
rX = (double)coord->img.width;
coord->ib.cenX -= diff;
}
if( tY < 0 ) {
diff = -tY;
tY = 0;
bY += diff;
coord->ib.cenY += diff;
} else if( bY > (double)coord->img.height ) {
diff = bY - (double)coord->img.height;
tY -= diff;
bY = (double)coord->img.height;
coord->ib.cenY -= diff;
}
/* set edges to integer pixel coords, rounding in from edge */
coord->ib.srcX1 = (int)(lX + 0.001);
coord->ib.srcY1 = (int)(tY + 0.001);
coord->ib.srcX2 = (int)(rX - 0.001);
coord->ib.srcY2 = (int)(bY - 0.001);
/* compute transforms */
set_transform(coord->ib.cenX, coord->ib.cenY, coord->ib.zoom,
&coord->buf, &coord->img,
&coord->buftoimg, &coord->imgtobuf);
combine_transform(&coord->buftofile, &coord->buftoimg, &coord->imgtofile);
set_edges(&coord->buftofile, &coord->file, &coord->buf, &coord->fb);
/* compute inverse of buftofile (used to stuff pixels from socket) */
invert_transform(&coord->filetobuf, &coord->buftofile, coord->file.ioff);
}
}
/*
* Subroutine: set_edges
* Purpose: Set up parameter to map image data from src (A) to dst (B)
* Set up the edges of dst sys (B) as plotted in src (A)
* Note: Used to set up transfer of image data from A to B
*/
void set_edges ( BAtrans, Asys, Bsys, ABmap )
Transform *BAtrans;
Coordsys *Asys, *Bsys;
Edges *ABmap;
{
float lX, tY, rX, bY, temp;
float BAzoom;
void d_transform();
/* compute four corner pixel coords */
d_transform(BAtrans, Bsys->X1, Bsys->Y1, &lX, &tY);
d_transform(BAtrans, Bsys->X2, Bsys->Y2, &rX, &bY);
/* account for any rotation or inversion */
if( lX > rX ) {
temp = lX;
lX = rX;
rX = temp;
}
if( tY > bY ) {
temp = tY;
tY = bY;
bY = temp;
}
/* clip AB area by src (A) area */
ABmap->clip = 0;
if( lX < Asys->X1 ) {
lX = Asys->X1;
ABmap->clip += LX;
}
if( rX > Asys->X2 ) {
rX = Asys->X2;
ABmap->clip += RX;
}
if( tY < Asys->Y1 ) {
tY = Asys->Y1;
ABmap->clip += TY;
}
if( bY > Asys->Y2 ) {
bY = Asys->Y2;
ABmap->clip += BY;
}
/* round any edges inward */
ABmap->srcX1 = (int)(lX + 0.001);
ABmap->srcY1 = (int)(tY + 0.001);
ABmap->srcX2 = (int)(rX - 0.001);
ABmap->srcY2 = (int)(bY - 0.001);
ABmap->srcXwdth = (int)(0.0001 + rX - lX);
ABmap->srcYhght = (int)(0.0001 + bY - tY);
/* get AB block and integer block code (opposite of BA) */
/* assume symetric orthogonal blocking - one factor is 0, other is block */
if( BAtrans->inx_outx > 0.000001 )
BAzoom = BAtrans->inx_outx;
else if( BAtrans->inx_outx < -0.000001 )
BAzoom = -BAtrans->inx_outx;
else if( BAtrans->iny_outx > 0.000001 )
BAzoom = BAtrans->iny_outx;
else
BAzoom = -BAtrans->iny_outx;
/* block code is integer factor (-1/block for fractional block) */
/* block is inverse of zoom in our usage of zoom */
ABmap->zoom = 1.0 / BAzoom;
if( BAzoom > 0.75 )
ABmap->block = (int)(BAzoom + 0.5);
else
ABmap->block = -(int)(ABmap->zoom + 0.5);
/* transfer basic mapping destination parameters */
ABmap->dstX1 = Bsys->X1i;
ABmap->dstY1 = Bsys->Y1i;
ABmap->dstX2 = Bsys->X2i;
ABmap->dstY2 = Bsys->Y2i;
ABmap->dstXwdth = Bsys->Xwdth;
ABmap->dstYhght = Bsys->Yhght;
}