Add support for FreeImage in nvimage.

Add support for floating point input images in nvtt.
This commit is contained in:
castano 2008-05-15 09:47:55 +00:00
parent 47bdab8e27
commit c01566cd2f
7 changed files with 242 additions and 7 deletions

View File

@ -11,6 +11,7 @@
#cmakedefine HAVE_JPEG
#cmakedefine HAVE_TIFF
#cmakedefine HAVE_OPENEXR
#cmakedefine HAVE_FREEIMAGE
#cmakedefine HAVE_MAYA

View File

@ -51,6 +51,11 @@ IF(OPENEXR_FOUND)
INCLUDE_DIRECTORIES(${OPENEXR_INCLUDE_PATHS})
ENDIF(OPENEXR_FOUND)
IF(FREEIMAGE_FOUND)
SET(LIBS ${LIBS} ${FREEIMAGE_LIBRARIES})
INCLUDE_DIRECTORIES(${FREEIMAGE_INCLUDE_PATHS})
ENDIF(FREEIMAGE_FOUND)
# targets
ADD_DEFINITIONS(-DNVIMAGE_EXPORTS)

View File

@ -1,7 +1,11 @@
#include "ColorSpace.h"
// This code is in the public domain -- jim@tilander.org
#include <nvcore/nvcore.h>
#include <nvmath/Color.h>
#include <nvimage/Image.h>
#include <nvcore/nvcore.h>
#include "ColorSpace.h"
namespace nv
{
@ -63,4 +67,4 @@ namespace nv
}
}
}
}
}

View File

@ -1,3 +1,4 @@
// This code is in the public domain -- jim@tilander.org
#ifndef NV_IMAGE_COLORSPACE_H
#define NV_IMAGE_COLORSPACE_H

View File

