2

I've encountered a weird issue that I seem to be unable to solve, involving OpenCV, Win32 API and jpeg2000 file format.

I've made a C++ program that asks for an image and then, later on, uses it as a texture, manipulates it etc. But here's the problem:

I ask for the path to the image file with OPENFILENAME and GetOpenFileName(). Here's an example code for this very basic format:

#include "pch.h"
#include <iostream>
#include <opencv2/opencv.hpp>
#include <Windows.h>


void SelectAndOpenImage()
{
    OPENFILENAME openFile;
    char filePath[MAX_PATH] = { 0 };

    ZeroMemory(&openFile, sizeof(OPENFILENAME));

    openFile.lStructSize = sizeof(OPENFILENAME);
    openFile.hwndOwner = NULL;
    openFile.lpstrFile = filePath;
    openFile.lpstrFile[0] = '\0';
    openFile.nMaxFile = MAX_PATH;
    openFile.lpstrFilter = "Jpeg2000 (*.jp2)\0*.jp2\0Bitmap (*.bmp)\0*.bmp\0Jpeg (*.jpg)\0*.jpg\0Png (*.png)\0*.png\0";
    openFile.nFilterIndex = 1;
    openFile.lpstrInitialDir = NULL;
    openFile.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR;

    if (GetOpenFileName(&openFile))
    {
        cv::Mat image = cv::imread(openFile.lpstrFile, CV_LOAD_IMAGE_COLOR);
        if (image.empty()) std::cout << "Empty" << std::endl;
        else
        {
            cv::imshow("testing", image);
            cv::waitKey(5000);
        }
    }
    else
    {
        std::cout << "Failure" << std::endl;
    }
}


int main()
{
    SelectAndOpenImage();
    return 0;
}

The problem is that cv::imread() works correctly for every image file format except Jpeg2000, cv::imshow() shows just a black image (data is full of zeros). Jpeg2000 works well along with the others if I do not use this GetOpenFileName() dialog at all (instead I just insert the file path directly to the source code). However, if I use the dialog but ignore the file selection and use my own hard coded file path instead, Jpeg2000 file format won't work then either, again just a blank black image. All other image file formats work, no matter how I do it.

I welcome all ideas. I'm missing something.

I'm currently using Windows10 and Visual Studio 2017 version 15.8.2 (MSVC++ 14.15). OpenCV is 3.4.2 (Release).

Fornjotr
  • 21
  • 1
  • The only known global side effect of `GetOpenFileName` is, that it changes the current working directory. Presumably, you are using a relative filename. This is *always* an error, and you just experienced one of the many reasons using a relative filename can fail. Besides that, you appear to be asking 2 distinct questions. Not sure, what you are *really* asking for here. – IInspectable Sep 15 '18 at 13:57
  • So, `image` is not empty, has the right size and colour depth, but the data is all zeros? That is rather odd. Maybe also create an issue on the [OpenCV github](https://github.com/opencv/opencv/issues). – Dan Mašek Sep 15 '18 at 14:04
  • 2
    @IInspectable Sorry, the question should be clarified. I just wanted to ask if someone has encountered this same issue with .jp2 files or knowns what else the GetOpenFileName() dialog messes up in addition to the current working directory. The OFN_NOCHANGEDIR flag should prevent the working directory from being changed, the file path is full path. – Fornjotr Sep 15 '18 at 15:23
  • 1
    @Dan Mašek Correct. image has the correct size, number of cols and rows, color depth, element size etc. but all the data zeros, resulting in blank black image. I will create an issue also on the OpenCV github. – Fornjotr Sep 15 '18 at 15:37
  • 1
    From the [documentation](https://learn.microsoft.com/en-us/windows/desktop/api/commdlg/ns-commdlg-tagofnw) of `OFN_NOCHANGEDIR`: *"This flag is ineffective for `GetOpenFileName`."* The dialog is a Shell window, and loads all installed Shell Namespace Extensions along the way. Those are known to have global side effects (like changing the calling thread's or process' current locale). Regardless of what they change, though, if OpenCV fails to decode an image given a file it can read is a bug in OpenCV. – IInspectable Sep 15 '18 at 15:49
  • @IInspectable Whoops, you're right. Haven't noticed that. But I agree with you, thank you for your opinion and help! – Fornjotr Sep 15 '18 at 16:25
  • I don't see how the current directory could matter in this case. According to the docs, `GetOpenFileName()` returns the absolute path of the selected file in `OPENFILENAME::lpstrFile`. Maybe you have a misbehaving shell extension installed, that gets loaded by the file dialog. Can you reproduce the problem on other machines? – zett42 Sep 15 '18 at 19:19
  • @zett42 I should try. – Fornjotr Sep 22 '18 at 10:02
  • 1
    I changed the `GetOpenFileName()` to `IFileDialog` interface. After that, `cv::imread()` was working with jpeg2000 files for two or three runs. Then, all of a sudden, it just stopped working and keeps on showing me black image. Rebooting, rebuilding, nothing helps. What on Earth.... – Fornjotr Sep 22 '18 at 10:08

0 Answers0