/*
* aptdec - A lightweight FOSS (NOAA) APT decoder
* Copyright (C) 2004-2009 Thierry Leconte (F4DWV) 2019-2023 Xerbo (xerbo@protonmail.com)
* Copyright (C) 2021 Jon Beniston (M7RCE)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifndef APTDEC_H_
#define APTDEC_H_
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__GNUC__) && (__GNUC__ >= 4)
# define APTDEC_API __attribute__((visibility("default")))
#elif defined(_MSC_VER)
# ifdef APTDEC_API_EXPORT
# define APTDEC_API __declspec(dllexport)
# else
# define APTDEC_API __declspec(dllimport)
# endif
#else
# define APTDEC_API
#endif
// Height of a single telemetry wedge
#define APTDEC_WEDGE_HEIGHT 8
// Numbers of wedges in a frame
#define APTDEC_FRAME_WEDGES 16
// Height of a telemetry frame
#define APTDEC_FRAME_LEN (APTDEC_WEDGE_HEIGHT * APTDEC_FRAME_WEDGES)
// Width of the overall image
#define APTDEC_IMG_WIDTH 2080
// Width of sync marker
#define APTDEC_SYNC_WIDTH 39
// Width of space view
#define APTDEC_SPC_WIDTH 47
// Width of telemetry
#define APTDEC_TELEMETRY_WIDTH 45
// Width of a single video channel
#define APTDEC_CH_WIDTH 909
// Offset to channel A video data
#define APTDEC_CHA_OFFSET (APTDEC_SYNC_WIDTH + APTDEC_SPC_WIDTH)
// Offset to channel B video data
#define APTDEC_CHB_OFFSET (APTDEC_SYNC_WIDTH + APTDEC_SPC_WIDTH + APTDEC_CH_WIDTH + APTDEC_TELEMETRY_WIDTH + APTDEC_SYNC_WIDTH + APTDEC_SPC_WIDTH)
// Number of rows needed for aptdec_normalize to (reliably) work
#define APTDEC_NORMALIZE_ROWS (APTDEC_FRAME_LEN * 2)
// Maximum amount of samples that will be requested from aptdec_callback_t
#define APTDEC_BUFFER_SIZE 16384
// Channel 1: visible (0.58-0.68 um)
// Channel 2: near-IR (0.725-1.0 um)
// Channel 3A: near-IR (1.58-1.64 um)
// Channel 3B: mid-infrared (3.55-3.93 um)
// Channel 4: thermal-infrared (10.3-11.3 um)
// Channel 5: thermal-infrared (11.5-12.5 um)
typedef enum aptdec_channel {
AVHRR_CHANNEL_UNKNOWN,
AVHRR_CHANNEL_1,
AVHRR_CHANNEL_2,
AVHRR_CHANNEL_3A,
AVHRR_CHANNEL_4,
AVHRR_CHANNEL_5,
AVHRR_CHANNEL_3B
} avhrr_channel_t;
typedef enum aptdec_satellite {
NOAA15,
NOAA18,
NOAA19
} aptdec_satellite_t;
typedef struct aptdec_image {
uint8_t *data; // Image data
size_t rows; // Number of rows
// Telemetry
aptdec_satellite_t satellite;
avhrr_channel_t ch[2];
float space_view[2];
float telemetry[2][16];
} aptdec_image_t;
typedef struct aptdec_rgb {
uint8_t r, g, b;
} aptdec_rgb_t;
typedef struct aptdec_region {
size_t offset;
size_t width;
} aptdec_region_t;
typedef struct aptdec aptdec_t;
// Callback function to get samples
// `context` is the same as passed to aptdec_getrow
typedef size_t (*aptdec_callback_t)(float *samples, size_t count, void *context);
// Clone an aptdec_image_t struct
// Useful for calibration
APTDEC_API aptdec_image_t aptdec_image_clone(aptdec_image_t img);
// Returns version of libaptdec in git tag format
// i.e. v2.0.0 or v2.0.0-1-xxxxxx
APTDEC_API char *aptdec_get_version(void);
// Create and destroy libaptdec instances
// If aptdec_init fails it will return NULL
APTDEC_API aptdec_t *aptdec_init(float sample_rate);
APTDEC_API void aptdec_free(aptdec_t *aptdec);
// Normalize and quantize raw image data
// Data is arranged so that each row starts at APTDEC_IMG_WIDTH*y
APTDEC_API aptdec_image_t aptdec_normalize(const float *data, size_t rows, aptdec_satellite_t satellite, int *error);
// Get an entire row of pixels
// Requires that `row` has enough space to store APTDEC_IMG_WIDTH*2
// Returns 0 when `callback` return value != count
APTDEC_API int aptdec_getrow(aptdec_t *aptdec, float *row, aptdec_callback_t callback, void *context);
// Calibrate channels
APTDEC_API int aptdec_calibrate_thermal(aptdec_image_t *img, aptdec_region_t region);
APTDEC_API int aptdec_calibrate_visible(aptdec_image_t *img, aptdec_region_t region);
APTDEC_API void aptdec_denoise (aptdec_image_t *img, aptdec_region_t region);
APTDEC_API void aptdec_flip (aptdec_image_t *img, aptdec_region_t region);
APTDEC_API void aptdec_stretch (aptdec_image_t *img, aptdec_region_t region);
APTDEC_API void aptdec_equalize(aptdec_image_t *img, aptdec_region_t region);
APTDEC_API int aptdec_crop (aptdec_image_t *img);
APTDEC_API void aptdec_strip (aptdec_image_t* img);
// Composite two RGB values as layers, in most cases bottom_a will be 1.0f
APTDEC_API aptdec_rgb_t aptdec_composite_rgb(aptdec_rgb_t top, float top_a, aptdec_rgb_t bottom, float bottom_a);
// Apply a gradient such as aptdec_temperature_gradient
// If gradient is less than 256 elements it is the callers responsibility
// that `val` does not exceed the length of the gradient
APTDEC_API aptdec_rgb_t aptdec_gradient(const uint32_t *gradient, uint8_t val);
static const aptdec_region_t APTDEC_REGION_CHA = { APTDEC_CHA_OFFSET, APTDEC_CH_WIDTH };
static const aptdec_region_t APTDEC_REGION_CHB = { APTDEC_CHB_OFFSET, APTDEC_CH_WIDTH };
static const aptdec_region_t APTDEC_REGION_CHA_FULL = { 0, APTDEC_IMG_WIDTH/2 };
static const aptdec_region_t APTDEC_REGION_CHB_FULL = { APTDEC_IMG_WIDTH/2, APTDEC_IMG_WIDTH/2 };
static const aptdec_region_t APTDEC_REGION_FULL = { 0, APTDEC_IMG_WIDTH };
APTDEC_API extern const uint32_t aptdec_temperature_gradient[256];
APTDEC_API extern const uint32_t aptdec_precipitation_gradient[58];
#ifdef __cplusplus
}
#endif
#endif