@@ -11,7 +11,7 @@ atpdec: $(OBJS) | |||||
main.o: main.c cmap.h | main.o: main.c cmap.h | ||||
dsp.o: dsp.c filtercoeff.h filter.h | dsp.o: dsp.c filtercoeff.h filter.h | ||||
filter.o: filter.c filter.h | filter.o: filter.c filter.h | ||||
image.o: image.c | |||||
image.o: image.c satcal.h | |||||
clean: | clean: | ||||
rm -f *.o atpdec | rm -f *.o atpdec |
@@ -14,13 +14,15 @@ into a soundfile with any soundcard. | |||||
Atpdec will convert these sounfiles into .png images. | Atpdec will convert these sounfiles into .png images. | ||||
For each soundfile up to 4 images could be generated : | |||||
For each soundfile up to 6 images could be generated : | |||||
1. Raw image : contains the 2 transmitted channel images + telemetry | 1. Raw image : contains the 2 transmitted channel images + telemetry | ||||
and synchro pulses. | and synchro pulses. | ||||
2. Calibrated channel A image | 2. Calibrated channel A image | ||||
3. Calibrated channel B image | 3. Calibrated channel B image | ||||
4. False color image | |||||
4. Temperature compensed I.R image | |||||
5. False color image | |||||
6. pixel distribution statistique (usefull for false color cmap debugging). | |||||
Input soundfiles must be mono signal sampled at 11025 Hz. | Input soundfiles must be mono signal sampled at 11025 Hz. | ||||
Atpdec use libsnd to read soundfile, so any sound file format supported by libsnd | Atpdec use libsnd to read soundfile, so any sound file format supported by libsnd | ||||
@@ -32,34 +34,10 @@ Atpdec is written in plain standart C and must be very portable. | |||||
It was only tested on Linux Suse 8.2, but must work on any Unix platform. | It was only tested on Linux Suse 8.2, but must work on any Unix platform. | ||||
Just adapt the Makefile and type make (sorry no configure). | Just adapt the Makefile and type make (sorry no configure). | ||||
atpdec use libsnd, libpng and libm | |||||
atpdec use libsnd, libpng and libm. | |||||
snd.h and png.h header must be present on your system. | snd.h and png.h header must be present on your system. | ||||
If they are not on standard path, edit the include path in the Makefile. | If they are not on standard path, edit the include path in the Makefile. | ||||
USAGE | USAGE | ||||
atpdec [options] soundfile | |||||
-c file.png | |||||
Use a given colormap for false color generation. Default : Internal colormap. | |||||
-i [r|a|b|c] | |||||
Toggle raw (r) , channel A (a) , channel B (b) or false color (c) output. | |||||
Default : "abc" | |||||
-d directory | |||||
Optional images destination directory. Default : sounfile directory. | |||||
-s Output 8bits grayscale images for chanel A|B and raw images. Default :16bits | |||||
Generated image are in png format, 16 or 8bits greyscale for raw and channel A|B images, | |||||
24bits RVB for false color. | |||||
Image names are soundfilename-x.png, where x is : | |||||
-r for raw images | |||||
-satellite instrument number (1,2,3A,3B,4,5) for channel A|B images | |||||
-c for false colors. | |||||
EXAMPLE | |||||
atpdec -d test -i ac 09121333.wav | |||||
Will process the 09121333.wav file and generate channel A test/09121333-2.png and false color test/09121333-c.png image files. | |||||
see atpdec.1 man page. |
@@ -3,12 +3,11 @@ ATPDEC TODO List | |||||
- Could be useful to read data directly from /dev/dsp | - Could be useful to read data directly from /dev/dsp | ||||
- False color generation give various results , from good to very poor. | - False color generation give various results , from good to very poor. | ||||
Temperature calibration for IR channel could be helpful in this area. | |||||
- GUI : I'm not a GUI man , but if someone want to do the job .... | - GUI : I'm not a GUI man , but if someone want to do the job .... | ||||
- Optimisation : Don't do anything in order to run fast. There is plenty | - Optimisation : Don't do anything in order to run fast. There is plenty | ||||
possibility to increase performance (but on my 1.7GHz celeron , it's | |||||
room for performance improuvement (but on my 1.7GHz celeron , it's | |||||
already faster than real time...) | already faster than real time...) | ||||
@@ -2,8 +2,8 @@ | |||||
.SH NAME | .SH NAME | ||||
atpdec | atpdec | ||||
.SH OVERVIEW | .SH OVERVIEW | ||||
atpdec is a decoder for NOAA weather satellite images (ATP). | |||||
It takes soundfiles recorded from an ATP receiver and convert them into .png images. | |||||
atpdec is a decoder for NOAA POES weather satellite images. | |||||
It takes soundfiles recorded from a dedicated receiver and convert them into .png images. | |||||
.SH SYNOPSIS | .SH SYNOPSIS | ||||
.B atpdec | .B atpdec | ||||
.I "[options]" soundfiles ... | .I "[options]" soundfiles ... | ||||
@@ -14,17 +14,21 @@ It takes soundfiles recorded from an ATP receiver and convert them into .png ima | |||||
Use a private colormap for false color generation. Default : Internal colormap. | Use a private colormap for false color generation. Default : Internal colormap. | ||||
.TP | .TP | ||||
.br | .br | ||||
.B \-i [r|a|b|c] | |||||
Toggle raw (r) , channel A (a) , channel B (b) or false color (c) output. | |||||
Default : "abc" | |||||
.B \-i [r|a|b|c|t|d] | |||||
Toggle raw (r) , channel A (a) , channel B (b) , false color (c) , temperatue (t) or pixel distrubution (d) output. | |||||
Default : "ac" | |||||
.TP | .TP | ||||
.br | .br | ||||
.B \-d directory | .B \-d directory | ||||
Optional images destination directory. Default : soundfile directory. | Optional images destination directory. Default : soundfile directory. | ||||
.TP | .TP | ||||
.br | .br | ||||
.B \-s | |||||
Output 8bits grayscale image for channel A|B and raw images. Default : 16bits images. | |||||
.B \-p | |||||
Output 16bits grayscale image for channel A|B and raw images. Default : 8bits images. | |||||
.TP | |||||
.br | |||||
.B \-s n | |||||
Satellite ident : n=0 :NOOA-15 n=1 :NOAA-17 (used by Temperature compensation step).Default : NOAA17 | |||||
Generated image are in png format, 16 or 8bits greyscale for raw and channel A|B images, | Generated image are in png format, 16 or 8bits greyscale for raw and channel A|B images, | ||||
24bits RVB for false color. | 24bits RVB for false color. | ||||
@@ -32,6 +36,7 @@ Image names are soundfilename-x.png, where x is : | |||||
-r for raw images | -r for raw images | ||||
-satellite instrument number (1,2,3A,3B,4,5) for channel A|B images | -satellite instrument number (1,2,3A,3B,4,5) for channel A|B images | ||||
-c for false colors. | -c for false colors. | ||||
-d for pixel distribution stats. | |||||
.SH DESCRIPTION | .SH DESCRIPTION | ||||
@@ -46,7 +51,7 @@ into a soundfile with any soundcard. | |||||
Atpdec will convert these sounfiles into .png images. | Atpdec will convert these sounfiles into .png images. | ||||
For each soundfile up to 4 images could be generated : | |||||
For each soundfile up to 6 images could be generated : | |||||
1) Raw image : contains the 2 transmitted channel images + telemetry and synchro pulses. | 1) Raw image : contains the 2 transmitted channel images + telemetry and synchro pulses. | ||||
Raw image is not calibrated, so it could be too dark or too light depending of | Raw image is not calibrated, so it could be too dark or too light depending of | ||||
the recording level. | the recording level. | ||||
@@ -55,7 +60,11 @@ For each soundfile up to 4 images could be generated : | |||||
3) Calibrated channel B image | 3) Calibrated channel B image | ||||
4) False color image | |||||
4) Temperature compensed I.R image | |||||
5) False color image | |||||
6) Pixel distribution statistique image (for cmap debugging only). | |||||
Input soundfiles must be mono signal sampled at 11025 Hz. | Input soundfiles must be mono signal sampled at 11025 Hz. | ||||
Atpdec use libsnd to read soundfile, so any sound file format supported by libsnd | Atpdec use libsnd to read soundfile, so any sound file format supported by libsnd | ||||
@@ -125,7 +125,7 @@ int n; | |||||
} | } | ||||
mult=(double)Fi/4800.0*fr*FreqLine; | mult=(double)Fi/4800.0*fr*FreqLine; | ||||
pvbuff[n]=rsfir(&(ambuff[idxam]),rsfilter,RSFilterLen,offset,mult)*RSMULT/2.0; | |||||
pvbuff[n]=rsfir(&(ambuff[idxam]),rsfilter,RSFilterLen,offset,mult)*RSMULT*128.0; | |||||
shift=(int)((RSMULT-offset+mult-1)/mult); | shift=(int)((RSMULT-offset+mult-1)/mult); | ||||
offset=shift*mult+offset-RSMULT; | offset=shift*mult+offset-RSMULT; | ||||
@@ -61,7 +61,7 @@ return(sf_read_float(inwav,sample,nb)); | |||||
} | } | ||||
png_text text_ptr[2]={ | png_text text_ptr[2]={ | ||||
{ PNG_TEXT_COMPRESSION_NONE, "Software", "atpdec (Thierry Leconte)",35 } | |||||
{ PNG_TEXT_COMPRESSION_NONE, "Software", "atpdec (c) Thierry Leconte 2003",32 } | |||||
}; | }; | ||||
static int ImageOut(char *filename,float **prow,int nrow,int depth,int width,int offset) | static int ImageOut(char *filename,float **prow,int nrow,int depth,int width,int offset) | ||||
{ | { | ||||
@@ -110,10 +110,10 @@ for(n=0;n<nrow;n++) { | |||||
pv=pixelv[i+offset]; | pv=pixelv[i+offset]; | ||||
switch(depth) { | switch(depth) { | ||||
case 8 : | case 8 : | ||||
pixel[i]=(png_byte)(pv*255.0); | |||||
pixel[i]=(png_byte)pv; | |||||
break; | break; | ||||
case 16 : | case 16 : | ||||
((unsigned short*)pixel)[i]=htons((unsigned short)(pv*65535.0)); | |||||
((unsigned short*)pixel)[i]=htons((unsigned short)(pv*255.0)); | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
@@ -170,8 +170,8 @@ for(n=0;n<nrow;n++) { | |||||
for(i=0;i<909;i++) { | for(i=0;i<909;i++) { | ||||
int x,y; | int x,y; | ||||
y=(int)(pixelv[i+85]*255.0); | |||||
x=(int)(pixelv[i+1125]*255.0); | |||||
y=(int)(pixelv[i+85]); | |||||
x=(int)(pixelv[i+1125]); | |||||
pixel[i]=cmap[y][x]; | pixel[i]=cmap[y][x]; | ||||
} | } | ||||
png_write_row(png_ptr,(png_bytep)pixel); | png_write_row(png_ptr,(png_bytep)pixel); | ||||
@@ -239,10 +239,9 @@ png_destroy_read_struct(&png_ptr,&info_ptr,NULL); | |||||
return(0); | return(0); | ||||
} | } | ||||
#ifdef DEBUG | |||||
unsigned int distrib[256][256]; | |||||
int Distrib(char *filename,float **prow,int nrow) | |||||
static int Distrib(char *filename,float **prow,int nrow) | |||||
{ | { | ||||
unsigned int distrib[256][256]; | |||||
int n; | int n; | ||||
int x,y; | int x,y; | ||||
int max=0; | int max=0; | ||||
@@ -254,23 +253,21 @@ for(y=0;y<256;y++) | |||||
for(n=0;n<nrow;n++) { | for(n=0;n<nrow;n++) { | ||||
float *pixelv; | float *pixelv; | ||||
png_color pixel[909]; | |||||
int i; | int i; | ||||
pixelv=prow[n]; | pixelv=prow[n]; | ||||
for(i=0;i<909;i++) { | for(i=0;i<909;i++) { | ||||
y=(int)(pixelv[i+85]*255.0); | |||||
x=(int)(pixelv[i+1125]*255.0); | |||||
if(x>255) x=255; | |||||
if(x<0) x=0; | |||||
if(y>255) y=255; | |||||
if(y<0) y=0; | |||||
y=(int)(pixelv[i+85]); | |||||
x=(int)(pixelv[i+1125]); | |||||
distrib[y][x]+=1; | distrib[y][x]+=1; | ||||
if(distrib[y][x]> max) max=distrib[y][x]; | if(distrib[y][x]> max) max=distrib[y][x]; | ||||
} | } | ||||
} | } | ||||
df=fopen(filename,"w"); | df=fopen(filename,"w"); | ||||
printf("Writing %s\n",filename); | |||||
fprintf(df,"P2\n#max %d\n",max); | fprintf(df,"P2\n#max %d\n",max); | ||||
fprintf(df,"256 256\n255\n"); | fprintf(df,"256 256\n255\n"); | ||||
for(y=0;y<256;y++) | for(y=0;y<256;y++) | ||||
@@ -278,28 +275,35 @@ for(y=0;y<256;y++) | |||||
fprintf(df,"%d\n",(int)((255.0*(double)(distrib[y][x]))/(double)max)); | fprintf(df,"%d\n",(int)((255.0*(double)(distrib[y][x]))/(double)max)); | ||||
fclose(df); | fclose(df); | ||||
} | } | ||||
#endif | |||||
extern int Calibrate(float **prow,int nrow,int offset); | extern int Calibrate(float **prow,int nrow,int offset); | ||||
extern int Temperature(float **prow,int nrow,int ch, int offset); | |||||
extern int optind,opterr; | extern int optind,opterr; | ||||
extern char *optarg; | extern char *optarg; | ||||
int satnum=1; | |||||
static void usage(void) | |||||
{ | |||||
fprintf(stderr,"atpdec [options] soundfiles ...\n"); | |||||
fprintf(stderr,"options:\n-d directory\n-i [a|b|c|t|d]\n-c cmap.png\n-p\n-s satnumber\n"); | |||||
} | |||||
main(int argc, char **argv) | main(int argc, char **argv) | ||||
{ | { | ||||
char pngfilename[1024]; | char pngfilename[1024]; | ||||
char name[1024]; | char name[1024]; | ||||
char *pngdirname=NULL; | char *pngdirname=NULL; | ||||
char imgopt[20]="abc"; | |||||
char imgopt[20]="ac"; | |||||
float *prow[3000]; | float *prow[3000]; | ||||
const char *chid[6]={ "1","2","3A","4","5","3B"}; | const char *chid[6]={ "1","2","3A","4","5","3B"}; | ||||
int depth=16; | |||||
int depth=8; | |||||
int n,nrow; | int n,nrow; | ||||
int ch; | int ch; | ||||
int c; | int c; | ||||
opterr=0; | opterr=0; | ||||
while ((c=getopt(argc,argv,"c:d:i:s"))!=EOF) { | |||||
while ((c=getopt(argc,argv,"c:d:i:ps:"))!=EOF) { | |||||
switch(c) { | switch(c) { | ||||
case 'd': | case 'd': | ||||
pngdirname=optarg; | pngdirname=optarg; | ||||
@@ -310,9 +314,18 @@ while ((c=getopt(argc,argv,"c:d:i:s"))!=EOF) { | |||||
case 'i': | case 'i': | ||||
strcpy(imgopt,optarg); | strcpy(imgopt,optarg); | ||||
break; | break; | ||||
case 'p': | |||||
depth=16; | |||||
break; | |||||
case 's': | case 's': | ||||
depth=8; | |||||
satnum=atoi(optarg); | |||||
if(satnum<0 || satnum > 1) { | |||||
fprintf(stderr,"invalid satellite\n"); | |||||
exit(1); | |||||
} | |||||
break; | break; | ||||
default: | |||||
usage(); | |||||
} | } | ||||
} | } | ||||
@@ -346,12 +359,12 @@ sf_close(inwav); | |||||
/* raw image */ | /* raw image */ | ||||
if(strchr(imgopt,(int)'r')!=NULL){ | if(strchr(imgopt,(int)'r')!=NULL){ | ||||
sprintf(pngfilename,"%s/%s.png",pngdirname,name); | |||||
sprintf(pngfilename,"%s/%s-r.png",pngdirname,name); | |||||
ImageOut(pngfilename,prow,nrow,depth,2080,0); | ImageOut(pngfilename,prow,nrow,depth,2080,0); | ||||
} | } | ||||
/* Channel A */ | /* Channel A */ | ||||
if(((strchr(imgopt,(int)'a')!=NULL) || (strchr(imgopt,(int)'c')!=NULL))) { | |||||
if(((strchr(imgopt,(int)'a')!=NULL) || (strchr(imgopt,(int)'c')!=NULL) || (strchr(imgopt,(int)'d')!=NULL))) { | |||||
ch=Calibrate(prow,nrow,85); | ch=Calibrate(prow,nrow,85); | ||||
if(ch>0) { | if(ch>0) { | ||||
a=1; | a=1; | ||||
@@ -366,18 +379,26 @@ if(((strchr(imgopt,(int)'a')!=NULL) || (strchr(imgopt,(int)'c')!=NULL))) { | |||||
if(((strchr(imgopt,(int)'b')!=NULL) || (strchr(imgopt,(int)'c')!=NULL))) { | if(((strchr(imgopt,(int)'b')!=NULL) || (strchr(imgopt,(int)'c')!=NULL))) { | ||||
ch=Calibrate(prow,nrow,1125); | ch=Calibrate(prow,nrow,1125); | ||||
if(ch>0) { | if(ch>0) { | ||||
b=1; | |||||
if(strchr(imgopt,(int)'b')!=NULL) { | if(strchr(imgopt,(int)'b')!=NULL) { | ||||
sprintf(pngfilename,"%s/%s-%s.png",pngdirname,name,chid[ch]); | |||||
ImageOut(pngfilename,prow,nrow,depth,954,1125); | |||||
sprintf(pngfilename,"%s/%s-%s.png",pngdirname,name,chid[ch]); | |||||
ImageOut(pngfilename,prow,nrow,depth,954,1125); | |||||
} | |||||
} | |||||
if(ch>2) { | |||||
b=1; | |||||
Temperature(prow,nrow,ch,1125); | |||||
if(strchr(imgopt,(int)'t')!=NULL) { | |||||
sprintf(pngfilename,"%s/%s-t.png",pngdirname,name); | |||||
ImageOut(pngfilename,prow,nrow,depth,954,1125); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
#ifdef DEBUG | |||||
/* distribution */ | |||||
if(a && b && strchr(imgopt,(int)'d')!=NULL){ | |||||
sprintf(pngfilename,"%s/%s-d.pnm",pngdirname,name); | sprintf(pngfilename,"%s/%s-d.pnm",pngdirname,name); | ||||
Distrib(pngfilename,prow,nrow); | Distrib(pngfilename,prow,nrow); | ||||
#endif | |||||
} | |||||
/* color image */ | /* color image */ | ||||
if(a && b && strchr(imgopt,(int)'c')!=NULL){ | if(a && b && strchr(imgopt,(int)'c')!=NULL){ | ||||