Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

mri_drawing.c

Go to the documentation of this file.
00001 /****************************************************************************
00002     Adapted from libppm5.c by RWCox, to draw stuff into an RGB image
00003 *****************************************************************************/
00004 
00005 /*---------------------------------------------------------------------------
00006 ** Copyright (C) 1989, 1991 by Jef Poskanzer.
00007 **
00008 ** Permission to use, copy, modify, and distribute this software and its
00009 ** documentation for any purpose and without fee is hereby granted, provided
00010 ** that the above copyright notice appear in all copies and that both that
00011 ** copyright notice and this permission notice appear in supporting
00012 ** documentation.  This software is provided "as is" without express or
00013 ** implied warranty.
00014 **
00015 ** The character drawing routines are by John Walker
00016 ** Copyright (C) 1994 by John Walker, kelvin@fourmilab.ch
00017 -----------------------------------------------------------------------------*/
00018 
00019 #include "mrilib.h"
00020 
00021 #undef  DDA_SCALE
00022 #define DDA_SCALE 8192
00023 
00024 /*---------------------- Set opacity [22 Jul 2004] ----------------------------*/
00025 static float opa = 1.0 ;
00026 void mri_draw_opacity( float val ){ if( val >= 0.0 && val <= 1.0 ) opa = val ; }
00027 
00028 #undef  ASSPIX
00029 #undef  ASSPIX_OLD
00030 #define ASSPIX_OLD(p,x,y,r,g,b) ( (p)[3*((x)+(y)*cols)  ] = (r) ,   \
00031                                   (p)[3*((x)+(y)*cols)+1] = (g) ,   \
00032                                   (p)[3*((x)+(y)*cols)+2] = (b)   )
00033 
00034 #define ASSPIX(p,x,y,r,g,b)                                         \
00035  do{ byte ro,go,bo ;                                                \
00036      if( opa == 1.0 ) ASSPIX_OLD(p,x,y,r,g,b) ;                     \
00037      else {                                                         \
00038        ro = (byte)(opa*(r) + (1.0-opa)*(p)[3*((x)+(y)*cols)  ]) ;   \
00039        go = (byte)(opa*(g) + (1.0-opa)*(p)[3*((x)+(y)*cols)+1]) ;   \
00040        bo = (byte)(opa*(b) + (1.0-opa)*(p)[3*((x)+(y)*cols)+2]) ;   \
00041        ASSPIX_OLD(p,x,y,ro,go,bo) ;                                 \
00042      } } while(0)
00043  
00044 
00045 /*--------------------------- Simple fill routine ---------------------------*/
00046 
00047 static
00048 void ppmd_filledrectangle( byte *pixels, int cols, int rows,
00049                            int x, int y, int width, int height , byte r,byte g,byte b )
00050 {
00051     register int cx, cy, cwidth, cheight, col, row;
00052 
00053     /* Clip. */
00054     cx = x; cy = y; cwidth = width; cheight = height;
00055     if ( cx < 0 ) { cx = 0; cwidth += x; }
00056     if ( cy < 0 ) { cy = 0; cheight += y; }
00057     if ( cx + cwidth > cols ) cwidth = cols - cx;
00058     if ( cy + cheight > rows ) cheight = rows - cy;
00059 
00060     /* Draw. */
00061     for ( row = cy; row < cy + cheight; ++row )
00062         for ( col = cx; col < cx + cwidth; ++col )
00063             ASSPIX(pixels,col,row,r,g,b) ;
00064 }
00065 
00066 /*----------------------------------------------------------------------------*/
00067 
00068 #define ppmd_lineclip 1  /* always clip lines */
00069 
00070 /*! Draw a line */
00071 
00072 static
00073 void ppmd_line( byte *pixels, int cols, int rows,
00074                 int x0, int y0, int x1, int y1, byte r,byte g,byte b )
00075 {
00076     register int cx0, cy0, cx1, cy1;
00077 
00078     /* Special case zero-length lines. */
00079     if ( x0 == x1 && y0 == y1 ) {
00080         if ( ( x0 >= 0 && x0 < cols && y0 >= 0 && y0 < rows ) )
00081             ASSPIX(pixels,x0,y0,r,g,b) ;
00082         return;
00083     }
00084 
00085     /* Clip. */
00086     cx0 = x0; cy0 = y0; cx1 = x1; cy1 = y1;
00087     if ( ppmd_lineclip ) {
00088         if ( cx0 < 0 )
00089             {
00090             if ( cx1 < 0 ) return;
00091             cy0 = cy0 + ( cy1 - cy0 ) * ( -cx0 ) / ( cx1 - cx0 );
00092             cx0 = 0;
00093             }
00094         else if ( cx0 >= cols )
00095             {
00096             if ( cx1 >= cols ) return;
00097             cy0 = cy0 + ( cy1 - cy0 ) * ( cols - 1 - cx0 ) / ( cx1 - cx0 );
00098             cx0 = cols - 1;
00099             }
00100         if ( cy0 < 0 )
00101             {
00102             if ( cy1 < 0 ) return;
00103             cx0 = cx0 + ( cx1 - cx0 ) * ( -cy0 ) / ( cy1 - cy0 );
00104             cy0 = 0;
00105             }
00106         else if ( cy0 >= rows )
00107             {
00108             if ( cy1 >= rows ) return;
00109             cx0 = cx0 + ( cx1 - cx0 ) * ( rows - 1 - cy0 ) / ( cy1 - cy0 );
00110             cy0 = rows - 1;
00111             }
00112         if ( cx1 < 0 )
00113             {
00114             cy1 = cy1 + ( cy0 - cy1 ) * ( -cx1 ) / ( cx0 - cx1 );
00115             cx1 = 0;
00116             }
00117         else if ( cx1 >= cols )
00118             {
00119             cy1 = cy1 + ( cy0 - cy1 ) * ( cols - 1 - cx1 ) / ( cx0 - cx1 );
00120             cx1 = cols - 1;
00121             }
00122         if ( cy1 < 0 )
00123             {
00124             cx1 = cx1 + ( cx0 - cx1 ) * ( -cy1 ) / ( cy0 - cy1 );
00125             cy1 = 0;
00126             }
00127         else if ( cy1 >= rows )
00128             {
00129             cx1 = cx1 + ( cx0 - cx1 ) * ( rows - 1 - cy1 ) / ( cy0 - cy1 );
00130             cy1 = rows - 1;
00131             }
00132 
00133         /* Check again for zero-length lines. */
00134         if ( cx0 == cx1 && cy0 == cy1 ){ ASSPIX(pixels,cx0,cy0,r,g,b) ; return; }
00135     } /* end of clip */
00136 
00137     /* Draw, using a simple DDA. */
00138     if ( abs( cx1 - cx0 ) > abs( cy1 - cy0 ) ) { /* Loop over X domain. */
00139         register long dy, srow;
00140         register int dx, col, row, prevrow;
00141 
00142         if ( cx1 > cx0 ) dx =  1;
00143         else             dx = -1;
00144         dy = ( cy1 - cy0 ) * DDA_SCALE / abs( cx1 - cx0 );
00145         prevrow = row = cy0;
00146         srow = row * DDA_SCALE + DDA_SCALE / 2;
00147         col = cx0;
00148         for ( ; ; ) {
00149             ASSPIX(pixels,col,row,r,g,b) ;
00150             if ( col == cx1 ) break;
00151             srow += dy; row = srow / DDA_SCALE; col += dx;
00152         }
00153     } else { /* Loop over Y domain. */
00154         register long dx, scol;
00155         register int dy, col, row, prevcol;
00156 
00157         if ( cy1 > cy0 ) dy =  1;
00158         else             dy = -1;
00159         dx = ( cx1 - cx0 ) * DDA_SCALE / abs( cy1 - cy0 );
00160         row = cy0;
00161         prevcol = col = cx0;
00162         scol = col * DDA_SCALE + DDA_SCALE / 2;
00163         for ( ; ; ) {
00164             ASSPIX(pixels,col,row,r,g,b) ;
00165             if ( row == cy1 ) break;
00166             row += dy; scol += dx; col = scol / DDA_SCALE;
00167         }
00168     }
00169 }
00170 
00171 /*----------------------------------------------------------------------------*/
00172 
00173 #define SPLINE_THRESH 3
00174 
00175 /*! Draw a spline between 3 points, using recursion and lines. */
00176 
00177 static
00178 void ppmd_spline3( byte *pixels, int cols, int rows,
00179                    int x0, int y0, int x1, int y1, int x2, int y2, byte r,byte g, byte b)
00180 {
00181     register int xa, ya, xb, yb, xc, yc, xp, yp;
00182 
00183     xa = ( x0 + x1 ) / 2; ya = ( y0 + y1 ) / 2;
00184     xc = ( x1 + x2 ) / 2; yc = ( y1 + y2 ) / 2;
00185     xb = ( xa + xc ) / 2; yb = ( ya + yc ) / 2;
00186 
00187     xp = ( x0 + xb ) / 2; yp = ( y0 + yb ) / 2;
00188     if ( abs( xa - xp ) + abs( ya - yp ) > SPLINE_THRESH )
00189         ppmd_spline3( pixels, cols, rows, x0, y0, xa, ya, xb, yb, r,g,b ) ;
00190     else
00191         ppmd_line( pixels, cols, rows, x0, y0, xb, yb, r,g,b ) ;
00192 
00193     xp = ( x2 + xb ) / 2; yp = ( y2 + yb ) / 2;
00194     if ( abs( xc - xp ) + abs( yc - yp ) > SPLINE_THRESH )
00195         ppmd_spline3( pixels, cols, rows, xb, yb, xc, yc, x2, y2, r,g,b ) ;
00196     else
00197         ppmd_line( pixels, cols, rows, xb, yb, x2, y2, r,g,b ) ;
00198 }
00199 
00200 /*----------------------------------------------------------------------------*/
00201 
00202 /*! Draw a spline between a bunch of points. */
00203 
00204 static
00205 void ppmd_polyspline( byte *pixels, int cols, int rows,
00206                       int x0,int y0, int nc, int* xc, int* yc, int x1,int y1, byte r,byte g,byte b )
00207 {
00208     register int i, x, y, xn, yn;
00209 
00210     x = x0; y = y0;
00211     for ( i = 0; i < nc - 1; ++i ) {
00212         xn = ( xc[i] + xc[i + 1] ) / 2;
00213         yn = ( yc[i] + yc[i + 1] ) / 2;
00214         ppmd_spline3( pixels, cols, rows, x, y, xc[i], yc[i], xn, yn, r,g,b ) ;
00215         x = xn; y = yn;
00216     }
00217     ppmd_spline3( pixels, cols, rows, x, y, xc[nc - 1], yc[nc - 1], x1, y1, r,g,b ) ;
00218 }
00219 
00220 /*----------------------------------------------------------------------------*/
00221 
00222 /*! Draw a circle. */
00223 
00224 static
00225 void ppmd_circle( byte *pixels, int cols, int rows,
00226                   int cx, int cy, int radius, byte r,byte g,byte b )
00227 {
00228     register int x0, y0, x, y, prevx, prevy, nopointsyet;
00229     register long sx, sy, e;
00230 
00231     x0 = x = radius;
00232     y0 = y = 0;
00233     sx = x * DDA_SCALE + DDA_SCALE / 2;
00234     sy = y * DDA_SCALE + DDA_SCALE / 2;
00235     e = DDA_SCALE / radius;
00236     ASSPIX(pixels,x+cx,y+cy,r,g,b) ;
00237     nopointsyet = 1;
00238     do {
00239         prevx = x; prevy = y;
00240         sx += e * sy / DDA_SCALE;
00241         sy -= e * sx / DDA_SCALE;
00242         x = sx / DDA_SCALE;
00243         y = sy / DDA_SCALE;
00244         if ( x != prevx || y != prevy ) {
00245             nopointsyet = 0;
00246             ASSPIX(pixels,x+cx,y+cy,r,g,b) ;
00247         }
00248     } while ( nopointsyet || x != x0 || y != y0 );
00249 }
00250 
00251 /*-------------------------------------------------------------------------------*/
00252 
00253 /*                Stroke character definitions
00254 
00255    The  following  character  definitions are derived from the (public
00256    domain) Hershey plotter  font  database,  using  the  single-stroke
00257    Roman font.
00258 
00259    Each  character  definition  begins  with 3 bytes which specify the
00260    number of X, Y plot pairs which follow, the negative  of  the  skip
00261    before  starting  to  draw  the  characters, and the skip after the
00262    character.  The first plot pair moves the pen to that location  and
00263    subsequent  pairs  draw  to  the  location given.  A pair of 192, 0
00264    raises the pen, moves to the location given by the following  pair,
00265    and resumes drawing with the pair after that.
00266 
00267    The  values  in  the  definition  tables are 8-bit two's complement
00268    signed numbers.  We  declare  the  table  as  "unsigned  char"  and
00269    manually  sign-extend  the  values because C compilers differ as to
00270    whether the type "char" is signed or unsigned, and  some  compilers
00271    don't  accept the qualifier "signed" which we would like to use for
00272    these items.  We specify negative numbers as their  unsigned  two's
00273    complements  to  avoid  complaints  from compilers which don't like
00274    initialising unsigned data with signed values.  Ahhh,  portability.
00275 */
00276 
00277 static unsigned char
00278 char32[] = { 0, 0, 21 },
00279 char33[] = { 8, 251, 5, 0, 244, 0, 2, 192, 0, 0, 7, 255, 8, 0, 9, 1, 8, 0, 7 },
00280 char34[] = { 17, 253, 15, 2, 244, 1, 245, 0, 244, 1, 243, 2, 244, 2, 246, 1,
00281              248, 0, 249, 192, 0, 10, 244, 9, 245, 8, 244, 9, 243, 10, 244,
00282              10, 246, 9, 248, 8, 249, },
00283 char35[] = { 11, 246, 11, 1, 240, 250, 16, 192, 0, 7, 240, 0, 16, 192, 0, 250,
00284              253, 8, 253, 192, 0, 249, 3, 7, 3 },
00285 char36[] = { 26, 246, 10, 254, 240, 254, 13, 192, 0, 2, 240, 2, 13, 192, 0, 7,
00286              247, 5, 245, 2, 244, 254, 244, 251, 245, 249, 247, 249, 249, 250,
00287              251, 251, 252, 253, 253, 3, 255, 5, 0, 6, 1, 7, 3, 7, 6, 5, 8, 2,
00288              9, 254, 9, 251, 8, 249, 6 },
00289 char37[] = { 31, 244, 12, 9, 244, 247, 9, 192, 0, 252, 244, 254, 246, 254,
00290              248, 253, 250, 251, 251, 249, 251, 247, 249, 247, 247, 248, 245,
00291              250, 244, 252, 244, 254, 245, 1, 246, 4, 246, 7, 245, 9, 244,
00292              192, 0, 5, 2, 3, 3, 2, 5, 2, 7, 4, 9, 6, 9, 8, 8, 9, 6, 9, 4, 7,
00293              2, 5, 2 },
00294 char38[] = { 34, 243, 13, 10, 253, 10, 252, 9, 251, 8, 251, 7, 252, 6, 254, 4,
00295              3, 2, 6, 0, 8, 254, 9, 250, 9, 248, 8, 247, 7, 246, 5, 246, 3,
00296              247, 1, 248, 0, 255, 252, 0, 251, 1, 249, 1, 247, 0, 245, 254,
00297              244, 252, 245, 251, 247, 251, 249, 252, 252, 254, 255, 3, 6, 5,
00298              8, 7, 9, 9, 9, 10, 8, 10, 7 },
00299 char39[] = { 7, 251, 5, 0, 246, 255, 245, 0, 244, 1, 245, 1, 247, 0, 249, 255,
00300              250 },
00301 char40[] = { 10, 249, 7, 4, 240, 2, 242, 0, 245, 254, 249, 253, 254, 253, 2,
00302              254, 7, 0, 11, 2, 14, 4, 16 },
00303 char41[] = { 10, 249, 7, 252, 240, 254, 242, 0, 245, 2, 249, 3, 254, 3, 2, 2,
00304              7, 0, 11, 254, 14, 252, 16 },
00305 char42[] = { 8, 248, 8, 0, 250, 0, 6, 192, 0, 251, 253, 5, 3, 192, 0, 5, 253,
00306              251, 3 },
00307 char43[] = { 5, 243, 13, 0, 247, 0, 9, 192, 0, 247, 0, 9, 0 },
00308 char44[] = { 8, 251, 5, 1, 8, 0, 9, 255, 8, 0, 7, 1, 8, 1, 10, 0, 12, 255, 13
00309            },
00310 char45[] = { 2, 243, 13, 247, 0, 9, 0 },
00311 char46[] = { 5, 251, 5, 0, 7, 255, 8, 0, 9, 1, 8, 0, 7 },
00312 char47[] = { 2, 245, 11, 9, 240, 247, 16 },
00313 char48[] = { 17, 246, 10, 255, 244, 252, 245, 250, 248, 249, 253, 249, 0, 250,
00314              5, 252, 8, 255, 9, 1, 9, 4, 8, 6, 5, 7, 0, 7, 253, 6, 248, 4,
00315              245, 1, 244, 255, 244 },
00316 char49[] = { 4, 246, 10, 252, 248, 254, 247, 1, 244, 1, 9 },
00317 char50[] = { 14, 246, 10, 250, 249, 250, 248, 251, 246, 252, 245, 254, 244, 2,
00318              244, 4, 245, 5, 246, 6, 248, 6, 250, 5, 252, 3, 255, 249, 9, 7, 9
00319            },
00320 char51[] = { 15, 246, 10, 251, 244, 6, 244, 0, 252, 3, 252, 5, 253, 6, 254, 7,
00321              1, 7, 3, 6, 6, 4, 8, 1, 9, 254, 9, 251, 8, 250, 7, 249, 5 },
00322 char52[] = { 6, 246, 10, 3, 244, 249, 2, 8, 2, 192, 0, 3, 244, 3, 9 },
00323 char53[] = { 17, 246, 10, 5, 244, 251, 244, 250, 253, 251, 252, 254, 251, 1,
00324              251, 4, 252, 6, 254, 7, 1, 7, 3, 6, 6, 4, 8, 1, 9, 254, 9, 251,
00325              8, 250, 7, 249, 5 },
00326 char54[] = { 23, 246, 10, 6, 247, 5, 245, 2, 244, 0, 244, 253, 245, 251, 248,
00327              250, 253, 250, 2, 251, 6, 253, 8, 0, 9, 1, 9, 4, 8, 6, 6, 7, 3,
00328              7, 2, 6, 255, 4, 253, 1, 252, 0, 252, 253, 253, 251, 255, 250, 2
00329              },
00330 char55[] = { 5, 246, 10, 7, 244, 253, 9, 192, 0, 249, 244, 7, 244 },
00331 char56[] = { 29, 246, 10, 254, 244, 251, 245, 250, 247, 250, 249, 251, 251,
00332              253, 252, 1, 253, 4, 254, 6, 0, 7, 2, 7, 5, 6, 7, 5, 8, 2, 9,
00333              254, 9, 251, 8, 250, 7, 249, 5, 249, 2, 250, 0, 252, 254, 255,
00334              253, 3, 252, 5, 251, 6, 249, 6, 247, 5, 245, 2, 244, 254, 244 },
00335 char57[] = { 23, 246, 10, 6, 251, 5, 254, 3, 0, 0, 1, 255, 1, 252, 0, 250,
00336              254, 249, 251, 249, 250, 250, 247, 252, 245, 255, 244, 0, 244, 3,
00337              245, 5, 247, 6, 251, 6, 0, 5, 5, 3, 8, 0, 9, 254, 9, 251, 8, 250,
00338              6 },
00339 char58[] = { 11, 251, 5, 0, 251, 255, 252, 0, 253, 1, 252, 0, 251, 192, 0, 0,
00340              7, 255, 8, 0, 9, 1, 8, 0, 7 },
00341 char59[] = { 14, 251, 5, 0, 251, 255, 252, 0, 253, 1, 252, 0, 251, 192, 0, 1,
00342              8, 0, 9, 255, 8, 0, 7, 1, 8, 1, 10, 0, 12, 255, 13 },
00343 char60[] = { 3, 244, 12, 8, 247, 248, 0, 8, 9 },
00344 char61[] = { 5, 243, 13, 247, 253, 9, 253, 192, 0, 247, 3, 9, 3 },
00345 char62[] = { 3, 244, 12, 248, 247, 8, 0, 248, 9 },
00346 char63[] = { 20, 247, 9, 250, 249, 250, 248, 251, 246, 252, 245, 254, 244, 2,
00347              244, 4, 245, 5, 246, 6, 248, 6, 250, 5, 252, 4, 253, 0, 255, 0,
00348              2, 192, 0, 0, 7, 255, 8, 0, 9, 1, 8, 0, 7 },
00349 char64[] = { 55, 243, 14, 5, 252, 4, 250, 2, 249, 255, 249, 253, 250, 252,
00350              251, 251, 254, 251, 1, 252, 3, 254, 4, 1, 4, 3, 3, 4, 1, 192, 0,
00351              255, 249, 253, 251, 252, 254, 252, 1, 253, 3, 254, 4, 192, 0, 5,
00352              249, 4, 1, 4, 3, 6, 4, 8, 4, 10, 2, 11, 255, 11, 253, 10, 250, 9,
00353              248, 7, 246, 5, 245, 2, 244, 255, 244, 252, 245, 250, 246, 248,
00354              248, 247, 250, 246, 253, 246, 0, 247, 3, 248, 5, 250, 7, 252, 8,
00355              255, 9, 2, 9, 5, 8, 7, 7, 8, 6, 192, 0, 6, 249, 5, 1, 5, 3, 6, 4
00356              },
00357 char65[] = { 8, 247, 9, 0, 244, 248, 9, 192, 0, 0, 244, 8, 9, 192, 0, 251, 2,
00358              5, 2 },
00359 char66[] = { 23, 245, 10, 249, 244, 249, 9, 192, 0, 249, 244, 2, 244, 5, 245,
00360              6, 246, 7, 248, 7, 250, 6, 252, 5, 253, 2, 254, 192, 0, 249, 254,
00361              2, 254, 5, 255, 6, 0, 7, 2, 7, 5, 6, 7, 5, 8, 2, 9, 249, 9 },
00362 char67[] = { 18, 246, 11, 8, 249, 7, 247, 5, 245, 3, 244, 255, 244, 253, 245,
00363              251, 247, 250, 249, 249, 252, 249, 1, 250, 4, 251, 6, 253, 8,
00364              255, 9, 3, 9, 5, 8, 7, 6, 8, 4 },
00365 char68[] = { 15, 245, 10, 249, 244, 249, 9, 192, 0, 249, 244, 0, 244, 3, 245,
00366              5, 247, 6, 249, 7, 252, 7, 1, 6, 4, 5, 6, 3, 8, 0, 9, 249, 9 },
00367 char69[] = { 11, 246, 9, 250, 244, 250, 9, 192, 0, 250, 244, 7, 244, 192, 0,
00368              250, 254, 2, 254, 192, 0, 250, 9, 7, 9 },
00369 char70[] = { 8, 246, 8, 250, 244, 250, 9, 192, 0, 250, 244, 7, 244, 192, 0,
00370              250, 254, 2, 254 },
00371 char71[] = { 22, 246, 11, 8, 249, 7, 247, 5, 245, 3, 244, 255, 244, 253, 245,
00372              251, 247, 250, 249, 249, 252, 249, 1, 250, 4, 251, 6, 253, 8,
00373              255, 9, 3, 9, 5, 8, 7, 6, 8, 4, 8, 1, 192, 0, 3, 1, 8, 1 },
00374 char72[] = { 8, 245, 11, 249, 244, 249, 9, 192, 0, 7, 244, 7, 9, 192, 0, 249,
00375              254, 7, 254 },
00376 char73[] = { 2, 252, 4, 0, 244, 0, 9 },
00377 char74[] = { 10, 248, 8, 4, 244, 4, 4, 3, 7, 2, 8, 0, 9, 254, 9, 252, 8, 251,
00378              7, 250, 4, 250, 2 },
00379 char75[] = { 8, 245, 10, 249, 244, 249, 9, 192, 0, 7, 244, 249, 2, 192, 0,
00380              254, 253, 7, 9 },
00381 char76[] = { 5, 246, 7, 250, 244, 250, 9, 192, 0, 250, 9, 6, 9 },
00382 char77[] = { 11, 244, 12, 248, 244, 248, 9, 192, 0, 248, 244, 0, 9, 192, 0, 8,
00383              244, 0, 9, 192, 0, 8, 244, 8, 9 },
00384 char78[] = { 8, 245, 11, 249, 244, 249, 9, 192, 0, 249, 244, 7, 9, 192, 0, 7,
00385              244, 7, 9 },
00386 char79[] = { 21, 245, 11, 254, 244, 252, 245, 250, 247, 249, 249, 248, 252,
00387              248, 1, 249, 4, 250, 6, 252, 8, 254, 9, 2, 9, 4, 8, 6, 6, 7, 4,
00388              8, 1, 8, 252, 7, 249, 6, 247, 4, 245, 2, 244, 254, 244 },
00389 char80[] = { 13, 245, 10, 249, 244, 249, 9, 192, 0, 249, 244, 2, 244, 5, 245,
00390              6, 246, 7, 248, 7, 251, 6, 253, 5, 254, 2, 255, 249, 255 },
00391 char81[] = { 24, 245, 11, 254, 244, 252, 245, 250, 247, 249, 249, 248, 252,
00392              248, 1, 249, 4, 250, 6, 252, 8, 254, 9, 2, 9, 4, 8, 6, 6, 7, 4,
00393              8, 1, 8, 252, 7, 249, 6, 247, 4, 245, 2, 244, 254, 244, 192, 0,
00394              1, 5, 7, 11 },
00395 char82[] = { 16, 245, 10, 249, 244, 249, 9, 192, 0, 249, 244, 2, 244, 5, 245,
00396              6, 246, 7, 248, 7, 250, 6, 252, 5, 253, 2, 254, 249, 254, 192, 0,
00397              0, 254, 7, 9 },
00398 char83[] = { 20, 246, 10, 7, 247, 5, 245, 2, 244, 254, 244, 251, 245, 249,
00399              247, 249, 249, 250, 251, 251, 252, 253, 253, 3, 255, 5, 0, 6, 1,
00400              7, 3, 7, 6, 5, 8, 2, 9, 254, 9, 251, 8, 249, 6 },
00401 char84[] = { 5, 248, 8, 0, 244, 0, 9, 192, 0, 249, 244, 7, 244 },
00402 char85[] = { 10, 245, 11, 249, 244, 249, 3, 250, 6, 252, 8, 255, 9, 1, 9, 4,
00403              8, 6, 6, 7, 3, 7, 244 },
00404 char86[] = { 5, 247, 9, 248, 244, 0, 9, 192, 0, 8, 244, 0, 9 },
00405 char87[] = { 11, 244, 12, 246, 244, 251, 9, 192, 0, 0, 244, 251, 9, 192, 0, 0,
00406              244, 5, 9, 192, 0, 10, 244, 5, 9 },
00407 char88[] = { 5, 246, 10, 249, 244, 7, 9, 192, 0, 7, 244, 249, 9 },
00408 char89[] = { 6, 247, 9, 248, 244, 0, 254, 0, 9, 192, 0, 8, 244, 0, 254 },
00409 char90[] = { 8, 246, 10, 7, 244, 249, 9, 192, 0, 249, 244, 7, 244, 192, 0,
00410             249, 9, 7, 9 },
00411 char91[] = { 11, 249, 7, 253, 240, 253, 16, 192, 0, 254, 240, 254, 16, 192, 0,
00412              253, 240, 4, 240, 192, 0, 253, 16, 4, 16 },
00413 char92[] = { 2, 245, 11, 9, 16, 247, 240 },
00414 char93[] = { 11, 249, 7, 2, 240, 2, 16, 192, 0, 3, 240, 3, 16, 192, 0, 252,
00415              240, 3, 240, 192, 0, 252, 16, 3, 16 },
00416 char94[] = { 7, 245, 11, 248, 2, 0, 253, 8, 2, 192, 0, 248, 2, 0, 254, 8, 2 },
00417 char95[] = { 2, 253, 22, 0, 9, 20, 9 },
00418 char96[] = { 7, 251, 5, 1, 244, 0, 245, 255, 247, 255, 249, 0, 250, 1, 249, 0,
00419              248 },
00420 char97[] = { 17, 247, 10, 6, 251, 6, 9, 192, 0, 6, 254, 4, 252, 2, 251, 255,
00421              251, 253, 252, 251, 254, 250, 1, 250, 3, 251, 6, 253, 8, 255, 9,
00422              2, 9, 4, 8, 6, 6 },
00423 char98[] = { 17, 246, 9, 250, 244, 250, 9, 192, 0, 250, 254, 252, 252, 254,
00424              251, 1, 251, 3, 252, 5, 254, 6, 1, 6, 3, 5, 6, 3, 8, 1, 9, 254,
00425              9, 252, 8, 250, 6 },
00426 char99[] = { 14, 247, 9, 6, 254, 4, 252, 2, 251, 255, 251, 253, 252, 251, 254,
00427              250, 1, 250, 3, 251, 6, 253, 8, 255, 9, 2, 9, 4, 8, 6, 6 },
00428 char100[] = { 17, 247, 10, 6, 244, 6, 9, 192, 0, 6, 254, 4, 252, 2, 251, 255,
00429               251, 253, 252, 251, 254, 250, 1, 250, 3, 251, 6, 253, 8, 255, 9,
00430               2, 9, 4, 8, 6, 6 },
00431 char101[] = { 17, 247, 9, 250, 1, 6, 1, 6, 255, 5, 253, 4, 252, 2, 251, 255,
00432               251, 253, 252, 251, 254, 250, 1, 250, 3, 251, 6, 253, 8, 255, 9,
00433               2, 9, 4, 8, 6, 6 },
00434 char102[] = { 8, 251, 7, 5, 244, 3, 244, 1, 245, 0, 248, 0, 9, 192, 0, 253,
00435               251, 4, 251 },
00436 char103[] = { 22, 247, 10, 6, 251, 6, 11, 5, 14, 4, 15, 2, 16, 255, 16, 253,
00437               15, 192, 0, 6, 254, 4, 252, 2, 251, 255, 251, 253, 252, 251,
00438               254, 250, 1, 250, 3, 251, 6, 253, 8, 255, 9, 2, 9, 4, 8, 6, 6 },
00439 char104[] = { 10, 247, 10, 251, 244, 251, 9, 192, 0, 251, 255, 254, 252, 0,
00440               251, 3, 251, 5, 252, 6, 255, 6, 9 },
00441 char105[] = { 8, 252, 4, 255, 244, 0, 245, 1, 244, 0, 243, 255, 244, 192, 0,
00442               0, 251, 0, 9 },
00443 char106[] = { 11, 251, 5, 0, 244, 1, 245, 2, 244, 1, 243, 0, 244, 192, 0, 1,
00444               251, 1, 12, 0, 15, 254, 16, 252, 16 },
00445 char107[] = { 8, 247, 8, 251, 244, 251, 9, 192, 0, 5, 251, 251, 5, 192, 0,
00446               255, 1, 6, 9 },
00447 char108[] = { 2, 252, 4, 0, 244, 0, 9 },
00448 char109[] = { 18, 241, 15, 245, 251, 245, 9, 192, 0, 245, 255, 248, 252, 250,
00449               251, 253, 251, 255, 252, 0, 255, 0, 9, 192, 0, 0, 255, 3, 252,
00450               5, 251, 8, 251, 10, 252, 11, 255, 11, 9 },
00451 char110[] = { 10, 247, 10, 251, 251, 251, 9, 192, 0, 251, 255, 254, 252, 0,
00452               251, 3, 251, 5, 252, 6, 255, 6, 9 },
00453 char111[] = { 17, 247, 10, 255, 251, 253, 252, 251, 254, 250, 1, 250, 3, 251,
00454               6, 253, 8, 255, 9, 2, 9, 4, 8, 6, 6, 7, 3, 7, 1, 6, 254, 4, 252,
00455               2, 251, 255, 251 },
00456 char112[] = { 17, 246, 9, 250, 251, 250, 16, 192, 0, 250, 254, 252, 252, 254,
00457               251, 1, 251, 3, 252, 5, 254, 6, 1, 6, 3, 5, 6, 3, 8, 1, 9, 254,
00458               9, 252, 8, 250, 6 },
00459 char113[] = { 17, 247, 10, 6, 251, 6, 16, 192, 0, 6, 254, 4, 252, 2, 251, 255,
00460               251, 253, 252, 251, 254, 250, 1, 250, 3, 251, 6, 253, 8, 255, 9,
00461               2, 9, 4, 8, 6, 6 },
00462 char114[] = { 8, 249, 6, 253, 251, 253, 9, 192, 0, 253, 1, 254, 254, 0, 252,
00463               2, 251, 5, 251 },
00464 char115[] = { 17, 248, 9, 6, 254, 5, 252, 2, 251, 255, 251, 252, 252, 251,
00465               254, 252, 0, 254, 1, 3, 2, 5, 3, 6, 5, 6, 6, 5, 8, 2, 9, 255, 9,
00466               252, 8, 251, 6 },
00467 char116[] = { 8, 251, 7, 0, 244, 0, 5, 1, 8, 3, 9, 5, 9, 192, 0, 253, 251, 4,
00468               251 },
00469 char117[] = { 10, 247, 10, 251, 251, 251, 5, 252, 8, 254, 9, 1, 9, 3, 8, 6, 5,
00470               192, 0, 6, 251, 6, 9 },
00471 char118[] = { 5, 248, 8, 250, 251, 0, 9, 192, 0, 6, 251, 0, 9 },
00472 char119[] = { 11, 245, 11, 248, 251, 252, 9, 192, 0, 0, 251, 252, 9, 192, 0,
00473               0, 251, 4, 9, 192, 0, 8, 251, 4, 9 },
00474 char120[] = { 5, 248, 9, 251, 251, 6, 9, 192, 0, 6, 251, 251, 9 },
00475 char121[] = { 9, 248, 8, 250, 251, 0, 9, 192, 0, 6, 251, 0, 9, 254, 13, 252,
00476               15, 250, 16, 249, 16 },
00477 char122[] = { 8, 248, 9, 6, 251, 251, 9, 192, 0, 251, 251, 6, 251, 192, 0,
00478               251, 9, 6, 9 },
00479 char123[] = { 39, 249, 7, 2, 240, 0, 241, 255, 242, 254, 244, 254, 246, 255,
00480               248, 0, 249, 1, 251, 1, 253, 255, 255, 192, 0, 0, 241, 255, 243,
00481               255, 245, 0, 247, 1, 248, 2, 250, 2, 252, 1, 254, 253, 0, 1, 2,
00482               2, 4, 2, 6, 1, 8, 0, 9, 255, 11, 255, 13, 0, 15, 192, 0, 255, 1,
00483               1, 3, 1, 5, 0, 7, 255, 8, 254, 10, 254, 12, 255, 14, 0, 15, 2,
00484               16 },
00485 char124[] = { 2, 252, 4, 0, 240, 0, 16 },
00486 char125[] = { 39, 249, 7, 254, 240, 0, 241, 1, 242, 2, 244, 2, 246, 1, 248, 0,
00487               249, 255, 251, 255, 253, 1, 255, 192, 0, 0, 241, 1, 243, 1, 245,
00488               0, 247, 255, 248, 254, 250, 254, 252, 255, 254, 3, 0, 255, 2,
00489               254, 4, 254, 6, 255, 8, 0, 9, 1, 11, 1, 13, 0, 15, 192, 0, 1, 1,
00490               255, 3, 255, 5, 0, 7, 1, 8, 2, 10, 2, 12, 1, 14, 0, 15, 254, 16,
00491               },
00492 char126[] = { 23, 255, 21, 2, 1, 0, 255, 1, 253, 3, 251, 5, 251, 7, 252,
00493               11, 255, 13, 0, 15, 0, 17, 255, 18, 254, 192, 0, 2, 0, 1,
00494               254, 3, 253, 5, 253, 7, 254, 11, 1, 13, 2, 15, 2, 17, 1, 18,
00495               255, 18, 252 };
00496 
00497 /*-------------------------------------------------------------------------------*/
00498 
00499 /*! Pointers to character definition tables. */
00500 
00501 static unsigned char *ctab[] = {
00502     char32, char33, char34, char35, char36, char37, char38, char39, char40,
00503     char41, char42, char43, char44, char45, char46, char47, char48, char49,
00504     char50, char51, char52, char53, char54, char55, char56, char57, char58,
00505     char59, char60, char61, char62, char63, char64, char65, char66, char67,
00506     char68, char69, char70, char71, char72, char73, char74, char75, char76,
00507     char77, char78, char79, char80, char81, char82, char83, char84, char85,
00508     char86, char87, char88, char89, char90, char91, char92, char93, char94,
00509     char95, char96, char97, char98, char99, char100, char101, char102,
00510     char103, char104, char105, char106, char107, char108, char109, char110,
00511     char111, char112, char113, char114, char115, char116, char117, char118,
00512     char119, char120, char121, char122, char123, char124, char125, char126
00513 };
00514 
00515 /*! Table used to look up sine of angles from 0 through 90 degrees.
00516    The value returned is the sine * 65536.  Symmetry is used to
00517    obtain sine and cosine for arbitrary angles using this table. */
00518 
00519 static long sintab[] = {
00520     0, 1143, 2287, 3429, 4571, 5711, 6850, 7986, 9120, 10252, 11380,
00521     12504, 13625, 14742, 15854, 16961, 18064, 19160, 20251, 21336,
00522     22414, 23486, 24550, 25606, 26655, 27696, 28729, 29752, 30767,
00523     31772, 32768, 33753, 34728, 35693, 36647, 37589, 38521, 39440,
00524     40347, 41243, 42125, 42995, 43852, 44695, 45525, 46340, 47142,
00525     47929, 48702, 49460, 50203, 50931, 51643, 52339, 53019, 53683,
00526     54331, 54963, 55577, 56175, 56755, 57319, 57864, 58393, 58903,
00527     59395, 59870, 60326, 60763, 61183, 61583, 61965, 62328, 62672,
00528     62997, 63302, 63589, 63856, 64103, 64331, 64540, 64729, 64898,
00529     65047, 65176, 65286, 65376, 65446, 65496, 65526, 65536
00530 };
00531 
00532 /*----------------------------------------------------------------------------*/
00533 
00534 /*! Return sine of an angle in integral degrees.  The
00535     value returned is 65536 times the sine.  */
00536 
00537 static long isin(int deg)
00538 {
00539     /* Domain reduce to 0 to 360 degrees. */
00540 
00541     if (deg < 0) {
00542         deg = (360 - ((- deg) % 360)) % 360;
00543     } else if (deg >= 360) {
00544         deg = deg % 360;
00545     }
00546 
00547     /* Now look up from table according to quadrant. */
00548 
00549     if (deg <= 90) {
00550         return sintab[deg];
00551     } else if (deg <= 180) {
00552         return sintab[180 - deg];
00553     } else if (deg <= 270) {
00554         return -sintab[deg - 180];
00555     }
00556     return -sintab[360 - deg];
00557 }
00558 
00559 /*-------------------------------------------------------------------------------*/
00560 
00561 /*! Return cosine of an angle in integral degrees.  The
00562       value returned is 65536 times the cosine.  */
00563 
00564 static long icos(int deg) { return isin(deg + 90); }
00565 
00566 /*-------------------------------------------------------------------------------*/
00567 
00568 #define Schar(x) (u = (x), (((u) & 0x80) ? ((u) | (-1 ^ 0xFF)) : (u)))
00569 
00570 #define Scalef 21       /* Font design size */
00571 #define Descend 9       /* Descender offset */
00572 
00573 /*----------------------------------------------------------------------------*/
00574 
00575 /*! Draw the zero-terminated  string  s, with  its  baseline
00576     starting at point  (x, y), inclined by angle degrees to
00577     the X axis, with letters height pixels  high (descenders
00578     will extend below the baseline).  ppmd_line does the actual drawing */
00579 
00580 static
00581 void ppmd_text(byte *pixels, int cols, int rows,
00582                int x, int y, int height, int angle, char *s, byte r,byte g,byte b )
00583 {
00584     int xpos = x, ypos = y;
00585     long rotsin, rotcos;
00586 
00587     x = y = 0;
00588     rotsin = isin(-angle);
00589     rotcos = icos(-angle);
00590     while (*s) {
00591         unsigned char ch = *s++;
00592         int pen = 1;
00593         int u;
00594 
00595         if (ch >= ' ' && ch < 127) {
00596             ch -= ' ';
00597             if (ctab[ch] != NULL) {
00598                 int cn = *ctab[ch];
00599                 unsigned char *cst = ctab[ch] + 3;
00600                 int lx, ly;
00601 
00602                 x -= Schar(*(ctab[ch] + 1));
00603                 lx = x + Schar(*cst++);
00604                 ly = y + Schar(*cst++);
00605                 while (--cn > 0) {
00606                     if (*cst == 192) {
00607                         pen = 0;
00608                         cst += 2;
00609                     } else {
00610                         int nx = x + Schar(*cst++);
00611                         int ny = y + Schar(*cst++);
00612                         if (pen) {
00613                             int mx1, my1, mx2, my2;
00614                             int tx1, ty1, tx2, ty2;
00615 
00616                             /* Note that up until this  moment  we've  been
00617                                working  in  an  arbitrary model co-ordinate
00618                                system with  fixed  size  and  no  rotation.
00619                                Before  drawing  the  stroke,  transform  to
00620                                viewing co-ordinates to  honour  the  height
00621                                and angle specifications. */
00622 
00623                             mx1 = (lx * height) / Scalef;
00624                             my1 = ((ly - Descend) * height) / Scalef;
00625                             mx2 = (nx * height) / Scalef;
00626                             my2 = ((ny - Descend) * height) / Scalef;
00627                             tx1 = xpos + (mx1 * rotcos - my1 * rotsin) / 65536;
00628                             ty1 = ypos + (mx1 * rotsin + my1 * rotcos) / 65536;
00629                             tx2 = xpos + (mx2 * rotcos - my2 * rotsin) / 65536;
00630                             ty2 = ypos + (mx2 * rotsin + my2 * rotcos) / 65536;
00631                             ppmd_line(pixels, cols, rows, tx1, ty1, tx2, ty2, r,g,b ) ;
00632                         }
00633                         lx = nx;
00634                         ly = ny;
00635                         pen = 1;
00636                     }
00637                 }
00638                 x += *(ctab[ch] + 2);
00639             }
00640         } else if (ch == '\n') {
00641             y += Scalef + Descend;
00642             x = 0;
00643         }
00644     }
00645 }
00646 
00647 /******************************************************************************/
00648 /*************** Interfaces that use mrilib.h images **************************/
00649 /******************************************************************************/
00650 
00651 /*----------------------------------------------------------------------------*/
00652 /*! Draw a line into an RGB image.
00653     - x0,y0 = start pixel coords
00654     - x1,y1 = end pixel coords
00655     - r,g,b = line color
00656 ------------------------------------------------------------------------------*/
00657 
00658 void mri_drawline( MRI_IMAGE *im, int x0,int y0, int x1,int y1, byte r,byte g,byte b )
00659 {
00660 ENTRY("mri_drawline") ;
00661    if( im == NULL || im->kind != MRI_rgb ) EXRETURN ;
00662    ppmd_line( MRI_RGB_PTR(im), im->nx, im->ny, x0,y0,x1,y1, r,g,b ) ;
00663    EXRETURN ;
00664 }
00665 
00666 /*----------------------------------------------------------------------------*/
00667 
00668 void mri_drawfilledrectangle( MRI_IMAGE *im,
00669                               int x, int y, int width, int height,
00670                               byte r,byte g,byte b )
00671 {
00672 ENTRY("mri_drawfilledrectangle") ;
00673    if( im == NULL || im->kind != MRI_rgb ) EXRETURN ;
00674    ppmd_filledrectangle( MRI_RGB_PTR(im), im->nx, im->ny, x,y,width,height, r,g,b ) ;
00675    EXRETURN ;
00676 }
00677 
00678 /*----------------------------------------------------------------------------*/
00679 
00680 void mri_drawemptyrectangle( MRI_IMAGE *im,
00681                              int x, int y, int width, int height,
00682                              byte r,byte g,byte b )
00683 {
00684     register int cx, cy, cwidth, cheight, col, row;
00685 
00686 ENTRY("mri_drawemptyrectangle") ;
00687     if( im == NULL || im->kind != MRI_rgb ) EXRETURN ;
00688 
00689     /* Clip. */
00690     cx = x; cy = y; cwidth = width; cheight = height;
00691     if ( cx < 0 ) { cx = 0; cwidth += x; }
00692     if ( cy < 0 ) { cy = 0; cheight += y; }
00693     if ( cx + cwidth > im->nx ) cwidth = im->nx - cx;
00694     if ( cy + cheight > im->ny ) cheight = im->ny - cy;
00695 
00696     ppmd_line( MRI_RGB_PTR(im),im->nx,im->ny,cx      ,cy       ,cx+width,cy       ,r,g,b);
00697     ppmd_line( MRI_RGB_PTR(im),im->nx,im->ny,cx+width,cy       ,cx+width,cy+height,r,g,b);
00698     ppmd_line( MRI_RGB_PTR(im),im->nx,im->ny,cx+width,cy+height,cx      ,cy+height,r,g,b);
00699     ppmd_line( MRI_RGB_PTR(im),im->nx,im->ny,cx      ,cy+height,cx      ,cy       ,r,g,b);
00700     EXRETURN ;
00701 }
00702 
00703 /*----------------------------------------------------------------------------*/
00704 /*! Draw text into an RGB image.
00705     - x,y = pixel coords of baseline start
00706     - height = pixel height of characters
00707     - angle = degrees of inclination of baseline to x-axis
00708     - s = string to draw
00709     - r,g,b = color to draw in
00710 ------------------------------------------------------------------------------*/
00711 
00712 void mri_drawtext( MRI_IMAGE *im ,
00713                    int x, int y, int height, int angle, char *s,
00714                    byte r,byte g,byte b )
00715 {
00716 ENTRY("mri_drawtext") ;
00717     if( im == NULL || im->kind != MRI_rgb ) EXRETURN ;
00718     ppmd_text( MRI_RGB_PTR(im), im->nx,im->ny, x,y,height,angle , s , r,g,b ) ;
00719     EXRETURN ;
00720 }
 

Powered by Plone

This site conforms to the following standards: