xp12camera
Owner: IIIlllIIIllI URL: git@github.com:nyangkosense/xp12camera.git
broken branch
Commit 264bb5f021fb5e3bcbec2470bea864d16546c01d by SM <seb.michalk@gmail.com> on 2025-07-01 09:52:09 +0200
diff --git a/FLIR_Camera.cpp b/FLIR_Camera.cpp
index b119e17..216a8eb 100644
--- a/FLIR_Camera.cpp
+++ b/FLIR_Camera.cpp
@@ -130,6 +130,8 @@ PLUGIN_API void XPluginStop(void)
XPLMDontControlCamera();
gCameraActive = 0;
}
+
+ CleanupVisualEffects();
}
PLUGIN_API void XPluginDisable(void) { }
PLUGIN_API int XPluginEnable(void) { return 1; }
diff --git a/FLIR_Camera.o b/FLIR_Camera.o
index e6a69be..ac69dda 100644
Binary files a/FLIR_Camera.o and b/FLIR_Camera.o differ
diff --git a/FLIR_VisualEffects.cpp b/FLIR_VisualEffects.cpp
index 9c98aac..1bd22ad 100644
--- a/FLIR_VisualEffects.cpp
+++ b/FLIR_VisualEffects.cpp
@@ -53,12 +53,165 @@ static float gContrast = 1.2f;
static float gNoiseIntensity = 0.1f;
static float gScanLineOpacity = 0.05f;
static int gFrameCounter = 0;
+static int gPostProcessingEnabled = 1;
+static unsigned char* gPixelBuffer = NULL;
+static int gBufferWidth = 0;
+static int gBufferHeight = 0;
void InitializeVisualEffects()
{
srand(time(NULL));
}
+void CleanupVisualEffects()
+{
+ if (gPixelBuffer) {
+ free(gPixelBuffer);
+ gPixelBuffer = NULL;
+ }
+}
+
+// Safety function to allocate pixel buffer
+int AllocatePixelBuffer(int width, int height)
+{
+ int newSize = width * height * 3; // RGB
+
+ if (!gPixelBuffer || gBufferWidth != width || gBufferHeight != height) {
+ if (gPixelBuffer) {
+ free(gPixelBuffer);
+ }
+
+ gPixelBuffer = (unsigned char*)malloc(newSize);
+ if (!gPixelBuffer) {
+ return 0; // Failed to allocate
+ }
+
+ gBufferWidth = width;
+ gBufferHeight = height;
+ }
+
+ return 1; // Success
+}
+
+// Convert RGB to grayscale with EO/IR processing
+void ProcessEOIR(unsigned char* pixels, int width, int height, int mode)
+{
+ for (int i = 0; i < width * height; i++) {
+ int idx = i * 3;
+ unsigned char r = pixels[idx];
+ unsigned char g = pixels[idx + 1];
+ unsigned char b = pixels[idx + 2];
+
+ // Convert to grayscale (0.0 - 1.0 range)
+ float gray = (0.299f * r + 0.587f * g + 0.114f * b) / 255.0f;
+
+ // Apply EO/IR processing based on mode
+ switch (mode) {
+ case 1: // Monochrome with enhancement
+ // Aggressive contrast curve
+ gray = powf(gray, 0.6f);
+ gray = gray * 1.8f - 0.4f;
+ gray = fmaxf(0.0f, fminf(1.0f, gray));
+
+ // Crush blacks and blow highlights for military look
+ if (gray < 0.25f) gray = gray * 0.3f; // Crush darks
+ else if (gray > 0.75f) gray = 0.8f + (gray - 0.75f) * 0.8f; // Compress highlights
+ break;
+
+ case 2: // Thermal simulation
+ // Thermal processing with inversion
+ gray = powf(gray, 0.5f) * 1.6f;
+ gray = 1.0f - gray; // Invert for thermal (hot = white)
+ gray = fmaxf(0.0f, fminf(1.0f, gray));
+ break;
+
+ case 3: // Enhanced IR
+ // Extreme contrast for IR look
+ gray = powf(gray, 0.4f);
+ gray = gray * 2.5f - 0.8f;
+ gray = fmaxf(0.0f, fminf(1.0f, gray));
+
+ // Quantize to simulate limited bit depth
+ gray = floorf(gray * 32.0f) / 32.0f;
+ break;
+
+ default:
+ // Standard - minimal processing
+ break;
+ }
+
+ // Add very subtle noise for realism
+ if (mode > 0) {
+ float noise = ((rand() % 21) - 10) / 2000.0f; // -0.005 to +0.005
+ gray += noise;
+ gray = fmaxf(0.0f, fminf(1.0f, gray));
+ }
+
+ // Convert back to RGB
+ unsigned char finalGray = (unsigned char)(gray * 255.0f);
+
+ // For monochrome, add slight green tint
+ if (mode == 1) {
+ pixels[idx] = (unsigned char)(finalGray * 0.7f); // R
+ pixels[idx + 1] = finalGray; // G
+ pixels[idx + 2] = (unsigned char)(finalGray * 0.7f); // B
+ } else {
+ pixels[idx] = finalGray; // R
+ pixels[idx + 1] = finalGray; // G
+ pixels[idx + 2] = finalGray; // B
+ }
+ }
+}
+
+// Main post-processing function with safety checks
+void RenderPostProcessing(int screenWidth, int screenHeight)
+{
+ // Safety check: skip if too small or too large
+ if (screenWidth < 100 || screenHeight < 100 ||
+ screenWidth > 4096 || screenHeight > 4096) {
+ return;
+ }
+
+ // Allocate buffer if needed
+ if (!AllocatePixelBuffer(screenWidth, screenHeight)) {
+ return; // Failed to allocate, skip processing
+ }
+
+ // Clear any OpenGL errors before we start
+ while (glGetError() != GL_NO_ERROR) { }
+
+ // Read the current framebuffer
+ glReadPixels(0, 0, screenWidth, screenHeight, GL_RGB, GL_UNSIGNED_BYTE, gPixelBuffer);
+
+ // Check for OpenGL errors
+ GLenum error = glGetError();
+ if (error != GL_NO_ERROR) {
+ return; // Failed to read pixels, skip processing
+ }
+
+ // Determine processing mode based on current visual effects
+ int processingMode = 0;
+ if (gMonochromeEnabled) processingMode = 1;
+ else if (gThermalEnabled) processingMode = 2;
+ else if (gIREnabled) processingMode = 3;
+
+ // Only process if we have an active mode
+ if (processingMode > 0) {
+ ProcessEOIR(gPixelBuffer, screenWidth, screenHeight, processingMode);
+ }
+
+ // Draw the processed image back
+ glRasterPos2f(0, 0);
+ glDrawPixels(screenWidth, screenHeight, GL_RGB, GL_UNSIGNED_BYTE, gPixelBuffer);
+
+ // Check for errors again
+ error = glGetError();
+ if (error != GL_NO_ERROR) {
+ // If drawing failed, disable post-processing for safety
+ gPostProcessingEnabled = 0;
+ }
+}
+
void SetMonochromeFilter(int enabled)
{
gMonochromeEnabled = enabled;
@@ -84,6 +237,42 @@ void RenderVisualEffects(int screenWidth, int screenHeight)
{
gFrameCounter++;
+ // Try post-processing first (real image processing)
+ if (gPostProcessingEnabled && (gMonochromeEnabled || gThermalEnabled || gIREnabled)) {
+ RenderPostProcessing(screenWidth, screenHeight);
+
+ // Still add overlays like noise and scan lines
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glOrtho(0, screenWidth, screenHeight, 0, -1, 1);
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_BLEND);
+
+ if (gNoiseEnabled) {
+ RenderCameraNoise(screenWidth, screenHeight);
+ }
+
+ if (gScanLinesEnabled) {
+ RenderScanLines(screenWidth, screenHeight);
+ }
+
+ glEnable(GL_DEPTH_TEST);
+ glDisable(GL_BLEND);
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+
+ return;
+ }
+
+ // Fallback to overlay mode if post-processing fails
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
diff --git a/FLIR_VisualEffects.h b/FLIR_VisualEffects.h
index 5aa8f7e..9205d87 100644
--- a/FLIR_VisualEffects.h
+++ b/FLIR_VisualEffects.h
@@ -32,7 +32,9 @@ extern "C" {
#endif
void InitializeVisualEffects();
+void CleanupVisualEffects();
void RenderVisualEffects(int screenWidth, int screenHeight);
+void RenderPostProcessing(int screenWidth, int screenHeight);
void SetMonochromeFilter(int enabled);
void SetThermalMode(int enabled);
diff --git a/FLIR_VisualEffects.o b/FLIR_VisualEffects.o
index 6fe768c..63090df 100644
Binary files a/FLIR_VisualEffects.o and b/FLIR_VisualEffects.o differ
diff --git a/build/FLIR_Camera/win_x64/FLIR_Camera.xpl b/build/FLIR_Camera/win_x64/FLIR_Camera.xpl
index a9f3566..37b281e 100755
Binary files a/build/FLIR_Camera/win_x64/FLIR_Camera.xpl and b/build/FLIR_Camera/win_x64/FLIR_Camera.xpl differ