@ -40,6 +40,10 @@ extern "C" {
# include <ImfArray.h>
#endif
#if defined(HAVE_FREEIMAGE)
# include <FreeImage.h>
#endif
using namespace nv;
namespace {
@ -58,6 +62,9 @@ namespace {
} // namespace
static Image * loadFreeImage(FREE_IMAGE_FORMAT fif, Stream & s);
static FloatImage * loadFloatFreeImage(FREE_IMAGE_FORMAT fif, Stream & s);
Image * nv::ImageIO::load(const char * fileName)
{
@ -78,10 +85,16 @@ Image * nv::ImageIO::load(const char * fileName, Stream & s)
nvDebugCheck(s.isLoading());
const char * extension = Path::extension(fileName);
if (strCaseCmp(extension, ".tga") == 0) {
return ImageIO::loadTGA(s);
}
#if defined(HAVE_FREEIMAGE)
FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(fileName);
if (fif != FIF_UNKNOWN && FreeImage_FIFSupportsReading(fif)) {
return loadFreeImage(fif, s);
}
#endif
#if defined(HAVE_JPEG)
if (strCaseCmp(extension, ".jpg") == 0 || strCaseCmp(extension, ".jpeg") == 0) {
return loadJPG(s);
@ -92,10 +105,13 @@ Image * nv::ImageIO::load(const char * fileName, Stream & s)
return loadPNG(s);
}
#endif
if (strCaseCmp(extension, ".psd") == 0) {
return loadPSD(s);
}
// @@ use image plugins?
return NULL;
}
@ -157,6 +173,12 @@ FloatImage * nv::ImageIO::loadFloat(const char * fileName, Stream & s)
return loadFloatEXR(fileName, s);
}
#endif
#if defined(HAVE_FREEIMAGE)
FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(fileName);
if (fif != FIF_UNKNOWN && FreeImage_FIFSupportsReading(fif)) {
return loadFloatFreeImage(fif, s);
}
#endif
/* // @@ Disable temporarily
if (strCaseCmp(extension, ".pfm") == 0) {
@ -600,6 +622,206 @@ Image * nv::ImageIO::loadPSD(Stream & s)
return img.release();
}
#if defined(HAVE_FREEIMAGE)
unsigned ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle)
{
Stream * s = (Stream *) handle;
s->serialize(buffer, size * count);
return count;
}
int SeekProc(fi_handle handle, long offset, int origin)
{
Stream * s = (Stream *) handle;
switch(origin) {
case SEEK_SET :
s->seek(offset);
break;
case SEEK_CUR :
s->seek(s->tell() + offset);
break;
default :
return 1;
}
return 0;
}
long TellProc(fi_handle handle)
{
Stream * s = (Stream *) handle;
return s->tell();
}
Image * loadFreeImage(FREE_IMAGE_FORMAT fif, Stream & s)
{
nvCheck(!s.isError());
FreeImageIO io;
io.read_proc = ReadProc;
io.write_proc = NULL;
io.seek_proc = SeekProc;
io.tell_proc = TellProc;
FIBITMAP * bitmap = FreeImage_LoadFromHandle(fif, &io, (fi_handle)&s, 0);
if (bitmap == NULL)
{
return NULL;
}
const int w = FreeImage_GetWidth(bitmap);
const int h = FreeImage_GetHeight(bitmap);
if (FreeImage_GetImageType(bitmap) == FIT_BITMAP)
{
if (FreeImage_GetBPP(bitmap) != 32)
{
FIBITMAP * tmp = FreeImage_ConvertTo32Bits(bitmap);
FreeImage_Unload(bitmap);
bitmap = tmp;
}
}
else
{
// @@ Use tone mapping?
FIBITMAP * tmp = FreeImage_ConvertToType(bitmap, FIT_BITMAP, true);
FreeImage_Unload(bitmap);
bitmap = tmp;
}
Image * image = new Image();
image->allocate(w, h);
// Copy the image over to our internal format, FreeImage has the scanlines bottom to top though.
for (int y=0; y < h; y++)
{
const void * src = FreeImage_GetScanLine(bitmap, h - y - 1);
void * dst = image->scanline(y);
memcpy(dst, src, 4 * w);
}
FreeImage_Unload(bitmap);
return image;
}
FloatImage * loadFloatFreeImage(FREE_IMAGE_FORMAT fif, Stream & s)
{
nvCheck(!s.isError());
FreeImageIO io;
io.read_proc = ReadProc;
io.write_proc = NULL;
io.seek_proc = SeekProc;
io.tell_proc = TellProc;
FIBITMAP * bitmap = FreeImage_LoadFromHandle(fif, &io, (fi_handle)&s, 0);
if (bitmap == NULL)
{
return NULL;
}
const int w = FreeImage_GetWidth(bitmap);
const int h = FreeImage_GetHeight(bitmap);
FREE_IMAGE_TYPE fit = FreeImage_GetImageType(bitmap);
FloatImage * floatImage = new FloatImage();
switch (fit)
{
case FIT_FLOAT:
floatImage->allocate(1, w, h);
for (int y=0; y < h; y++)
{
const float * src = (const float *)FreeImage_GetScanLine(bitmap, h - y - 1 );
float * dst = floatImage->scanline(y, 0);
for (int x=0; x < w; x++)
{
dst[x] = src[x];
}
}
break;
case FIT_COMPLEX:
floatImage->allocate(2, w, h);
for (int y=0; y < h; y++)
{
const FICOMPLEX * src = (const FICOMPLEX *)FreeImage_GetScanLine(bitmap, h - y - 1 );
float * dst_real = floatImage->scanline(y, 0);
float * dst_imag = floatImage->scanline(y, 1);
for (int x=0; x < w; x++)
{
dst_real[x] = src[x].r;
dst_imag[x] = src[x].i;
}
}
break;
case FIT_RGBF:
floatImage->allocate(3, w, h);
for (int y=0; y < h; y++)
{
const FIRGBF * src = (const FIRGBF *)FreeImage_GetScanLine(bitmap, h - y - 1 );
float * dst_red = floatImage->scanline(y, 0);
float * dst_green = floatImage->scanline(y, 1);
float * dst_blue = floatImage->scanline(y, 2);
for (int x=0; x < w; x++)
{
dst_red[x] = src[x].red;
dst_green[x] = src[x].green;
dst_blue[x] = src[x].blue;
}
}
break;
case FIT_RGBAF:
floatImage->allocate(4, w, h);
for (int y=0; y < h; y++)
{
const FIRGBAF * src = (const FIRGBAF *)FreeImage_GetScanLine(bitmap, h - y - 1 );
float * dst_red = floatImage->scanline(y, 0);
float * dst_green = floatImage->scanline(y, 1);
float * dst_blue = floatImage->scanline(y, 2);
float * dst_alpha = floatImage->scanline(y, 3);
for (int x=0; x < w; x++)
{
dst_red[x] = src[x].red;
dst_green[x] = src[x].green;
dst_blue[x] = src[x].blue;
dst_alpha[x] = src[x].alpha;
}
}
break;
default:
delete floatImage;
floatImage = NULL;
}
FreeImage_Unload(bitmap);
return floatImage;
}
#endif // defined(HAVE_FREEIMAGE)
#if defined(HAVE_PNG)
static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length)

View File

@ -211,7 +211,7 @@ bool InputOptions::setMipmapData(const void * data, int width, int height, int d
{
image->allocate(width, height);
memcpy(image->pixels(), data, width * height * 4);
m.images[idx].data = image;
m.images[idx].uint8data = image;
}
else
{
@ -234,7 +234,7 @@ bool InputOptions::setMipmapData(const void * data, int width, int height, int d
}
}
m.images[idx].data = image;
m.images[idx].floatdata = image;
}
else
{
@ -467,7 +467,7 @@ const Image * InputOptions::Private::image(uint idx) const
return image.uint8data.ptr();
}
const FloatImage * InputOptions::Private::image(uint idx) const
const FloatImage * InputOptions::Private::floatImage(uint idx) const
{
nvDebugCheck(idx < faceCount * mipmapCount);

View File

@ -104,6 +104,8 @@ namespace nvtt
{
InputImage() {}
bool hasValidData() const { return uint8data != NULL || floatdata != NULL; }
int mipLevel;
int face;