1 #include "mrilib.h"
2 #include <string.h>
3 
4 #define MMAX 82   /* max # colors */
5 #define NOUT 61   /* max # chars per output line */
6 
7 static byte rmap[MMAX], gmap[MMAX], bmap[MMAX] ;          /* color map */
8 
9 static char alpha[MMAX] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"    /* color codes */
10                           "abcdefghijklmnopqrstuvwxyz"    /* do not use */
11                           ",<.>/?;:'[{]}|=+-_)(*&^%$#@!`~" ; /* digits */
12 
13 static char num[10] = "0123456789" ;                      /* number codes */
14 
15 static MRI_IMAGE * SPLASH_decodexx( int , int , int , int ,
16                                     byte *, byte *, byte * , char ** ) ;
17 
18 #include "splash_blank_new.h"
19 
main(int argc,char * argv[])20 int main( int argc , char * argv[] )
21 {
22    MRI_IMAGE *im ;
23    byte *bp , rr,bb,gg ;
24    int ii,jj,nmap,kk , nn , qq , nlin=0 ;
25    char out[NOUT+1] , zout[NOUT+1] , cc,nc , *nam ;
26 
27    if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
28      printf("Usage: toxx NAME input.ppm > output.xx\n"
29             "Converts a PPM image to an 'xx' (C header) image\n"
30             "for use in afni_splash.c -- NAME is the string to\n"
31             "use in the output file variables defining the data.\n"
32             "Probably get the input by\n"
33             "  ppmquant xx image.ppm > input.ppm\n"
34             "where 'xx' is the number of colors to use.\n"
35             "Max value of 'xx' is %d.\n\n" , MMAX
36            ) ;
37      printf("Alternative usage:\n"
38             "  toxx -splash > output.ppm\n"
39             "Outputs the blank AFNI splash screen to a PPM image.\n"
40             "The .xx data for this is stored in splash_blank_new.h\n"
41            ) ;
42      exit(0);
43    }
44 
45    /*----- alternative usage -----*/
46 
47    if( strcasecmp(argv[1],"-splash") == 0 ){  /* 30 Nov 2009 */
48      MRI_IMAGE *imspl ;
49      imspl = SPLASH_decodexx( NX_blank, NY_blank, NLINE_blank, NC_blank,
50                               RMAP_blank,GMAP_blank,BMAP_blank, BAR_blank ) ;
51      if( imspl == NULL ) ERROR_exit("Can't create splash image?!") ;
52      mri_write_pnm( "-" , imspl ) ; /* to stdout */
53      exit(0) ;
54    }
55 
56    /*----- normal usage -----*/
57 
58    nam = argv[1] ;
59    im = mri_read( argv[2] ) ;
60    if( im == NULL ){
61      fprintf(stderr,"** Can't read file %s\n",argv[2]); exit(1);
62    }
63    switch( im->kind ){
64      case MRI_rgb:
65        INFO_message("Input is color %dx%d",im->nx,im->ny) ;
66      break ;
67      case MRI_byte:{
68        MRI_IMAGE *qim = mri_to_rgb(im) ;
69        mri_free(im) ; im = qim ;
70        INFO_message("Input is grayscale %dx%d",im->nx,im->ny) ;
71      }
72      break ;
73      default:
74        ERROR_exit("Input %s is wrong kind of image!",argv[2]) ;
75    }
76    bp = MRI_RGB_PTR(im) ;
77 
78    /*--- build color map (MMAX or fewer entries allowed) ---*/
79 
80    rmap[0] = bp[0] ; gmap[0] = bp[1] ; bmap[0] = bp[2] ;
81 
82    for( ii=nmap=1 ; ii < im->nvox ; ii++ ){
83      rr = bp[3*ii] ; gg = bp[3*ii+1] ; bb = bp[3*ii+2] ;
84      for( kk=0 ; kk < nmap ; kk++ ){
85        if( rr==rmap[kk] && gg==gmap[kk] && bb==bmap[kk] ) break ;
86      }
87      if( kk == nmap ){  /* new color */
88        if( nmap == MMAX )
89          ERROR_exit("Too many colors (> %d) in input %s\n",MMAX,argv[2]) ;
90        rmap[nmap] = rr ; gmap[nmap] = gg ; bmap[nmap] = bb ;
91        nmap++ ;
92      }
93    }
94 
95    INFO_message("Input has %d distinct colors",nmap) ;
96 
97    /*--- print header ---*/
98 
99    nn = 0 ; qq = 0 ;
100    printf( "#define NX_%s %d\n",nam,im->nx) ;
101    printf( "#define NY_%s %d\n",nam,im->ny) ;
102    printf( "#define NC_%s %d\n",nam,nmap  ) ;
103 
104    printf( "static byte RMAP_%s[] = {\n " , nam ) ;
105    for( kk=0 ; kk < nmap ; kk++ )
106      printf("%d%s",(int)rmap[kk] , (kk==nmap-1) ? "};\n" : "," ) ;
107 
108    printf( "static byte GMAP_%s[] = {\n " , nam ) ;
109    for( kk=0 ; kk < nmap ; kk++ )
110      printf("%d%s",(int)gmap[kk] , (kk==nmap-1) ? "};\n" : "," ) ;
111 
112    printf( "static byte BMAP_%s[] = {\n " , nam ) ;
113    for( kk=0 ; kk < nmap ; kk++ )
114      printf("%d%s",(int)bmap[kk] , (kk==nmap-1) ? "};\n" : "," ) ;
115 
116    /*--- print image data (BAR = byte array) ---*/
117 
118    printf( "static char *BAR_%s[] = {\n" , nam ) ;
119    for( ii=0 ; ii < im->nvox ; ii++ ){
120 
121       /* find color index kk of ii-th pixel */
122 
123       rr = bp[3*ii] ; gg = bp[3*ii+1] ; bb = bp[3*ii+2] ;
124       for( kk=0 ; kk < nmap ; kk++ ){
125         if( rr==rmap[kk] && gg==gmap[kk] && bb==bmap[kk] ) break ;
126       }
127 
128       out[nn++] = alpha[kk] ;  /* save character code for this color */
129 
130       /* when output line buffer is filled, write it */
131 
132       if( nn == NOUT && ii < im->nvox-1 ){  /* output line is full; RLE it */
133         out[nn] = '\0' ;
134         cc = out[0] ;      /* first character in output line */
135         qq = 1 ; kk = 0 ;  /* qq = repetition count; kk = pos in zout buffer */
136         for( jj=1 ; jj <= nn ; jj++ ){
137           nc = out[jj] ;   /* next character (cc = last character) */
138           if( nc == cc ){  /* same character ==> store */
139             if( qq == 9 ){ zout[kk++] = num[qq] ; zout[kk++] = cc ; qq = 0 ; }
140             qq++ ;
141           } else {         /* new character */
142             if( qq == 1 ){
143               zout[kk++] = cc ; qq = 1 ;
144             } else if( qq == 2 ){
145               zout[kk++] = cc ; zout[kk++] = cc ; qq = 1 ;
146             } else {
147               zout[kk++] = num[qq] ; zout[kk++] = cc ; qq = 1 ;
148             }
149           }
150           cc = nc ;
151         }
152         zout[kk] = '\0' ;
153         printf("   \"%s\",\n",zout) ; nlin++ ; nn = 0 ;
154       }
155    }
156 
157    /* put the last line out (no RLE here, because I'm lazy scum) */
158 
159    out[nn] = '\0' ;
160    printf("   \"%s\"\n};\n",out) ; nlin++ ;
161    printf("#define NLINE_%s %d\n",nam,nlin) ;  /* number of lines */
162    exit(0) ;
163 }
164 
165 /*--------------------------------------------------------------------------
166   Decode 'xx' data into an image.
167 ----------------------------------------------------------------------------*/
168 
SPLASH_decodexx(int nx,int ny,int nl,int nmap,byte * rmap,byte * gmap,byte * bmap,char ** imxx)169 static MRI_IMAGE * SPLASH_decodexx( int nx, int ny, int nl, int nmap,
170                                     byte *rmap, byte *gmap, byte *bmap ,
171                                     char **imxx )
172 {
173    MRI_IMAGE *im ;
174    byte *bim ;
175    int ii,jj , cc,qq , dd,ee , kk ;
176    char bb ;
177    static int first=1 , ainv[256] ;
178 
179 ENTRY("SPLASH_decodexx") ;
180 
181    if( nmap == 0 ) RETURN(NULL) ;
182 
183    if( nx < 3       || ny < 3       || nl < 3 ||
184        rmap == NULL || gmap == NULL ||
185        bmap == NULL || imxx == NULL             ) RETURN(NULL) ;
186 
187    if( first ){
188      for( ii=0 ; ii < 256 ; ii++ ) ainv[ii] = -1 ;
189      for( ii=0 ; ii < MMAX ; ii++ ){
190        bb = alpha[ii] ; ainv[bb] = ii ;
191      }
192      first = 0 ;
193    }
194 
195    im  = mri_new( nx , ny , MRI_rgb ) ;
196    bim = MRI_RGB_PTR(im) ;
197 
198    /* decode the RLE image data into a real image array */
199 
200    cc = qq = 0 ;
201    for( ii=0 ; ii < 3*im->nvox && qq < nl ; ){
202      bb = imxx[qq][cc++] ; if( bb == '\0' ) break ;
203      jj = ainv[bb] ;
204      if( jj >= 0 ){
205        bim[ii++] = rmap[jj]; bim[ii++] = gmap[jj]; bim[ii++] = bmap[jj];
206      } else {
207        dd = bb - '0' ;
208        bb = imxx[qq][cc++] ; if( bb == '\0' ) break ;
209        jj = ainv[bb] ;
210        for( ee=0 ; ee < dd && ii < 3*im->nvox ; ee++ ){
211          bim[ii++] = rmap[jj]; bim[ii++] = gmap[jj]; bim[ii++] = bmap[jj];
212        }
213      }
214      if( imxx[qq][cc] == '\0' ){ cc = 0 ; qq++ ; }
215    }
216 
217    RETURN(im) ;
218 }
219