Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

#31 LibJPEG using SetMessageOutput proc for warnings, not just errors

None
closed
Hervé Drolon
None
5
2013-09-09
2013-08-14
Anonymous
No

Referencing https://github.com/seattlerb/image_science/issues/21 it appears that LibJPEG/jdmarker.c line 946 calls WARNMS2 whenever there is extraneous bytes in the jpeg header. But... it's just a warning. Unfortunately, the way freeimage wires up to libjpeg, it seems that it boils up to whatever is registered with FreeImage_SetOutputMessage.

The documentation for that function clearly states that it is to be used for errors: "When a certain bitmap cannot be loaded or saved there is usually an explanation for it. ... Whenever something fails in FreeImage internally a log-string is generated, which can be captured by an application driving FreeImage."

My ruby library image_science uses that to raise exceptions but it appears that it is now being used for both errors and warnings. This seems like an overloaded function now. Is there a way to turn OFF warning messages from boiling up to the error handler function I've registered? This is causing crashes in user code when it need not do so.

Discussion

  • Hervé Drolon
    Hervé Drolon
    2013-09-01

    Hi,

    Whenever something fails in FreeImage internally a log-string is generated, which can be captured by an application driving FreeImage. You use the function FreeImage_SetOutputMessage to capture the log string so that you can show it to the user of the program.
    This being said, you can load an image that looks suspicious to FreeImage (you will then get an error message or a warning message that can be catched using FreeImage_SetOutputMessage), but still have a correct dib on output (i.e. a dib that is not NULL).
    As long as the returned dib is not NULL, then you can trust FreeImage. The fact that you get warning/error messages is not a problem as long as the returned dib is not NULL.
    So the problem here is not with FreeImage but with your code. Your code MUST check for returned values of FreeImage functions in order to decide for an error or for something else.

    Hervé

     

  • Anonymous
    2013-09-09

    That design doesn't make a lick of sense and it breaks the contract described in the documentation.

    Here's the code I have:

      void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
        rb_raise(rb_eRuntimeError,
                 "FreeImage exception for type %s: %s",
                  (fif == FIF_UNKNOWN) ? "???" : FreeImage_GetFormatFromFIF(fif),
                  message);
      }
    
      FreeImage_SetOutputMessage(FreeImageErrorHandler);
    
      VALUE with_image(char * input) {
        FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
        int flags;
    
        fif = FreeImage_GetFileType(input, 0);
        if (fif == FIF_UNKNOWN) fif = FreeImage_GetFIFFromFilename(input);
        if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
          FIBITMAP *bitmap;
          VALUE result = Qnil;
          flags = fif == FIF_JPEG ? JPEG_ACCURATE : 0;
          if ((bitmap = FreeImage_Load(fif, input, flags))) {
            bitmap = ReOrient(bitmap);
            result = wrap_and_yield(bitmap, self, fif);
          }
          return result;
        }
        rb_raise(rb_eTypeError, "Unknown file format");
        return Qnil;
      }
    

    As you describe, FreeImage_SetOutputMessage is used for BOTH warnings and errors (despite what the documentation says) but I'm supposed to check whether or not I get a valid pointer from FreeImage_Load, but that pointer isn't provided or available at the time the callback is triggered.

    So, the problem might be with my code... but it is also with the documentation and the design of FreeImage. Either only errors should go to the registered error handler, or the documentation needs to be clear AND there needs to be more information passed to the error handler so it can do its job properly.

    Just to save some time on the back and forth... Having the error handler set some global state is NOT an acceptable workaround. This code can be called from a web service and multiple calls into with_image can be occuring at any given time.

     


Anonymous


Cancel   Add attachments