1 #include <loader_common.h>
4 //TODO: add a color table.
5 //invert gray scale, Check if feh or qiv can do this.
6 // add option to check for datamin and datamax on the header
7 // make it more robust. datamax > datamin
8 // write the fits writer!
10 #define SWAP32(x) (x) = \
11 ((((x) & 0x000000ff ) << 24) |\
12 (((x) & 0x0000ff00 ) << 8) |\
13 (((x) & 0x00ff0000 ) >> 8) |\
14 (((x) & 0xff000000 ) >> 24))
16 void getRGB( double, double, double, short, short, DATA8 *, DATA8 *, DATA8 * );
19 load(ImlibImage * im, ImlibProgressFunction progress,
20 char progress_granularity, char immediate_load)
23 int w = 0, h = 0, alpha = 0;
30 //f = fopen(im->real_file, "rb");
31 if ( fits_open_file( &f, im->real_file, READONLY, &status) ) {
42 //char buf[256], buf2[256];
44 /* read the NAXIS1 and NAXIS2 keyword to get image size */
45 if ( fits_read_keys_lng( f, "NAXIS", 1, 2, naxes, &nfound, &status ) ){
46 fits_close_file(f, &status);
54 if (!fgets(buf, 255, f))
60 sscanf(buf, "%s %i %i %i", buf2, &w, &h, &alpha);
61 if (strcmp(buf2, "ARGB"))
67 if (!IMAGE_DIMENSIONS_OK(w, h))
69 fits_close_file(f, &status);
78 SET_FLAG(im->flags, F_HAS_ALPHA);
80 UNSET_FLAG(im->flags, F_HAS_ALPHA);
81 im->format = strdup("fits");
84 if (((!im->data) && (im->loader)) || (immediate_load) || (progress))
90 double *buffer, datamin, datamax, nullval = 0, *subim;
93 long *bin, nmax = 0, ndataok, sumpix = 0;
94 int nbin, k, kmin, mostfreq = 0, nsub;
96 char *envdmin, *envdmax;
97 short color, inv, stepx, stepy;
99 fprintf(stderr, "%s\n", im->real_file );
100 /* must set the im->data member before callign progress function */
101 ptr = im->data = malloc(w * h * sizeof(DATA32));
103 buffer = malloc( nbuffer * sizeof( double ) );
107 fits_close_file(f, &status);
112 envdmin = getenv( "DATAMIN" );
113 envdmax = getenv( "DATAMAX" );
114 if( envdmin != NULL && envdmax != NULL ){
115 datamin = atof( envdmin );
116 datamax = atof( envdmax );
117 fprintf(stderr, "ENV:data min %g, max %g\n", datamin, datamax);}
121 datamax = -HUGE_VALF;
125 if( stepx == 0 ) stepx = 1;
126 if( stepy == 0 ) stepy = 1;
128 fprintf(stderr, "subsample image: %d %d\n", stepx, stepy );
130 //Find min max and save a subsample image
133 subim = malloc( (w / stepx + 1)*(h / stepy +1)*sizeof( double ) );
134 fprintf(stderr, "image: %d %d %d \n", (w / stepx + 1) * (h / stepy + 1), w/stepx+1,h/stepy+1);
135 for (y = 0; y < h; y += stepy )
137 fits_read_img( f, TDOUBLE, fpixel, nbuffer, &nullval,
138 buffer, &anynull, &status);
139 for( x = 0; x < w; x += stepx ){
140 subim[ nsub ] = buffer[ x ];
142 if( buffer[ x ] > datamax )
143 datamax = buffer[ x ];
144 if( buffer[ x ] < datamin )
145 datamin = buffer[ x ];
147 fpixel += nbuffer * stepy;
149 fprintf(stderr, "data min %g, max %g\n", datamin, datamax);
150 fprintf(stderr, "subimage has %d pixels out of %d... %d %d\n", nsub, w*h, x/stepx, y/stepy);
152 nbin = 4 * sqrt( datamax - datamin );
153 if( nbin > 5000 ) nbin = 1000;
154 binw = ( datamax - datamin ) / nbin;
155 fprintf(stderr, "nbin and bin width:%d %g\n", nbin, binw);
156 bin = calloc( nbin, sizeof( long ) );
159 for( y = 0; y < nsub; y++ ){
160 for( k = 0; k < nbin; k++ ){
161 if( subim[ y ] >= k*binw && subim[ y ] < ( k+1 )*binw ){
170 for (y = 0; y < h; y++)
172 fits_read_img( f, TDOUBLE, fpixel, nbuffer, &nullval,
173 buffer, &anynull, &status);
174 for( x = 0; x < w; x++ ){
175 for( k = 0; k < nbin; k++ ){
176 if( buffer[ x ] >= k * binw &&
177 buffer[ x ] < ( k + 1 ) * binw ){
187 //Find most frequent pixel value
188 for( k = 0; k < nbin; k++ ){
189 if( bin[ k ] > nmax ){
193 //fprintf(stderr, "%ld ", bin[ k ] );
195 fprintf(stderr, "\nmostfreq and nmax = %d %ld ", mostfreq, nmax );
197 //Set new DATAMIN. look for FWHM on a log scale
198 nmax = log( nmax ) / 2;
199 datamin = ( mostfreq + 0.5 ) * binw;
200 for( k = mostfreq - 1; k >= 0; k-- ){
202 if( log( bin[ k ] ) < nmax ){
204 datamin = ( (kmin) + 0.5 ) * binw;
208 fprintf(stderr, "\n after fwfm log datamin, kmin: %g %d %d ", datamin,kmin, k );
209 if( k <= 0 ){ //case were we have one single peak surrounded by 0
211 datamin = ( (kmin) + 0.5 ) * binw;
214 fprintf(stderr, "\n after fwfm log datamin, kmin: %g %d ", datamin,kmin );
216 //Set new DATAMAX when we have 99.5% of the pixels accounted for
219 for( k = 0; k < kmin; k++)
221 //ndataok = h * w; //To get values closer to ds9's uncomment this
222 ndataok = 0.997 * ndataok;
223 for( k = kmin; k < nbin; k++){
225 if( sumpix > ndataok )
228 datamax = ( ( k + 1 ) + 0.5 ) * binw;
233 // use the new datamin datamax values to rescale and create imlib im
238 for (y = 0; y < h; y++)
240 fits_read_img( f, TDOUBLE, fpixel, nbuffer, &nullval,
241 buffer, &anynull, &status);
243 for( x = w - 1; x >= 0; x-- ){
244 getRGB( buffer[ x ], datamin, datamax, color, inv, &r, &g, &b);
245 if( x == w / 100 && y == h / 100 ) fprintf( stderr, "\n%d %d %d %g\n",r,g,b, buffer[ x ]);
246 *ptr = (((( (0xff << 8) | r) << 8) | g) << 8) | b ;
256 per = (char)((100 * y) / im->h);
257 if (((per - pper) >= progress_granularity) ||
261 if (!progress(im, per, 0, (y - l), im->w, l))
263 fits_close_file(f, &status);
272 fprintf(stderr, "\ndata min %g, max %g\n", datamin, datamax);
277 fits_close_file(f, &status);
282 save(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity)
286 int y, pl = 0, alpha = 0;
290 /* no image data? abort */
293 f = fopen(im->real_file, "wb");
296 if (im->flags & F_HAS_ALPHA)
298 fprintf(f, "ARGB %i %i %i\n", im->w, im->h, alpha);
300 for (y = 0; y < im->h; y++)
302 fwrite(ptr, im->w, 4, f);
309 per = (char)((100 * y) / im->h);
310 if (((per - pper) >= progress_granularity) || (y == (im->h - 1)))
313 if (!progress(im, per, 0, (y - l), im->w, l))
329 formats(ImlibLoader * l)
331 char *list_formats[] = { "fits", "fts", "fit" };
336 l->num_formats = (sizeof(list_formats) / sizeof(char *));
337 l->formats = malloc(sizeof(char *) * l->num_formats);
338 for (i = 0; i < l->num_formats; i++)
339 l->formats[i] = strdup(list_formats[i]);
343 void getRGB( double val, double min, double max, short color, short inv,
344 DATA8 *r, DATA8 *g, DATA8 *b ){
347 const float slsR[200]={0, 0.043442, 0.086883, 0.130325, 0.173767, 0.217208,
348 0.260650, 0.304092, 0.347533, 0.390975, 0.434417, 0.477858, 0.521300,
349 0.506742, 0.492183, 0.477625, 0.463067, 0.448508, 0.433950, 0.419392,
350 0.404833, 0.390275, 0.375717, 0.361158, 0.346600, 0.317717, 0.288833,
351 0.259950, 0.231067, 0.202183, 0.173300, 0.144417, 0.115533, 0.086650,
352 0.057767, 0.028883, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
353 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
354 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.033167,
355 0.066333, 0.099500, 0.132667, 0.165833, 0.199000, 0.232167, 0.265333,
356 0.298500, 0.331667, 0.364833, 0.398000, 0.430950, 0.463900, 0.496850,
357 0.529800, 0.562750, 0.595700, 0.628650, 0.661600, 0.694550, 0.727500,
358 0.760450, 0.793400, 0.810617, 0.827833, 0.845050, 0.862267, 0.879483,
359 0.896700, 0.913917, 0.931133, 0.948350, 0.965567, 0.982783, 1, 0.995725,
360 0.991450, 0.987175, 0.982900, 0.978625, 0.974350, 0.970075, 0.965800,
361 0.961525, 0.957250, 0.952975, 0.948700, 0.952975, 0.957250, 0.961525,
362 0.965800, 0.970075, 0.974350, 0.978625, 0.982900, 0.987175, 0.991450,
363 0.995725, 1, 0.998342, 0.996683, 0.995025, 0.993367, 0.991708, 0.990050,
364 0.988392, 0.986733, 0.985075, 0.983417, 0.981758, 0.980100, 0.955925,
365 0.931750, 0.907575, 0.883400, 0.859225, 0.835050, 0.810875, 0.786700,
366 0.762525, 0.738350, 0.714175, 0.690000, 0.715833, 0.741667, 0.767500,
367 0.793333, 0.819167, 0.845000, 0.870833, 0.896667, 0.922500, 0.948333,
368 0.974167, 1, 1, 1, 1, 1, 1, 1, 1};
370 const float slsG[200]={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
371 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.019817,
372 0.039633, 0.059450, 0.079267, 0.099083, 0.118900, 0.138717, 0.158533,
373 0.178350, 0.198167, 0.217983, 0.237800, 0.268533, 0.299267, 0.330000,
374 0.360733, 0.391467, 0.422200, 0.452933, 0.483667, 0.514400, 0.545133,
375 0.575867, 0.606600, 0.631733, 0.656867, 0.682000, 0.707133, 0.732267,
376 0.757400, 0.782533, 0.807667, 0.832800, 0.857933, 0.883067, 0.908200,
377 0.901908, 0.895617, 0.889325, 0.883033, 0.876742, 0.870450, 0.864158,
378 0.857867, 0.851575, 0.845283, 0.838992, 0.832700, 0.832308, 0.831917,
379 0.831525, 0.831133, 0.830742, 0.830350, 0.829958, 0.829567, 0.829175,
380 0.828783, 0.828392, 0.828000, 0.834167, 0.840333, 0.846500, 0.852667,
381 0.858833, 0.865000, 0.871167, 0.877333, 0.883500, 0.889667, 0.895833,
382 0.902000, 0.902000, 0.902000, 0.902000, 0.902000, 0.902000, 0.902000,
383 0.902000, 0.902000, 0.902000, 0.902000, 0.902000, 0.902000, 0.897133,
384 0.892267, 0.887400, 0.882533, 0.877667, 0.872800, 0.867933, 0.863067,
385 0.858200, 0.853333, 0.848467, 0.843600, 0.824892, 0.806183, 0.787475,
386 0.768767, 0.750058, 0.731350, 0.712642, 0.693933, 0.675225, 0.656517,
387 0.637808, 0.619100, 0.600408, 0.581717, 0.563025, 0.544333, 0.525642,
388 0.506950, 0.488258, 0.469567, 0.450875, 0.432183, 0.413492, 0.394800,
389 0.361900, 0.329000, 0.296100, 0.263200, 0.230300, 0.197400, 0.164500,
390 0.131600, 0.098700, 0.065800, 0.032900, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
391 0, 0, 0, 0.083333, 0.166667, 0.250000, 0.333333, 0.416667, 0.500000,
392 0.583333, 0.666667, 0.750000, 0.833333, 0.916667, 1, 1, 1, 1, 1, 1, 1,
395 const float slsB[200]={0, 0.052883, 0.105767, 0.158650, 0.211533, 0.264417,
396 0.317300, 0.370183, 0.423067, 0.475950, 0.528833, 0.581717, 0.634600,
397 0.640217, 0.645833, 0.651450, 0.657067, 0.662683, 0.668300, 0.673917,
398 0.679533, 0.685150, 0.690767, 0.696383, 0.702000, 0.712192, 0.722383,
399 0.732575, 0.742767, 0.752958, 0.763150, 0.773342, 0.783533, 0.793725,
400 0.803917, 0.814108, 0.824300, 0.838942, 0.853583, 0.868225, 0.882867,
401 0.897508, 0.912150, 0.926792, 0.941433, 0.956075, 0.970717, 0.985358,
402 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.975300, 0.950600, 0.925900,
403 0.901200, 0.876500, 0.851800, 0.827100, 0.802400, 0.777700, 0.753000,
404 0.728300, 0.703600, 0.676675, 0.649750, 0.622825, 0.595900, 0.568975,
405 0.542050, 0.515125, 0.488200, 0.461275, 0.434350, 0.407425, 0.380500,
406 0.354858, 0.329217, 0.303575, 0.277933, 0.252292, 0.226650, 0.201008,
407 0.175367, 0.149725, 0.124083, 0.098442, 0.072800, 0.066733, 0.060667,
408 0.054600, 0.048533, 0.042467, 0.036400, 0.030333, 0.024267, 0.018200,
409 0.012133, 0.006067, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.003983,
410 0.007967, 0.011950, 0.015933, 0.019917, 0.023900, 0.027883, 0.031867,
411 0.035850, 0.039833, 0.043817, 0.047800, 0.051600, 0.055400, 0.059200,
412 0.063000, 0.066800, 0.070600, 0.074400, 0.078200, 0.082000, 0.085800,
413 0.089600, 0.093400, 0.085617, 0.077833, 0.070050, 0.062267, 0.054483,
414 0.046700, 0.038917, 0.031133, 0.023350, 0.015567, 0.007783, 0, 0, 0,
415 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
416 0.083333, 0.166667, 0.250000, 0.333333, 0.416667, 0.500000, 0.583333,
417 0.666667, 0.750000, 0.833333, 0.916667, 1, 1, 1, 1, 1, 1, 1, 1};
425 fac = ( val - min ) / ( max - min );
427 if( inv ) fac = 1 - fac;
429 if( color == 0 ){ // gray
430 *r = ceil ( fac * 255 );
435 if( color == 1 ){ // color SLS
436 ind = ceil( fac * 199 ); // color table has 200 elements
437 *r = ceil( slsR[ ind ] * 255 );
438 *g = ceil( slsG[ ind ] * 255 );
439 *b = ceil( slsB[ ind ] * 255 );