1 #include "mrilib.h"
2 
3 /*===========================================================================*/
4 #ifndef HAVE_ZLIB
5 
zz_compress_dosave(int ii)6 void zz_compress_dosave( int ii ){return;}
zz_compress_dlev(int ii)7 void zz_compress_dlev( int ii ){return;}
zz_compress_some(int nsrc,void * ptr)8 int zz_compress_some( int nsrc, void *ptr ){return -1;}
zz_compress_all(int nsrc,char * src,char ** dest)9 int zz_compress_all( int nsrc , char *src , char **dest ){return -1;}
zz_uncompress_some(int nsrc,char * src,int ndest,char * dest)10 int zz_uncompress_some( int nsrc, char *src, int ndest, char *dest ){return -1;}
zz_uncompress_all(int nsrc,byte * src,char ** dest)11 int zz_uncompress_all( int nsrc , byte *src , char **dest ){return -1;}
zz_ncd_many(int nar,int * nsrc,char ** src)12 MRI_IMAGE * zz_ncd_many( int nar , int *nsrc , char **src ){return NULL;}
zz_ncd_pair(int n1,char * s1,int n2,char * s2)13 float zz_ncd_pair( int n1 , char *s1 , int n2 , char *s2 ){return -1.0f;}
THD_ncdfloat(int n,float * x,float * y)14 float THD_ncdfloat( int n , float *x , float *y ){return -1.0f;}
THD_ncdfloat_scl(int n,float xbot,float xtop,float * x,float ybot,float ytop,float * y)15 float THD_ncdfloat_scl( int n , float xbot,float xtop,float *x ,
16                                 float ybot,float ytop,float *y  ){return -1.0f;}
17 
array_to_zzb64(int nsrc,char * src,int linelen)18 char * array_to_zzb64( int nsrc , char *src , int linelen ){ return NULL; }
zzb64_to_array(char * zb,char ** dest)19 int    zzb64_to_array( char *zb , char **dest ){ return -1; }
20 
21 /*===========================================================================*/
22 #else  /* HAVE_ZLIB */
23 
24 #include "zlib.h"
25 
26 #define CHUNK 262144  /* 256 K */
27 
28 /*------------------------------------------------------------------------*/
29 
30 static int dosave = 1 ;
zz_compress_dosave(int ii)31 void zz_compress_dosave( int ii ){ dosave = ii ; }
32 
33 static int dlev = 6 ;
zz_compress_dlev(int ii)34 void zz_compress_dlev( int ii ){ dlev = (ii < 1 || ii > 9) ? 6 : ii ; }
35 
36 /*------------------------------------------------------------------------*/
37 /*! Start, continue, or end compressing a byte stream.
38      - Startup:  nsrc = 0, ptr == NULL
39      - Continue: nsrc > 0, ptr == (char *)source (mustn't be NULL)
40      - Finish:   nsrc < 0, ptr == (char **)dest  (might be NULL)
41      - Return value is total number of bytes in output thus far.
42        Will be 0 for Startup call, will be >= 0 for other calls.
43      - If a negative number is returned, that's bad news.
44      - On return from the Finish call, the compressed byte stream
45        will be available in *dest, if dest!=NULL, and dosave!=0;
46        the array should be free()-ed by the caller when done with it.
47 *//*----------------------------------------------------------------------*/
48 
zz_compress_some(int nsrc,void * ptr)49 int zz_compress_some( int nsrc, void *ptr )
50 {
51    static int busy=0 ; static z_stream strm;
52    static char *saved=NULL ; static unsigned int nsaved=0 ;
53    int ret ; unsigned int have; char buf[CHUNK] ;
54 
55    /**----- Startup case -----**/
56 
57    if( nsrc == 0 || (nsrc > 0 && ptr == NULL) ){
58      int lev = (nsrc < 1 || nsrc > 9) ? dlev : nsrc ;
59 
60      if( busy )
61        ERROR_message("zz_compress_some: busy during Startup!") ;
62      if( saved != NULL ){ free(saved); saved=NULL; }
63      nsaved = 0 ;
64 
65      strm.zalloc = Z_NULL ;
66      strm.zfree  = Z_NULL ;
67      strm.opaque = Z_NULL ;
68      ret = deflateInit( &strm , lev ) ;
69      if( ret != Z_OK ){
70        ERROR_message("zz_compress_none: Startup fails!") ;
71        busy = 0 ; return -1 ;
72      }
73      busy = 1 ; return 0 ;
74    }
75 
76    /**----- Continue case -----**/
77 
78    if( nsrc > 0 && ptr != NULL ){
79      if( !busy ){
80        ERROR_message("zz_compress_some: Continue from non-busy state!") ;
81        if( saved != NULL ){ free(saved); saved=NULL; nsaved=0; }
82        busy = 0 ; return -1 ;
83      }
84 
85      strm.avail_in = nsrc ;
86      strm.next_in  = ptr ;
87 
88      /** compress input data until it is all consumed **/
89 
90 /* INFO_message("zz_compress_some: nsrc=%d bytes",nsrc) ; */
91      do{
92        strm.avail_out = CHUNK ;
93        strm.next_out  = buf ;
94        ret = deflate( &strm, Z_NO_FLUSH ) ;
95        if( ret == Z_STREAM_ERROR ){
96          ERROR_message("zz_compress_some: deflate failure!") ;
97          if( saved != NULL ){ free(saved); saved=NULL; nsaved=0; }
98          busy = 0 ; deflateEnd(&strm) ; return -1 ;
99        }
100        have = CHUNK - strm.avail_out;
101        if( dosave && have > 0 ){
102          saved = (char *)realloc( saved , sizeof(char)*(nsaved+have+1) ) ;
103          memcpy( saved+nsaved , buf , have ) ;
104          nsaved += have ;
105        }
106 /* INFO_message("                  have=%u bytes",have) ; */
107      } while( strm.avail_out == 0 ) ;
108 
109      if( strm.avail_in > 0 ){
110        strm.avail_out = CHUNK ;
111        strm.next_out  = buf ;
112        ret = deflate( &strm, Z_SYNC_FLUSH ) ;
113        if( ret == Z_STREAM_ERROR ){
114          ERROR_message("zz_compress_some: deflate failure!") ;
115          if( saved != NULL ){ free(saved); saved=NULL; nsaved=0; }
116          busy = 0 ; deflateEnd(&strm) ; return -1 ;
117        }
118        have = CHUNK - strm.avail_out;
119        if( dosave && have > 0 ){
120          saved = (char *)realloc( saved , sizeof(char)*(nsaved+have+1) ) ;
121          memcpy( saved+nsaved , buf , have ) ;
122          nsaved += have ;
123        }
124 /* INFO_message("             last have=%u bytes",have) ; */
125      }
126 
127      return (int)strm.total_out ;
128    }
129 
130     /**----- Finish case -----**/
131 
132    if( nsrc < 0 ){
133      if( !busy ){
134        ERROR_message("zz_compress_some: not busy during Finish!") ;
135        if( saved != NULL ){ free(saved); saved=NULL; nsaved=0; }
136        busy = 0 ; return -1 ;
137      }
138 
139      do{
140        strm.avail_in  = 0 ;
141        strm.avail_out = CHUNK ;
142        strm.next_out  = buf ;
143        ret = deflate( &strm , Z_FINISH ) ;
144        if( ret == Z_STREAM_ERROR ){
145          ERROR_message("zz_compress_some: error during Finish!") ;
146          if( saved != NULL ){ free(saved); saved=NULL; nsaved=0; }
147          deflateEnd(&strm) ; busy = 0 ; return -1 ;
148        }
149        have = CHUNK - strm.avail_out ;
150        if( dosave && have > 0 ){
151          saved = (char *)realloc( saved , sizeof(char)*(nsaved+have+1) ) ;
152          memcpy( saved+nsaved , buf , have ) ;
153          nsaved += have ;
154        }
155 /* INFO_message("           finish have=%u bytes",have) ; */
156      } while( ret != Z_STREAM_END ) ;
157 
158      (void)deflateEnd(&strm) ;
159 
160      if( ptr != NULL && dosave ){
161        char **cpt = (char **)ptr ; *cpt = saved ; ret = (int)nsaved ;
162      } else {
163        free(saved) ; ret = (int)strm.total_out ;
164      }
165 
166      saved = NULL ; nsaved = 0 ; busy = 0 ; return ret ;
167    }
168 
169    /* should never be reached */
170 
171    ERROR_message("zz_compress_some: runoff error!") ; return -1 ;
172 }
173 
174 /*------------------------------------------------------------------------*/
175 /*! Compress all of src array into the *dest array (if not NULL).
176     Return value is size of dest array, as malloc()-ed.
177 *//*----------------------------------------------------------------------*/
178 
zz_compress_all(int nsrc,char * src,char ** dest)179 int zz_compress_all( int nsrc , char *src , char **dest )
180 {
181    int ret ;
182    zz_compress_dosave( (dest != NULL) ) ;
183    ret = zz_compress_some( 0 , NULL )   ; if( ret < 0 ) return 0 ;
184    ret = zz_compress_some( nsrc , src ) ; if( ret < 0 ) return 0 ;
185    ret = zz_compress_some( -1 , dest )  ;
186    return ret ;
187 }
188 
189 /*------------------------------------------------------------------------*/
190 /*! - Startup:  nsrc >  0, src != NULL
191     - Continue: nsrc == 0, src == don't care
192     - Finish:   nsrc <  0, src == don't care
193     - Return value = actual number of bytes stored into dest
194     - Finish calls should repeat until this value is 0, to make sure
195       that all the data has been extracted.  If you wish to stop the
196       extraction before getting all the data, call with nsrc=-666.
197     - A negative return value indicates an error.
198 *//*----------------------------------------------------------------------*/
199 
zz_uncompress_some(int nsrc,char * src,int ndest,char * dest)200 int zz_uncompress_some( int nsrc, char *src, int ndest, char *dest )
201 {
202    static int busy=0 ; static z_stream strm;
203    int ret , done ;
204 
205    if( ndest <= 0 || dest == NULL ){
206      ERROR_message("zz_uncompress_some: bad dest inputs!") ;
207      if( busy ) inflateEnd(&strm) ;
208      busy = 0 ; return -1 ;
209    }
210    if( nsrc > 0 && src == NULL ){
211      ERROR_message("zz_uncompress_some: bad src inputs!") ;
212      if( busy ) inflateEnd(&strm) ;
213      busy = 0 ; return -1 ;
214    }
215 
216    /**----- Start case -----**/
217 
218    if( nsrc > 0 ){
219      if( busy )
220        ERROR_message("zz_uncompress_some: Start call in busy state!") ;
221      busy = 0 ;
222 
223      strm.zalloc   = Z_NULL ;
224      strm.zfree    = Z_NULL ;
225      strm.opaque   = Z_NULL ;
226      strm.avail_in = nsrc ;
227      strm.next_in  = src ;
228      ret = inflateInit( &strm ) ;
229      if( ret != Z_OK ){
230        ERROR_message("zz_uncompress_some: can't initalize inflation!") ;
231        return -1 ;
232      }
233      busy = 1 ;
234    }
235 
236    if( !busy ){
237      ERROR_message("zz_uncompress_some: non-Start call in non-busy state!") ;
238      return -1 ;
239    }
240 
241    /**----- Quit right now -----**/
242 
243    if( nsrc == -666 ){
244      inflateEnd(&strm) ; busy = 0 ; return 0 ;
245    }
246 
247    /**----- Continuation -----**/
248 
249    strm.avail_out = ndest ;
250    strm.next_out  = dest ;
251    ret = inflate( &strm , (nsrc >= 0) ? Z_SYNC_FLUSH : Z_FINISH ) ;
252 /* INFO_message("inflate ret=%d",ret) ; */
253 
254    if( ret != Z_OK && ret != Z_STREAM_END ){
255      ERROR_message("zz_uncompress_some: inflation fails: %d",ret) ;
256      inflateEnd(&strm) ; busy = 0 ; return -1 ;
257    }
258    done = (ret == Z_STREAM_END) ;
259 
260    ret = ndest - strm.avail_out ;  /* number of bytes output */
261 /* ININFO_message("  #bytes = %d",ret) ; */
262 
263    if( ret == 0 ){ inflateEnd(&strm); busy = 0; } /* finished */
264 
265    if( ret == 0 && done ) ret = -1 ;
266    return ret ;
267 }
268 
269 /*------------------------------------------------------------------------*/
270 /*! Uncompress all nsrc bytes in src at once, malloc()-ing *dest;
271     the number of bytes in *dest is the return value of this function.
272 *//*----------------------------------------------------------------------*/
273 
zz_uncompress_all(int nsrc,byte * src,char ** dest)274 int zz_uncompress_all( int nsrc , byte *src , char **dest )
275 {
276    char buf[CHUNK] , *ddd=NULL ; int nbuf , nddd ;
277 
278    if( nsrc <= 0 || src == NULL || dest == NULL ) return -1 ;
279 
280 /* INFO_message("zz_uncompress_all: nsrc=%d",nsrc) ; */
281 
282    nbuf = zz_uncompress_some( nsrc , src , CHUNK , buf ) ;
283 /* ININFO_message("zz_uncompress_some returns %d",nbuf) ; */
284    if( nbuf <= 0 ) return -1 ;
285 
286    nddd = nbuf ;
287    ddd  = (char *)malloc(sizeof(char)*nddd) ;
288    memcpy( ddd , buf , nbuf ) ;
289 
290    while(1){
291      nbuf = zz_uncompress_some( 0 , NULL , CHUNK , buf ) ;
292 /* ININFO_message("zz_uncompress_some returns %d",nbuf) ; */
293      if( nbuf <= 0 ) break ;
294      ddd = (char *)realloc(ddd,sizeof(char)*(nddd+nbuf)) ;
295      memcpy(ddd+nddd,buf,nbuf) ;
296      nddd += nbuf ;
297    }
298 
299    if( nbuf == 0 ){
300      while(1){
301        nbuf = zz_uncompress_some( -1 , NULL , CHUNK , buf ) ;
302 /* ININFO_message("cleanup zz_uncompress_some returns %d",nbuf) ; */
303        if( nbuf <= 0 ) break ;
304        ddd = (char *)realloc(ddd,sizeof(char)*(nddd+nbuf)) ;
305        memcpy(ddd+nddd,buf,nbuf) ;
306        nddd += nbuf ;
307      }
308    }
309 
310 /* ININFO_message("Finally: %d bytes",nddd) ; */
311    *dest = ddd ; return nddd ;
312 }
313 
314 /*------------------------------------------------------------------------*/
315 
zz_ncd_many(int nar,int * nsrc,char ** src)316 MRI_IMAGE * zz_ncd_many( int nar , int *nsrc , char **src )
317 {
318    int ii , jj , nstop ;
319    MRI_IMAGE *fim ;
320    float     *far , *ncom , qcom,rcom , ncd ;
321    char *qbuf ;
322 
323    if( nar < 2 || nsrc == NULL || src == NULL ) return NULL ;
324 
325    for( ii=0 ; ii < nar ; ii++ )
326      if( nsrc[ii] <= 0 || src[ii] == NULL ) return NULL ;
327 
328    qbuf = getenv("ZLIB_NCD_FACTOR") ; ii = 6 ;
329    if( qbuf != NULL ){
330      ii = (int)strtol(qbuf,NULL,10) ;
331      if( ii < 1 || ii > 9 ) ii = 6 ;
332    }
333    zz_compress_dlev(ii) ;
334 
335    ncom = (float *)malloc(sizeof(float)*nar) ;
336    for( nstop=ii=0 ; ii < nar ; ii++ ){
337      nstop    = MAX( nstop , nsrc[ii] ) ;
338      ncom[ii] = zz_compress_all( nsrc[ii] , src[ii] , NULL ) ;
339      if( ncom[ii] <= 0 ){ free(ncom); return NULL; }
340    }
341 
342    qbuf = (char *)malloc(sizeof(char)*(2*nstop+16)) ;
343    fim  = mri_new( nar , nar , MRI_float ) ;
344    far  = MRI_FLOAT_PTR(fim) ;
345    for( ii=0 ; ii < nar ; ii++ ){
346      for( jj=ii+1 ; jj < nar ; jj++ ){
347        memcpy( qbuf          , src[ii] , nsrc[ii] ) ;
348        memcpy( qbuf+nsrc[ii] , src[jj] , nsrc[jj] ) ;
349        qcom = zz_compress_all( nsrc[ii]+nsrc[jj] , qbuf , NULL ) ;
350 
351        memcpy( qbuf          , src[jj] , nsrc[jj] ) ;
352        memcpy( qbuf+nsrc[jj] , src[ii] , nsrc[ii] ) ;
353        rcom = zz_compress_all( nsrc[ii]+nsrc[jj] , qbuf , NULL ) ;
354 
355        ncd = (MIN(rcom,qcom)-MIN(ncom[ii],ncom[jj])) / MAX(ncom[ii],ncom[jj]) ;
356        if( ncd > 1.0f ) ncd = 1.0f ;
357        far[ii+jj*nar] = far[jj+ii*nar] = ncd ;
358      }
359      far[ii+ii*nar] = 1.0f ;
360    }
361 
362    free(qbuf) ; free(ncom) ; return fim ;
363 }
364 
365 /*------------------------------------------------------------------------*/
366 
zz_ncd_pair(int n1,char * s1,int n2,char * s2)367 float zz_ncd_pair( int n1 , char *s1 , int n2 , char *s2 )
368 {
369    int nsrc[2] ; char *src[2] ;
370    MRI_IMAGE *fim ; float ncd , *far ;
371 
372    nsrc[0] = n1 ; src[0] = s1 ;
373    nsrc[1] = n2 ; src[1] = s2 ;
374    fim = zz_ncd_many( 2 , nsrc , src ) ;
375    if( fim == NULL ) return -1.0f ;
376    far = MRI_FLOAT_PTR(fim) ;
377    ncd = far[1] ;
378    mri_free(fim) ; return ncd ;
379 }
380 
381 /*------------------------------------------------------------------------*/
382 /*! Compute NCD between two float vectors,
383     which will be scaled to bytes in build_byteized_vectors().
384 *//*----------------------------------------------------------------------*/
385 
THD_ncdfloat_scl(int n,float xbot,float xtop,float * x,float ybot,float ytop,float * y)386 float THD_ncdfloat_scl( int n , float xbot,float xtop,float *x ,
387                                 float ybot,float ytop,float *y  )
388 {
389    MRI_IMAGE *bim ; byte *xbar,*ybar,*qbuf ; int nbar,ii ;
390    float ncd , nx,ny,nxy,nxy2 ;
391 
392 ENTRY("THD_ncdfloat_scl") ;
393 
394    /* scale data vectors to bytes (cf. thd_correlate.c) */
395 
396    bim = build_byteized_vectors( n , xbot,xtop,x , ybot,ytop,y ) ;
397    if( bim == NULL ) RETURN(1.0f) ;
398 
399    nbar = bim->nx ;
400    xbar = MRI_BYTE_PTR(bim) ;
401    ybar = xbar + nbar ;
402 
403    qbuf = (byte *)getenv("ZLIB_NCD_FACTOR") ; ii = 6 ;
404    if( qbuf != NULL ){
405      ii = (int)strtol((char *)qbuf,NULL,10) ;
406      if( ii < 1 || ii > 9 ) ii = 6 ;
407    }
408    zz_compress_dlev(ii) ;
409 
410    nx = (float)zz_compress_all( nbar , xbar , NULL ) ;
411    ny = (float)zz_compress_all( nbar , ybar , NULL ) ;
412 
413    qbuf = (byte *)malloc(2*nbar) ;
414    for( ii=0 ; ii < nbar ; ii++ ){  /* interleave */
415      qbuf[2*ii] = xbar[ii] ; qbuf[2*ii+1] = ybar[ii] ;
416    }
417    nxy  = (float)zz_compress_all( 2*nbar , qbuf , NULL ) ;
418 
419    memcpy(qbuf     ,xbar,nbar) ;    /* x then y */
420    memcpy(qbuf+nbar,ybar,nbar) ;
421    nxy2 = (float)zz_compress_all( 2*nbar , qbuf , NULL ) ;
422    nxy  = MIN(nxy,nxy2) ;
423 
424    memcpy(qbuf     ,ybar,nbar) ;    /* y then x */
425    memcpy(qbuf+nbar,xbar,nbar) ;
426    nxy2 = (float)zz_compress_all( 2*nbar , qbuf , NULL ) ;
427    nxy  = MIN(nxy,nxy2) ;
428 
429    ncd = (nxy-MIN(nx,ny)) / MAX(nx,ny) ;
430    if( ncd < 0.0f || ncd > 1.0f ) ncd = 1.0f ;
431 
432    free(qbuf) ; mri_free(bim) ; RETURN(ncd) ;
433 }
434 
435 /*------------------------------------------------------------------------*/
436 /*! Compute NCD between two float vectors, autoscaled to bytes. */
437 
THD_ncdfloat(int n,float * x,float * y)438 float THD_ncdfloat( int n , float *x , float *y )
439 {
440    return THD_ncdfloat_scl( n, 1.0f,-1.0f, x, 1.0f,-1.0f, y ) ;
441 }
442 
443 /*------------------------------------------------------------------------*/
444 /*! Compress and Base64 string-ify an input array. */
445 
array_to_zzb64(int nsrc,char * src,int linelen)446 char * array_to_zzb64( int nsrc , char *src , int linelen )
447 {
448    int nzb    ; char *zb    ;
449    int nzdest ; char *zdest ;
450 
451    if( nsrc <= 0 || src == NULL ) return NULL ;
452 
453    zz_compress_dosave(1) ; zz_compress_dlev(9) ;
454 
455    nzdest = zz_compress_all( nsrc , src , &zdest ) ;
456    if( nzdest <= 0 ) return NULL ;
457 
458    if( linelen < 4 ) B64_set_crlf(0);
459    else            { B64_set_crlf(1); B64_set_linelen(linelen); }
460 
461    B64_to_base64( nzdest , (byte *)zdest , &nzb , (byte **)(&zb) ) ;
462    free(zdest) ;
463    if( nzb <= 0 ) return NULL ;
464    return zb ;
465 }
466 
467 /*------------------------------------------------------------------------*/
468 /*! Inverse to array_to_zzb64(). */
469 
zzb64_to_array(char * zb,char ** dest)470 int zzb64_to_array( char *zb , char **dest )
471 {
472    int nzdest=0 ; byte *zdest=NULL ;
473    int nout     ; char *cout       ;
474 
475    if( zb == NULL ) return 0 ;
476 
477    B64_to_binary( strlen(zb) , (byte *)zb , &nzdest , &zdest ) ;
478 
479    if( nzdest <= 0 ) return 0 ;
480 
481    nout = zz_uncompress_all( nzdest , zdest , dest ) ;
482    free(zdest) ;
483    return nout ;
484 }
485 
486 #endif /* HAVE_ZLIB */
487 /*===========================================================================*/
488