@@ -70,6 +70,7 @@ Apply a falsecolor palette | |||
-m <path> Path to WXtoImg map | |||
-p <path> Path to palette | |||
-r Realtime decode | |||
-g Gamma adjustment (1.0 = off) | |||
``` | |||
### Image types | |||
@@ -46,6 +46,7 @@ typedef struct { | |||
int realtime; // Realtime decoding | |||
char *filename; // Output filename | |||
char *palette; // Filename of palette | |||
float gamma; // Gamma | |||
} options_t; | |||
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; | |||
// Options | |||
@@ -276,7 +276,7 @@ void distrib(options_t *opts, image_t *img, char *chid) { | |||
for(int y = 0; y < 256; y++) | |||
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); | |||
} | |||
@@ -36,7 +36,7 @@ extern int getpixelrow(float *pixelv, int nrow, int *zenith, int reset); | |||
// I/O | |||
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 void pushRow(float *row, int width); | |||
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 temperature(options_t *opts, image_t *img, 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); | |||
// Palettes | |||
@@ -74,11 +74,11 @@ int main(int argc, char **argv) { | |||
usage(); | |||
} | |||
options_t opts = { "r", "", 19, "", ".", 0, "" }; | |||
options_t opts = { "r", "", 19, "", ".", 0, "", "", 1.0 }; | |||
// Parse arguments | |||
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) { | |||
case 'd': | |||
opts.path = optarg; | |||
@@ -108,6 +108,9 @@ int main(int argc, char **argv) { | |||
case 'p': | |||
opts.palette = optarg; | |||
break; | |||
case 'g': | |||
opts.gamma = atof(optarg); | |||
break; | |||
default: | |||
usage(); | |||
} | |||
@@ -296,7 +299,7 @@ static int initsnd(char *filename) { | |||
return 1; | |||
} | |||
// Read samples from the wave file | |||
// Read samples from the audio file | |||
int getsample(float *sample, int nb) { | |||
if(channels == 1){ | |||
return sf_read_float(audioFile, sample, nb); | |||
@@ -335,6 +338,7 @@ static void usage(void) { | |||
" -m <path> Map file\n" | |||
" -p <path> Path to palette\n" | |||
" -r Realtime decode\n" | |||
" -g Gamma adjustment (1.0 = off)\n" | |||
"\nRefer to the README for more infomation\n"); | |||
exit(EINVAL); | |||
@@ -100,12 +100,12 @@ int mapOverlay(char *filename, rgb_t **crow, int nrow, int zenith, int MCIR) { | |||
if(MCIR){ | |||
if(map.b < 128 && map.g > 128){ | |||
// 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{ | |||
// 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 | |||
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); | |||
} | |||
} | |||
@@ -409,6 +409,11 @@ int ImageOut(options_t *opts, image_t *img, int offset, int width, char *desc, c | |||
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 | |||
for (int y = 0; y < img->nrow; y++) { | |||
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; | |||
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; | |||
} | |||
if(greyscale){ | |||
mpix[x] = img->prow[y][x + skip + offset]; | |||
mpix[x] = POWF(img->prow[y][x + skip + offset], opts->gamma)/a; | |||
}else{ | |||
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 | |||
}; | |||
} | |||
} | |||