diff --git a/modules/ANSCV/ANSOpenCV.cpp b/modules/ANSCV/ANSOpenCV.cpp index f92f0b3..9547527 100644 --- a/modules/ANSCV/ANSOpenCV.cpp +++ b/modules/ANSCV/ANSOpenCV.cpp @@ -22,6 +22,7 @@ #include #include #include "ANSCVVendorGate.h" +#include "ANSLicense.h" // ANS_DBG macro #include #include #include @@ -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 lock(imageMutex); std::unique_lock 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 lock(imageMutex); std::unique_lock 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 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 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 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 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 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 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(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 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 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(std::round(targetWidth * static_cast(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 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 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 lock(imageMutex); std::unique_lock 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(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 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 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 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 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 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 lock(imageMutex); // Automatically locks and unlocks std::unique_lock 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 }