diff --git a/README.md b/README.md
index ac0fa8c..5c95021 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@ For each audio file up to 6 images can be generated:
3. Calibrated channel B image
4. Temperature compensated IR image
5. False color image
-6. Layered image, boosts cloud visibility
+6. MCIR (Map Color InfraRed) image
The input audio file must be mono with a sample rate in the range of 4160-62400 Hz, lower samples rates will process faster.
Aptdec uses `libsndfile` to read the input audio, so any format supported by `libsndfile` may be used (however it has only tested with `.wav` files).
@@ -53,7 +53,7 @@ To uninstall
```
-i [r|a|b|c|t|l]
Output image type
-Raw (r), Channel A (a), Channel B (b), False Color (c), Temperature (t), Layered (l)
+Raw (r), Channel A (a), Channel B (b), False Color (c), Temperature (t)
Default: "ab"
-d
@@ -65,10 +65,13 @@ Satellite number
For temperature calibration
Default: "19"
--e [c|t|h]
+-e [t|h]
Enhancements
-Contrast calibration (c), Histogram equalise (h), Crop Telemetry (t)
-Defaults: "ct"
+Histogram equalise (h), Crop Telemetry (t)
+Defaults: off
+
+-m
+Map overlay generated by wxmap
-c
Use configuration file for false color generation.
@@ -85,13 +88,11 @@ Image names are `audiofile-x.png`, where `x` is:
- Sensor ID (1, 2, 3A, 3B, 4, 5) for channel A|B images
- `c` for false color.
- `t` for temperature calibrated images
- - `l` for layered images
Currently there are 3 available enhancements:
- - `c` for calibration, 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
+ - `t` for crop telemetry, off by default, only has effects on raw images
+ - `h` for histogram equalise, stretch the colors in the image to black and white
## Example
diff --git a/dsp.c b/dsp.c
index 90412bb..5743f8d 100755
--- a/dsp.c
+++ b/dsp.c
@@ -59,7 +59,7 @@ int init_dsp(double F) {
K1 = DFc / Fe;
K2 = K1 * K1 / 2.0;
- // Number of samples for each cycle
+ // Number of samples per cycle
FreqOsc = Fc / Fe;
return(0);
@@ -209,7 +209,8 @@ int getpixelv(float *pvbuff, int count) {
}
// Get an entire row of pixels, aligned with sync markers
-int getpixelrow(float *pixelv) {
+double minDoppler = 100;
+int getpixelrow(float *pixelv, int nrow, int *zenith) {
static float pixels[PixelLine + SyncFilterLen];
static int npv;
static int synced = 0;
@@ -230,11 +231,17 @@ int getpixelrow(float *pixelv) {
if (npv < SyncFilterLen + 2) return(0);
}
- // Calculate the sub-pixel offset
+ // Calculate the frequency offset
ecorr = fir(pixelv, Sync, SyncFilterLen);
corr = fir(&(pixelv[1]), Sync, SyncFilterLen - 1);
lcorr = fir(&(pixelv[2]), Sync, SyncFilterLen - 2);
FreqLine = 1.0+((ecorr-lcorr) / corr / PixelLine / 4.0);
+
+ // Find the point in which ecorr and lcorr intercept, make sure that it's not too perfect
+ if(fabs(lcorr - ecorr) < minDoppler && fabs(lcorr - ecorr) > 1){
+ minDoppler = fabs(lcorr - ecorr);
+ *zenith = nrow;
+ }
// The point in which the pixel offset is recalculated
if (corr < 0.75 * max) {
diff --git a/filter.c b/filter.c
index 919297b..f0de8c3 100755
--- a/filter.c
+++ b/filter.c
@@ -36,13 +36,13 @@ float fir(float *buff, const float *coeff, const int len) {
* Turn samples into a single IQ sample
*/
void iqfir(float *buff, const float *coeff, const int len, double *I, double *Q) {
- double i, q;
+ double i = 0.0, q = 0.0;
- i = q = 0.0;
for (int k = 0; k < len; k++) {
q += buff[2*k] * coeff[k];
i += buff[2*k];
}
+
i = buff[len-1] - (i / len);
*I = i, *Q = q;
}
diff --git a/image.c b/image.c
index c4fafae..830872d 100644
--- a/image.c
+++ b/image.c
@@ -126,7 +126,7 @@ void calibrateBrightness(float **prow, int nrow, int offset, int width, int tele
}
// Get telemetry data for thermal calibration/equalization
-int calibrate(float **prow, int nrow, int offset, int width, int calibrate) {
+int calibrate(float **prow, int nrow, int offset, int width) {
double teleline[3000] = { 0.0 };
double wedge[16];
rgparam regr[30];
@@ -236,7 +236,7 @@ int calibrate(float **prow, int nrow, int offset, int width, int calibrate) {
}
nbtele = k;
- if(calibrate) calibrateBrightness(prow, nrow, offset, width, telestart, regr);
+ calibrateBrightness(prow, nrow, offset, width, telestart, regr);
return(channel + 1);
}
@@ -308,13 +308,13 @@ static double tempcal(float Ce, tempparam * rgpr) {
}
// Temperature calibration wrapper
-void temperature(float **prow, int nrow, int channel, int offset) {
+void temperature(float **prow, int nrow, int ch, int offset){
tempparam temp;
printf("Temperature... ");
fflush(stdout);
- tempcomp(tele, channel, &temp);
+ tempcomp(tele, ch, &temp);
for (int n = 0; n < nrow; n++) {
float *pixelv = prow[n];
diff --git a/main.c b/main.c
index a4d2cce..64222d0 100644
--- a/main.c
+++ b/main.c
@@ -30,7 +30,7 @@
#include "offsets.h"
#include "palette.h"
-extern int getpixelrow(float *pixelv);
+extern int getpixelrow(float *pixelv, int nrow, int *zenith);
extern int init_dsp(double F);
static SNDFILE *inwav;
@@ -77,119 +77,185 @@ static png_text text_ptr[] = {
{PNG_TEXT_COMPRESSION_NONE, "Description", "NOAA satellite image", 20}
};
-// TODO: this function needs to be tidied up
-/* Effects
- * 0 - Nothing
- * 1 - Crop telemetry
- * 2 - False color
- * 3 - Layered
- */
-static int ImageOut(char *filename, char *chid, float **prow, int nrow, int width, int offset, png_color *palette, int effects) {
+int mapOverlay(char *filename, float **crow, int nrow, int zenith, int MCIR) {
+ FILE *fp = fopen(filename, "rb");
+
+ // Create reader
+ png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if(!png) return 0;
+ png_infop info = png_create_info_struct(png);
+ if(!info) return 0;
+ png_init_io(png, fp);
+
+ // Read info from header
+ png_read_info(png, info);
+ int width = png_get_image_width(png, info);
+ int height = png_get_image_height(png, info);
+ png_byte color_type = png_get_color_type(png, info);
+ png_byte bit_depth = png_get_bit_depth(png, info);
+
+ // Check the image
+ if(width != 1040){
+ fprintf(stderr, "Map must be 1040px wide.\n");
+ return 0;
+ }else if(bit_depth != 16){
+ fprintf(stderr, "Map must be 16 bit color.\n");
+ return 0;
+ }else if(color_type != PNG_COLOR_TYPE_RGB){
+ fprintf(stderr, "Map must be RGB.\n");
+ return 0;
+ }else if(zenith > height/2 || nrow-zenith > height/2){
+ fprintf(stderr, "WARNING: Map is too short to cover entire image\n");
+ }
+
+ // Create row buffers
+ png_bytep *mapRows = NULL;
+ mapRows = (png_bytep *) malloc(sizeof(png_bytep) * height);
+ for(int y = 0; y < height; y++) mapRows[y] = (png_byte *) malloc(png_get_rowbytes(png, info));
+
+ // Read image
+ png_read_image(png, mapRows);
+
+ // Tidy up
+ fclose(fp);
+ png_destroy_read_struct(&png, &info, NULL);
+
+ int mapOffset = (height/2)-zenith;
+ for(int y = 0; y < nrow; y++) {
+ for(int x = 49; x < width - 82; x++){
+ // Maps are 16 bit / channel
+ png_bytep px = &mapRows[CLIP(y + mapOffset, 0, height)][x * 6];
+ uint16_t r = (uint16_t)(px[0] << 8) | px[1];
+ uint16_t g = (uint16_t)(px[2] << 8) | px[3];
+ uint16_t b = (uint16_t)(px[4] << 8) | px[5];
+
+ // Pointers to the current pixel in each channel
+ float *cha = &crow[y][(x+36) * 3];
+ float *chb = &crow[y][(x+CHB_OFFSET-49) * 3];
+
+ // Fill in map
+ if(MCIR){
+ // Sea
+ cha[0] = 42; cha[1] = 53; cha[2] = 105;
+
+ // Land
+ if(g > 128){
+ float vegetation = (r-160) / 96.0;
+ cha[0] = 120; cha[1] = vegetation*60.0 + 100; cha[2] = 95;
+ }
+ }
+
+ // Color -> alpha: composite
+ int composite = r + g + b;
+ // Color -> alpha: flattern color depth
+ float factor = (255 * 255 * 2.0) / composite;
+ r *= factor; g *= factor; b *= factor;
+ // Color -> alpha: convert black to alpha
+ float alpha = CLIP(abs(0 - composite) / 65535.0, 0, 1);
+
+ // Map overlay on channel A
+ cha[0] = MCOMPOSITE(r/257, alpha, cha[0], 1);
+ cha[1] = MCOMPOSITE(g/257, alpha, cha[1], 1);
+ cha[2] = MCOMPOSITE(b/257, alpha, cha[2], 1);
+
+ // Map overlay on channel B
+ if(!MCIR){
+ chb[0] = MCOMPOSITE(r/257, alpha, chb[0], 1);
+ chb[1] = MCOMPOSITE(g/257, alpha, chb[1], 1);
+ chb[2] = MCOMPOSITE(b/257, alpha, chb[2], 1);
+ }
+
+ // Cloud overlay on channel A
+ if(MCIR){
+ float cloud = (chb[0] - 110) / 120;
+ cha[0] = MCOMPOSITE(240, cloud, cha[0], 1);
+ cha[1] = MCOMPOSITE(250, cloud, cha[1], 1);
+ cha[2] = MCOMPOSITE(255, cloud, cha[2], 1);
+ }
+ }
+ }
+
+ return 1;
+}
+
+// Row where to satellite reaches peak elevation
+int zenith = 0;
+
+static int ImageOut(char *filename, char *chid, float **prow, int nrow, int width, int offset, char *palette, char *effects, char *mapFile) {
FILE *pngfile;
- png_infop info_ptr;
- png_structp png_ptr;
// Reduce the width of the image to componsate for the missing telemetry
- if(effects == 1) width -= TOTAL_TELE;
+ if(CONTAINS(effects, 't')) width -= TOTAL_TELE;
- // Initalise the PNG writer
- png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ // Create writer
+ png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
+ png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
fprintf(stderr, ERR_PNG_WRITE);
return(0);
}
-
- // Metadata
- info_ptr = png_create_info_struct(png_ptr);
+ png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
fprintf(stderr, ERR_PNG_INFO);
return(0);
}
- extern void falsecolor(float vis, float temp, float *r, float *g, float *b);
-
- if(effects == 2){
- // 8 bit RGB image
- png_set_IHDR(png_ptr, info_ptr, width, nrow,
- 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
- }else if(palette == NULL) {
- // Greyscale image
- png_set_IHDR(png_ptr, info_ptr, width, nrow,
- 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
- } else {
- // Palleted color image
- png_set_IHDR(png_ptr, info_ptr, width, nrow,
- 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
- png_set_PLTE(png_ptr, info_ptr, palette, 256);
- }
+ // 8 bit RGB image
+ png_set_IHDR(png_ptr, info_ptr, width, nrow,
+ 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
text_ptr[1].text = chid;
text_ptr[1].text_length = strlen(chid);
png_set_text(png_ptr, info_ptr, text_ptr, 3);
- png_set_pHYs(png_ptr, info_ptr, 4000, 4000, PNG_RESOLUTION_METER);
-
- if(effects == 2){
- printf("Computing false color & writing: %s", filename);
- }else{
- printf("Writing %s", filename);
- }
- fflush(stdout);
+ png_set_pHYs(png_ptr, info_ptr, 4160, 4160, PNG_RESOLUTION_METER);
+ // Init I/O
pngfile = fopen(filename, "wb");
- if (pngfile == NULL) {
+ if (!pngfile) {
fprintf(stderr, ERR_FILE_WRITE, filename);
return(1);
}
png_init_io(png_ptr, pngfile);
png_write_info(png_ptr, info_ptr);
- for (int n = 0; n < nrow; n++) {
- png_color pix[width];
- png_byte pixel[width];
+ // Move prow into crow, crow ~ color rows
+ float *crow[3000];
+ for(int i = 0; i < nrow; i++){
+ crow[i] = (float *) malloc(sizeof(float) * 2080 * 3);
- float *pixelv = prow[n];
- int f = 0;
- for (int i = 0; i < width; i++) {
- // Skip parts of the image that are telemetry
- if(effects == 1){
- switch (i) {
- case 0:
- f += SYNC_WIDTH + SPC_WIDTH;
- break;
- case CH_WIDTH:
- f += TELE_WIDTH + SYNC_WIDTH + SPC_WIDTH;
- break;
- case CH_WIDTH*2:
- f += TELE_WIDTH;
- }
- }
+ for(int x = 0; x < 2080; x++)
+ crow[i][x*3 + 0] = crow[i][x*3 + 1] = crow[i][x*3 + 2] = prow[i][x];
+ }
- if(effects == 2){
- float r = 0, g = 0, b = 0;
- falsecolor(pixelv[i+CHA_OFFSET], pixelv[i+CHB_OFFSET], &r, &g, &b);
- pix[i].red = r;
- pix[i].green = g;
- pix[i].blue = b;
- }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(240, cloud, pixelv[i+CHA_OFFSET], 1);
- }else{
- pixel[i] = CLIP(pixelv[i + offset + f], 0, 255);
- }
+ if(mapFile != NULL && mapFile[0] != '\0'){
+ if(mapOverlay(mapFile, crow, nrow, zenith, strcmp(chid, "MCIR") == 0) == 0){
+ fprintf(stderr, "Skipping MCIR generation; see above.\n");
+ return 0;
}
+ }else if(strcmp(chid, "MCIR")){
+ fprintf(stderr, "Skipping MCIR generation; no map provided.\n");
+ return 0;
+ }
- if(effects == 2){
- png_write_row(png_ptr, (png_bytep) pix);
- }else{
- png_write_row(png_ptr, pixel);
+ printf("Writing %s", filename);
+
+ // Build RGB image
+ for (int n = 0; n < nrow; n++) {
+ png_color pix[width];
+
+ for (int i = 0; i < width; i++) {
+ float *px = &crow[n][offset*3 + i*3];
+ pix[i].red = CLIP(px[0], 0, 255);
+ pix[i].green = CLIP(px[1], 0, 255);
+ pix[i].blue = CLIP(px[2], 0, 255);
}
+
+ png_write_row(png_ptr, (png_bytep) pix);
}
+ // Tidy up
png_write_end(png_ptr, info_ptr);
fclose(pngfile);
printf("\nDone\n");
@@ -223,10 +289,10 @@ static void distrib(char *filename, float **prow, int nrow) {
for(int y = 0; y < 256; y++)
distrib[y][x] = distrib[y][x] / max * 255;
- ImageOut(filename, "Brightness distribution", distrib, 256, 256, 0, NULL, 0);
+ ImageOut(filename, "Brightness distribution", distrib, 256, 256, 0, NULL, 0, NULL);
}
-extern int calibrate(float **prow, int nrow, int offset, int width, int calibrate);
+extern int calibrate(float **prow, int nrow, int offset, int width);
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);
@@ -240,8 +306,7 @@ int satnum = 4;
static void usage(void) {
printf("Aptdec [options] audio files ...\n"
"Options:\n"
- " -e [c|t] Enhancements\n"
- " c: Contrast calibration\n"
+ " -e [t|h] Enhancements\n"
" t: Crop telemetry\n"
" h: Histogram equalise\n"
" -i [r|a|b|c|t] Output image type\n"
@@ -250,26 +315,22 @@ static void usage(void) {
" b: Channel B\n"
" c: False color\n"
" t: Temperature\n"
- " l: Layered\n"
+ " m: MCIR\n"
" -d Image destination directory.\n"
" -s [15-19] Satellite number\n"
- " -c False color config file\n");
+ " -c False color config file\n"
+ " -m Map file\n");
exit(1);
}
int readRawImage(char *filename, float **prow, int *nrow) {
- png_bytep *PNGrows = NULL;
FILE *fp = fopen(filename, "r");
- // Create read struct
+ // Create reader
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if(!png) return 0;
-
- // Create info struct
png_infop info = png_create_info_struct(png);
if(!info) return 0;
-
- // Init I/O
png_init_io(png, fp);
// Read info from header
@@ -281,25 +342,25 @@ int readRawImage(char *filename, float **prow, int *nrow) {
// Check the image
if(width != 2080){
- fprintf(stderr, "Expected a 2080px wide PNG, got a %ipx wide PNG", width);
+ fprintf(stderr, "Raw image must be 2080px wide.\n");
return 0;
- }
- if(bit_depth != 8){
- fprintf(stderr, "Expected an 8 bit PNG, got an %i bit PNG", bit_depth);
+ }else if(bit_depth != 8){
+ fprintf(stderr, "Raw image must have 8 bit color.\n");
return 0;
- }
- if(color_type != PNG_COLOR_TYPE_GRAY){
- fprintf(stderr, "Expected a grayscale PNG");
+ }else if(color_type != PNG_COLOR_TYPE_GRAY){
+ fprintf(stderr, "Raw image must be grayscale.\n");
return 0;
}
// Create row buffers
+ png_bytep *PNGrows = NULL;
PNGrows = (png_bytep *) malloc(sizeof(png_bytep) * height);
for(int y = 0; y < height; y++) PNGrows[y] = (png_byte *) malloc(png_get_rowbytes(png, info));
+ // Read image
png_read_image(png, PNGrows);
- // Tidy up
+ // Tidy up
fclose(fp);
png_destroy_read_struct(&png, &info, NULL);
@@ -307,6 +368,7 @@ int readRawImage(char *filename, float **prow, int *nrow) {
*nrow = height;
for(int y = 0; y < height; y++) {
prow[y] = (float *) malloc(sizeof(float) * width);
+
for(int x = 0; x < width; x++)
prow[y][x] = (float)PNGrows[y][x];
}
@@ -318,11 +380,12 @@ int main(int argc, char **argv) {
char pngfilename[1024];
char name[128];
char pngdirname[128] = "";
+ char mapFile[256];
char *extension;
- // Default to a raw image, with equalization and cropped telemetry
+ // Default to a raw image, with no enhancements
char imgopt[20] = "r";
- char enchancements[20] = "ct";
+ char enhancements[20] = "";
// Image buffer
float *prow[3000];
@@ -348,7 +411,7 @@ int main(int argc, char **argv) {
usage();
int c;
- while ((c = getopt(argc, argv, "c:d:i:s:e:")) != EOF) {
+ while ((c = getopt(argc, argv, "c:m:d:i:s:e:")) != EOF) {
switch (c) {
// Output directory name
case 'd':
@@ -358,6 +421,10 @@ int main(int argc, char **argv) {
case 'c':
readfcconf(optarg);
break;
+ // Map file
+ case 'm':
+ strcpy(mapFile, optarg);
+ break;
// Output image type
case 'i':
strncpy(imgopt, optarg, 20);
@@ -373,7 +440,7 @@ int main(int argc, char **argv) {
break;
// Enchancements
case 'e':
- strncpy(enchancements, optarg, 20);
+ strncpy(enhancements, optarg, 20);
break;
default:
usage();
@@ -399,7 +466,10 @@ int main(int argc, char **argv) {
if(strcmp(extension, "png") == 0){
printf("Reading %s", argv[optind]);
- readRawImage(argv[optind], prow, &nrow);
+ if(readRawImage(argv[optind], prow, &nrow) == 0){
+ fprintf(stderr, "Skipping %s; see above.\n", name);
+ continue;
+ }
}else{
// Open sound file, exit if that fails
if (initsnd(argv[optind]) == 0) exit(1);
@@ -410,7 +480,7 @@ int main(int argc, char **argv) {
prow[nrow] = (float *) malloc(sizeof(float) * 2150);
// Read into prow and break the loop once we reach the end of the image
- if (getpixelrow(prow[nrow]) == 0) break;
+ if (getpixelrow(prow[nrow], nrow, &zenith) == 0) break;
printf("Row: %d\r", nrow);
fflush(stdout);
@@ -420,49 +490,61 @@ int main(int argc, char **argv) {
sf_close(inwav);
}
+ if(zenith == 0 & mapFile[0] != '\0'){
+ fprintf(stderr, "WARNING: Guessing peak elevation in image, map will most likely not be aligned.\n");
+ zenith = nrow / 2;
+ }
+
printf("\nTotal rows: %d\n", nrow);
- chA = calibrate(prow, nrow, CHA_OFFSET, CH_WIDTH, 0);
- chB = calibrate(prow, nrow, CHB_OFFSET, CH_WIDTH, 0);
+ // Calibrate
+ chA = calibrate(prow, nrow, CHA_OFFSET, CH_WIDTH);
+ chB = calibrate(prow, nrow, CHB_OFFSET, CH_WIDTH);
printf("Channel A: %s (%s)\n", ch.id[chA], ch.name[chA]);
printf("Channel B: %s (%s)\n", ch.id[chB], ch.name[chB]);
// Temperature
if (CONTAINS(imgopt, 't') && chB >= 4) {
+ // TODO: Doesn't work with channel 4
temperature(prow, nrow, chB, CHB_OFFSET);
sprintf(pngfilename, "%s/%s-t.png", pngdirname, name);
- ImageOut(pngfilename, "Temperature", prow, nrow, CH_WIDTH, CHB_OFFSET, (png_color*)TempPalette, 0);
+ ImageOut(pngfilename, "Temperature", prow, nrow, 2080, 0, TempPalette, enhancements, mapFile);
}
- // Run the brightness calibration here because the temperature calibration requires raw data
- // Layered & false color images both also need brightness calibration
- 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);
+ // False color image
+ if(CONTAINS(imgopt, 'c')){
+ if (chA == 2 && chB >= 4) { // Normal false color
+ sprintf(pngfilename, "%s/%s-c.png", pngdirname, name);
+ //ImageRGBOut(pngfilename, prow, nrow);
+ ImageOut(pngfilename, "False Color", prow, nrow, CH_WIDTH, 0, NULL, enhancements, mapFile);
+ } else if (chB == 2) { // GVI (global vegetation index) false color
+ Ngvi(prow, nrow);
+ sprintf(pngfilename, "%s/%s-c.png", pngdirname, name);
+ ImageOut(pngfilename, "GVI False Color", prow, nrow, CH_WIDTH, CHB_OFFSET, GviPalette, enhancements, mapFile);
+ } else {
+ fprintf(stderr, "Skipping False Color generation; lacking required channels.\n");
+ }
+ }
+
+ // MCIR
+ if (CONTAINS(imgopt, 'm')) {
+ sprintf(pngfilename, "%s/%s-m.png", pngdirname, name);
+ ImageOut(pngfilename, "MCIR", prow, nrow, 909, CHA_OFFSET, NULL, enhancements, mapFile);
+ }
// Histogram equalise
- if(CONTAINS(enchancements, 'h')){
+ if(CONTAINS(enhancements, 'h')){
histogramEqualise(prow, nrow, CHA_OFFSET, CH_WIDTH);
histogramEqualise(prow, nrow, CHB_OFFSET, CH_WIDTH);
}
- // Layered
- if (CONTAINS(imgopt, 'l')){
- if(chA == 1){
- sprintf(pngfilename, "%s/%s-l.png", pngdirname, name);
- ImageOut(pngfilename, "Layered", prow, nrow, CH_WIDTH, 0, NULL, 3);
- }else{
- fprintf(stderr, "Lacking channels required for generting a layered image.\n");
- }
- }
-
// Raw image
if (CONTAINS(imgopt, 'r')) {
- int croptele = CONTAINS(enchancements, 't');
char channelstr[45];
sprintf(channelstr, "%s (%s) & %s (%s)", ch.id[chA], ch.name[chA], ch.id[chB], ch.name[chB]);
sprintf(pngfilename, "%s/%s-r.png", pngdirname, name);
- ImageOut(pngfilename, channelstr, prow, nrow, IMG_WIDTH, 0, NULL, croptele ? 1 : 0);
+ ImageOut(pngfilename, channelstr, prow, nrow, IMG_WIDTH, 0, NULL, enhancements, mapFile);
}
// Channel A
@@ -471,7 +553,7 @@ int main(int argc, char **argv) {
sprintf(channelstr, "%s (%s)", ch.id[chA], ch.name[chA]);
sprintf(pngfilename, "%s/%s-%s.png", pngdirname, name, ch.id[chA]);
- ImageOut(pngfilename, channelstr, prow, nrow, CH_WIDTH, CHA_OFFSET, NULL, 0);
+ ImageOut(pngfilename, channelstr, prow, nrow, CH_WIDTH, CHA_OFFSET, NULL, enhancements, mapFile);
}
// Channel B
@@ -480,7 +562,7 @@ int main(int argc, char **argv) {
sprintf(channelstr, "%s (%s)", ch.id[chB], ch.name[chB]);
sprintf(pngfilename, "%s/%s-%s.png", pngdirname, name, ch.id[chB]);
- ImageOut(pngfilename, channelstr, prow, nrow, CH_WIDTH , CHB_OFFSET, NULL, 0);
+ ImageOut(pngfilename, channelstr, prow, nrow, CH_WIDTH , CHB_OFFSET, NULL, enhancements, mapFile);
}
// Distribution image
@@ -488,21 +570,6 @@ int main(int argc, char **argv) {
sprintf(pngfilename, "%s/%s-d.png", pngdirname, name);
distrib(pngfilename, prow, nrow);
}
-
- // False color image
- if(CONTAINS(imgopt, 'c')){
- if (chA == 2 && chB >= 4) { // Normal false color
- sprintf(pngfilename, "%s/%s-c.png", pngdirname, name);
- //ImageRGBOut(pngfilename, prow, nrow);
- ImageOut(pngfilename, "False Color", prow, nrow, CH_WIDTH, 0, NULL, 2);
- } else if (chB == 2) { // GVI (global vegetation index) false color
- Ngvi(prow, nrow);
- sprintf(pngfilename, "%s/%s-c.png", pngdirname, name);
- ImageOut(pngfilename, "GVI False Color", prow, nrow, CH_WIDTH, CHB_OFFSET, (png_color*)GviPalette, 0);
- } else {
- fprintf(stderr, "Lacking channels required for generating a false color image.\n");
- }
- }
}
exit(0);
diff --git a/palette.h b/palette.h
index 52182d0..08e506d 100644
--- a/palette.h
+++ b/palette.h
@@ -17,7 +17,7 @@
*
*/
-unsigned char GviPalette[256*3] = {
+char *GviPalette = {
"\230t\17\233x\22\236{\27\241\200\33\244\203\37\247\210#\252\214'\255\220"
",\260\2240\264\2305\267\2358\272\240=\274\245A\300\251E\303\255I\306\262"
"M\311\266Q\314\272V\317\276Z\322\302^\325\306b\330\312g\334\317k\337\323"
@@ -48,8 +48,8 @@ unsigned char GviPalette[256*3] = {
"M\225\1I\221\2E\217\1@\214\1;\211\1""7\206\1""1\203\1-\200\0(~\1${\0\37y"
"\0\33u\0\25r\0\21p\0\14l\0\7j\0\3"
};
-unsigned char TempPalette[256*3] = {
- "\376\376\376\376\376\376\375\375\376\374\375\376\374\375\375\374\373\375"
+char *TempPalette = {
+ "\000\000\000\376\376\376\375\375\376\374\375\376\374\375\375\374\373\375"
"\373\373\375\372\373\375\372\373\374\372\372\374\371\372\374\371\371\375"
"\370\371\374\367\370\375\367\370\374\367\367\374\366\367\373\366\366\373"
"\365\366\373\364\366\373\364\365\374\363\365\373\363\364\373\363\364\373"