0

I try to open a jpeg file with jpeglib, and I get a runtime error in reading the jpeg file header. On further inspection I started suspecting that the FILE* after fopen is probably not valid.

I am ripping out GDI+ from an older legacy Windows service that grabs images from a folder and prints them to a local printer. This service failed on Windows Server 2012, and it appears GDI+ is not supported inside Windows services:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms533798(v=VS.85).aspx "GDI+ functions and classes are not supported for use within a Windows service."

I succeeded in replacing GDI+ calls with Win32 API print functions, and the function below attempts to open a JPEG image with jpeglib.

HBITMAP LoadJpegAsBitmap(LPCSTR pszFileName)
{ // Function copied fom http://katahiromz.web.fc2.com/win32/loadjpeg.html

    FILE *fp;
    struct jpeg_decompress_struct decomp;
    struct jpeg_error_mgr jerror;
    BITMAPINFO bi;
    LPBYTE lpBuf, pb;
    HBITMAP hbm;
    JSAMPARRAY buffer;
    INT row;

    fp = fopen(pszFileName, "rb");
    if (fp == NULL)  //<- fp is not NULL, but suspect...
        return NULL;

    decomp.err = jpeg_std_error(&jerror);
    jpeg_create_decompress(&decomp);
    jpeg_stdio_src(&decomp, fp);
    jpeg_read_header(&decomp, TRUE); //<- RUNTIME CRASH
    jpeg_start_decompress(&decomp);

    //... ... ...
    //... ..
}

After calling fopen at "if (fp == NULL)" the pointer has a value like 0x5fa97350 so the function does not return after the NULL check. Visual Studio runtime inspection shows the FILE* member variables are null at that stage, like so:

fp->
        __ptr = 0x00000000 (NULL)
        _cnt = 0
        _base = 0x00000000 (NULL)
        _flag = 1
        _file = 3
        _charbuf = 0
        _bufsiz = 0
        _tmpfname = 0x00000000 (NULL)

The nulls led me to suspect the file did not open correctly. To test, I inserted the code below just after the nullptr check: char c = getc(fp);

while (c != EOF) // file is EOF from the very first byte
{                // loop is not executed
    putchar(c);
    c = getc(fp);
}   

Above check convinced me the FILE* is not really valid after the fopen call.

Anyway, the next steps in the function are where the jpeg image is opened. After calling jpeg_stdio_src(&decomp, fp); the decomp structure shows 0xcccccccc for client_data. I suspect that explains why jpeglib crashes at the next line: a runtime exception inside jpeg_read_header(&decomp, TRUE); (Can be explained if fp is corrupt).

I do not think this is a duplicate of other stackoverflow questions regarding fopen:

  • I do not get null after calling fopen // C - fopen() doesn't work (returns null pointer)
  • The jpeg file has no security privileges, and I am admin on the machine anyway. Simple fopen and fprintf not working
  • I hard-coded a full, valid path, so the path is not the issue.
  • I supplied double backslashes for the Windows path. Forward slash made no difference
  • I built the above with Unicode on and off. No difference.
  • Corrupt JPEG file? It opens fine in other software. like Paint, Photoshop.

So I am at a loss here, not sure why the file apparently fails to open and be read in jpeglib.

I also looked at Need help in reading JPEG file using libjpeg but I think my code is in line with the examples there.

I appreciate your help.

Community
  • 1
  • 1
CppDev
  • 49
  • 5
  • I can't see anything obviously wrong, but do this as a useful debugging tip. At the top of your function, initialize all your pointers to `NULL`. e.g. `FILE* fp = NULL;` Ditto for the HBITMAP. Other structs get declared with `= {};` Make sure you are debugging with a debug build instead of an optimized retail build. Also, my psychic powers tell me that you probably just need to build clean and run again. Add print statements on variously lines to print out the values. – selbie Sep 03 '16 at 06:56
  • Thank you selbie. This is good practice. I applied the changes, did a full rebuild in debug mode, 32-bit platform. (64 bit can wait). Still same result. Print lines show variables values as per initial post. – CppDev Sep 03 '16 at 13:55
  • Your problem is somewhere else in your code. Post a complete minimal example with a "main" that we can use. Someone, possibly me, will be willing to test your code if you can provide the whole source to an example. http://stackoverflow.com/help/mcve – selbie Sep 03 '16 at 16:40
  • Hi, thanks for your kind offer. I think you were right. I made a little program, copied the above code into main() and then it worked. The original code had the above function in a class, so I created a class with only that function, and it still worked. So I guess I can now put the original includes back one by one and see when it breaks, and then discover what the issue is. I hope to report back if I discover the cause. – CppDev Sep 05 '16 at 18:49

0 Answers0