diff --git a/CMakeLists.txt b/CMakeLists.txt
index 19bec16..b7173c9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,32 +2,62 @@ cmake_minimum_required (VERSION 3.0.0)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
project(aptdec)
-file(GLOB_RECURSE C_SOURCE_FILES src/*.c src/libs/*.c)
-add_executable(aptdec ${C_SOURCE_FILES})
+
+# libpng
+find_package(PNG)
+
+# libsndfile
+find_package(LibSndFile)
+
+set(LIB_C_SOURCE_FILES src/color.c src/dsp.c src/filter.c src/image.c src/libs/reg.c src/libs/median.c)
+set(EXE_C_SOURCE_FILES src/main.c src/pngio.c src/libs/argparse.c)
+set(LIB_C_HEADER_FILES src/apt.h)
+
+# Link with static library for aptdec executable, so we don't need to set the path
+add_library(aptstatic STATIC ${LIB_C_SOURCE_FILES})
+# Create shared library for 3rd party apps
+add_library(apt SHARED ${LIB_C_SOURCE_FILES})
add_compile_definitions(PALETTE_DIR="../palettes")
-# Math
-target_link_libraries(aptdec PRIVATE m)
+if (PNG_FOUND AND LIBSNDFILE_FOUND)
+ add_executable(aptdec ${EXE_C_SOURCE_FILES})
+ include_directories(${PNG_PNG_INCLUDE_DIR})
+ include_directories(${LIBSNDFILE_INCLUDE_DIR})
+ target_link_libraries(aptdec PRIVATE PNG::PNG)
+ target_link_libraries(aptdec PRIVATE ${LIBSNDFILE_LIBRARY})
+ target_link_libraries(aptdec PRIVATE aptstatic)
+ if (MSVC)
+ target_compile_options(aptdec PRIVATE /D_CRT_SECURE_NO_WARNINGS=1 /DAPT_API_STATIC)
+ else()
+ # Math
+ target_link_libraries(aptdec PRIVATE m)
-# Throw errors on warnings on release builds
-if(CMAKE_BUILD_TYPE MATCHES "Release")
- target_compile_options(aptdec PRIVATE -Wall -Wextra -pedantic -Wno-missing-field-initializers -Werror)
+ # Throw errors on warnings on release builds
+ if(CMAKE_BUILD_TYPE MATCHES "Release")
+ target_compile_options(aptdec PRIVATE -Wall -Wextra -pedantic -Wno-missing-field-initializers -Werror)
+ else()
+ target_compile_options(aptdec PRIVATE -Wall -Wextra -pedantic)
+ endif()
+ endif()
else()
- target_compile_options(aptdec PRIVATE -Wall -Wextra -pedantic)
+ MESSAGE(STATUS "WARNING: Only building apt library, as not all of the required libraries were found for aptdec.")
endif()
-# libpng
-target_link_libraries(aptdec PRIVATE PNG::PNG)
-if(WIN32 AND NOT MINGW)
- find_package(PNG CONFIG REQUIRED)
+if (MSVC)
+ target_compile_options(apt PRIVATE /D_CRT_SECURE_NO_WARNINGS=1 /DAPT_API_EXPORT)
+ target_compile_options(aptstatic PRIVATE /D_CRT_SECURE_NO_WARNINGS=1 /DAPT_API_STATIC)
else()
- find_package(PNG REQUIRED)
-endif()
+ # Math
+ target_link_libraries(apt PRIVATE m)
+ target_link_libraries(aptstatic PRIVATE m)
-# libsndfile
-find_package(LibSndFile REQUIRED)
-target_link_libraries(aptdec PRIVATE ${LIBSNDFILE_LIBRARY})
+ if(CMAKE_BUILD_TYPE MATCHES "Release")
+ target_compile_options(apt PRIVATE -Wall -Wextra -pedantic -Wno-missing-field-initializers -Werror)
+ else()
+ target_compile_options(apt PRIVATE -Wall -Wextra -pedantic)
+ endif()
+endif()
# TODO: get this from git
set(PROJECT_VERSION "1.7.0")
@@ -45,16 +75,25 @@ IF(NOT WIN32)
set(CPACK_GENERATOR "DEB;TGZ")
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.${CMAKE_SYSTEM_PROCESSOR}")
- install(TARGETS aptdec DESTINATION "bin/")
- install(DIRECTORY "${PROJECT_SOURCE_DIR}/palettes/" DESTINATION "palettes/")
+ if (TARGET aptdec)
+ install(TARGETS aptdec DESTINATION "bin/")
+ install(DIRECTORY "${PROJECT_SOURCE_DIR}/palettes/" DESTINATION "palettes/")
+ endif()
+
+ install(TARGETS apt LIBRARY DESTINATION lib)
+ install(FILES ${LIB_C_HEADER_FILES} DESTINATION include/apt )
else()
#set(CPACK_GENERATOR "ZIP;NSIS")
set(CPACK_GENERATOR "ZIP")
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
- install(TARGETS aptdec DESTINATION "bin/")
- file(GLOB_RECURSE DLLS *.dll)
- install(FILES ${DLLS} DESTINATION "bin/")
+ if (TARGET aptdec)
+ install(TARGETS aptdec DESTINATION "bin/")
+ file(GLOB_RECURSE DLLS *.dll)
+ install(FILES ${DLLS} DESTINATION "bin/")
+ endif()
+ install(TARGETS apt DESTINATION "bin/")
+ install(FILES ${LIB_C_HEADER_FILES} DESTINATION include/apt )
install(DIRECTORY "${PROJECT_SOURCE_DIR}/palettes/" DESTINATION "palettes/")
endif()
diff --git a/README.md b/README.md
index f1b6ce3..b6a3745 100644
--- a/README.md
+++ b/README.md
@@ -129,11 +129,18 @@ cmake ..
make
```
-Since CMake is now being used for building, windows support has come. You can build for windows with the `build_windows.sh` script, you will need the following:
+You can cross build for Windows from Linux with the `build_windows.sh` script, you will need the following:
```
sudo apt install wget cmake make mingw-w64 git unzip
```
+To build natively on Windows using MSVC, you will also need: git, ninja and cmake. Then run:
+```
+.\build_windows.bat
+```
+
+If you just wish to build libaptdec on Windows, libpng and libsndfile aren't needed.
+
## Further Reading
[User's Guide for Building and Operating
diff --git a/build_windows.bat b/build_windows.bat
new file mode 100644
index 0000000..c0872ec
--- /dev/null
+++ b/build_windows.bat
@@ -0,0 +1,36 @@
+REM Build using Visual Studio 2019 on Windows
+REM Additional tools needed: git, cmake and ninja
+
+REM Build zlib
+git clone https://github.com/madler/zlib
+cd zlib
+mkdir build
+cd build
+cmake -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DMSVC_TOOLSET_VERSION=190 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../../winpath ..
+ninja install
+cd ../../
+
+REM Build libpng
+git clone https://github.com/glennrp/libpng
+cd libpng
+mkdir build
+cd build
+cmake -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DMSVC_TOOLSET_VERSION=190 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../../winpath ..
+ninja install
+cd ../..
+
+REM Build libsndfile - Could build Vorbis, FLAC and Opus first for extra support
+git clone https://github.com/libsndfile/libsndfile.git
+cd libsndfile
+mkdir build
+cd build
+cmake -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DMSVC_TOOLSET_VERSION=190 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../../winpath ..
+ninja install
+cd ../..
+
+REM Build aptdec
+mkdir winbuild
+cd winbuild
+cmake -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DMSVC_TOOLSET_VERSION=190 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../winpath ..
+ninja install
+cd ..
diff --git a/build_windows.sh b/build_windows.sh
index 33fb150..4cb578a 100755
--- a/build_windows.sh
+++ b/build_windows.sh
@@ -1,3 +1,6 @@
+#!/bin/bash
+# Cross compile for Windows from Linux
+
TEMP_PATH="$(pwd)/winpath"
set -e
diff --git a/src/apt.h b/src/apt.h
new file mode 100644
index 0000000..3f12618
--- /dev/null
+++ b/src/apt.h
@@ -0,0 +1,114 @@
+/*
+ * This file is part of Aptdec.
+ * Copyright (c) 2004-2009 Thierry Leconte (F4DWV), Xerbo (xerbo@protonmail.com) 2019-2020
+ * Copyright (c) 2021 Jon Beniston (M7RCE)
+ *
+ * Aptdec 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 APT_H
+#define APT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined (__GNUC__) && (__GNUC__ >= 4)
+#define APT_API __attribute__((visibility("default")))
+#elif defined (_MSC_VER)
+#ifdef APT_API_EXPORT
+#define APT_API __declspec(dllexport)
+#elif APT_API_STATIC
+#define APT_API
+#else if
+#define APT_API __declspec(dllimport)
+#endif
+#else
+#define APT_API
+#endif
+
+// Maximum height of an APT image in number of rows
+#define APT_MAX_HEIGHT 3000
+// Width in pixels of sync
+#define APT_SYNC_WIDTH 39
+// Width in pixels of space
+#define APT_SPC_WIDTH 47
+// Width in pixels of telemetry
+#define APT_TELE_WIDTH 45
+// Width in pixels of a single channel image
+#define APT_CH_WIDTH 909
+#define APT_FRAME_LEN 128
+#define APT_CH_OFFSET (APT_SYNC_WIDTH+APT_SPC_WIDTH+APT_CH_WIDTH+APT_TELE_WIDTH)
+// Width in pixels of full frame, including sync, space, images and telemetry
+#define APT_IMG_WIDTH 2080
+// Offset in pixels to channel A
+#define APT_CHA_OFFSET (APT_SYNC_WIDTH+APT_SPC_WIDTH)
+// Offset in pixels to channel B
+#define APT_CHB_OFFSET (APT_SYNC_WIDTH+APT_SPC_WIDTH+APT_CH_WIDTH+APT_TELE_WIDTH+APT_SYNC_WIDTH+APT_SPC_WIDTH)
+#define APT_TOTAL_TELE (APT_SYNC_WIDTH+APT_SPC_WIDTH+APT_TELE_WIDTH+APT_SYNC_WIDTH+APT_SPC_WIDTH+APT_TELE_WIDTH)
+
+// Number of rows required for apt_calibrate
+#define APT_CALIBRATION_ROWS 192
+// Channel ID returned by apt_calibrate
+// NOAA-15: https://nssdc.gsfc.nasa.gov/nmc/experiment/display.action?id=1998-030A-01
+// 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 apt_channel {APT_CHANNEL_UNKNOWN, APT_CHANNEL_1, APT_CHANNEL_2, APT_CHANNEL_3A, APT_CHANNEL_4, APT_CHANNEL_5, APT_CHANNEL_3B} apt_channel_t;
+
+// Width in elements of apt_image_t.prow arrays
+#define APT_PROW_WIDTH 2150
+
+// apt_getpixelrow callback function to get audio samples.
+// context is the same as passed to apt_getpixelrow.
+typedef int (*apt_getsamples_t)(void *context, float *samples, int count);
+
+typedef struct {
+ float *prow[APT_MAX_HEIGHT]; // Row buffers
+ int nrow; // Number of rows
+ int zenith; // Row in image where satellite reaches peak elevation
+ apt_channel_t chA, chB; // ID of each channel
+ char name[256]; // Stripped filename
+ char *palette; // Filename of palette
+} apt_image_t;
+
+typedef struct {
+ float r, g, b;
+} apt_rgb_t;
+
+int APT_API apt_init(double sample_rate);
+int APT_API apt_getpixelrow(float *pixelv, int nrow, int *zenith, int reset, apt_getsamples_t getsamples, void *context);
+
+void APT_API apt_histogramEqualise(float **prow, int nrow, int offset, int width);
+void APT_API apt_linearEnhance(float **prow, int nrow, int offset, int width);
+apt_channel_t APT_API apt_calibrate(float **prow, int nrow, int offset, int width) ;
+void APT_API apt_denoise(float **prow, int nrow, int offset, int width);
+void APT_API apt_flipImage(apt_image_t *img, int width, int offset);
+int APT_API apt_cropNoise(apt_image_t *img);
+
+apt_rgb_t APT_API apt_applyPalette(char *palette, int val);
+apt_rgb_t APT_API apt_RGBcomposite(apt_rgb_t top, float top_a, apt_rgb_t bottom, float bottom_a);
+
+extern char APT_API apt_TempPalette[256*3];
+extern char APT_API apt_PrecipPalette[58*3];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/color.c b/src/color.c
index dda501c..9d1b635 100644
--- a/src/color.c
+++ b/src/color.c
@@ -17,18 +17,19 @@
*
*/
+#include "apt.h"
#include "color.h"
-rgb_t applyPalette(char *palette, int val){
- return (rgb_t){
+apt_rgb_t apt_applyPalette(char *palette, int val){
+ return (apt_rgb_t){
palette[(int)CLIP(val, 0, 255)*3 + 0],
palette[(int)CLIP(val, 0, 255)*3 + 1],
palette[(int)CLIP(val, 0, 255)*3 + 2]
};
}
-rgb_t RGBcomposite(rgb_t top, float top_a, rgb_t bottom, float bottom_a){
- return (rgb_t){
+apt_rgb_t apt_RGBcomposite(apt_rgb_t top, float top_a, apt_rgb_t bottom, float bottom_a){
+ return (apt_rgb_t){
MCOMPOSITE(top.r, top_a, bottom.r, bottom_a),
MCOMPOSITE(top.g, top_a, bottom.g, bottom_a),
MCOMPOSITE(top.b, top_a, bottom.b, bottom_a)
@@ -36,7 +37,7 @@ rgb_t RGBcomposite(rgb_t top, float top_a, rgb_t bottom, float bottom_a){
}
// The "I totally didn't just steal this from WXtoImg" palette
-char TempPalette[256*3] = {
+char apt_TempPalette[256*3] = {
"\x45\x0\x8f\x46\x0\x91\x47\x0\x92\x48\x0\x94\x49\x0\x96\x4a\x0\x98\x4b\x0\x9b\x4d\x0\x9d"
"\x4e\x0\xa0\x50\x0\xa2\x51\x0\xa5\x52\x0\xa7\x54\x0\xaa\x56\x0\xae\x57\x0\xb1"
"\x58\x0\xb4\x5a\x0\xb7\x5c\x0\xba\x5e\x0\xbd\x5f\x0\xc0\x61\x0\xc4\x64\x0\xc8"
@@ -76,7 +77,7 @@ char TempPalette[256*3] = {
"\xc8\x0\x0\xcc\x0\x0\xcc\x0\x0"
};
-char PrecipPalette[58*3] = {
+char apt_PrecipPalette[58*3] = {
"\x8\x89\x41\x0\xc5\x44\x0\xd1\x2c\x0\xe3\x1c\x0\xf9\x6\x14\xff\x0\x3e\xff\x0\x5d\xff\x0"
"\x80\xff\x0\xab\xff\x0\xcd\xfe\x0\xf8\xff\x0\xff\xe6\x0\xff\xb8\x0\xff\x98\x0"
"\xff\x75\x0\xff\x49\x0\xfe\x26\x0\xff\x4\x0\xdf\x0\x0\xa8\x0\x0\x87\x0\x0"
diff --git a/src/color.h b/src/color.h
index d6a4307..6441fb2 100644
--- a/src/color.h
+++ b/src/color.h
@@ -1,9 +1,3 @@
#include "common.h"
#define MCOMPOSITE(m1, a1, m2, a2) (m1*a1 + m2*a2*(1-a1))
-
-rgb_t applyPalette(char *palette, int val);
-rgb_t RGBcomposite(rgb_t top, float top_a, rgb_t bottom, float bottom_a);
-
-extern char TempPalette[256*3];
-extern char PrecipPalette[58*3];
diff --git a/src/common.h b/src/common.h
index 6f36d29..08e4834 100644
--- a/src/common.h
+++ b/src/common.h
@@ -19,7 +19,6 @@
// Constants
#define VERSION "Aptdec; (c) 2004-2009 Thierry Leconte F4DWV, Xerbo (xerbo@protonmail.com) 2019-2020"
-#define MAX_HEIGHT 3000
// Useful macros
#define CLIP(v, lo, hi) (v > hi ? hi : (v > lo ? v : lo))
@@ -28,17 +27,6 @@
// Typedefs
#ifndef STRUCTS_DEFINED
#define STRUCTS_DEFINED
-typedef struct {
- float r, g, b;
-} rgb_t;
-typedef struct {
- float *prow[MAX_HEIGHT]; // Row buffers
- int nrow; // Number of rows
- int zenith; // Row in image where satellite reaches peak elevation
- int chA, chB; // ID of each channel
- char name[256]; // Stripped filename
- char *palette; // Filename of palette
-} image_t;
typedef struct {
char *type; // Output image type
char *effects; // Effects on the image
@@ -70,4 +58,5 @@ enum effects {
Linear_Equalise='l',
Crop_Noise='c'
};
+
#endif
diff --git a/src/dsp.c b/src/dsp.c
index c567863..63bf1da 100755
--- a/src/dsp.c
+++ b/src/dsp.c
@@ -22,6 +22,7 @@
#include
#include
+#include "apt.h"
#include "filter.h"
// In case your C compiler is so old that Pi hadn't been invented yet
@@ -40,8 +41,6 @@
#define RSMULT 15
#define Fi (Fp * RSMULT)
-extern int getsample(float *inbuff, int count);
-
static double Fe;
static double offset = 0.0;
@@ -51,7 +50,7 @@ static double FreqOsc;
static double K1, K2;
// Check the sample rate and calculate some constants
-int init_dsp(double F) {
+int apt_init(double F) {
if(F > Fi) return 1;
if(F < Fp) return -1;
Fe = F;
@@ -132,7 +131,7 @@ static double pll(double I, double Q) {
}
// Convert samples into pixels
-static int getamp(double *ampbuff, int count) {
+static int getamp(double *ampbuff, int count, apt_getsamples_t getsamples, void *context) {
static float inbuff[BLKIN];
static int idxin = 0;
static int nin = 0;
@@ -148,7 +147,7 @@ static int getamp(double *ampbuff, int count) {
idxin = 0;
// Read some samples
- res = getsample(&(inbuff[nin]), BLKIN - nin);
+ res = getsamples(context, &(inbuff[nin]), BLKIN - nin);
nin += res;
// Make sure there is enough samples to continue
@@ -169,7 +168,7 @@ static int getamp(double *ampbuff, int count) {
}
// Sub-pixel offsetting + FIR compensation
-int getpixelv(float *pvbuff, int count) {
+int getpixelv(float *pvbuff, int count, apt_getsamples_t getsamples, void *context) {
// Amplitude buffer
static double ampbuff[BLKAMP];
static int nam = 0;
@@ -179,7 +178,7 @@ int getpixelv(float *pvbuff, int count) {
// Gaussian resampling factor
mult = (double) Fi / Fe * FreqLine;
- int m = RSFilterLen / mult + 1;
+ int m = (int)(RSFilterLen / mult + 1);
for (int n = 0; n < count; n++) {
int shift;
@@ -188,14 +187,14 @@ int getpixelv(float *pvbuff, int count) {
int res;
memmove(ampbuff, &(ampbuff[idxam]), nam * sizeof(double));
idxam = 0;
- res = getamp(&(ampbuff[nam]), BLKAMP - nam);
+ res = getamp(&(ampbuff[nam]), BLKAMP - nam, getsamples, context);
nam += res;
if (nam < m)
return n;
}
// Gaussian FIR compensation filter
- pvbuff[n] = rsfir(&(ampbuff[idxam]), rsfilter, RSFilterLen, offset, mult) * mult * 256.0;
+ pvbuff[n] = (float)(rsfir(&(ampbuff[idxam]), rsfilter, RSFilterLen, offset, mult) * mult * 256.0);
shift = ((int) floor((RSMULT - offset) / mult)) + 1;
offset = shift * mult + offset - RSMULT;
@@ -208,7 +207,7 @@ int getpixelv(float *pvbuff, int count) {
}
// Get an entire row of pixels, aligned with sync markers
-int getpixelrow(float *pixelv, int nrow, int *zenith, int reset) {
+int apt_getpixelrow(float *pixelv, int nrow, int *zenith, int reset, apt_getsamples_t getsamples, void *context) {
static float pixels[PixelLine + SyncFilterLen];
static int npv;
static int synced = 0;
@@ -226,7 +225,7 @@ int getpixelrow(float *pixelv, int nrow, int *zenith, int reset) {
// Get the sync line
if (npv < SyncFilterLen + 2) {
- res = getpixelv(&(pixelv[npv]), SyncFilterLen + 2 - npv);
+ res = getpixelv(&(pixelv[npv]), SyncFilterLen + 2 - npv, getsamples, context);
npv += res;
if (npv < SyncFilterLen + 2)
return 0;
@@ -257,7 +256,7 @@ int getpixelrow(float *pixelv, int nrow, int *zenith, int reset) {
static int lastmshift;
if (npv < PixelLine + SyncFilterLen) {
- res = getpixelv(&(pixelv[npv]), PixelLine + SyncFilterLen - npv);
+ res = getpixelv(&(pixelv[npv]), PixelLine + SyncFilterLen - npv, getsamples, context);
npv += res;
if (npv < PixelLine + SyncFilterLen)
return 0;
@@ -295,7 +294,7 @@ int getpixelrow(float *pixelv, int nrow, int *zenith, int reset) {
// Get the rest of this row
if (npv < PixelLine) {
- res = getpixelv(&(pixelv[npv]), PixelLine - npv);
+ res = getpixelv(&(pixelv[npv]), PixelLine - npv, getsamples, context);
npv += res;
if (npv < PixelLine)
return 0;
diff --git a/src/filter.c b/src/filter.c
index d850fd0..dbc1d71 100755
--- a/src/filter.c
+++ b/src/filter.c
@@ -27,7 +27,7 @@ float fir(float *buff, const float *coeff, const int len) {
for (int i = 0; i < len; i++) {
r += buff[i] * coeff[i];
}
- return r;
+ return (float)r;
}
/* IQ finite impulse response
@@ -61,5 +61,5 @@ float rsfir(double *buff, const float *coeff, const int len, const double offset
alpha = n - k;
out += buff[i] * (coeff[k] * (1.0 - alpha) + coeff[k + 1] * alpha);
}
- return out;
+ return (float)out;
}
diff --git a/src/image.c b/src/image.c
index 05fb2a4..11a2ef9 100644
--- a/src/image.c
+++ b/src/image.c
@@ -19,11 +19,10 @@
#include
#include
-#include
#include
#include
-#include "offsets.h"
+#include "apt.h"
#include "libs/reg.h"
#include "image.h"
@@ -55,7 +54,7 @@ static double rgcal(float x, rgparam_t *rgpr) {
static double tele[16];
static double Cs;
-void histogramEqualise(float **prow, int nrow, int offset, int width){
+void apt_histogramEqualise(float **prow, int nrow, int offset, int width){
// Plot histogram
int histogram[256] = { 0 };
for(int y = 0; y < nrow; y++)
@@ -73,13 +72,13 @@ void histogramEqualise(float **prow, int nrow, int offset, int width){
int area = nrow * width;
for(int y = 0; y < nrow; y++){
for(int x = 0; x < width; x++){
- int k = prow[y][x+offset];
- prow[y][x+offset] = (256.0/area) * cf[k];
+ int k = (int)prow[y][x+offset];
+ prow[y][x+offset] = (256.0f/area) * cf[k];
}
}
}
-void linearEnhance(float **prow, int nrow, int offset, int width){
+void apt_linearEnhance(float **prow, int nrow, int offset, int width){
// Plot histogram
int histogram[256] = { 0 };
for(int y = 0; y < nrow; y++)
@@ -98,19 +97,19 @@ void linearEnhance(float **prow, int nrow, int offset, int width){
// 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.0;
- prow[y][x+offset] = CLIP(prow[y][x+offset], 0.0, 255.0);
+ prow[y][x+offset] = (prow[y][x+offset]-min) / (max-min) * 255.0f;
+ prow[y][x+offset] = CLIP(prow[y][x+offset], 0.0f, 255.0f);
}
}
}
// Brightness calibrate, including telemetry
void calibrateImage(float **prow, int nrow, int offset, int width, rgparam_t regr){
- offset -= SYNC_WIDTH+SPC_WIDTH;
+ offset -= APT_SYNC_WIDTH+APT_SPC_WIDTH;
for (int y = 0; y < nrow; y++) {
- for (int x = 0; x < width+SYNC_WIDTH+SPC_WIDTH+TELE_WIDTH; x++) {
- float pv = rgcal(prow[y][x + offset], ®r);
+ for (int x = 0; x < width+APT_SYNC_WIDTH+APT_SPC_WIDTH+APT_TELE_WIDTH; x++) {
+ float pv = (float)rgcal(prow[y][x + offset], ®r);
prow[y][x + offset] = CLIP(pv, 0, 255);
}
}
@@ -126,17 +125,17 @@ double teleNoise(double wedges[16]){
}
// Get telemetry data for thermal calibration
-int calibrate(float **prow, int nrow, int offset, int width) {
- double teleline[MAX_HEIGHT] = { 0.0 };
+apt_channel_t apt_calibrate(float **prow, int nrow, int offset, int width) {
+ double teleline[APT_MAX_HEIGHT] = { 0.0 };
double wedge[16];
- rgparam_t regr[MAX_HEIGHT/FRAME_LEN + 1];
+ rgparam_t regr[APT_MAX_HEIGHT/APT_FRAME_LEN + 1];
int telestart, mtelestart = 0;
int channel = -1;
// The minimum rows required to decode a full frame
- if (nrow < 192) {
+ if (nrow < APT_CALIBRATION_ROWS) {
fprintf(stderr, "Telemetry decoding error, not enough rows\n");
- return 0;
+ return APT_CHANNEL_UNKNOWN;
}
// Calculate average of a row of telemetry
@@ -156,8 +155,8 @@ int calibrate(float **prow, int nrow, int offset, int width) {
float df;
// (sum 4px below) - (sum 4px above)
- df = (teleline[n - 4] + teleline[n - 3] + teleline[n - 2] + teleline[n - 1]) -
- (teleline[n + 0] + teleline[n + 1] + teleline[n + 2] + teleline[n + 3]);
+ df = (float)((teleline[n - 4] + teleline[n - 3] + teleline[n - 2] + teleline[n - 1]) -
+ (teleline[n + 0] + teleline[n + 1] + teleline[n + 2] + teleline[n + 3]));
// Find the maximum difference
if (df > max) {
@@ -166,18 +165,18 @@ int calibrate(float **prow, int nrow, int offset, int width) {
}
}
- telestart = (mtelestart + 64) % FRAME_LEN;
+ telestart = (mtelestart + 64) % APT_FRAME_LEN;
// Make sure that theres at least one full frame in the image
- if (nrow < telestart + FRAME_LEN) {
+ if (nrow < telestart + APT_FRAME_LEN) {
fprintf(stderr, "Telemetry decoding error, not enough rows\n");
- return 0;
+ return APT_CHANNEL_UNKNOWN;
}
// Find the least noisy frame
double minNoise = -1;
int bestFrame = -1;
- for (int n = telestart, k = 0; n < nrow - FRAME_LEN; n += FRAME_LEN, k++) {
+ for (int n = telestart, k = 0; n < nrow - APT_FRAME_LEN; n += APT_FRAME_LEN, k++) {
int j;
for (j = 0; j < 16; j++) {
@@ -197,7 +196,7 @@ int calibrate(float **prow, int nrow, int offset, int width) {
// Compute & apply regression on the wedges
rgcomp(wedge, ®r[k]);
for (int j = 0; j < 16; j++)
- tele[j] = rgcal(wedge[j], ®r[k]);
+ tele[j] = (float)rgcal((float)wedge[j], ®r[k]);
/* Compare the channel ID wedge to the reference
* wedges, the wedge with the closest match will
@@ -205,7 +204,7 @@ int calibrate(float **prow, int nrow, int offset, int width) {
*/
float min = -1;
for (int j = 0; j < 6; j++) {
- float df = tele[15] - tele[j];
+ float df = (float)(tele[15] - tele[j]);
df *= df;
if (df < min || min == -1) {
@@ -217,10 +216,10 @@ int calibrate(float **prow, int nrow, int offset, int width) {
// Find the brightness of the minute marker, I don't really know what for
Cs = 0.0;
int i, j = n;
- for (i = 0, j = n; j < n + FRAME_LEN; j++) {
+ for (i = 0, j = n; j < n + APT_FRAME_LEN; j++) {
float csline = 0.0;
for (int l = 3; l < 43; l++)
- csline += prow[n][l + offset - SPC_WIDTH];
+ csline += prow[n][l + offset - APT_SPC_WIDTH];
csline /= 40.0;
if (csline > 50.0) {
@@ -228,18 +227,18 @@ int calibrate(float **prow, int nrow, int offset, int width) {
i++;
}
}
- Cs = rgcal(Cs / i, ®r[k]);
+ Cs = rgcal((float)(Cs / i), ®r[k]);
}
}
if(bestFrame == -1){
fprintf(stderr, "Something has gone very wrong, please file a bug report.\n");
- return 0;
+ return APT_CHANNEL_UNKNOWN;
}
calibrateImage(prow, nrow, offset, width, regr[bestFrame]);
- return channel + 1;
+ return (apt_channel_t)(channel + 1);
}
@@ -247,7 +246,7 @@ extern float quick_select(float arr[], int n);
// Biased median denoise, pretyt ugly
#define TRIG_LEVEL 40
-void denoise(float **prow, int nrow, int offset, int width){
+void apt_denoise(float **prow, int nrow, int offset, int width){
for(int y = 2; y < nrow-2; y++){
for(int x = offset+1; x < offset+width-1; x++){
if(prow[y][x+1] - prow[y][x] > TRIG_LEVEL ||
@@ -267,7 +266,7 @@ void denoise(float **prow, int nrow, int offset, int width){
#undef TRIG_LEVEL
// Flips a channel, for northbound passes
-void flipImage(image_t *img, int width, int offset){
+void apt_flipImage(apt_image_t *img, int width, int offset){
for(int y = 1; y < img->nrow; y++){
for(int x = 1; x < ceil(width / 2.0); x++){
// Flip top-left & bottom-right
@@ -279,17 +278,17 @@ void flipImage(image_t *img, int width, int offset){
}
// Calculate crop to reomve noise from the start and end of an image
-int cropNoise(image_t *img){
+int apt_cropNoise(apt_image_t *img){
#define NOISE_THRESH 180.0
// Average value of minute marker
- float spc_rows[MAX_HEIGHT] = { 0.0 };
+ float spc_rows[APT_MAX_HEIGHT] = { 0.0 };
int startCrop = 0; int endCrop = img->nrow;
for(int y = 0; y < img->nrow; y++) {
- for(int x = 0; x < SPC_WIDTH; x++) {
- spc_rows[y] += img->prow[y][x + (CHB_OFFSET - SPC_WIDTH)];
+ for(int x = 0; x < APT_SPC_WIDTH; x++) {
+ spc_rows[y] += img->prow[y][x + (APT_CHB_OFFSET - APT_SPC_WIDTH)];
}
- spc_rows[y] /= SPC_WIDTH;
+ spc_rows[y] /= APT_SPC_WIDTH;
// Skip minute markings
if(spc_rows[y] < 10) {
@@ -319,7 +318,7 @@ int cropNoise(image_t *img){
// Remove the noisy rows at start
for(int y = 0; y < img->nrow-startCrop; y++) {
- memmove(img->prow[y], img->prow[y+startCrop], sizeof(float)*2150);
+ memmove(img->prow[y], img->prow[y+startCrop], sizeof(float)*APT_PROW_WIDTH);
}
// Ignore the noisy rows at the end
@@ -396,7 +395,7 @@ static double tempcal(float Ce, int satnum, tempparam_t * rgpr) {
}
// Temperature calibration wrapper
-void temperature(options_t *opts, image_t *img, int offset, int width){
+void temperature(options_t *opts, apt_image_t *img, int offset, int width){
tempparam_t temp;
printf("Temperature... ");
@@ -406,7 +405,7 @@ void temperature(options_t *opts, image_t *img, int offset, int width){
for (int y = 0; y < img->nrow; y++) {
for (int x = 0; x < width; x++) {
- img->prow[y][x + offset] = tempcal(img->prow[y][x + offset], opts->satnum - 15, &temp);
+ img->prow[y][x + offset] = (float)tempcal(img->prow[y][x + offset], opts->satnum - 15, &temp);
}
}
printf("Done\n");
diff --git a/src/image.h b/src/image.h
index 2fb7e8d..ff6309f 100644
--- a/src/image.h
+++ b/src/image.h
@@ -1,9 +1,4 @@
+#include "apt.h"
#include "common.h"
-void histogramEqualise(float **prow, int nrow, int offset, int width);
-void linearEnhance(float **prow, int nrow, int offset, int width);
-int calibrate(float **prow, int nrow, int offset, int width) ;
-void denoise(float **prow, int nrow, int offset, int width);
-void flipImage(image_t *img, int width, int offset);
-int cropNoise(image_t *img);
-void temperature(options_t *opts, image_t *img, int offset, int width);
+void APT_API temperature(options_t *opts, apt_image_t *img, int offset, int width);
diff --git a/src/main.c b/src/main.c
index 6c9143d..56c487b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -20,18 +20,19 @@
#include
#include
#include
+#ifndef _MSC_VER
#include
+#else
+#include
+#endif
#include
#include
#include
#include
#include "libs/argparse.h"
-#include "offsets.h"
-
-// DSP
-extern int init_dsp(double F);
-extern int getpixelrow(float *pixelv, int nrow, int *zenith, int reset);
+#include "common.h"
+#include "apt.h"
#include "pngio.h"
#include "image.h"
@@ -44,9 +45,26 @@ int channels = 1;
// Function declarations
static int initsnd(char *filename);
-int getsample(float *sample, int nb);
+int getsamples(void *context, float *samples, int nb);
static int processAudio(char *filename, options_t *opts);
+#ifdef _MSC_VER
+// Functions not supported by MSVC
+static char *dirname(char *path)
+{
+ static char dir[MAX_PATH];
+ _splitpath(path, NULL, dir, NULL, NULL);
+ return dir;
+}
+
+static char *basename(char *path)
+{
+ static char base[MAX_PATH];
+ _splitpath(path, NULL, NULL, base, NULL);
+ return base;
+}
+#endif
+
int main(int argc, const char **argv) {
options_t opts = { "r", "", 19, "", ".", 0, "", "", 1.0, 0 };
@@ -98,7 +116,7 @@ int main(int argc, const char **argv) {
static int processAudio(char *filename, options_t *opts){
// Image info struct
- image_t img;
+ apt_image_t img;
// Mapping between wedge value and channel ID
static struct {
@@ -106,7 +124,7 @@ static int processAudio(char *filename, options_t *opts){
char *name[7];
} ch = {
{ "?", "1", "2", "3A", "4", "5", "3B" },
- { "unknown", "visble", "near-infrared", "mid-infrared", "thermal-infrared", "thermal-infrared", "mid-infrared" }
+ { "unknown", "visble", "near-infrared", "near-infrared", "thermal-infrared", "thermal-infrared", "mid-infrared" }
};
// Buffer for image channel
@@ -125,7 +143,7 @@ static int processAudio(char *filename, options_t *opts){
strncpy(img.name, ctime(&t), 24);
// Init a row writer
- initWriter(opts, &img, IMG_WIDTH, MAX_HEIGHT, "Unprocessed realtime image", "r");
+ initWriter(opts, &img, APT_IMG_WIDTH, APT_MAX_HEIGHT, "Unprocessed realtime image", "r");
}
if(strcmp(extension, "png") == 0){
@@ -141,15 +159,15 @@ static int processAudio(char *filename, options_t *opts){
// Build image
// TODO: multithreading, would require some sort of input buffer
- for (img.nrow = 0; img.nrow < MAX_HEIGHT; img.nrow++) {
+ for (img.nrow = 0; img.nrow < APT_MAX_HEIGHT; img.nrow++) {
// Allocate memory for this row
- img.prow[img.nrow] = (float *) malloc(sizeof(float) * 2150);
+ img.prow[img.nrow] = (float *) malloc(sizeof(float) * APT_PROW_WIDTH);
// Write into memory and break the loop when there are no more samples to read
- if (getpixelrow(img.prow[img.nrow], img.nrow, &img.zenith, (img.nrow == 0)) == 0)
+ if (apt_getpixelrow(img.prow[img.nrow], img.nrow, &img.zenith, (img.nrow == 0), getsamples, NULL) == 0)
break;
- if(opts->realtime) pushRow(img.prow[img.nrow], IMG_WIDTH);
+ if(opts->realtime) pushRow(img.prow[img.nrow], APT_IMG_WIDTH);
fprintf(stderr, "Row: %d\r", img.nrow);
fflush(stderr);
@@ -171,81 +189,81 @@ static int processAudio(char *filename, options_t *opts){
}
// Calibrate
- img.chA = calibrate(img.prow, img.nrow, CHA_OFFSET, CH_WIDTH);
- img.chB = calibrate(img.prow, img.nrow, CHB_OFFSET, CH_WIDTH);
+ img.chA = apt_calibrate(img.prow, img.nrow, APT_CHA_OFFSET, APT_CH_WIDTH);
+ img.chB = apt_calibrate(img.prow, img.nrow, APT_CHB_OFFSET, APT_CH_WIDTH);
printf("Channel A: %s (%s)\n", ch.id[img.chA], ch.name[img.chA]);
printf("Channel B: %s (%s)\n", ch.id[img.chB], ch.name[img.chB]);
// Crop noise from start and end of image
if(CONTAINS(opts->effects, Crop_Noise)){
- img.zenith -= cropNoise(&img);
+ img.zenith -= apt_cropNoise(&img);
}
// Denoise
if(CONTAINS(opts->effects, Denoise)){
- denoise(img.prow, img.nrow, CHA_OFFSET, CH_WIDTH);
- denoise(img.prow, img.nrow, CHB_OFFSET, CH_WIDTH);
+ apt_denoise(img.prow, img.nrow, APT_CHA_OFFSET, APT_CH_WIDTH);
+ apt_denoise(img.prow, img.nrow, APT_CHB_OFFSET, APT_CH_WIDTH);
}
// Flip, for northbound passes
if(CONTAINS(opts->effects, Flip_Image)){
- flipImage(&img, CH_WIDTH, CHA_OFFSET);
- flipImage(&img, CH_WIDTH, CHB_OFFSET);
+ apt_flipImage(&img, APT_CH_WIDTH, APT_CHA_OFFSET);
+ apt_flipImage(&img, APT_CH_WIDTH, APT_CHB_OFFSET);
}
// Temperature
if (CONTAINS(opts->type, Temperature) && img.chB >= 4) {
// Create another buffer as to not modify the orignal
- image_t tmpimg = img;
+ apt_image_t tmpimg = img;
for(int i = 0; i < img.nrow; i++){
- tmpimg.prow[i] = (float *) malloc(sizeof(float) * 2150);
- memcpy(tmpimg.prow[i], img.prow[i], sizeof(float) * 2150);
+ tmpimg.prow[i] = (float *) malloc(sizeof(float) * APT_PROW_WIDTH);
+ memcpy(tmpimg.prow[i], img.prow[i], sizeof(float) * APT_PROW_WIDTH);
}
// Perform temperature calibration
- temperature(opts, &tmpimg, CHB_OFFSET, CH_WIDTH);
- ImageOut(opts, &tmpimg, CHB_OFFSET, CH_WIDTH, "Temperature", Temperature, (char *)TempPalette);
+ temperature(opts, &tmpimg, APT_CHB_OFFSET, APT_CH_WIDTH);
+ ImageOut(opts, &tmpimg, APT_CHB_OFFSET, APT_CH_WIDTH, "Temperature", Temperature, (char *)apt_TempPalette);
}
// MCIR
if (CONTAINS(opts->type, MCIR))
- ImageOut(opts, &img, CHA_OFFSET, CH_WIDTH, "MCIR", MCIR, NULL);
+ ImageOut(opts, &img, APT_CHA_OFFSET, APT_CH_WIDTH, "MCIR", MCIR, NULL);
// Linear equalise
if(CONTAINS(opts->effects, Linear_Equalise)){
- linearEnhance(img.prow, img.nrow, CHA_OFFSET, CH_WIDTH);
- linearEnhance(img.prow, img.nrow, CHB_OFFSET, CH_WIDTH);
+ apt_linearEnhance(img.prow, img.nrow, APT_CHA_OFFSET, APT_CH_WIDTH);
+ apt_linearEnhance(img.prow, img.nrow, APT_CHB_OFFSET, APT_CH_WIDTH);
}
// Histogram equalise
if(CONTAINS(opts->effects, Histogram_Equalise)){
- histogramEqualise(img.prow, img.nrow, CHA_OFFSET, CH_WIDTH);
- histogramEqualise(img.prow, img.nrow, CHB_OFFSET, CH_WIDTH);
+ apt_histogramEqualise(img.prow, img.nrow, APT_CHA_OFFSET, APT_CH_WIDTH);
+ apt_histogramEqualise(img.prow, img.nrow, APT_CHB_OFFSET, APT_CH_WIDTH);
}
// Raw image
if (CONTAINS(opts->type, Raw_Image)) {
sprintf(desc, "%s (%s) & %s (%s)", ch.id[img.chA], ch.name[img.chA], ch.id[img.chB], ch.name[img.chB]);
- ImageOut(opts, &img, 0, IMG_WIDTH, desc, Raw_Image, NULL);
+ ImageOut(opts, &img, 0, APT_IMG_WIDTH, desc, Raw_Image, NULL);
}
// Palette image
if (CONTAINS(opts->type, Palleted)) {
img.palette = opts->palette;
strcpy(desc, "Palette composite");
- ImageOut(opts, &img, CHA_OFFSET, 909, desc, Palleted, NULL);
+ ImageOut(opts, &img, APT_CHA_OFFSET, 909, desc, Palleted, NULL);
}
// Channel A
if (CONTAINS(opts->type, Channel_A)) {
sprintf(desc, "%s (%s)", ch.id[img.chA], ch.name[img.chA]);
- ImageOut(opts, &img, CHA_OFFSET, CH_WIDTH, desc, Channel_A, NULL);
+ ImageOut(opts, &img, APT_CHA_OFFSET, APT_CH_WIDTH, desc, Channel_A, NULL);
}
// Channel B
if (CONTAINS(opts->type, Channel_B)) {
sprintf(desc, "%s (%s)", ch.id[img.chB], ch.name[img.chB]);
- ImageOut(opts, &img, CHB_OFFSET, CH_WIDTH, desc, Channel_B, NULL);
+ ImageOut(opts, &img, APT_CHB_OFFSET, APT_CH_WIDTH, desc, Channel_B, NULL);
}
return 1;
@@ -263,7 +281,7 @@ static int initsnd(char *filename) {
return 0;
}
- res = init_dsp(infwav.samplerate);
+ res = apt_init(infwav.samplerate);
printf("Input file: %s\n", filename);
if(res < 0) {
fprintf(stderr, "Input sample rate too low: %d\n", infwav.samplerate);
@@ -280,16 +298,18 @@ static int initsnd(char *filename) {
}
// Read samples from the audio file
-int getsample(float *sample, int nb) {
+int getsamples(void *context, float *samples, int nb) {
+ (void) context;
if(channels == 1){
- return sf_read_float(audioFile, sample, nb);
+ return (int)sf_read_float(audioFile, samples, nb);
}else{
/* Multi channel audio is encoded such as:
* Ch1,Ch2,Ch1,Ch2,Ch1,Ch2
*/
- float buf[nb * channels]; // Something like BLKIN*2 could also be used
- int samples = sf_read_float(audioFile, buf, nb * channels);
- for(int i = 0; i < nb; i++) sample[i] = buf[i * channels];
- return samples / channels;
+ float *buf = malloc(sizeof(float) * nb * channels); // Something like BLKIN*2 could also be used
+ int samplesRead = (int)sf_read_float(audioFile, buf, nb * channels);
+ for(int i = 0; i < nb; i++) samples[i] = buf[i * channels];
+ free(buf);
+ return samplesRead / channels;
}
}
diff --git a/src/offsets.h b/src/offsets.h
deleted file mode 100644
index 158f5de..0000000
--- a/src/offsets.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * This file is part of Aptdec.
- * Copyright (c) 2004-2009 Thierry Leconte (F4DWV), Xerbo (xerbo@protonmail.com) 2019-2020
- *
- * Aptdec 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 .
- *
- */
-
-#define SYNC_WIDTH 39
-#define SPC_WIDTH 47
-#define TELE_WIDTH 45
-#define CH_WIDTH 909
-#define FRAME_LEN 128
-#define CH_OFFSET (SYNC_WIDTH+SPC_WIDTH+CH_WIDTH+TELE_WIDTH)
-#define IMG_WIDTH 2080
-#define CHA_OFFSET (SYNC_WIDTH+SPC_WIDTH)
-#define CHB_OFFSET (SYNC_WIDTH+SPC_WIDTH+CH_WIDTH+TELE_WIDTH+SYNC_WIDTH+SPC_WIDTH)
-#define TOTAL_TELE (SYNC_WIDTH+SPC_WIDTH+TELE_WIDTH+SYNC_WIDTH+SPC_WIDTH+TELE_WIDTH)
diff --git a/src/pngio.c b/src/pngio.c
index a350d19..e605fd9 100644
--- a/src/pngio.c
+++ b/src/pngio.c
@@ -26,7 +26,7 @@
#include "pngio.h"
-int mapOverlay(char *filename, rgb_t **crow, int nrow, int zenith, int MCIR) {
+int mapOverlay(char *filename, apt_rgb_t **crow, int nrow, int zenith, int MCIR) {
FILE *fp = fopen(filename, "rb");
if(!fp) {
fprintf(stderr, "Cannot open %s\n", filename);
@@ -88,14 +88,14 @@ int mapOverlay(char *filename, rgb_t **crow, int nrow, int zenith, int MCIR) {
for(int x = 49; x < width - 82; x++){
// Maps are 16 bit / channel
png_bytep px = &mapRows[CLIP(y + mapOffset, 0, height-1)][x * 6];
- rgb_t map = {
+ apt_rgb_t map = {
(px[0] << 8) | px[1],
(px[2] << 8) | px[3],
(px[4] << 8) | px[5]
};
// Pixel offsets
- int chb = x + CHB_OFFSET - 49;
+ int chb = x + APT_CHB_OFFSET - 49;
int cha = x + 36;
// Fill in map
@@ -105,10 +105,10 @@ int mapOverlay(char *filename, rgb_t **crow, int nrow, int zenith, int MCIR) {
float darken = ((255-crow[y][chb].r)-100)/50;
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*darken, green*98*darken, blue*500.0*darken};
+ crow[y][cha] = (apt_rgb_t){blue*1000*darken, green*98*darken, blue*500.0*darken};
}else{
// Sea
- crow[y][cha] = (rgb_t){9, 17, 74};
+ crow[y][cha] = (apt_rgb_t){9, 17, 74};
}
}
@@ -125,15 +125,15 @@ int mapOverlay(char *filename, rgb_t **crow, int nrow, int zenith, int MCIR) {
map.b = CLIP(map.b, 0, 255.0);
// Map overlay on channel A
- crow[y][cha] = RGBcomposite(map, alpha, crow[y][cha], 1);
+ crow[y][cha] = apt_RGBcomposite(map, alpha, crow[y][cha], 1);
// Map overlay on channel B
if(!MCIR)
- crow[y][chb] = RGBcomposite(map, alpha, crow[y][chb], 1);
+ crow[y][chb] = apt_RGBcomposite(map, alpha, crow[y][chb], 1);
// Cloud overlay on channel A
if(MCIR){
float cloud = CLIP((crow[y][chb].r - 113) / 90.0, 0, 1);
- crow[y][cha] = RGBcomposite((rgb_t){255, 250, 245}, cloud, crow[y][cha], 1);
+ crow[y][cha] = apt_RGBcomposite((apt_rgb_t){255, 250, 245}, cloud, crow[y][cha], 1);
}
}
}
@@ -170,8 +170,8 @@ int readRawImage(char *filename, float **prow, int *nrow) {
png_byte bit_depth = png_get_bit_depth(png, info);
// Check the image
- if(width != IMG_WIDTH){
- fprintf(stderr, "Raw image must be %ipx wide.\n", IMG_WIDTH);
+ if(width != APT_IMG_WIDTH){
+ fprintf(stderr, "Raw image must be %ipx wide.\n", APT_IMG_WIDTH);
return 0;
}else if(bit_depth != 8){
fprintf(stderr, "Raw image must have 8 bit color.\n");
@@ -206,7 +206,7 @@ int readRawImage(char *filename, float **prow, int *nrow) {
return 1;
}
-int readPalette(char *filename, rgb_t **pixels) {
+int readPalette(char *filename, apt_rgb_t **pixels) {
FILE *fp = fopen(filename, "rb");
if(!fp) {
char buffer[1024];
@@ -266,10 +266,10 @@ int readPalette(char *filename, rgb_t **pixels) {
// Put into crow
for(int y = 0; y < height; y++) {
- pixels[y] = (rgb_t *) malloc(sizeof(rgb_t) * width);
+ pixels[y] = (apt_rgb_t *) malloc(sizeof(apt_rgb_t) * width);
for(int x = 0; x < width; x++)
- pixels[y][x] = (rgb_t){
+ pixels[y][x] = (apt_rgb_t){
PNGrows[y][x*3],
PNGrows[y][x*3 + 1],
PNGrows[y][x*3 + 2]
@@ -279,38 +279,38 @@ int readPalette(char *filename, rgb_t **pixels) {
return 1;
}
-void prow2crow(float **prow, int nrow, char *palette, rgb_t **crow){
+void prow2crow(float **prow, int nrow, char *palette, apt_rgb_t **crow){
for(int y = 0; y < nrow; y++){
- crow[y] = (rgb_t *) malloc(sizeof(rgb_t) * IMG_WIDTH);
+ crow[y] = (apt_rgb_t *) malloc(sizeof(apt_rgb_t) * APT_IMG_WIDTH);
- for(int x = 0; x < IMG_WIDTH; x++){
+ for(int x = 0; x < APT_IMG_WIDTH; x++){
if(palette == NULL)
crow[y][x].r = crow[y][x].g = crow[y][x].b = prow[y][x];
else
- crow[y][x] = applyPalette(palette, prow[y][x]);
+ crow[y][x] = apt_applyPalette(palette, prow[y][x]);
}
}
}
-int applyUserPalette(float **prow, int nrow, char *filename, rgb_t **crow){
- rgb_t *pal_row[256];
+int applyUserPalette(float **prow, int nrow, char *filename, apt_rgb_t **crow){
+ apt_rgb_t *pal_row[256];
if(!readPalette(filename, pal_row)){
fprintf(stderr, "Could not read palette\n");
return 0;
}
for(int y = 0; y < nrow; y++){
- for(int x = 0; x < CH_WIDTH; x++){
- int cha = CLIP(prow[y][x + CHA_OFFSET], 0, 255);
- int chb = CLIP(prow[y][x + CHB_OFFSET], 0, 255);
- crow[y][x + CHA_OFFSET] = pal_row[chb][cha];
+ for(int x = 0; x < APT_CH_WIDTH; x++){
+ int cha = CLIP(prow[y][x + APT_CHA_OFFSET], 0, 255);
+ int chb = CLIP(prow[y][x + APT_CHB_OFFSET], 0, 255);
+ crow[y][x + APT_CHA_OFFSET] = pal_row[chb][cha];
}
}
return 1;
}
-int ImageOut(options_t *opts, image_t *img, int offset, int width, char *desc, char chid, char *palette){
+int ImageOut(options_t *opts, apt_image_t *img, int offset, int width, char *desc, char chid, char *palette){
char outName[512];
if(opts->filename == NULL || opts->filename[0] == '\0'){
sprintf(outName, "%s/%s-%c.png", opts->path, img->name, chid);
@@ -346,8 +346,8 @@ int ImageOut(options_t *opts, image_t *img, int offset, int width, char *desc, c
for(unsigned long int i = 0; i < strlen(opts->effects); i++){
switch (opts->effects[i]) {
case Crop_Telemetry:
- width -= TOTAL_TELE;
- offset += SYNC_WIDTH + SPC_WIDTH;
+ width -= APT_TOTAL_TELE;
+ offset += APT_SYNC_WIDTH + APT_SPC_WIDTH;
crop_telemetry = 1;
break;
case Precipitation_Overlay:
@@ -409,7 +409,7 @@ int ImageOut(options_t *opts, image_t *img, int offset, int width, char *desc, c
png_write_info(png_ptr, info_ptr);
// Move prow into crow, crow ~ color rows, if required
- rgb_t *crow[MAX_HEIGHT];
+ apt_rgb_t *crow[APT_MAX_HEIGHT];
if(!greyscale){
prow2crow(img->prow, img->nrow, palette, crow);
}
@@ -422,9 +422,9 @@ int ImageOut(options_t *opts, image_t *img, int offset, int width, char *desc, c
// Precipitation overlay
if(CONTAINS(opts->effects, Precipitation_Overlay)){
for(int y = 0; y < img->nrow; y++){
- for(int x = 0; x < CH_WIDTH; x++){
- if(img->prow[y][x + CHB_OFFSET] >= 198)
- crow[y][x + CHB_OFFSET] = crow[y][x + CHA_OFFSET] = applyPalette(PrecipPalette, img->prow[y][x + CHB_OFFSET]-198);
+ for(int x = 0; x < APT_CH_WIDTH; x++){
+ if(img->prow[y][x + APT_CHB_OFFSET] >= 198)
+ crow[y][x + APT_CHB_OFFSET] = crow[y][x + APT_CHA_OFFSET] = apt_applyPalette(apt_PrecipPalette, img->prow[y][x + APT_CHB_OFFSET]-198);
}
}
}
@@ -448,13 +448,13 @@ int ImageOut(options_t *opts, image_t *img, int offset, int width, char *desc, c
// Build image
for (int y = 0; y < img->nrow; y++) {
- png_color pix[width]; // Color
- png_byte mpix[width]; // Mono
+ png_color pix[APT_IMG_WIDTH]; // Color
+ png_byte mpix[APT_IMG_WIDTH]; // Mono
int skip = 0;
for (int x = 0; x < width; x++) {
- if(crop_telemetry && x == CH_WIDTH)
- skip += TELE_WIDTH + SYNC_WIDTH + SPC_WIDTH;
+ if(crop_telemetry && x == APT_CH_WIDTH)
+ skip += APT_TELE_WIDTH + APT_SYNC_WIDTH + APT_SPC_WIDTH;
if(greyscale){
mpix[x] = POWF(img->prow[y][x + skip + offset], opts->gamma)/a;
@@ -488,7 +488,7 @@ png_structp rt_png_ptr;
png_infop rt_info_ptr;
FILE *rt_pngfile;
-int initWriter(options_t *opts, image_t *img, int width, int height, char *desc, char *chid){
+int initWriter(options_t *opts, apt_image_t *img, int width, int height, char *desc, char *chid){
char outName[384];
sprintf(outName, "%s/%s-%s.png", opts->path, img->name, chid);
@@ -538,7 +538,7 @@ int initWriter(options_t *opts, image_t *img, int width, int height, char *desc,
}
void pushRow(float *row, int width){
- png_byte pix[width];
+ png_byte pix[APT_IMG_WIDTH];
for(int i = 0; i < width; i++)
pix[i] = row[i];
diff --git a/src/pngio.h b/src/pngio.h
index cdb7cfd..193cbdf 100644
--- a/src/pngio.h
+++ b/src/pngio.h
@@ -1,13 +1,12 @@
+#include "apt.h"
#include "common.h"
-#include "offsets.h"
-#include "color.h"
-int mapOverlay(char *filename, rgb_t **crow, int nrow, int zenith, int MCIR);
+int mapOverlay(char *filename, apt_rgb_t **crow, int nrow, int zenith, int MCIR);
int readRawImage(char *filename, float **prow, int *nrow);
-int readPalette(char *filename, rgb_t **pixels);
-void prow2crow(float **prow, int nrow, char *palette, rgb_t **crow);
-int applyUserPalette(float **prow, int nrow, char *filename, rgb_t **crow);
-int ImageOut(options_t *opts, image_t *img, int offset, int width, char *desc, char chid, char *palette);
-int initWriter(options_t *opts, image_t *img, int width, int height, char *desc, char *chid);
+int readPalette(char *filename, apt_rgb_t **pixels);
+void prow2crow(float **prow, int nrow, char *palette, apt_rgb_t **crow);
+int applyUserPalette(float **prow, int nrow, char *filename, apt_rgb_t **crow);
+int ImageOut(options_t *opts, apt_image_t *img, int offset, int width, char *desc, char chid, char *palette);
+int initWriter(options_t *opts, apt_image_t *img, int width, int height, char *desc, char *chid);
void pushRow(float *row, int width);
void closeWriter();
diff --git a/src/satcal.h b/src/satcal.h
index 2615ce1..a68a95e 100644
--- a/src/satcal.h
+++ b/src/satcal.h
@@ -32,94 +32,94 @@ const struct {
} satcal[] = {
{ // NOAA 15
{ // PRT coefficient d0, d1, d2
- {276.60157, 0.051045, 1.36328E-06},
- {276.62531, 0.050909, 1.47266E-06},
- {276.67413, 0.050907, 1.47656E-06},
- {276.59258, 0.050966, 1.47656E-06}
+ {276.60157f, 0.051045f, 1.36328E-06f},
+ {276.62531f, 0.050909f, 1.47266E-06f},
+ {276.67413f, 0.050907f, 1.47656E-06f},
+ {276.59258f, 0.050966f, 1.47656E-06f}
},
{ // Channel radiance coefficient vc, A, B
- {925.4075, 0.337810, 0.998719}, // Channel 4
- {839.8979, 0.304558, 0.999024}, // Channel 5
- {2695.9743, 1.621256, 0.998015} // Channel 3B
+ {925.4075f, 0.337810f, 0.998719f}, // Channel 4
+ {839.8979f, 0.304558f, 0.999024f}, // Channel 5
+ {2695.9743f, 1.621256f, 0.998015f} // Channel 3B
},
{ // Nonlinear radiance correction Ns, b0, b1, b2
- {-4.50, {4.76, -0.0932, 0.0004524}}, // Channel 4
- {-3.61, {3.83, -0.0659, 0.0002811}}, // Channel 5
- {0.0, {0.0, 0.0, 0.0}} // Channel 3B
+ {-4.50f, {4.76f, -0.0932f, 0.0004524f}}, // Channel 4
+ {-3.61f, {3.83f, -0.0659f, 0.0002811f}}, // Channel 5
+ {0.0f, {0.0f, 0.0f, 0.0f}} // Channel 3B
}
},
{ // NOAA 16
{ // PRT coeff d0, d1, d2
- {276.355, 5.562E-02, -1.590E-05},
- {276.142, 5.605E-02, -1.707E-05},
- {275.996, 5.486E-02, -1.223E-05},
- {276.132, 5.494E-02, -1.344E-05}
+ {276.355f, 5.562E-02f, -1.590E-05f},
+ {276.142f, 5.605E-02f, -1.707E-05f},
+ {275.996f, 5.486E-02f, -1.223E-05f},
+ {276.132f, 5.494E-02f, -1.344E-05f}
},
{ // Channel radiance coefficient vc, A, B
- {917.2289, 0.332380, 0.998522}, // Channel 4
- {838.1255, 0.674623, 0.998363}, // Channel 5
- {2700.1148, 1.592459, 0.998147} // Channel 3B
+ {917.2289f, 0.332380f, 0.998522f}, // Channel 4
+ {838.1255f, 0.674623f, 0.998363f}, // Channel 5
+ {2700.1148f, 1.592459f, 0.998147f} // Channel 3B
},
{ // Nonlinear radiance correction Ns, b0, b1, b2
- {-2.467, {2.96, -0.05411, 0.00024532}}, // Channel 4
- {-2.009, {2.25, -0.03665, 0.00014854}}, // Channel 5
- {0.0, {0.0, 0.0, 0.0}} // Channel 3B
+ {-2.467f, {2.96f, -0.05411f, 0.00024532f}}, // Channel 4
+ {-2.009f, {2.25f, -0.03665f, 0.00014854f}}, // Channel 5
+ {0.0f, {0.0f, 0.0f, 0.0f}} // Channel 3B
}
},
{ // NOAA 17
{ // PRT coefficient d0, d1, d2
- {276.628, 0.05098, 1.371e-06},
- {276.538, 0.05098, 1.371e-06},
- {276.761, 0.05097, 1.369e-06},
- {276.660, 0.05100, 1.348e-06}
+ {276.628f, 0.05098f, 1.371e-06f},
+ {276.538f, 0.05098f, 1.371e-06f},
+ {276.761f, 0.05097f, 1.369e-06f},
+ {276.660f, 0.05100f, 1.348e-06f}
},
{ // Channel radiance coefficient vc, A, B
- {926.2947, 0.271683, 0.998794}, // Channel 4
- {839.8246, 0.309180, 0.999012}, // Channel 5
- {2669.3554, 1.702380, 0.997378} // Channel 3B
+ {926.2947f, 0.271683f, 0.998794f}, // Channel 4
+ {839.8246f, 0.309180f, 0.999012f}, // Channel 5
+ {2669.3554f, 1.702380f, 0.997378f} // Channel 3B
},
{ // Nonlinear radiance correction Ns, b0, b1, b2
- {-8.55, {8.22, -0.15795, 0.00075579}}, // Channel 4
- {-3.97, {4.31, -0.07318, 0.00030976}}, // Channel 5
- {0.0, {0.0, 0.0, 0.0}} // Channel 3B
+ {-8.55f, {8.22f, -0.15795f, 0.00075579f}}, // Channel 4
+ {-3.97f, {4.31f, -0.07318f, 0.00030976f}}, // Channel 5
+ {0.0f, {0.0f, 0.0f, 0.0f}} // Channel 3B
}
},
{ // NOAA 18
{ // PRT coefficient d0, d1, d2
- {276.601, 0.05090, 1.657e-06},
- {276.683, 0.05101, 1.482e-06},
- {276.565, 0.05117, 1.313e-06},
- {276.615, 0.05103, 1.484e-06}
+ {276.601f, 0.05090f, 1.657e-06f},
+ {276.683f, 0.05101f, 1.482e-06f},
+ {276.565f, 0.05117f, 1.313e-06f},
+ {276.615f, 0.05103f, 1.484e-06f}
},
{ // Channel radiance coefficient vc, A, B
- {928.1460, 0.436645, 0.998607}, // Channel 4
- {833.2532, 0.253179, 0.999057}, // Channel 5
- {2659.7952, 1.698704, 0.996960} // Channel 3B
+ {928.1460f, 0.436645f, 0.998607f}, // Channel 4
+ {833.2532f, 0.253179f, 0.999057f}, // Channel 5
+ {2659.7952f, 1.698704f, 0.996960f} // Channel 3B
},
{ // Nonlinear radiance correction Ns, b0, b1, b2
- {-5.53, {5.82, -0.11069, 0.00052337}}, // Channel 4
- {-2.22, {2.67, -0.04360, 0.00017715}}, // Channel 5
- {0.0, {0.0, 0.0, 0.0}} // Channel 3B
+ {-5.53f, {5.82f, -0.11069f, 0.00052337f}}, // Channel 4
+ {-2.22f, {2.67f, -0.04360f, 0.00017715f}}, // Channel 5
+ {0.0f, {0.0f, 0.0f, 0.0f}} // Channel 3B
}
},
{ // NOAA 19
{ // PRT coefficient d0, d1, d2
- {276.6067, 0.051111, 1.405783E-06},
- {276.6119, 0.051090, 1.496037E-06},
- {276.6311, 0.051033, 1.496990E-06},
- {276.6268, 0.051058, 1.493110E-06}
+ {276.6067f, 0.051111f, 1.405783E-06f},
+ {276.6119f, 0.051090f, 1.496037E-06f},
+ {276.6311f, 0.051033f, 1.496990E-06f},
+ {276.6268f, 0.051058f, 1.493110E-06f}
},
{ // Channel radiance coefficient vc, A, B
- {928.9, 0.53959, 0.998534}, // Channel 4
- {831.9, 0.36064, 0.998913}, // Channel 5
- {2670.0, 1.67396, 0.997364} // Channel 3B
+ {928.9f, 0.53959f, 0.998534f}, // Channel 4
+ {831.9f, 0.36064f, 0.998913f}, // Channel 5
+ {2670.0f, 1.67396f, 0.997364f} // Channel 3B
},
{ // Nonlinear radiance correction Ns, b0, b1, b2
- {-5.49, {5.70 -0.11187, 0.00054668}}, // Channel 4
- {-3.39, {3.58 -0.05991, 0.00024985}}, // Channel 5
- {0.0, {0.0, 0.0, 0.0}} // Channel 3B
+ {-5.49f, {5.70f, -0.11187f, 0.00054668f}}, // Channel 4
+ {-3.39f, {3.58f, -0.05991f, 0.00024985f}}, // Channel 5
+ {0.0f, {0.0f, 0.0f, 0.0f}} // Channel 3B
}
}};
-const float c1 = 1.1910427e-5;
-const float c2 = 1.4387752;
+const float c1 = 1.1910427e-5f;
+const float c2 = 1.4387752f;