@@ -1,17 +1,18 @@ | |||||
INCLUDES=-I. | INCLUDES=-I. | ||||
CFLAGS= -O4 $(INCLUDES) | |||||
CFLAGS= -O3 $(INCLUDES) | |||||
OBJS= main.o image.o dsp.o filter.o | |||||
OBJS= main.o image.o dsp.o filter.o reg.o fcolor.o | |||||
atpdec: $(OBJS) | atpdec: $(OBJS) | ||||
$(CC) -o $@ $(OBJS) -lm -lsndfile -lpng | $(CC) -o $@ $(OBJS) -lm -lsndfile -lpng | ||||
main.o: main.c cmap.h | |||||
main.o: main.c | |||||
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 satcal.h | image.o: image.c satcal.h | ||||
fcolor.o : fcolor.c | |||||
clean: | clean: | ||||
rm -f *.o atpdec | rm -f *.o atpdec |
@@ -22,10 +22,10 @@ and synchro pulses. | |||||
3. Calibrated channel B image | 3. Calibrated channel B image | ||||
4. Temperature compensed I.R image | 4. Temperature compensed I.R image | ||||
5. False color image | 5. False color image | ||||
6. pixel distribution statistique (usefull for false color cmap debugging). | |||||
6. pixel distribution statistique (usefull for false color parameter 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 libsndfile to read soundfile, so any sound file format supported by libsndfile | |||||
could be read.(Only tested with .wav file). | could be read.(Only tested with .wav file). | ||||
COMPILATION | COMPILATION | ||||
@@ -40,4 +40,46 @@ If they are not on standard path, edit the include path in the Makefile. | |||||
USAGE | USAGE | ||||
see atpdec.1 man page. | |||||
atpdec [options] soundfiles ... | |||||
OPTIONS | |||||
-i [r|a|b|c|t|d] | |||||
Toggle raw (r) , channel A (a) , channel B (b) , false color (c) , | |||||
temperature (t) or pixel distrubution (d) output. | |||||
Default : "ac" | |||||
-d directory | |||||
Optional images destination directory. | |||||
Default : soundfile directory. | |||||
-s n | |||||
Satellite ident : n=0 :NOOA-15 n=1 :NOAA-17 | |||||
Used for Temperature compensation. | |||||
Default : NOAA17 | |||||
-c conf_file | |||||
Use configuration file for false color generation. | |||||
Default : Internal parameters. | |||||
-p 8|16 | |||||
Output 16bits grayscale image for channel A|B and raw images. | |||||
Default : 8bits images. | |||||
OUTPUT | |||||
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. | |||||
-d for pixel distribution stats. | |||||
EXAMPLE | |||||
atpdec -d image -i ac *.wav | |||||
Will process all .wav files in the current directory, generate only channel A and false color images and put them in the image directory. | |||||
@@ -1,80 +0,0 @@ | |||||
.TH ATPDEC 1 "Atpdec ATP satellite image decoder" | |||||
.SH NAME | |||||
atpdec | |||||
.SH OVERVIEW | |||||
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 | |||||
.B atpdec | |||||
.I "[options]" soundfiles ... | |||||
.SH OPTIONS | |||||
.TP | |||||
.br | |||||
.B \-c file.png | |||||
Use a private colormap for false color generation. Default : Internal colormap. | |||||
.TP | |||||
.br | |||||
.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 | |||||
.br | |||||
.B \-d directory | |||||
Optional images destination directory. Default : soundfile directory. | |||||
.TP | |||||
.br | |||||
.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, | |||||
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. | |||||
-d for pixel distribution stats. | |||||
.SH DESCRIPTION | |||||
Atpdec is a open source program that decode images transmitted by POES | |||||
NOAA weather satellite serie. | |||||
These satellites transmit continuously, among other things, medium resolution | |||||
images of the earth on 137Mhz. | |||||
These transmitions could be easely received with | |||||
an inexpensive antenna and dedicated receiver. | |||||
Output from such a receiver, is an audio signal that could be recorded | |||||
into a soundfile with any soundcard. | |||||
Atpdec will convert these sounfiles into .png images. | |||||
For each soundfile up to 6 images could be generated : | |||||
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 | |||||
the recording level. | |||||
2) Calibrated channel A image | |||||
3) Calibrated channel B 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. | |||||
Atpdec use libsnd to read soundfile, so any sound file format supported by libsnd | |||||
could be read. | |||||
.SH EXAMPLE | |||||
atpdec -d image -i ac *.wav | |||||
.br | |||||
Will process all .wav files in the current directory, generate only channel A and false color images and put them in the image directory. | |||||
.SH AUTHOR | |||||
Thierry Leconte (2003) |
@@ -20,8 +20,11 @@ | |||||
* | * | ||||
*/ | */ | ||||
#include <math.h> | #include <math.h> | ||||
#include <filter.h> | |||||
#include <filtercoeff.h> | |||||
#ifndef M_PI | |||||
#define M_PI 3.14159265358979323846 /* for OS that don't know it */ | |||||
#endif | |||||
#include "filter.h" | |||||
#include "filtercoeff.h" | |||||
#define Fe 11025 | #define Fe 11025 | ||||
#define PixelLine 2080 | #define PixelLine 2080 | ||||
@@ -3,7 +3,7 @@ | |||||
typedef struct { | typedef struct { | ||||
double h,s,v; | |||||
float h,s,v; | |||||
} hsvpix_t; | } hsvpix_t; | ||||
static void HSVtoRGB( float *r, float *g, float *b, hsvpix_t pix ) | static void HSVtoRGB( float *r, float *g, float *b, hsvpix_t pix ) | ||||
@@ -48,8 +48,8 @@ static void HSVtoRGB( float *r, float *g, float *b, hsvpix_t pix ) | |||||
} | } | ||||
static struct { | static struct { | ||||
double Vthresold; | |||||
double Tthresold; | |||||
float Vthresold; | |||||
float Tthresold; | |||||
hsvpix_t CloudTop; | hsvpix_t CloudTop; | ||||
hsvpix_t CloudBot; | hsvpix_t CloudBot; | ||||
hsvpix_t SeaTop; | hsvpix_t SeaTop; | ||||
@@ -57,8 +57,8 @@ hsvpix_t SeaBot; | |||||
hsvpix_t GroundTop; | hsvpix_t GroundTop; | ||||
hsvpix_t GroundBot; | hsvpix_t GroundBot; | ||||
} fcinfo= { | } fcinfo= { | ||||
28.0, | |||||
180.0, | |||||
30.0, | |||||
170.0, | |||||
{0,0.0,0.3},{0,0.0,1.0}, | {0,0.0,0.3},{0,0.0,1.0}, | ||||
{240.0,0.9,0.5},{220.0,0.8,0.8}, | {240.0,0.9,0.5},{220.0,0.8,0.8}, | ||||
{90.0,0.8,0.3},{50.0,0.8,1.0} | {90.0,0.8,0.3},{50.0,0.8,1.0} | ||||
@@ -19,7 +19,7 @@ | |||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
* | * | ||||
*/ | */ | ||||
#include <filter.h> | |||||
#include "filter.h" | |||||
float fir( float *buff, const float *coeff, const int len) | float fir( float *buff, const float *coeff, const int len) | ||||
{ | { | ||||
@@ -34,7 +34,7 @@ static void rgcomp(double x[16], rgparam *rgpr) | |||||
{ | { | ||||
/* 0.106,0.215,0.324,0.434,0.542,0.652,0.78,0.87 ,0.0 */ | /* 0.106,0.215,0.324,0.434,0.542,0.652,0.78,0.87 ,0.0 */ | ||||
const double y[9] = { 31.1,63.0,95.0,127.2,158.9,191.1,228.6,255.0, 0.0 }; | const double y[9] = { 31.1,63.0,95.0,127.2,158.9,191.1,228.6,255.0, 0.0 }; | ||||
extern void polyreg(int m,int n,double x[],double y[],double c[]); | |||||
extern void polyreg(const int m,const int n,const double x[],const double y[],double c[]); | |||||
polyreg(REGORDER,9,x,y,rgpr->cf); | polyreg(REGORDER,9,x,y,rgpr->cf); | ||||
} | } | ||||
@@ -21,14 +21,21 @@ | |||||
*/ | */ | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <unistd.h> | |||||
#include <string.h> | |||||
#ifdef WIN32 | |||||
#include "w32util.h" | |||||
#else | |||||
#include <libgen.h> | #include <libgen.h> | ||||
#endif | |||||
#include <string.h> | |||||
#include <sndfile.h> | #include <sndfile.h> | ||||
#include <png.h> | #include <png.h> | ||||
extern getpixelrow(float *pixelv); | extern getpixelrow(float *pixelv); | ||||
#define CHA_OFFSET 86 | |||||
#define CHB_OFFSET 1126 | |||||
#define CH_WIDTH 909 | |||||
#define IMG_WIDTH 2080 | |||||
static SNDFILE *inwav; | static SNDFILE *inwav; | ||||
static int initsnd(char *filename) | static int initsnd(char *filename) | ||||
@@ -65,7 +72,7 @@ png_text text_ptr[]={ | |||||
{ PNG_TEXT_COMPRESSION_NONE, "Channel", NULL ,0 }, | { PNG_TEXT_COMPRESSION_NONE, "Channel", NULL ,0 }, | ||||
{ PNG_TEXT_COMPRESSION_NONE, "Description", "NOAA POES satellite Image" ,25 } | { PNG_TEXT_COMPRESSION_NONE, "Description", "NOAA POES satellite Image" ,25 } | ||||
}; | }; | ||||
static int ImageOut(char *filename,const char* chid,float **prow,int nrow,int depth,int width,int offset) | |||||
static int ImageOut(char *filename,char* chid,float **prow,int nrow,int depth,int width,int offset) | |||||
{ | { | ||||
FILE *pngfile; | FILE *pngfile; | ||||
png_infop info_ptr; | png_infop info_ptr; | ||||
@@ -106,7 +113,7 @@ png_write_info(png_ptr,info_ptr); | |||||
for(n=0;n<nrow;n++) { | for(n=0;n<nrow;n++) { | ||||
float *pixelv; | float *pixelv; | ||||
png_byte pixel[2*2080]; | |||||
png_byte pixel[2*IMG_WIDTH]; | |||||
int i; | int i; | ||||
pixelv=prow[n]; | pixelv=prow[n]; | ||||
@@ -155,7 +162,7 @@ info_ptr = png_create_info_struct(png_ptr); | |||||
return(1); | return(1); | ||||
} | } | ||||
png_set_IHDR(png_ptr, info_ptr, 909, nrow, | |||||
png_set_IHDR(png_ptr, info_ptr, CH_WIDTH, nrow, | |||||
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, | 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, | ||||
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); | PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); | ||||
@@ -175,16 +182,16 @@ png_write_info(png_ptr,info_ptr); | |||||
for(n=0;n<nrow;n++) { | for(n=0;n<nrow;n++) { | ||||
float *pixelv; | float *pixelv; | ||||
png_color pixel[909]; | |||||
png_color pixel[CH_WIDTH]; | |||||
int i; | int i; | ||||
pixelv=prow[n]; | pixelv=prow[n]; | ||||
for(i=0;i<909;i++) { | |||||
for(i=0;i<CH_WIDTH;i++) { | |||||
double v,t; | double v,t; | ||||
float r,g,b; | float r,g,b; | ||||
v=pixelv[i+85]; | |||||
t=pixelv[i+1125]; | |||||
v=pixelv[i+CHA_OFFSET]; | |||||
t=pixelv[i+CHB_OFFSET]; | |||||
falsecolor(v,t,&r,&g,&b); | falsecolor(v,t,&r,&g,&b); | ||||
pixel[i].red=( unsigned int)(255.0*r); | pixel[i].red=( unsigned int)(255.0*r); | ||||
pixel[i].green=( unsigned int)(255.0*g); | pixel[i].green=( unsigned int)(255.0*g); | ||||
@@ -218,8 +225,8 @@ for(n=0;n<nrow;n++) { | |||||
pixelv=prow[n]; | pixelv=prow[n]; | ||||
for(i=0;i<909;i++) { | for(i=0;i<909;i++) { | ||||
y=(int)(pixelv[i+85]); | |||||
x=(int)(pixelv[i+1125]); | |||||
y=(int)(pixelv[i+CHA_OFFSET]); | |||||
x=(int)(pixelv[i+CHB_OFFSET]); | |||||
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]; | ||||
} | } | ||||
@@ -256,7 +263,7 @@ char name[1024]; | |||||
char pngdirname[1024]=""; | char pngdirname[1024]=""; | ||||
char imgopt[20]="ac"; | char imgopt[20]="ac"; | ||||
float *prow[3000]; | float *prow[3000]; | ||||
const char *chid[6]={ "1","2","3A","4","5","3B"}; | |||||
char *chid[6]={ "1","2","3A","4","5","3B"}; | |||||
int depth=8; | int depth=8; | ||||
int n,nrow; | int n,nrow; | ||||
int ch; | int ch; | ||||
@@ -321,36 +328,36 @@ sf_close(inwav); | |||||
/* raw image */ | /* raw image */ | ||||
if(strchr(imgopt,(int)'r')!=NULL){ | if(strchr(imgopt,(int)'r')!=NULL){ | ||||
sprintf(pngfilename,"%s/%s-r.png",pngdirname,name); | sprintf(pngfilename,"%s/%s-r.png",pngdirname,name); | ||||
ImageOut(pngfilename,"raw",prow,nrow,depth,2080,0); | |||||
ImageOut(pngfilename,"raw",prow,nrow,depth,IMG_WIDTH,0); | |||||
} | } | ||||
/* Channel A */ | /* Channel A */ | ||||
if(((strchr(imgopt,(int)'a')!=NULL) || (strchr(imgopt,(int)'c')!=NULL) || (strchr(imgopt,(int)'d')!=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,CHA_OFFSET); | |||||
if(ch>0) { | if(ch>0) { | ||||
a=1; | a=1; | ||||
if(strchr(imgopt,(int)'a')!=NULL) { | if(strchr(imgopt,(int)'a')!=NULL) { | ||||
sprintf(pngfilename,"%s/%s-%s.png",pngdirname,name,chid[ch]); | sprintf(pngfilename,"%s/%s-%s.png",pngdirname,name,chid[ch]); | ||||
ImageOut(pngfilename,chid[ch],prow,nrow,depth,954,85); | |||||
ImageOut(pngfilename,chid[ch],prow,nrow,depth,CH_WIDTH,CHA_OFFSET); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
/* Channel B */ | /* Channel B */ | ||||
if((strchr(imgopt,(int)'b')!=NULL) || (strchr(imgopt,(int)'c')!=NULL) || (strchr(imgopt,(int)'t')!=NULL)) { | if((strchr(imgopt,(int)'b')!=NULL) || (strchr(imgopt,(int)'c')!=NULL) || (strchr(imgopt,(int)'t')!=NULL)) { | ||||
ch=Calibrate(prow,nrow,1125); | |||||
ch=Calibrate(prow,nrow,CHB_OFFSET); | |||||
if(ch>0) { | if(ch>0) { | ||||
if(strchr(imgopt,(int)'b')!=NULL) { | if(strchr(imgopt,(int)'b')!=NULL) { | ||||
sprintf(pngfilename,"%s/%s-%s.png",pngdirname,name,chid[ch]); | sprintf(pngfilename,"%s/%s-%s.png",pngdirname,name,chid[ch]); | ||||
ImageOut(pngfilename,chid[ch],prow,nrow,depth,954,1125); | |||||
ImageOut(pngfilename,chid[ch],prow,nrow,depth,CH_WIDTH,CHB_OFFSET); | |||||
} | } | ||||
} | } | ||||
if(ch>2) { | if(ch>2) { | ||||
b=1; | b=1; | ||||
Temperature(prow,nrow,ch,1125); | |||||
Temperature(prow,nrow,ch,CHB_OFFSET); | |||||
if(strchr(imgopt,(int)'t')!=NULL) { | if(strchr(imgopt,(int)'t')!=NULL) { | ||||
sprintf(pngfilename,"%s/%s-t.png",pngdirname,name); | sprintf(pngfilename,"%s/%s-t.png",pngdirname,name); | ||||
ImageOut(pngfilename,"Temperature", prow,nrow,depth,954,1125); | |||||
ImageOut(pngfilename,"Temperature", prow,nrow,depth,CH_WIDTH,CHB_OFFSET); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -17,7 +17,7 @@ | |||||
static void FactPiv(int N, double A[DMAX][DMAX], double B[], double Cf[]); | static void FactPiv(int N, double A[DMAX][DMAX], double B[], double Cf[]); | ||||
void polyreg(int M, int N, double X[], double Y[], double C[]) | |||||
void polyreg(const int M, const int N, const double X[], const double Y[], double C[]) | |||||
{ | { | ||||
int R, K, J; /* Loop counters */ | int R, K, J; /* Loop counters */ | ||||
double A[DMAX][DMAX]; /* A */ | double A[DMAX][DMAX]; /* A */ | ||||