add debug

This commit is contained in:
2026-04-25 09:44:55 +10:00
parent 3a527d2dad
commit 8a95ed6b8c

View File

@@ -22,6 +22,7 @@
#include <nvjpeg.h>
#include <cuda_runtime.h>
#include "ANSCVVendorGate.h"
#include "ANSLicense.h" // ANS_DBG macro
#include <thread>
#include <future>
#include <opencv2/imgproc.hpp>
@@ -4252,15 +4253,23 @@ extern "C" __declspec(dllexport) int ANSCV_ResizeImage_Static(unsigned char* in
// Image Reference Management
extern "C" __declspec(dllexport) int ANSCV_CloneImage_S(cv::Mat** imageIn, cv::Mat** imageOut) {
ANS_DBG("ANSCV_CloneImage", "ENTRY imageIn=%p imageOut=%p src=%p",
(void*)imageIn, (void*)imageOut, (imageIn ? (void*)*imageIn : nullptr));
try {
//std::lock_guard<std::mutex> lock(imageMutex);
std::unique_lock<std::timed_mutex> lock(timeImageMutex, std::defer_lock);
if (!lock.try_lock_for(std::chrono::milliseconds(MUTEX_TIMEOUT_MS))) {
ANS_DBG("ANSCV_CloneImage", "ERROR mutex timeout (%dms)", (int)MUTEX_TIMEOUT_MS);
std::cerr << "Error: Mutex timeout in ANSCV_CloneImage_S!" << std::endl;
return -6;
}
try {
if (!imageIn || !(*imageIn) || (*imageIn)->empty() || !(*imageIn)->data) {
ANS_DBG("ANSCV_CloneImage", "ERROR invalid input imageIn=%p src=%p empty=%d data=%p",
(void*)imageIn,
(imageIn ? (void*)*imageIn : nullptr),
(imageIn && *imageIn) ? (int)(*imageIn)->empty() : -1,
(imageIn && *imageIn) ? (void*)(*imageIn)->data : nullptr);
std::cerr << "Error: Invalid or empty input image in ANSCV_CloneImage_S!" << std::endl;
return -2;
}
@@ -4268,47 +4277,62 @@ extern "C" __declspec(dllexport) int ANSCV_CloneImage_S(cv::Mat** imageIn, cv::M
*imageOut = anscv_mat_new(**imageIn);
// Link clone to same NV12 frame data (refcount++)
gpu_frame_addref(*imageIn, *imageOut);
ANS_DBG("ANSCV_CloneImage", "SUCCESS dst=%p size=%dx%d type=%d",
(void*)*imageOut, (*imageOut)->cols, (*imageOut)->rows, (*imageOut)->type());
return 1; // Success
}
}
catch (const std::bad_alloc& e) {
ANS_DBG("ANSCV_CloneImage", "ERROR bad_alloc inner: %s", e.what());
std::cerr << "Memory allocation failed in ANSCV_CloneImage_S: " << e.what() << std::endl;
return -1;
}
catch (const std::exception& e) {
ANS_DBG("ANSCV_CloneImage", "ERROR exception inner: %s", e.what());
std::cerr << "Error: Exception occurred in ANSCV_CloneImage_S: " << e.what() << std::endl;
return -3;
}
}
catch (const std::bad_alloc& e) {
ANS_DBG("ANSCV_CloneImage", "ERROR bad_alloc outer: %s", e.what());
std::cerr << "Memory allocation failed in ANSCV_CloneImage_S: " << e.what() << std::endl;
return -1;
}
catch (const std::exception& e) {
ANS_DBG("ANSCV_CloneImage", "ERROR exception outer: %s", e.what());
std::cerr << "Error: Exception occurred in ANSCV_CloneImage_S: " << e.what() << std::endl;
return -3;
}
}
extern "C" __declspec(dllexport) int ANSCV_ReleaseImage_S(cv::Mat** imageIn) {
void* matPtr = (imageIn ? (void*)*imageIn : nullptr);
ANS_DBG("ANSCV_ReleaseImage", "ENTRY imageIn=%p mat=%p", (void*)imageIn, matPtr);
try {
if (!imageIn || !(*imageIn)) {
ANS_DBG("ANSCV_ReleaseImage", "SKIP null imageIn=%p mat=%p", (void*)imageIn, matPtr);
return -2;
}
// anscv_mat_delete is thread-safe: checks the registry, only deletes if
// the pointer is still registered (not already freed by a stream source).
bool deleted = anscv_mat_delete(imageIn);
ANS_DBG("ANSCV_ReleaseImage", "%s mat=%p", deleted ? "DELETED" : "NOT_REGISTERED", matPtr);
return deleted ? 1 : -4;
}
catch (const std::exception& e) {
ANS_DBG("ANSCV_ReleaseImage", "ERROR exception mat=%p: %s", matPtr, e.what());
std::cerr << "Error: Exception occurred in ANSCV_ReleaseImage_S: " << e.what() << std::endl;
return -3;
}
catch (...) {
ANS_DBG("ANSCV_ReleaseImage", "ERROR unknown exception mat=%p", matPtr);
std::cerr << "Error: Unknown exception in ANSCV_ReleaseImage_S." << std::endl;
return -3;
}
}
extern "C" __declspec(dllexport) int ANSCV_CropImage_S(cv::Mat** imageIn, int x, int y, int width, int height, int originalImageSize) {
void* matPtr = (imageIn ? (void*)*imageIn : nullptr);
ANS_DBG("ANSCV_CropImage", "ENTRY mat=%p roi=(%d,%d,%dx%d) origSize=%d",
matPtr, x, y, width, height, originalImageSize);
gpu_frame_invalidate(imageIn ? *imageIn : nullptr);
try {
// Step 1: Validate and copy input image safely
@@ -4317,11 +4341,13 @@ extern "C" __declspec(dllexport) int ANSCV_CropImage_S(cv::Mat** imageIn, int x,
//std::lock_guard<std::mutex> lock(imageMutex);
std::unique_lock<std::timed_mutex> lock(timeImageMutex, std::defer_lock);
if (!lock.try_lock_for(std::chrono::milliseconds(MUTEX_TIMEOUT_MS))) {
ANS_DBG("ANSCV_CropImage", "ERROR mutex timeout (copy phase) mat=%p", matPtr);
std::cerr << "Error: Mutex timeout in ANSCV_CropImage_S!" << std::endl;
return -6;
}
try {
if (!imageIn || !(*imageIn) || (*imageIn)->empty() || !(*imageIn)->data) {
ANS_DBG("ANSCV_CropImage", "ERROR invalid input mat=%p", matPtr);
std::cerr << "Error: Invalid or empty input image in ANSCV_CloneImage_S!" << std::endl;
return -2;
}
@@ -4330,10 +4356,12 @@ extern "C" __declspec(dllexport) int ANSCV_CropImage_S(cv::Mat** imageIn, int x,
}
}
catch (const std::bad_alloc& e) {
ANS_DBG("ANSCV_CropImage", "ERROR bad_alloc on copy mat=%p: %s", matPtr, e.what());
std::cerr << "Memory allocation failed in ANSCV_CloneImage_S: " << e.what() << std::endl;
return -1;
}
catch (const std::exception& e) {
ANS_DBG("ANSCV_CropImage", "ERROR exception on copy mat=%p: %s", matPtr, e.what());
std::cerr << "Error: Exception occurred in ANSCV_CloneImage_S: " << e.what() << std::endl;
return -3;
}
@@ -4341,6 +4369,7 @@ extern "C" __declspec(dllexport) int ANSCV_CropImage_S(cv::Mat** imageIn, int x,
// Step 2: Validate cropping parameters
if (width <= 0 || height <= 0) {
ANS_DBG("ANSCV_CropImage", "ERROR invalid width/height w=%d h=%d", width, height);
std::cerr << "Error: Invalid width or height for cropping image in ANSCV_CropImage_S!" << std::endl;
return -2;
}
@@ -4354,10 +4383,13 @@ extern "C" __declspec(dllexport) int ANSCV_CropImage_S(cv::Mat** imageIn, int x,
height = min(height, originalHeight - y);
cv::Rect roi(x, y, width, height);
ANS_DBG("ANSCV_CropImage", "CLAMPED roi=(%d,%d,%dx%d) src=%dx%d",
x, y, width, height, originalWidth, originalHeight);
// Step 3: Process crop outside lock
ANSCENTER::ANSOPENCV ansCVInstance;
if (!ansCVInstance.Init("")) {
ANS_DBG("ANSCV_CropImage", "ERROR ansCVInstance.Init failed");
std::cerr << "Error: Failed to initialize ANSCV instance!" << std::endl;
return -5;
}
@@ -4367,16 +4399,20 @@ extern "C" __declspec(dllexport) int ANSCV_CropImage_S(cv::Mat** imageIn, int x,
{
std::unique_lock<std::timed_mutex> lock(timeImageMutex, std::defer_lock);
if (!lock.try_lock_for(std::chrono::milliseconds(MUTEX_TIMEOUT_MS))) {
ANS_DBG("ANSCV_CropImage", "ERROR mutex timeout (writeback) mat=%p", matPtr);
std::cerr << "Error: Mutex timeout in ANSCV_CropImage_S!" << std::endl;
return -6;
}
//std::lock_guard<std::mutex> lock(imageMutex);
if (croppedImage.empty()) {
ANS_DBG("ANSCV_CropImage", "ERROR cropped image empty mat=%p", matPtr);
std::cerr << "Error: Failed to crop image in ANSCV_CropImage_S!" << std::endl;
return 0;
}
else {
if (!imageIn || !(*imageIn) || (*imageIn)->empty() || !(*imageIn)->data) {
ANS_DBG("ANSCV_CropImage", "ERROR input invalid at writeback mat=%p",
(imageIn ? (void*)*imageIn : nullptr));
std::cerr << "Error: Invalid or empty input image in ANSCV_CloneImage_S!" << std::endl;
return -2;
}
@@ -4385,9 +4421,14 @@ extern "C" __declspec(dllexport) int ANSCV_CropImage_S(cv::Mat** imageIn, int x,
}
ANS_DBG("ANSCV_CropImage", "SUCCESS mat=%p new=%dx%d",
(imageIn && *imageIn) ? (void*)*imageIn : nullptr,
(imageIn && *imageIn) ? (*imageIn)->cols : -1,
(imageIn && *imageIn) ? (*imageIn)->rows : -1);
return 1; // Success
}
catch (const std::exception& e) {
ANS_DBG("ANSCV_CropImage", "ERROR exception outer mat=%p: %s", matPtr, e.what());
std::cerr << "Exception in ANSCV_CropImage_S: " << e.what() << std::endl;
return -3;
}
@@ -4395,8 +4436,11 @@ extern "C" __declspec(dllexport) int ANSCV_CropImage_S(cv::Mat** imageIn, int x,
extern "C" __declspec(dllexport) int ANSCV_GetImage_CPP(cv::Mat** imageIn, int width, int quality,
int& newWidth, int& newHeight, std::string& outputImage) {
void* matPtr = (imageIn ? (void*)*imageIn : nullptr);
ANS_DBG("ANSCV_GetImage_CPP", "ENTRY mat=%p targetW=%d quality=%d", matPtr, width, quality);
try {
if (!imageIn || !(*imageIn) || (*imageIn)->empty() || !(*imageIn)->data) {
ANS_DBG("ANSCV_GetImage_CPP", "ERROR invalid input mat=%p", matPtr);
std::cerr << "Error: Invalid or empty input image!" << std::endl;
return -2;
}
@@ -4408,11 +4452,13 @@ extern "C" __declspec(dllexport) int ANSCV_GetImage_CPP(cv::Mat** imageIn, int w
{
std::unique_lock<std::timed_mutex> lock(timeImageMutex, std::chrono::milliseconds(1000));
if (!lock.owns_lock()) {
ANS_DBG("ANSCV_GetImage_CPP", "ERROR mutex timeout (dims) mat=%p", matPtr);
std::cerr << "Error: Mutex timeout!" << std::endl;
return -6;
}
if (img->empty() || !img->data) {
ANS_DBG("ANSCV_GetImage_CPP", "ERROR invalid after lock mat=%p", matPtr);
std::cerr << "Error: Invalid image!" << std::endl;
return -2;
}
@@ -4425,33 +4471,57 @@ extern "C" __declspec(dllexport) int ANSCV_GetImage_CPP(cv::Mat** imageIn, int w
cv::Mat processedImage;
if (width > 0 && width < imageMaxSize) {
ANS_DBG("ANSCV_GetImage_CPP", "RESIZE mat=%p src=%dx%d targetW=%d",
matPtr, originalWidth, originalHeight, width);
// Only lock when we need to resize
std::unique_lock<std::timed_mutex> lock(timeImageMutex, std::chrono::milliseconds(1000));
if (!lock.owns_lock()) return -6;
if (!lock.owns_lock()) {
ANS_DBG("ANSCV_GetImage_CPP", "ERROR mutex timeout (resize) mat=%p", matPtr);
return -6;
}
ANSCENTER::ANSOPENCV ansCVInstance;
if (!ansCVInstance.Init("")) return -5;
if (!ansCVInstance.Init("")) {
ANS_DBG("ANSCV_GetImage_CPP", "ERROR ansCVInstance.Init failed");
return -5;
}
processedImage = ansCVInstance.ImageResizeV2(*img, width);
}
else {
ANS_DBG("ANSCV_GetImage_CPP", "CLONE_ONLY mat=%p src=%dx%d targetW=%d",
matPtr, originalWidth, originalHeight, width);
// No resize needed - just copy quickly
std::unique_lock<std::timed_mutex> lock(timeImageMutex, std::chrono::milliseconds(1000));
if (!lock.owns_lock()) return -6;
if (!lock.owns_lock()) {
ANS_DBG("ANSCV_GetImage_CPP", "ERROR mutex timeout (clone) mat=%p", matPtr);
return -6;
}
processedImage = img->clone(); // Slightly faster than copyTo
}
if (processedImage.empty()) return -8;
if (processedImage.empty()) {
ANS_DBG("ANSCV_GetImage_CPP", "ERROR processedImage empty mat=%p", matPtr);
return -8;
}
newWidth = processedImage.cols;
newHeight = processedImage.rows;
outputImage = ANSCENTER::CompressJpegToString(processedImage, quality);
return outputImage.empty() ? -9 : 1;
if (outputImage.empty()) {
ANS_DBG("ANSCV_GetImage_CPP", "ERROR JPEG compression empty mat=%p %dx%d q=%d",
matPtr, newWidth, newHeight, quality);
return -9;
}
ANS_DBG("ANSCV_GetImage_CPP", "SUCCESS mat=%p out=%dx%d jpegBytes=%zu",
matPtr, newWidth, newHeight, outputImage.size());
return 1;
}
catch (...) {
ANS_DBG("ANSCV_GetImage_CPP", "ERROR unknown exception mat=%p", matPtr);
return -4;
}
}
@@ -4600,13 +4670,18 @@ extern "C" __declspec(dllexport) int ANSCV_GetImage_CPP(cv::Mat** imageIn, int w
//}
extern "C" __declspec(dllexport) int ANSCV_GetImage_S(cv::Mat** imageIn, int width, int quality, int& newWidth, int& newHeight, LStrHandle outputImage) {
void* matPtr = (imageIn ? (void*)*imageIn : nullptr);
ANS_DBG("ANSCV_GetImage", "ENTRY mat=%p targetW=%d quality=%d outHandle=%p",
matPtr, width, quality, (void*)outputImage);
try {
if (!imageIn || !(*imageIn) || (*imageIn)->empty() || !(*imageIn)->data) {
ANS_DBG("ANSCV_GetImage", "ERROR invalid input mat=%p", matPtr);
std::cerr << "Error: Invalid or empty input image in ANSCV_GetImage_S!" << std::endl;
return -2;
}
if (!outputImage) {
ANS_DBG("ANSCV_GetImage", "ERROR null LStrHandle");
std::cerr << "Error: Output image handle is null!" << std::endl;
return -2;
}
@@ -4615,11 +4690,14 @@ extern "C" __declspec(dllexport) int ANSCV_GetImage_S(cv::Mat** imageIn, int wid
{
std::unique_lock<std::timed_mutex> lock(timeImageMutex, std::defer_lock);
if (!lock.try_lock_for(std::chrono::milliseconds(MUTEX_TIMEOUT_MS))) {
ANS_DBG("ANSCV_GetImage", "ERROR mutex timeout mat=%p", matPtr);
std::cerr << "Error: Mutex timeout in ANSCV_GetImage_S!" << std::endl;
return -6;
}
if (!imageIn || !(*imageIn) || (*imageIn)->empty() || !(*imageIn)->data) {
ANS_DBG("ANSCV_GetImage", "ERROR invalid after lock mat=%p",
(imageIn ? (void*)*imageIn : nullptr));
std::cerr << "Error: Image became invalid after mutex acquisition!" << std::endl;
return -2;
}
@@ -4628,12 +4706,14 @@ extern "C" __declspec(dllexport) int ANSCV_GetImage_S(cv::Mat** imageIn, int wid
(*imageIn)->copyTo(imgCopy);
}
catch (const cv::Exception& e) {
ANS_DBG("ANSCV_GetImage", "ERROR cv::Exception on copyTo mat=%p: %s", matPtr, e.what());
std::cerr << "Error: OpenCV exception during image copy: " << e.what() << std::endl;
return -7;
}
}
if (imgCopy.empty() || !imgCopy.data) {
ANS_DBG("ANSCV_GetImage", "ERROR imgCopy empty after copy mat=%p", matPtr);
std::cerr << "Error: Copied image is invalid in ANSCV_GetImage_S!" << std::endl;
return -2;
}
@@ -4643,14 +4723,18 @@ extern "C" __declspec(dllexport) int ANSCV_GetImage_S(cv::Mat** imageIn, int wid
int imageMaxSize = max(originalWidth, originalHeight);
if (width > 0 && width < imageMaxSize) {
ANS_DBG("ANSCV_GetImage", "RESIZE mat=%p src=%dx%d targetW=%d",
matPtr, originalWidth, originalHeight, width);
ANSCENTER::ANSOPENCV ansCVInstance;
if (!ansCVInstance.Init("")) {
ANS_DBG("ANSCV_GetImage", "ERROR ansCVInstance.Init failed");
std::cerr << "Error: Failed to initialize ANSOPENCV instance!" << std::endl;
return -5;
}
cv::Mat resized = ansCVInstance.ImageResizeV2(imgCopy, width);
if (resized.empty()) {
ANS_DBG("ANSCV_GetImage", "ERROR resize result empty mat=%p", matPtr);
std::cerr << "Error: Resizing failed!" << std::endl;
return -8;
}
@@ -4661,6 +4745,8 @@ extern "C" __declspec(dllexport) int ANSCV_GetImage_S(cv::Mat** imageIn, int wid
newHeight = imgCopy.rows;
std::string jpegString = ANSCENTER::CompressJpegToString(imgCopy, quality);
if (jpegString.empty()) {
ANS_DBG("ANSCV_GetImage", "ERROR JPEG compress empty mat=%p %dx%d q=%d",
matPtr, newWidth, newHeight, quality);
std::cerr << "Error: JPEG compression failed!" << std::endl;
return -9;
}
@@ -4668,12 +4754,15 @@ extern "C" __declspec(dllexport) int ANSCV_GetImage_S(cv::Mat** imageIn, int wid
int32_t size = static_cast<int32_t>(jpegString.size());
if (size > 50 * 1024 * 1024) {
ANS_DBG("ANSCV_GetImage", "ERROR jpeg too large mat=%p bytes=%d", matPtr, (int)size);
std::cerr << "Error: Compressed image size too large: " << size << " bytes" << std::endl;
return -10;
}
MgErr error = DSSetHandleSize(outputImage, sizeof(int32) + size);
if (error != noErr) {
ANS_DBG("ANSCV_GetImage", "ERROR DSSetHandleSize failed code=%d bytes=%d",
(int)error, (int)size);
std::cerr << "Error: Failed to allocate memory for output image! Error code: " << error << std::endl;
return -10;
}
@@ -4681,32 +4770,41 @@ extern "C" __declspec(dllexport) int ANSCV_GetImage_S(cv::Mat** imageIn, int wid
(*outputImage)->cnt = size;
memcpy((*outputImage)->str, jpegString.data(), size);
ANS_DBG("ANSCV_GetImage", "SUCCESS mat=%p out=%dx%d jpegBytes=%d",
matPtr, newWidth, newHeight, (int)size);
return 1;
}
catch (const std::exception& e) {
ANS_DBG("ANSCV_GetImage", "ERROR exception mat=%p: %s", matPtr, e.what());
std::cerr << "Exception in ANSCV_GetImage_S: " << e.what() << std::endl;
return -3;
}
catch (...) {
ANS_DBG("ANSCV_GetImage", "ERROR unknown exception mat=%p", matPtr);
std::cerr << "Unknown exception in ANSCV_GetImage_S!" << std::endl;
return -4;
}
}
extern "C" __declspec(dllexport) int ANSCV_ReSizeImage_S(cv::Mat** imageIn, int width, int originalImageSize) {
void* matPtr = (imageIn ? (void*)*imageIn : nullptr);
ANS_DBG("ANSCV_ReSizeImage", "ENTRY mat=%p width=%d origSize=%d",
matPtr, width, originalImageSize);
gpu_frame_invalidate(imageIn ? *imageIn : nullptr);
try {
cv::Mat localImage;
{
std::unique_lock<std::timed_mutex> lock(timeImageMutex, std::defer_lock);
if (!lock.try_lock_for(std::chrono::milliseconds(MUTEX_TIMEOUT_MS))) {
ANS_DBG("ANSCV_ReSizeImage", "ERROR mutex timeout (copy phase) mat=%p", matPtr);
std::cerr << "Error: Mutex timeout in ANSCV_ReSizeImage_S!" << std::endl;
return -6;
}
//std::lock_guard<std::mutex> lock(imageMutex);
try {
if (!imageIn || !(*imageIn) || (*imageIn)->empty() || !(*imageIn)->data) {
ANS_DBG("ANSCV_ReSizeImage", "ERROR invalid input mat=%p", matPtr);
std::cerr << "Error: Invalid or empty input image in ANSCV_CloneImage_S!" << std::endl;
return -2;
}
@@ -4715,16 +4813,19 @@ extern "C" __declspec(dllexport) int ANSCV_ReSizeImage_S(cv::Mat** imageIn, int
}
}
catch (const std::bad_alloc& e) {
ANS_DBG("ANSCV_ReSizeImage", "ERROR bad_alloc mat=%p: %s", matPtr, e.what());
std::cerr << "Memory allocation failed in ANSCV_CloneImage_S: " << e.what() << std::endl;
return -1;
}
catch (const std::exception& e) {
ANS_DBG("ANSCV_ReSizeImage", "ERROR exception copy mat=%p: %s", matPtr, e.what());
std::cerr << "Error: Exception occurred in ANSCV_CloneImage_S: " << e.what() << std::endl;
return -3;
}
}
if (width <= 0) {
ANS_DBG("ANSCV_ReSizeImage", "ERROR invalid target width=%d", width);
std::cerr << "Error: Invalid target width in ANSCV_ReSizeImage_S!" << std::endl;
return -2;
}
@@ -4744,27 +4845,37 @@ extern "C" __declspec(dllexport) int ANSCV_ReSizeImage_S(cv::Mat** imageIn, int
int targetHeight = static_cast<int>(std::round(targetWidth * static_cast<double>(originalHeight) / originalWidth));
if (targetHeight <= 0) {
ANS_DBG("ANSCV_ReSizeImage", "ERROR computed height invalid targetW=%d origW=%d origH=%d",
targetWidth, originalWidth, originalHeight);
std::cerr << "Error: Computed height is invalid!" << std::endl;
return -2;
}
ANS_DBG("ANSCV_ReSizeImage", "RESIZE mat=%p src=%dx%d -> %dx%d",
matPtr, originalWidth, originalHeight, targetWidth, targetHeight);
cv::resize(localImage, resizedImage, cv::Size(targetWidth, targetHeight), 0, 0, cv::INTER_LANCZOS4);
}
else {
ANS_DBG("ANSCV_ReSizeImage", "SKIP_RESIZE mat=%p targetW=%d >= origW=%d",
matPtr, targetWidth, originalWidth);
resizedImage = localImage.clone(); // No resizing needed
}
{
std::unique_lock<std::timed_mutex> lock(timeImageMutex, std::defer_lock);
if (!lock.try_lock_for(std::chrono::milliseconds(MUTEX_TIMEOUT_MS))) {
ANS_DBG("ANSCV_ReSizeImage", "ERROR mutex timeout (writeback) mat=%p", matPtr);
std::cerr << "Error: Mutex timeout in ANSCV_ReSizeImage_S!" << std::endl;
return -6;
}
//std::lock_guard<std::mutex> lock(imageMutex);
if (resizedImage.empty()) {
ANS_DBG("ANSCV_ReSizeImage", "ERROR resized empty mat=%p", matPtr);
std::cerr << "Error: Resizing failed!" << std::endl;
return 0;
}
else {
if (!imageIn || !(*imageIn) || (*imageIn)->empty() || !(*imageIn)->data) {
ANS_DBG("ANSCV_ReSizeImage", "ERROR input invalid at writeback mat=%p",
(imageIn ? (void*)*imageIn : nullptr));
std::cerr << "Error: Invalid or empty input image in ANSCV_CloneImage_S!" << std::endl;
return -2;
}
@@ -4773,15 +4884,23 @@ extern "C" __declspec(dllexport) int ANSCV_ReSizeImage_S(cv::Mat** imageIn, int
}
ANS_DBG("ANSCV_ReSizeImage", "SUCCESS mat=%p new=%dx%d",
(imageIn && *imageIn) ? (void*)*imageIn : nullptr,
(imageIn && *imageIn) ? (*imageIn)->cols : -1,
(imageIn && *imageIn) ? (*imageIn)->rows : -1);
return 1;
}
catch (const std::exception& e) {
ANS_DBG("ANSCV_ReSizeImage", "ERROR exception outer mat=%p: %s", matPtr, e.what());
std::cerr << "Exception in ANSCV_ReSizeImage_S: " << e.what() << std::endl;
return -3;
}
}
extern "C" __declspec(dllexport) int ANSCV_GetImageAndRemoveImgRef_S(cv::Mat** imageIn, int width, int quality, int& newWidth, int& newHeight, LStrHandle outputImage) {
void* matPtr = (imageIn ? (void*)*imageIn : nullptr);
ANS_DBG("ANSCV_GetImageAndRemove", "ENTRY mat=%p targetW=%d quality=%d outHandle=%p",
matPtr, width, quality, (void*)outputImage);
bool cleanupRequired = true;
try {
cv::Mat imgCopy;
@@ -4789,19 +4908,24 @@ extern "C" __declspec(dllexport) int ANSCV_GetImageAndRemoveImgRef_S(cv::Mat** i
//std::lock_guard<std::mutex> lock(imageMutex);
std::unique_lock<std::timed_mutex> lock(timeImageMutex, std::defer_lock);
if (!lock.try_lock_for(std::chrono::milliseconds(MUTEX_TIMEOUT_MS))) {
ANS_DBG("ANSCV_GetImageAndRemove", "ERROR mutex timeout mat=%p", matPtr);
std::cerr << "Error: Mutex timeout in ANSCV_ReSizeImage_S!" << std::endl;
return -6;
}
if (!imageIn || !(*imageIn) || (*imageIn)->empty() || !(*imageIn)->data) {
ANS_DBG("ANSCV_GetImageAndRemove", "ERROR invalid input mat=%p",
(imageIn ? (void*)*imageIn : nullptr));
std::cerr << "Error: Invalid or empty input image in ANSCV_GetImageAndRemoveImgRef_S!" << std::endl;
return -2;
}
(*imageIn)->copyTo(imgCopy);
ANS_DBG("ANSCV_GetImageAndRemove", "DELETING mat=%p (after copy)", matPtr);
anscv_mat_delete(imageIn); // Safe delete + null
cleanupRequired = false; // We already deleted inside lock
}
if (imgCopy.empty() || !imgCopy.data) {
ANS_DBG("ANSCV_GetImageAndRemove", "ERROR imgCopy invalid (orig mat=%p)", matPtr);
std::cerr << "Error: Copied image is invalid in ANSCV_GetImageAndRemoveImgRef_S!" << std::endl;
return 0;
}
@@ -4811,13 +4935,17 @@ extern "C" __declspec(dllexport) int ANSCV_GetImageAndRemoveImgRef_S(cv::Mat** i
int imageMaxSize = max(originalWidth, originalHeight);
if (width > 0 && width < imageMaxSize) {
ANS_DBG("ANSCV_GetImageAndRemove", "RESIZE src=%dx%d targetW=%d",
originalWidth, originalHeight, width);
ANSCENTER::ANSOPENCV ansCVInstance;
if (!ansCVInstance.Init("")) {
ANS_DBG("ANSCV_GetImageAndRemove", "ERROR ansCVInstance.Init failed");
std::cerr << "Error: Failed to initialize ANSOPENCV instance!" << std::endl;
return -5;
}
cv::Mat resized = ansCVInstance.ImageResizeV2(imgCopy, width);
if (resized.empty()) {
ANS_DBG("ANSCV_GetImageAndRemove", "ERROR resize empty");
std::cerr << "Error: Resizing failed!" << std::endl;
return 0;
}
@@ -4829,6 +4957,8 @@ extern "C" __declspec(dllexport) int ANSCV_GetImageAndRemoveImgRef_S(cv::Mat** i
std::string jpegString = ANSCENTER::CompressJpegToString(imgCopy, quality);
if (jpegString.empty()) {
ANS_DBG("ANSCV_GetImageAndRemove", "ERROR JPEG compress empty %dx%d q=%d",
newWidth, newHeight, quality);
std::cerr << "Error: JPEG compression failed in ANSCV_GetImageAndRemoveImgRef_S!" << std::endl;
return 0;
}
@@ -4836,6 +4966,8 @@ extern "C" __declspec(dllexport) int ANSCV_GetImageAndRemoveImgRef_S(cv::Mat** i
int32_t size = static_cast<int32_t>(jpegString.size());
MgErr error = DSSetHandleSize(outputImage, sizeof(int32) + size);
if (error != noErr) {
ANS_DBG("ANSCV_GetImageAndRemove", "ERROR DSSetHandleSize failed code=%d bytes=%d",
(int)error, (int)size);
std::cerr << "Error: Failed to allocate memory for output image!" << std::endl;
return 0;
}
@@ -4843,19 +4975,27 @@ extern "C" __declspec(dllexport) int ANSCV_GetImageAndRemoveImgRef_S(cv::Mat** i
(*outputImage)->cnt = size;
memcpy((*outputImage)->str, jpegString.data(), size);
ANS_DBG("ANSCV_GetImageAndRemove", "SUCCESS out=%dx%d jpegBytes=%d (deleted mat=%p)",
newWidth, newHeight, (int)size, matPtr);
return 1; // Success
}
catch (const std::exception& e) {
ANS_DBG("ANSCV_GetImageAndRemove", "ERROR exception mat=%p: %s", matPtr, e.what());
std::cerr << "Exception in ANSCV_GetImageAndRemoveImgRef_S: " << e.what() << std::endl;
}
catch (...) {
ANS_DBG("ANSCV_GetImageAndRemove", "ERROR unknown exception mat=%p", matPtr);
std::cerr << "Unknown exception in ANSCV_GetImageAndRemoveImgRef_S!" << std::endl;
}
// Cleanup in case of exception and still pending
if (cleanupRequired) {
ANS_DBG("ANSCV_GetImageAndRemove", "CLEANUP delete pending mat=%p",
(imageIn ? (void*)*imageIn : nullptr));
std::unique_lock<std::timed_mutex> lock(timeImageMutex, std::defer_lock);
if (!lock.try_lock_for(std::chrono::milliseconds(MUTEX_TIMEOUT_MS))) {
ANS_DBG("ANSCV_GetImageAndRemove", "ERROR cleanup mutex timeout mat=%p",
(imageIn ? (void*)*imageIn : nullptr));
std::cerr << "Error: Mutex timeout in ANSCV_ReSizeImage_S!" << std::endl;
return -6;
}
@@ -4866,17 +5006,21 @@ extern "C" __declspec(dllexport) int ANSCV_GetImageAndRemoveImgRef_S(cv::Mat** i
}
extern "C" __declspec(dllexport) int ANSCV_GetImageInfo_S(cv::Mat** imageIn, int& width, int& height) {
void* matPtr = (imageIn ? (void*)*imageIn : nullptr);
ANS_DBG("ANSCV_GetImageInfo", "ENTRY mat=%p", matPtr);
try {
cv::Mat imgCopy;
{
std::unique_lock<std::timed_mutex> lock(timeImageMutex, std::defer_lock);
if (!lock.try_lock_for(std::chrono::milliseconds(MUTEX_TIMEOUT_MS))) {
ANS_DBG("ANSCV_GetImageInfo", "ERROR mutex timeout mat=%p", matPtr);
std::cerr << "Error: Mutex timeout in ANSCV_ReSizeImage_S!" << std::endl;
return -6;
}
//std::lock_guard<std::mutex> lock(imageMutex);
try {
if (!imageIn || !(*imageIn) || (*imageIn)->empty() || !(*imageIn)->data) {
ANS_DBG("ANSCV_GetImageInfo", "ERROR invalid input mat=%p", matPtr);
std::cerr << "Error: Invalid or empty input image in ANSCV_CloneImage_S!" << std::endl;
return -2;
}
@@ -4885,15 +5029,18 @@ extern "C" __declspec(dllexport) int ANSCV_GetImageInfo_S(cv::Mat** imageIn, int
}
}
catch (const std::bad_alloc& e) {
ANS_DBG("ANSCV_GetImageInfo", "ERROR bad_alloc mat=%p: %s", matPtr, e.what());
std::cerr << "Memory allocation failed in ANSCV_CloneImage_S: " << e.what() << std::endl;
return -1;
}
catch (const std::exception& e) {
ANS_DBG("ANSCV_GetImageInfo", "ERROR exception inner mat=%p: %s", matPtr, e.what());
std::cerr << "Error: Exception occurred in ANSCV_CloneImage_S: " << e.what() << std::endl;
return -3;
}
}
if (imgCopy.empty() || !imgCopy.data) {
ANS_DBG("ANSCV_GetImageInfo", "ERROR imgCopy invalid mat=%p", matPtr);
std::cerr << "Error: Dereferenced image is invalid in ANSCV_GetImageInfo_S!" << std::endl;
return 0;
}
@@ -4901,13 +5048,16 @@ extern "C" __declspec(dllexport) int ANSCV_GetImageInfo_S(cv::Mat** imageIn, int
// Assign the width and height once the image is validated
width = imgCopy.cols;
height = imgCopy.rows;
ANS_DBG("ANSCV_GetImageInfo", "SUCCESS mat=%p %dx%d", matPtr, width, height);
return 1; // Success
}
catch (const std::exception& e) {
ANS_DBG("ANSCV_GetImageInfo", "ERROR exception outer mat=%p: %s", matPtr, e.what());
std::cerr << "Exception in ANSCV_GetImageInfo_S: " << e.what() << std::endl;
return -3;
}
catch (...) {
ANS_DBG("ANSCV_GetImageInfo", "ERROR unknown exception mat=%p", matPtr);
std::cerr << "Unknown exception in ANSCV_GetImageInfo_S!" << std::endl;
return -4;
}
@@ -4917,8 +5067,12 @@ extern "C" __declspec(dllexport) int ANSCV_CreateImageFromJpegString_S(
unsigned int bufferLength,
cv::Mat** image)
{
ANS_DBG("ANSCV_CreateFromJpeg", "ENTRY buf=%p bytes=%u outPtr=%p",
(void*)inputImage, bufferLength, (void*)image);
// Validate input parameters
if (!inputImage || bufferLength == 0 || image == nullptr) {
ANS_DBG("ANSCV_CreateFromJpeg", "ERROR invalid params buf=%p bytes=%u outPtr=%p",
(void*)inputImage, bufferLength, (void*)image);
std::cerr << "Error: Invalid input parameters in ANSCV_CreateImageFromJpegString_S!" << std::endl;
return -2;
}
@@ -4931,39 +5085,49 @@ extern "C" __declspec(dllexport) int ANSCV_CreateImageFromJpegString_S(
{
std::unique_lock<std::timed_mutex> lock(timeImageMutex, std::defer_lock);
if (!lock.try_lock_for(std::chrono::milliseconds(MUTEX_TIMEOUT_MS))) {
ANS_DBG("ANSCV_CreateFromJpeg", "ERROR mutex timeout bytes=%u", bufferLength);
std::cerr << "Error: Mutex timeout in ANSCV_ReSizeImage_S!" << std::endl;
return -6;
}
//std::lock_guard<std::mutex> lock(imageMutex);
// Check if decoding was successful
if (decodedImage.empty()) {
ANS_DBG("ANSCV_CreateFromJpeg", "ERROR imdecode empty bytes=%u", bufferLength);
std::cerr << "Error: Failed to decode JPEG image in ANSCV_CreateImageFromJpegString_S!" << std::endl;
return 0;
}
else {
*image = anscv_mat_new(decodedImage);
ANS_DBG("ANSCV_CreateFromJpeg", "SUCCESS mat=%p %dx%d type=%d (jpeg=%u bytes)",
(void*)*image, (*image)->cols, (*image)->rows, (*image)->type(), bufferLength);
return 1; // Success
}
}
}
catch (const std::bad_alloc& e) {
ANS_DBG("ANSCV_CreateFromJpeg", "ERROR bad_alloc bytes=%u: %s", bufferLength, e.what());
std::cerr << "Memory allocation failed in ANSCV_CreateImageFromJpegString_S: " << e.what() << std::endl;
return -1;
}
catch (const std::exception& e) {
ANS_DBG("ANSCV_CreateFromJpeg", "ERROR exception bytes=%u: %s", bufferLength, e.what());
std::cerr << "Exception in ANSCV_CreateImageFromJpegString_S: " << e.what() << std::endl;
return -3;
}
catch (...) {
ANS_DBG("ANSCV_CreateFromJpeg", "ERROR unknown exception bytes=%u", bufferLength);
std::cerr << "Unknown exception in ANSCV_CreateImageFromJpegString_S!" << std::endl;
return -4;
}
}
extern "C" __declspec(dllexport) int ANSCV_CreateImageFromFile_S(const char* imageFilePath, cv::Mat** image)
{
ANS_DBG("ANSCV_CreateFromFile", "ENTRY path=%s outPtr=%p",
imageFilePath ? imageFilePath : "(null)", (void*)image);
try {
if (!imageFilePath) {
ANS_DBG("ANSCV_CreateFromFile", "ERROR null path");
std::cerr << "Error: Null input parameter in ANSCV_CreateImageFromFile_S!" << std::endl;
return -1; // Null pointer input
}
@@ -4971,6 +5135,7 @@ extern "C" __declspec(dllexport) int ANSCV_CreateImageFromFile_S(const char* ima
std::string stImageFileName(imageFilePath);
if (stImageFileName.empty()) {
ANS_DBG("ANSCV_CreateFromFile", "ERROR empty path");
std::cerr << "Error: Empty file path in ANSCV_CreateImageFromFile_S!" << std::endl;
return -2; // Empty path
}
@@ -4978,6 +5143,8 @@ extern "C" __declspec(dllexport) int ANSCV_CreateImageFromFile_S(const char* ima
// Check if file exists
std::ifstream fileCheck(stImageFileName);
if (!fileCheck.good()) {
ANS_DBG("ANSCV_CreateFromFile", "ERROR file missing/inaccessible path=%s",
stImageFileName.c_str());
std::cerr << "Error: File does not exist or is inaccessible: " << stImageFileName << std::endl;
return -4; // File does not exist
}
@@ -4989,29 +5156,41 @@ extern "C" __declspec(dllexport) int ANSCV_CreateImageFromFile_S(const char* ima
//std::lock_guard<std::mutex> lock(imageMutex); // Automatically locks and unlocks
std::unique_lock<std::timed_mutex> lock(timeImageMutex, std::defer_lock);
if (!lock.try_lock_for(std::chrono::milliseconds(MUTEX_TIMEOUT_MS))) {
ANS_DBG("ANSCV_CreateFromFile", "ERROR mutex timeout path=%s",
stImageFileName.c_str());
std::cerr << "Error: Mutex timeout in ANSCV_ReSizeImage_S!" << std::endl;
return -6;
}
if (loadedImage.empty()) {
ANS_DBG("ANSCV_CreateFromFile", "ERROR imread empty path=%s",
stImageFileName.c_str());
std::cerr << "Error: Failed to load image from file in ANSCV_CreateImageFromFile_S!" << std::endl;
return 0; // Load failed
}
else {
if (image == nullptr) {
ANS_DBG("ANSCV_CreateFromFile", "WARN outPtr was null - allocating internal pointer (caller will leak it)");
image = new cv::Mat*; // Allocate pointer to cv::Mat*
*image = nullptr; // Initialize to nullptr
}
*image = anscv_mat_new(loadedImage); // Use registry for safe lifecycle
ANS_DBG("ANSCV_CreateFromFile", "SUCCESS path=%s mat=%p %dx%d type=%d",
stImageFileName.c_str(), (void*)*image,
(*image)->cols, (*image)->rows, (*image)->type());
return 1; // Success
}
}
}
catch (const std::exception& e) {
ANS_DBG("ANSCV_CreateFromFile", "ERROR exception path=%s: %s",
imageFilePath ? imageFilePath : "(null)", e.what());
std::cerr << "Error: Exception occurred in ANSCV_CreateImageFromFile_S: " << e.what() << std::endl;
return -3; // Exception
}
catch (...) {
ANS_DBG("ANSCV_CreateFromFile", "ERROR unknown exception path=%s",
imageFilePath ? imageFilePath : "(null)");
std::cerr << "Unknown error occurred in ANSCV_CreateImageFromFile_S!" << std::endl;
return -5; // Unknown error
}