Anyone using FreeImage?


#1

I just came across it. The feature set - well, the formats supported, is great.

Bruce


#2

I use freeImage in one of my application comes with a make file on mac. Had few issues with architectures. But used lipo to fix them.


#3

We use it since a long time and don’t have problems with it.

I’ve written a wrapper to use freeimage as a juce ImageFileFormat if you want.


#4

I’d like to see it, if you don’t mind, thanks. The API looks a bit windowsy, so a head-start would be nice.

Does it seem fairly fast to you?

Bruce


#5

I didn’t make performance tests, it is not particularly slow, we were using devil a long ago and didn’t notice performance issues when we switched.
As an example, the famous Ogre 3D engine also uses it as a multiformat image loader, so it must be a good alternative.
Anyway when we need performance, we make a special loader for a specific format.

Here is the code for the wrapper, I didn’t make extensive tests, as wrapping to a juce image is used mostly for gui and preview.

[code]//----------------------------------------------------------------------
class FreeImageInputWrapper
{
public:
static FreeImageIO* getFreeImageIO()
{
static FreeImageIO io = { read, write, seek, tell };
return &io;
}
static FREE_IMAGE_FORMAT findFIF(InputStream& stream)
{
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
int64 pos = stream.getPosition();
stream.readByte();
stream.setPosition(pos);

fif = FreeImage_GetFileTypeFromHandle(getFreeImageIO(), (fi_handle)&stream, 16);
if (!FreeImage_FIFSupportsReading(fif))
  fif = FIF_UNKNOWN;
jassert(pos == stream.getPosition());
return fif;

}

juce_UseDebuggingNewOperator

private:
static unsigned DLL_CALLCONV read(void* buffer, unsigned size, unsigned count, fi_handle handle)
{
InputStream* is = (InputStream*)handle;
return (unsigned)(is->read(buffer, size * count) / size);
}
static unsigned DLL_CALLCONV write(void* buffer, unsigned size, unsigned count, fi_handle handle)
{
return (unsigned)-1;
}
static int DLL_CALLCONV seek(fi_handle handle, long offset, int origin)
{
bool ok = false;
InputStream* is = (InputStream*)handle;
if (origin == SEEK_SET)
ok = is->setPosition(offset);
else if (origin == SEEK_CUR)
ok = is->setPosition(is->getPosition() + offset);
else if (origin == SEEK_END)
ok = is->setPosition(is->getTotalLength());
jassert(ok);
return ok ? (int)is->getPosition() : -1;
}
static long DLL_CALLCONV tell(fi_handle handle)
{
InputStream* is = (InputStream*)handle;
return (long)is->getPosition();
}
};

class FreeImageInitialisationSingleton
{
public:
FreeImageInitialisationSingleton()
{
FreeImage_Initialise();
}

~FreeImageInitialisationSingleton()
{
FreeImage_DeInitialise();
}
};

static FreeImageInitialisationSingleton freeImageInitialisation;

//----------------------------------------------------------------------
// FreeImage Wrapper for juce

class FreeImageImageFileFormat : public ImageFileFormat
{
public:
const String getFormatName()
{
return “FreeImage”;
}

bool canUnderstand(InputStream& input) const
{
return FreeImageInputWrapper::findFIF(input) != FIF_UNKNOWN;
}

Image* decodeImage (InputStream& input)
{
Image* image = 0;

/* // You may want to map the file in memory for faster loading
MemoryBlock m;
int64 pos = input->getPosition();
input->readIntoMemoryBlock(m, (int)input->getTotalLength());
input->setPosition(pos);
MemoryInputStream memoryStream(m.getData(), m.getSize(), false);
*/

FREE_IMAGE_FORMAT fif = FreeImageInputWrapper::findFIF(input);
if (fif != FIF_UNKNOWN)
{
  FIBITMAP* dib = FreeImage_LoadFromHandle(fif, FreeImageInputWrapper::getFreeImageIO(), (fi_handle)&input);
  if (dib)
  {
    // FreeImage stores images up side down
    FreeImage_FlipVertical(dib);
    int bpp = FreeImage_GetBPP(dib);
    FREE_IMAGE_COLOR_TYPE  color_type = FreeImage_GetColorType(dib);

    Image::PixelFormat pf = (Image::PixelFormat)-1;
    if (color_type == FIC_RGB && bpp == 24)
      pf = Image::RGB;
    else if (color_type == FIC_RGBALPHA && bpp == 32)
      pf = Image::ARGB;
    else 
    {
      FIBITMAP* converted_dib = FreeImage_ConvertTo32Bits(dib);
      if (converted_dib)
      {
    		FreeImage_Unload(dib);
        dib = converted_dib;
        pf = Image::ARGB;
      }
    }
    if (pf != -1)
    {
      image = new Image((Image::PixelFormat)pf, FreeImage_GetWidth(dib), FreeImage_GetHeight(dib), false);
      int line_stride, pixel_stride;
      juce::uint8* pixels = image->lockPixelDataReadWrite(0, 0, image->getWidth(), image->getHeight(), line_stride, pixel_stride);
      memcpy(pixels, FreeImage_GetBits(dib), FreeImage_GetHeight(dib) * FreeImage_GetPitch(dib));
      image->releasePixelDataReadWrite(pixels);
    }
  }
}

return 0;

}

bool writeImageToStream (Image& sourceImage, OutputStream& destStream)
{
return false;
}
};

[/code]


#6

Thanks