Menu

Can't save image with FreeImage_Save

Developers
2021-01-18
2021-01-25
  • William Copeland

    I have been struggling with my initial use of the FreeImage library. Below is my code. It compiles and runs, however, it fails to save the PNG image. I am also unable to get the FreeImage_SetOutputMessage function to work properly to see what the save error message is.

    I'm building a simple DOS console in Visual Studio Community 2015. It is configured for Release/x86 and I have set the C/C++and Linker properties for the FreeImage.h and .lib files and placed the FreeImage.dll in the Release folder with the executable.

    I'm running the IDE on Windows 8.1.

    Furthermore, I've attached a DOS console capture to show my results running the EXE built from this code.

    Any help would be greatly appreciated.

    #include <iostream>
    #include <fstream>  
    #include <string.h>
    #include <io.h>
    #include <time.h>
    #include <stdio.h>
    #include <ctype.h>
    #include <stdlib.h> 
    #include <ctime>
    #include <math.h>
    #include <Windows.h>
    #include "FreeImage\FreeImage.h"
    
    using namespace std;
    
    void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message){
        printf("\n*** ");
        if(fif != FIF_UNKNOWN) {
            if (FreeImage_GetFormatFromFIF(fif))
                printf("%s Format\n", FreeImage_GetFormatFromFIF(fif));
        }
        printf(message);
        printf(" ***\n");
    }
    
    
    int main(int argc, char *argv[])
    {
    FreeImage_Initialise();
    enum FREE_IMAGE_FORMAT imgfmt = FREE_IMAGE_FORMAT::FIF_PNG;
    std::string fnstr = "test.png";
    int iWDTH = 800;
    int iHGHT = 600;
    int bpp = 24;
    
    boolean succsave_flg = false;
    FIBITMAP* bitmap = FreeImage_Allocate(iWDTH, iHGHT, bpp);
    RGBQUAD color;
    
    if (bpp <= 8)
      FreeImage_GetPalette(bitmap);
    
    if (bitmap)  //only continue if OK so far
      {
      for (int ii=0; ii<iWDTH; ii++)    //draws a gradient from blue to green
        {
        for (int jj=0; jj<iHGHT; jj++)
          {
          color.rgbRed = 0;
          color.rgbGreen = (double) ii / iWDTH * 255.0;
          color.rgbBlue = (double) jj / iHGHT * 255.0;
          FreeImage_SetPixelColor(bitmap, ii, jj, &color);
          }  //end jj "for" loop
        }  //end ii "for" loop
      }  //end bitmap "if"
    
    succsave_flg = FreeImage_Save(imgfmt, bitmap, fnstr.c_str(), 0);
    FreeImage_SetOutputMessage(FreeImageErrorHandler);
    
    cout << "FreeImage version =" << FreeImage_GetVersion() << "\n";
    cout << "  copyright message=>" << "\n";
    cout << FreeImage_GetCopyrightMessage() << "\n\n";
    if (bitmap)
      cout << "Image allocation success!" << "\n";
    else
      cout << "ERROR: Image allocation failure" << "\n";
    if (FreeImage_FIFSupportsWriting(imgfmt))
      cout << "FIFSupportsWriting Image Format Supported" << "\n";
    else
      cout << "ERROR: FIFSupportsWriting Image Format NOT Supported" << "\n";
    if (FreeImage_FIFSupportsExportBPP(imgfmt,bpp))
      cout << "FIFSupportsExportBPP Image Bit Depth Supported" << "\n";
    else
      cout << "ERROR FIFSupportsExportBPP Image Bit Depth NOT Supported" << "\n";
    if (FreeImage_FIFSupportsExportType(imgfmt, FIT_BITMAP))
      cout << "FIFSupportsExportType Image Type Supported" << "\n";
    else
      cout << "ERROR: FIFSupportsExportType Image Type NOT Supported" << "\n";
    if (succsave_flg)
      cout << "Image save success!" << "\n";
    else
      cout << "ERROR: Image save failure" << "\n";
    
    FreeImage_DeInitialise();       //clean-up
    }
    
     
  • Carsten Klein

    Carsten Klein - 2021-01-22

    Hello William,

    I'm not a C++ specialist but have some remarks on your code.

    First, when using the DLL (not linking FreeImage statically), FreeImage_Initialize() and FreeImage_DeInitialise() need not be called, since the DLL does this already in its DllMain entry point.

    Although FreeImage will not necessarily provide error information for your problem, you must register the FreeImageErrorHandler before calling FreeImage_Save(...). FreeImage's error handler is called directly when an error occurs. There is no mechanism that collects errors and calls the error handler whenever one is registered. Registering the error handler is always the first thing to do.

    These two lines have no effect:

    if (bpp <= 8)
       FreeImage_GetPalette(bitmap);
    

    FreeImage_GetPalette returns a pointer to the palette, which your code actually does not use at all. However, that's harmless and very likely not causing your problem.

    Otherwise, your code seems quite correct, so I'm curious whether the error handler will provide something useful when registered before the image is saved.

    Carsten

     
  • William Copeland

    Hi Carsten,
    I appreciate those insights and I will certainly be making those corrections.

    I am glad that I saw your post and re-visited this because it now is working fine. I did some experimentation but could not re-produce the image save error. I even dropped in the original code that I posted here.

    I am dumbfounded and can't say for certainty what caused the error to occur. Perhaps I messed up my library files, IDE needed to reset build configuration, etc.

    Here is DOS console today:

     
  • William Copeland

    Resulting PNG file

     
  • Carsten Klein

    Carsten Klein - 2021-01-25

    Hi William,

    glad to hear that it's working now :-)

    Carsten

     

Log in to post a comment.