xp12camera
Owner: IIIlllIIIllI URL: git@github.com:nyangkosense/xp12camera.git
performance
Commit 7081e3b11d4d572d2a8f7a9ab5e0f418ae7b615d by SM <seb.michalk@gmail.com> on 2025-07-01 10:02:07 +0200
diff --git a/FLIR_Camera.o b/FLIR_Camera.o
deleted file mode 100644
index ac69dda..0000000
Binary files a/FLIR_Camera.o and /dev/null differ
diff --git a/FLIR_SimpleLock.o b/FLIR_SimpleLock.o
deleted file mode 100644
index 96d933e..0000000
Binary files a/FLIR_SimpleLock.o and /dev/null differ
diff --git a/FLIR_VisualEffects.cpp b/FLIR_VisualEffects.cpp
index 1bd22ad..fe4b3e4 100644
--- a/FLIR_VisualEffects.cpp
+++ b/FLIR_VisualEffects.cpp
@@ -55,8 +55,15 @@ static float gScanLineOpacity = 0.05f;
static int gFrameCounter = 0;
static int gPostProcessingEnabled = 1;
static unsigned char* gPixelBuffer = NULL;
+static unsigned char* gProcessedBuffer = NULL;
static int gBufferWidth = 0;
static int gBufferHeight = 0;
+static int gProcessingCounter = 0;
+static int gProcessingSkip = 2; // Process every 3rd frame
+static float gProcessingScale = 0.5f; // Process at half resolution
+
+// Forward declarations
+void ProcessEOIROptimized(unsigned char* input, unsigned char* output, int width, int height, int mode);
void InitializeVisualEffects()
{
@@ -69,20 +76,31 @@ void CleanupVisualEffects()
free(gPixelBuffer);
gPixelBuffer = NULL;
}
+ if (gProcessedBuffer) {
+ free(gProcessedBuffer);
+ gProcessedBuffer = NULL;
+ }
}
-// Safety function to allocate pixel buffer
+// Safety function to allocate pixel buffers
int AllocatePixelBuffer(int width, int height)
{
- int newSize = width * height * 3; // RGB
+ int fullSize = width * height * 3; // RGB for full resolution
+ int processedSize = fullSize;
if (!gPixelBuffer || gBufferWidth != width || gBufferHeight != height) {
if (gPixelBuffer) {
free(gPixelBuffer);
}
+ if (gProcessedBuffer) {
+ free(gProcessedBuffer);
+ }
+
+ gPixelBuffer = (unsigned char*)malloc(fullSize);
+ gProcessedBuffer = (unsigned char*)malloc(processedSize);
- gPixelBuffer = (unsigned char*)malloc(newSize);
- if (!gPixelBuffer) {
+ if (!gPixelBuffer || !gProcessedBuffer) {
+ CleanupVisualEffects();
return 0; // Failed to allocate
}
@@ -163,7 +181,7 @@ void ProcessEOIR(unsigned char* pixels, int width, int height, int mode)
}
}
-// Main post-processing function with safety checks
+// Optimized post-processing function
void RenderPostProcessing(int screenWidth, int screenHeight)
{
// Safety check: skip if too small or too large
@@ -172,43 +190,152 @@ void RenderPostProcessing(int screenWidth, int screenHeight)
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) { }
+ // Skip frames for better performance
+ gProcessingCounter++;
+ int shouldProcess = (gProcessingCounter % (gProcessingSkip + 1)) == 0;
- // 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
+ // Determine processing mode
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);
+ if (processingMode == 0) return; // No processing needed
+
+ // Allocate buffers if needed
+ if (!AllocatePixelBuffer(screenWidth, screenHeight)) {
+ return;
+ }
+
+ // Only do expensive processing every few frames
+ if (shouldProcess) {
+ // Clear any OpenGL errors
+ while (glGetError() != GL_NO_ERROR) { }
+
+ // Read framebuffer
+ glReadPixels(0, 0, screenWidth, screenHeight, GL_RGB, GL_UNSIGNED_BYTE, gPixelBuffer);
+
+ // Check for errors
+ if (glGetError() != GL_NO_ERROR) {
+ return;
+ }
+
+ // Process with optimized function
+ ProcessEOIROptimized(gPixelBuffer, gProcessedBuffer, screenWidth, screenHeight, processingMode);
}
- // Draw the processed image back
+ // Always draw the (possibly cached) processed result
glRasterPos2f(0, 0);
- glDrawPixels(screenWidth, screenHeight, GL_RGB, GL_UNSIGNED_BYTE, gPixelBuffer);
+ glDrawPixels(screenWidth, screenHeight, GL_RGB, GL_UNSIGNED_BYTE, gProcessedBuffer);
- // Check for errors again
- error = glGetError();
- if (error != GL_NO_ERROR) {
- // If drawing failed, disable post-processing for safety
- gPostProcessingEnabled = 0;
+ // Check for errors
+ if (glGetError() != GL_NO_ERROR) {
+ gPostProcessingEnabled = 0; // Disable on error
+ }
+}
+
+// Much faster processing function with fake heat signatures
+void ProcessEOIROptimized(unsigned char* input, unsigned char* output, int width, int height, int mode)
+{
+ int totalPixels = width * height;
+ int step = 1; // Process every pixel, but optimize the loop
+
+ // Pre-calculate noise once per frame
+ static int noiseFrame = 0;
+ static float frameNoise = 0.0f;
+ if (noiseFrame != gFrameCounter) {
+ frameNoise = ((rand() % 21) - 10) / 3000.0f; // Even more subtle
+ noiseFrame = gFrameCounter;
+ }
+
+ for (int i = 0; i < totalPixels; i += step) {
+ int idx = i * 3;
+ int x = i % width;
+ int y = i / width;
+
+ // Original RGB values
+ unsigned char r = input[idx];
+ unsigned char g = input[idx + 1];
+ unsigned char b = input[idx + 2];
+
+ // Fast integer-based grayscale conversion
+ int gray = (r * 77 + g * 151 + b * 28) >> 8; // /256
+
+ // Fake heat signature logic based on color analysis
+ int heatBonus = 0;
+
+ // Sky detection (blue-ish areas are cold)
+ if (b > r && b > g && b > 100) {
+ heatBonus = -30; // Sky is cold
+ }
+ // Vegetation detection (green areas are cooler)
+ else if (g > r && g > b && g > 80) {
+ heatBonus = -15; // Vegetation is cooler
+ }
+ // Ground/concrete detection (neutral colors)
+ else if (abs(r - g) < 20 && abs(g - b) < 20 && gray > 60) {
+ heatBonus = 10; // Ground/concrete slightly warm
+ }
+ // Bright objects (could be hot engines, lights, etc)
+ else if (gray > 200) {
+ heatBonus = 25; // Bright objects assumed warm
+ }
+ // Very dark objects (shadows, cold areas)
+ else if (gray < 40) {
+ heatBonus = -20; // Deep shadows are cold
+ }
+
+ // Ground level is warmer than sky (simple atmospheric model)
+ float skyFactor = (float)y / height; // 0 = top, 1 = bottom
+ heatBonus += (int)(skyFactor * 15); // Ground +15, sky +0
+
+ // Apply heat simulation based on mode
+ switch (mode) {
+ case 1: // Monochrome - enhanced but not too harsh
+ gray += heatBonus / 2; // Subtle heat effect
+ gray = (gray * 5) >> 2; // *1.25 instead of *1.5
+ if (gray < 0) gray = 20; // Don't go pure black
+ if (gray > 255) gray = 255;
+
+ // Green tint for night vision
+ output[idx] = (unsigned char)((gray * 180) >> 8); // R * 0.7
+ output[idx + 1] = (unsigned char)gray; // G
+ output[idx + 2] = (unsigned char)((gray * 180) >> 8); // B * 0.7
+ break;
+
+ case 2: // Thermal - with heat signatures
+ gray += heatBonus; // Full heat effect
+ if (gray < 0) gray = 30; // Minimum visible level
+ if (gray > 255) gray = 255;
+
+ // Don't fully invert - partial inversion looks more realistic
+ gray = 200 - (gray * 3 >> 2); // Partial invert and enhance
+ if (gray < 40) gray = 40; // Keep some visibility
+ if (gray > 255) gray = 255;
+
+ output[idx] = output[idx + 1] = output[idx + 2] = (unsigned char)gray;
+ break;
+
+ case 3: // Enhanced IR - high contrast but not crushing
+ gray += heatBonus;
+ if (gray < 0) gray = 25;
+ if (gray > 255) gray = 255;
+
+ // Less harsh threshold
+ if (gray > 140) gray = 240;
+ else if (gray > 80) gray = 160;
+ else if (gray > 40) gray = 80;
+ else gray = 30; // Minimum visibility
+
+ output[idx] = output[idx + 1] = output[idx + 2] = (unsigned char)gray;
+ break;
+
+ default:
+ output[idx] = input[idx];
+ output[idx + 1] = input[idx + 1];
+ output[idx + 2] = input[idx + 2];
+ break;
+ }
}
}
diff --git a/FLIR_VisualEffects.o b/FLIR_VisualEffects.o
deleted file mode 100644
index 63090df..0000000
Binary files a/FLIR_VisualEffects.o and /dev/null differ
diff --git a/build/FLIR_Camera/win_x64/FLIR_Camera.xpl b/build/FLIR_Camera/win_x64/FLIR_Camera.xpl
deleted file mode 100755
index 37b281e..0000000
Binary files a/build/FLIR_Camera/win_x64/FLIR_Camera.xpl and /dev/null differ