Repository: opencv/opencv
File: modules/imgcodecs/src/grfmt_tiff.cpp (C++)

Code before:

// to extend cvtColor() to support CV_8S, CV_16S, CV_32S and CV_64F.
static void extend_cvtColor( InputArray _src, OutputArray _dst, int code );

#define CV_TIFF_CHECK_CALL(call) \
    if (0 == (call)) { \
        CV_LOG_WARNING(NULL, "OpenCV TIFF(line " << __LINE__ << "): failed " #call); \
        CV_Error(Error::StsError, "OpenCV TIFF: failed " #call); \
    }

#define CV_TIFF_CHECK_CALL_DEBUG(call) \
    if (0 == (call)) { \
        CV_LOG_DEBUG(NULL, "OpenCV TIFF(line " << __LINE__ << "): failed optional call: " #call ", ignoring"); \
    }

static void cv_tiffCloseHandle(void* handle)
{
    TIFFClose((TIFF*)handle);
}

static int cv_tiffErrorHandler(TIFF *, void * userData, const char* module, const char* fmt, va_list ap)
{
    // return non-zero means "don't call the global error handler"
    // TODO tiff-specific log tag
    if (cv::utils::logging::getLogLevel() < cv::utils::logging::LOG_LEVEL_DEBUG)
        return 1;

    auto header = reinterpret_cast<const char*>(userData);
    // TODO cv::vformat() with va_list parameter
    fprintf(stderr, "OpenCV TIFF: ");
    if (header)
        fprintf(stderr, "%s: ", header);
    if (module && module[0] != '\0')
        fprintf(stderr, "%s: ", module);
    vfprintf(stderr, fmt, ap);
    fprintf(stderr, ".\n");
    return 1;
}

#ifdef OCV_HAVE_TIFF_OPEN_OPTIONS
static TIFFOpenOptions* cv_tiffCreateOptions()
{
    auto opts = TIFFOpenOptionsAlloc();
    TIFFOpenOptionsSetErrorHandlerExtR(opts, &cv_tiffErrorHandler, (void*)"error");
    TIFFOpenOptionsSetWarningHandlerExtR(opts, &cv_tiffErrorHandler, (void*)"warning");
#if TIFFLIB_AT_LEAST(4, 7, 1)
    TIFFOpenOptionsSetWarnAboutUnknownTags(opts, 1);
#endif
    return opts;
}
#endif

Review comment (suggestion):
Errors and warnings should be printed by default without environment settings.
I propose to move the condition to the wrappers `cv_tiffErrorHandler` and `cv_tiffWarningHandler` and use different threshold there. You can replace `fprintf` with `CV_LOG_ERROR` and `CV_LOG_WARNING` and condition is not needed.

Code after:
namespace cv
{

// to extend cvtColor() to support CV_8S, CV_16S, CV_32S and CV_64F.
static void extend_cvtColor( InputArray _src, OutputArray _dst, int code );

#define CV_TIFF_CHECK_CALL(call) \
    if (0 == (call)) { \
        CV_LOG_WARNING(NULL, "OpenCV TIFF(line " << __LINE__ << "): failed " #call); \
        CV_Error(Error::StsError, "OpenCV TIFF: failed " #call); \
    }

#define CV_TIFF_CHECK_CALL_DEBUG(call) \
    if (0 == (call)) { \
        CV_LOG_DEBUG(NULL, "OpenCV TIFF(line " << __LINE__ << "): failed optional call: " #call ", ignoring"); \
    }

static void cv_tiffCloseHandle(void* handle)
{
    TIFFClose((TIFF*)handle);
}

static std::string vformat(const char* fmt, va_list ap)
{
    if (!fmt)
        return {};
    va_list ap_copy;
    va_copy(ap_copy, ap);
    const int len = std::vsnprintf(nullptr, 0, fmt, ap_copy);
    va_end(ap_copy);
    if (len < 0)
        return fmt;

    std::string buf(static_cast<size_t>(len) + 1, '\0');
    std::vsnprintf(&buf[0], buf.size(), fmt, ap);
    buf.pop_back();
    return buf;
}

static std::string formatTiffMessage(const char* module, const char* fmt, va_list ap)
{
    std::stringstream ss;
    if (module && module[0] != '\0')
        ss << module << ": ";
    ss << cv::vformat(fmt, ap);
    return ss.str();
}

static int TIFF_Error(TIFF *, void *, const char* module, const char* fmt, va_list ap)
{
    CV_LOG_ERROR(NULL, formatTiffMessage(module, fmt, ap));