@@ -70,6 +70,7 @@ Apply a falsecolor palette | |||||
-m <path> Path to WXtoImg map | -m <path> Path to WXtoImg map | ||||
-p <path> Path to palette | -p <path> Path to palette | ||||
-r Realtime decode | -r Realtime decode | ||||
-g Gamma adjustment (1.0 = off) | |||||
``` | ``` | ||||
### Image types | ### Image types | ||||
@@ -46,6 +46,7 @@ typedef struct { | |||||
int realtime; // Realtime decoding | int realtime; // Realtime decoding | ||||
char *filename; // Output filename | char *filename; // Output filename | ||||
char *palette; // Filename of palette | char *palette; // Filename of palette | ||||
float gamma; // Gamma | |||||
} options_t; | } options_t; | ||||
enum imagetypes { | enum imagetypes { | ||||
@@ -241,7 +241,7 @@ int calibrate(float **prow, int nrow, int offset, int width) { | |||||
} | } | ||||
void distrib(options_t *opts, image_t *img, char *chid) { | |||||
void distrib(options_t *opts, image_t *img, char chid) { | |||||
int max = 0; | int max = 0; | ||||
// Options | // Options | ||||
@@ -276,7 +276,7 @@ void distrib(options_t *opts, image_t *img, char *chid) { | |||||
for(int y = 0; y < 256; y++) | for(int y = 0; y < 256; y++) | ||||
distrib.prow[y][x] = distrib.prow[y][x] / max * 255.0; | distrib.prow[y][x] = distrib.prow[y][x] / max * 255.0; | ||||
extern int ImageOut(options_t *opts, image_t *img, int offset, int width, char *desc, char *chid, char *palette); | |||||
extern int ImageOut(options_t *opts, image_t *img, int offset, int width, char *desc, char chid, char *palette); | |||||
ImageOut(&options, &distrib, 0, 256, "Distribution", chid, NULL); | ImageOut(&options, &distrib, 0, 256, "Distribution", chid, NULL); | ||||
} | } | ||||
@@ -36,7 +36,7 @@ extern int getpixelrow(float *pixelv, int nrow, int *zenith, int reset); | |||||
// I/O | // I/O | ||||
extern int readRawImage(char *filename, float **prow, int *nrow); | extern int readRawImage(char *filename, float **prow, int *nrow); | ||||
extern int ImageOut(options_t *opts, image_t *img, int offset, int width, char *desc, char *chid, char *palette); | |||||
extern int ImageOut(options_t *opts, image_t *img, int offset, int width, char *desc, char chid, char *palette); | |||||
extern int initWriter(options_t *opts, image_t *img, int width, int height, char *desc, char *chid); | extern int initWriter(options_t *opts, image_t *img, int width, int height, char *desc, char *chid); | ||||
extern void pushRow(float *row, int width); | extern void pushRow(float *row, int width); | ||||
extern void closeWriter(); | extern void closeWriter(); | ||||
@@ -47,7 +47,7 @@ extern void histogramEqualise(float **prow, int nrow, int offset, int width); | |||||
extern void linearEnhance(float **prow, int nrow, int offset, int width); | extern void linearEnhance(float **prow, int nrow, int offset, int width); | ||||
extern void temperature(options_t *opts, image_t *img, int offset, int width); | extern void temperature(options_t *opts, image_t *img, int offset, int width); | ||||
extern void denoise(float **prow, int nrow, int offset, int width); | extern void denoise(float **prow, int nrow, int offset, int width); | ||||
extern void distrib(options_t *opts, image_t *img, char *chid); | |||||
extern void distrib(options_t *opts, image_t *img, char chid); | |||||
extern void flipImage(image_t *img, int width, int offset); | extern void flipImage(image_t *img, int width, int offset); | ||||
// Palettes | // Palettes | ||||
@@ -74,11 +74,11 @@ int main(int argc, char **argv) { | |||||
usage(); | usage(); | ||||
} | } | ||||
options_t opts = { "r", "", 19, "", ".", 0, "" }; | |||||
options_t opts = { "r", "", 19, "", ".", 0, "", "", 1.0 }; | |||||
// Parse arguments | // Parse arguments | ||||
int opt; | int opt; | ||||
while ((opt = getopt(argc, argv, "o:m:d:i:s:e:rp:")) != EOF) { | |||||
while ((opt = getopt(argc, argv, "o:m:d:i:s:e:p:g:r")) != EOF) { | |||||
switch (opt) { | switch (opt) { | ||||
case 'd': | case 'd': | ||||
opts.path = optarg; | opts.path = optarg; | ||||
@@ -108,6 +108,9 @@ int main(int argc, char **argv) { | |||||
case 'p': | case 'p': | ||||
opts.palette = optarg; | opts.palette = optarg; | ||||
break; | break; | ||||
case 'g': | |||||
opts.gamma = atof(optarg); | |||||
break; | |||||
default: | default: | ||||
usage(); | usage(); | ||||
} | } | ||||
@@ -296,7 +299,7 @@ static int initsnd(char *filename) { | |||||
return 1; | return 1; | ||||
} | } | ||||
// Read samples from the wave file | |||||
// Read samples from the audio file | |||||
int getsample(float *sample, int nb) { | int getsample(float *sample, int nb) { | ||||
if(channels == 1){ | if(channels == 1){ | ||||
return sf_read_float(audioFile, sample, nb); | return sf_read_float(audioFile, sample, nb); | ||||
@@ -335,6 +338,7 @@ static void usage(void) { | |||||
" -m <path> Map file\n" | " -m <path> Map file\n" | ||||
" -p <path> Path to palette\n" | " -p <path> Path to palette\n" | ||||
" -r Realtime decode\n" | " -r Realtime decode\n" | ||||
" -g Gamma adjustment (1.0 = off)\n" | |||||
"\nRefer to the README for more infomation\n"); | "\nRefer to the README for more infomation\n"); | ||||
exit(EINVAL); | exit(EINVAL); | ||||
@@ -100,12 +100,12 @@ int mapOverlay(char *filename, rgb_t **crow, int nrow, int zenith, int MCIR) { | |||||
if(MCIR){ | if(MCIR){ | ||||
if(map.b < 128 && map.g > 128){ | if(map.b < 128 && map.g > 128){ | ||||
// Land | // Land | ||||
float green = CLIP((map.g-256)/32.0, 0, 1); | |||||
float blue = 1 - CLIP((map.b-32)/64.0, 0, 1); | |||||
crow[y][cha] = (rgb_t){blue*127, 30+green*80, 40}; | |||||
float green = CLIP(map.g/300, 0, 1); | |||||
float blue = 0.15 - CLIP(map.b/960.0, 0, 1); | |||||
crow[y][cha] = (rgb_t){blue*1000, green*98, blue*500.0}; | |||||
}else{ | }else{ | ||||
// Sea | // Sea | ||||
crow[y][cha] = (rgb_t){12, 30, 85}; | |||||
crow[y][cha] = (rgb_t){9, 17, 74}; | |||||
} | } | ||||
} | } | ||||
@@ -125,7 +125,7 @@ int mapOverlay(char *filename, rgb_t **crow, int nrow, int zenith, int MCIR) { | |||||
// Cloud overlay on channel A | // Cloud overlay on channel A | ||||
if(MCIR){ | if(MCIR){ | ||||
float cloud = CLIP((crow[y][chb].r - 115) / 107, 0, 1); | |||||
float cloud = CLIP((crow[y][chb].r - 105) / 150, 0, 1); | |||||
crow[y][cha] = RGBcomposite((rgb_t){240, 250, 255}, cloud, crow[y][cha], 1); | crow[y][cha] = RGBcomposite((rgb_t){240, 250, 255}, cloud, crow[y][cha], 1); | ||||
} | } | ||||
} | } | ||||
@@ -409,6 +409,11 @@ int ImageOut(options_t *opts, image_t *img, int offset, int width, char *desc, c | |||||
printf("Writing %s", outName); | printf("Writing %s", outName); | ||||
// Float power macro (for gamma adjustment) | |||||
#define POWF(a, b) (b == 1.0 ? a : exp(b * log(a))) | |||||
float a = POWF(255, opts->gamma)/255; | |||||
// Build image | // Build image | ||||
for (int y = 0; y < img->nrow; y++) { | for (int y = 0; y < img->nrow; y++) { | ||||
png_color pix[width]; // Color | png_color pix[width]; // Color | ||||
@@ -416,17 +421,16 @@ int ImageOut(options_t *opts, image_t *img, int offset, int width, char *desc, c | |||||
int skip = 0; | int skip = 0; | ||||
for (int x = 0; x < width; x++) { | for (int x = 0; x < width; x++) { | ||||
if(crop_telemetry && x == CH_WIDTH){ | |||||
if(crop_telemetry && x == CH_WIDTH) | |||||
skip += TELE_WIDTH + SYNC_WIDTH + SPC_WIDTH; | skip += TELE_WIDTH + SYNC_WIDTH + SPC_WIDTH; | ||||
} | |||||
if(greyscale){ | if(greyscale){ | ||||
mpix[x] = img->prow[y][x + skip + offset]; | |||||
mpix[x] = POWF(img->prow[y][x + skip + offset], opts->gamma)/a; | |||||
}else{ | }else{ | ||||
pix[x] = (png_color){ | pix[x] = (png_color){ | ||||
crow[y][x + skip + offset].r, | |||||
crow[y][x + skip + offset].g, | |||||
crow[y][x + skip + offset].b | |||||
POWF(crow[y][x + skip + offset].r, opts->gamma)/a, | |||||
POWF(crow[y][x + skip + offset].g, opts->gamma)/a, | |||||
POWF(crow[y][x + skip + offset].b, opts->gamma)/a | |||||
}; | }; | ||||
} | } | ||||
} | } | ||||