Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/PluginPFM.cpp view on Meta::CPAN
}
static const char * DLL_CALLCONV
Description() {
return "Portable floatmap";
}
static const char * DLL_CALLCONV
Extension() {
return "pfm";
}
static const char * DLL_CALLCONV
RegExpr() {
return NULL;
}
static const char * DLL_CALLCONV
MimeType() {
return "image/x-portable-floatmap";
}
static BOOL DLL_CALLCONV
Validate(FreeImageIO *io, fi_handle handle) {
BYTE pfm_id1[] = { 0x50, 0x46 };
BYTE pfm_id2[] = { 0x50, 0x66 };
BYTE signature[2] = { 0, 0 };
io->read_proc(signature, 1, sizeof(pfm_id1), handle);
if (memcmp(pfm_id1, signature, sizeof(pfm_id1)) == 0)
return TRUE;
if (memcmp(pfm_id2, signature, sizeof(pfm_id2)) == 0)
return TRUE;
return FALSE;
}
static BOOL DLL_CALLCONV
SupportsExportDepth(int depth) {
return FALSE;
}
static BOOL DLL_CALLCONV
SupportsExportType(FREE_IMAGE_TYPE type) {
return (
(type == FIT_FLOAT) ||
(type == FIT_RGBF)
);
}
static BOOL DLL_CALLCONV
SupportsNoPixels() {
return TRUE;
}
// ----------------------------------------------------------
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
char line_buffer[PFM_MAXLINE];
char id_one = 0, id_two = 0;
FIBITMAP *dib = NULL;
float *lineBuffer = NULL;
if (!handle) {
return NULL;
}
BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
try {
FREE_IMAGE_TYPE image_type = FIT_UNKNOWN;
// Read the first two bytes of the file to determine the file format
// "PF" = color image
// "Pf" = greyscale image
io->read_proc(&id_one, 1, 1, handle);
io->read_proc(&id_two, 1, 1, handle);
if(id_one == 'P') {
if(id_two == 'F') {
image_type = FIT_RGBF;
} else if(id_two == 'f') {
image_type = FIT_FLOAT;
}
}
if(image_type == FIT_UNKNOWN) {
// signature error
throw FI_MSG_ERROR_MAGIC_NUMBER;
}
// Read the header information: width, height and the scale value
unsigned width = (unsigned) pfm_get_int(io, handle);
unsigned height = (unsigned) pfm_get_int(io, handle);
float scalefactor = 1;
BOOL bResult = pfm_get_line(io, handle, line_buffer, PFM_MAXLINE);
if(bResult) {
bResult = (sscanf(line_buffer, "%f", &scalefactor) == 1) ? TRUE : FALSE;
}
if(!bResult) {
throw "Read error: invalid PFM header";
}
// Create a new DIB
dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height);
if (dib == NULL) {
throw FI_MSG_ERROR_DIB_MEMORY;
}
if(header_only) {
// header only mode
return dib;
}
// Read the image...
if(image_type == FIT_RGBF) {
const unsigned lineWidth = 3 * width;
lineBuffer = (float*)malloc(lineWidth * sizeof(float));
if(!lineBuffer) {
throw FI_MSG_ERROR_MEMORY;
}
for (unsigned y = 0; y < height; y++) {
FIRGBF *bits = (FIRGBF*)FreeImage_GetScanLine(dib, height - 1 - y);
if(io->read_proc(lineBuffer, sizeof(float), lineWidth, handle) != lineWidth) {
src/Source/FreeImage/PluginPFM.cpp view on Meta::CPAN
} else {
// LSB
for (unsigned x = 0; x < width; x++) {
bits[x].red = *channel++;
bits[x].green = *channel++;
bits[x].blue = *channel++;
}
}
}
free(lineBuffer);
lineBuffer = NULL;
} else if(image_type == FIT_FLOAT) {
const unsigned lineWidth = width;
lineBuffer = (float*)malloc(lineWidth * sizeof(float));
if(!lineBuffer) {
throw FI_MSG_ERROR_MEMORY;
}
for (unsigned y = 0; y < height; y++) {
float *bits = (float*)FreeImage_GetScanLine(dib, height - 1 - y);
if(io->read_proc(lineBuffer, sizeof(float), lineWidth, handle) != lineWidth) {
throw "Read error";
}
float *channel = lineBuffer;
if(scalefactor > 0) {
// MSB - File is Big endian
for (unsigned x = 0; x < width; x++) {
REVERSEBYTES(channel++, &bits[x]);
}
} else {
// LSB - File is Little Endian
for (unsigned x = 0; x < width; x++) {
bits[x] = *channel++;
}
}
}
free(lineBuffer);
lineBuffer = NULL;
}
return dib;
} catch (const char *text) {
if(lineBuffer) free(lineBuffer);
if(dib) FreeImage_Unload(dib);
if(NULL != text) {
FreeImage_OutputMessageProc(s_format_id, text);
}
return NULL;
}
}
static BOOL DLL_CALLCONV
Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
if(!dib || !handle) return FALSE;
FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
if((image_type != FIT_RGBF) && (image_type != FIT_FLOAT)) {
return FALSE;
}
unsigned width = FreeImage_GetWidth(dib);
unsigned height = FreeImage_GetHeight(dib);
unsigned lineWidth = FreeImage_GetLine(dib);
// save image as Little Endian
const float scalefactor = -1.0F;
char buffer[PFM_MAXLINE]; // temporary buffer whose size should be enough for what we need
// Find the appropriate magic number for this file type
char magic = 0;
switch(image_type) {
case FIT_RGBF:
magic = 'F'; // RGBF
break;
case FIT_FLOAT:
magic = 'f'; // float greyscale
break;
default:
return FALSE;
}
// Write the header info
sprintf(buffer, "P%c\n%d %d\n%f\n", magic, width, height, scalefactor);
io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle);
// Write the image data
for (unsigned y = 0; y < height; y++) {
BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);
io->write_proc(bits, 1, lineWidth, handle);
}
return TRUE;
}
// ==========================================================
// Init
// ==========================================================
void DLL_CALLCONV
InitPFM(Plugin *plugin, int format_id) {
s_format_id = format_id;
plugin->format_proc = Format;
plugin->description_proc = Description;
plugin->extension_proc = Extension;
plugin->regexpr_proc = RegExpr;
plugin->open_proc = NULL;
plugin->close_proc = NULL;
plugin->pagecount_proc = NULL;
( run in 1.264 second using v1.01-cache-2.11-cpan-63c85eba8c4 )