Also made some floating-point math more explicittags/v1.8.0
@@ -65,9 +65,9 @@ Satellite number | |||
For temperature calibration | |||
Default: "19" | |||
-e [c|t] | |||
-e [c|t|h] | |||
Enhancements | |||
Contrast (c) or Crop Telemetry (t) | |||
Contrast calibration (c), Histogram equalise (h), Crop Telemetry (t) | |||
Defaults: "ct" | |||
-c <file> | |||
@@ -77,7 +77,7 @@ Default: Internal defaults | |||
## Output | |||
Generated images are outputted in PNG, 8 bit greyscale for raw and channel A|B images, 24 bit RGB for false color. | |||
Generated images are outputted in PNG, 8 bit greyscale for raw and channel A|B images, palleted images for temperature and GVI false color, 24 bit RGB for false color. | |||
Image names are `audiofile-x.png`, where `x` is: | |||
@@ -87,10 +87,11 @@ Image names are `audiofile-x.png`, where `x` is: | |||
- `t` for temperature calibrated images | |||
- `l` for layered images | |||
Currently there are 2 available enchancements: | |||
Currently there are 3 available enhancements: | |||
- `c` for contrast equalise, on by default | |||
- `t` for crop telemetry, on by default, only has effects on raw images | |||
- `h` for histogram equalise, make the darkest color black and the brightest white | |||
## Example | |||
@@ -213,7 +213,7 @@ int getpixelrow(float *pixelv) { | |||
static float pixels[PixelLine + SyncFilterLen]; | |||
static int npv; | |||
static int synced = 0; | |||
static double max = 0; | |||
static double max = 0.0; | |||
double corr, ecorr, lcorr; | |||
int res; | |||
@@ -83,7 +83,7 @@ rgba composite(rgba top, rgba bottom){ | |||
void falsecolor(float vis, float temp, float *r, float *g, float *b){ | |||
rgba buffer; | |||
fcinfo.Land.a = 0; fcinfo.Sea.a = 0; | |||
fcinfo.Land.a = 0.0f; fcinfo.Sea.a = 0.0f; | |||
// Calculate intensity of sea and land | |||
fcinfo.Sea.a = CLIP(vis, 0, 20)/fcinfo.Seaintensity + fcinfo.Seaoffset; | |||
@@ -91,7 +91,7 @@ void falsecolor(float vis, float temp, float *r, float *g, float *b){ | |||
// Composite land on top of sea | |||
buffer = composite(fcinfo.Land, fcinfo.Sea); | |||
buffer.a = 1; | |||
buffer.a = 1.0f; | |||
// Composite clouds on top | |||
fcinfo.Cloud.a = CLIP(temp-fcinfo.Cloudthreshold, 0, fcinfo.Cloudintensity)/fcinfo.Cloudintensity; | |||
@@ -56,6 +56,33 @@ static double tele[16]; | |||
static double Cs; | |||
static int nbtele; | |||
void histogramEqualise(float **prow, int nrow, int offset, int width){ | |||
// Plot histogram | |||
int histogram[256] = { 0 }; | |||
for(int y = 0; y < nrow; y++) | |||
for(int x = 0; x < width; x++) | |||
histogram[(int)floor(prow[y][x+offset])]++; | |||
// Find min/max points | |||
int min = -1, max = -1; | |||
for(int i = 5; i < 250; i++){ | |||
if(histogram[i]/width/(nrow/255.0) > 1.0){ | |||
if(min == -1) min = i; | |||
max = i; | |||
} | |||
} | |||
//printf("Min Value: %i, Max Value %i\n", min, max); | |||
// Spread values to avoid overshoot | |||
min -= 5; max += 5; | |||
// Stretch the brightness into the new range | |||
for(int y = 0; y < nrow; y++) | |||
for(int x = 0; x < width; x++) | |||
prow[y][x+offset] = (prow[y][x+offset]-min) / (max-min) * 255; | |||
} | |||
// Brightness equalise, including telemetry | |||
void equalise(float **prow, int nrow, int offset, int width, int telestart, rgparam regr[30]){ | |||
offset -= SYNC_WIDTH+SPC_WIDTH; | |||
@@ -100,7 +127,7 @@ void equalise(float **prow, int nrow, int offset, int width, int telestart, rgpa | |||
// Get telemetry data for thermal calibration/equalization | |||
int calibrate(float **prow, int nrow, int offset, int width, int contrastEqualise) { | |||
double teleline[3000]; | |||
double teleline[3000] = { 0.0 }; | |||
double wedge[16]; | |||
rgparam regr[30]; | |||
int n, k; | |||
@@ -112,7 +139,6 @@ int calibrate(float **prow, int nrow, int offset, int width, int contrastEqualis | |||
float *pixelv = prow[n]; | |||
// Average the center 40px | |||
teleline[n] = 0.0; | |||
for (int i = 3; i < 43; i++) teleline[n] += pixelv[i + offset + width]; | |||
teleline[n] /= 40.0; | |||
} | |||
@@ -127,7 +153,7 @@ int calibrate(float **prow, int nrow, int offset, int width, int contrastEqualis | |||
* difference in brightness, this will always be in the center of | |||
* the frame and can thus be used to find the start of the frame | |||
*/ | |||
float max = 0; | |||
double max = 0.0; | |||
for (n = nrow / 3 - 64; n < 2 * nrow / 3 - 64; n++) { | |||
float df; | |||
@@ -177,9 +177,9 @@ static int ImageOut(char *filename, char *chid, float **prow, int nrow, int widt | |||
}else if(effects == 3){ | |||
// Layered image, overlay clouds in channel B over channel A | |||
float cloud = CLIP(pixelv[i+CHB_OFFSET]-141, 0, 255)/114; | |||
pixel[i] = MCOMPOSITE(255, cloud, pixelv[i+CHA_OFFSET], 1); | |||
pixel[i] = MCOMPOSITE(240, cloud, pixelv[i+CHA_OFFSET], 1); | |||
}else{ | |||
pixel[i] = pixelv[i + offset + f]; | |||
pixel[i] = CLIP(pixelv[i + offset + f], 0, 255); | |||
} | |||
} | |||
@@ -228,6 +228,7 @@ static void distrib(char *filename, float **prow, int nrow) { | |||
} | |||
extern int calibrate(float **prow, int nrow, int offset, int width, int contrastEqualise); | |||
extern void histogramEqualise(float **prow, int nrow, int offset, int width); | |||
extern void temperature(float **prow, int nrow, int ch, int offset); | |||
extern int Ngvi(float **prow, int nrow); | |||
extern void readfcconf(char *file); | |||
@@ -243,6 +244,7 @@ static void usage(void) { | |||
" -e [c|t] Enhancements\n" | |||
" c: Contrast equalise\n" | |||
" t: Crop telemetry\n" | |||
" h: Histogram equalise\n" | |||
" -i [r|a|b|c|t] Output image type\n" | |||
" r: Raw\n" | |||
" a: Channel A\n" | |||
@@ -350,7 +352,6 @@ int main(int argc, char **argv) { | |||
if (getpixelrow(prow[nrow]) == 0) | |||
break; | |||
printf("Row: %d\r", nrow); | |||
fflush(stdout); | |||
} | |||
@@ -358,9 +359,6 @@ int main(int argc, char **argv) { | |||
sf_close(inwav); | |||
// Layered & false color images both need brightness equalization | |||
int contrastEqualise = CONTAINS(enchancements, 'c') || CONTAINS(imgopt, 'l') || CONTAINS(imgopt, 'c'); | |||
chA = calibrate(prow, nrow, CHA_OFFSET, CH_WIDTH, 0); | |||
chB = calibrate(prow, nrow, CHB_OFFSET, CH_WIDTH, 0); | |||
printf("Channel A: %s (%s)\n", ch.id[chA], ch.name[chA]); | |||
@@ -374,9 +372,15 @@ int main(int argc, char **argv) { | |||
} | |||
// Run the contrast equalise here because the temperature calibration requires raw data | |||
if(contrastEqualise) | |||
// Also layered & false color images both need brightness equalization | |||
if(CONTAINS(enchancements, 'c') || CONTAINS(enchancements, 'h') || CONTAINS(imgopt, 'l') || CONTAINS(imgopt, 'c')) | |||
calibrate(prow, nrow, CHA_OFFSET, CH_WIDTH+TELE_WIDTH+SYNC_WIDTH+SPC_WIDTH+CH_WIDTH, 1); | |||
if(CONTAINS(enchancements, 'h')){ | |||
histogramEqualise(prow, nrow, CHA_OFFSET, CH_WIDTH); | |||
histogramEqualise(prow, nrow, CHB_OFFSET, CH_WIDTH); | |||
} | |||
// Layered | |||
if (CONTAINS(imgopt, 'l')){ | |||
if(chA == 1){ | |||