Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/PluginJXR.cpp view on Meta::CPAN
// HACK : we use fMem to avoid a stream destruction by the library
// because FreeImage MUST HAVE the ownership of the stream
// see _jxr_io_Close
pWS->fMem = FALSE;
return WMP_errSuccess;
}
return WMP_errOutOfMemory;
}
// ==========================================================
// JPEG XR Error handling
// ==========================================================
static const char*
JXR_ErrorMessage(const int error) {
switch(error) {
case WMP_errNotYetImplemented:
case WMP_errAbstractMethod:
return "Not yet implemented";
case WMP_errOutOfMemory:
return "Out of memory";
case WMP_errFileIO:
return "File I/O error";
case WMP_errBufferOverflow:
return "Buffer overflow";
case WMP_errInvalidParameter:
return "Invalid parameter";
case WMP_errInvalidArgument:
return "Invalid argument";
case WMP_errUnsupportedFormat:
return "Unsupported format";
case WMP_errIncorrectCodecVersion:
return "Incorrect codec version";
case WMP_errIndexNotFound:
return "Format converter: Index not found";
case WMP_errOutOfSequence:
return "Metadata: Out of sequence";
case WMP_errMustBeMultipleOf16LinesUntilLastCall:
return "Must be multiple of 16 lines until last call";
case WMP_errPlanarAlphaBandedEncRequiresTempFile:
return "Planar alpha banded encoder requires temp files";
case WMP_errAlphaModeCannotBeTranscoded:
return "Alpha mode cannot be transcoded";
case WMP_errIncorrectCodecSubVersion:
return "Incorrect codec subversion";
case WMP_errFail:
case WMP_errNotInitialized:
default:
return "Invalid instruction - please contact the FreeImage team";
}
}
// ==========================================================
// Helper functions & macro
// ==========================================================
#define JXR_CHECK(error_code) \
if(error_code < 0) { \
const char *error_message = JXR_ErrorMessage(error_code); \
throw error_message; \
}
// --------------------------------------------------------------------------
/**
Input conversions natively understood by FreeImage
@see GetNativePixelFormat
*/
typedef struct tagJXRInputConversion {
BITDEPTH_BITS bdBitDepth;
U32 cbitUnit;
FREE_IMAGE_TYPE image_type;
unsigned red_mask;
unsigned green_mask;
unsigned blue_mask;
} JXRInputConversion;
/**
Conversion table for native FreeImage formats
@see GetNativePixelFormat
*/
static JXRInputConversion s_FreeImagePixelInfo[] = {
// 1-bit bitmap
{ BD_1, 1, FIT_BITMAP, 0, 0, 0 },
// 8-, 24-, 32-bit bitmap
{ BD_8, 8, FIT_BITMAP, 0, 0, 0 },
{ BD_8, 24, FIT_BITMAP, 0, 0, 0 },
{ BD_8, 32, FIT_BITMAP, 0, 0, 0 },
// 16-bit RGB 565
{ BD_565, 16, FIT_BITMAP, FI16_565_RED_MASK, FI16_565_GREEN_MASK, FI16_565_BLUE_MASK },
// 16-bit RGB 555
{ BD_5, 16, FIT_BITMAP, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK },
// 16-bit greyscale, RGB16, RGBA16 bitmap
{ BD_16, 16, FIT_UINT16, 0, 0, 0 },
{ BD_16, 48, FIT_RGB16, 0, 0, 0 },
{ BD_16, 64, FIT_RGBA16, 0, 0, 0 },
// 32-bit float, RGBF, RGBAF bitmap
{ BD_32F, 32, FIT_FLOAT, 0, 0, 0 },
{ BD_32F, 96, FIT_RGBF, 0, 0, 0 },
{ BD_32F, 128, FIT_RGBAF, 0, 0, 0 }
};
/**
Scan input pixelInfo specifications and return the equivalent FreeImage info for loading
@param pixelInfo Image specifications
@param out_guid_format (returned value) output pixel format
@param image_type (returned value) Image type
@param bpp (returned value) Image bit depth
@param red_mask (returned value) RGB mask
@param green_mask (returned value) RGB mask
@param blue_mask (returned value) RGB mask
@return Returns WMP_errSuccess if successful, returns WMP_errFail otherwise
@see GetInputPixelFormat
*/
static ERR
GetNativePixelFormat(const PKPixelInfo *pixelInfo, PKPixelFormatGUID *out_guid_format, FREE_IMAGE_TYPE *image_type, unsigned *bpp, unsigned *red_mask, unsigned *green_mask, unsigned *blue_mask) {
const unsigned s_FreeImagePixelInfoSize = (unsigned)sizeof(s_FreeImagePixelInfo) / sizeof(*(s_FreeImagePixelInfo));
for(unsigned i = 0; i < s_FreeImagePixelInfoSize; i++) {
if(pixelInfo->bdBitDepth == s_FreeImagePixelInfo[i].bdBitDepth) {
src/Source/FreeImage/PluginJXR.cpp view on Meta::CPAN
return WMP_errSuccess;
} catch(...) {
// free the local buffer
PKFreeAligned((void **) &pb);
// free the pixel format converter
PKFormatConverter_Release(&pConverter);
return error_code;
}
}
// --------------------------------------------------------------------------
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
PKImageDecode *pDecoder = NULL; // decoder interface
ERR error_code = 0; // error code as returned by the interface
PKPixelFormatGUID guid_format; // loaded pixel format (== input file pixel format if no conversion needed)
FREE_IMAGE_TYPE image_type = FIT_UNKNOWN; // input image type
unsigned bpp = 0; // input image bit depth
FIBITMAP *dib = NULL;
// get the I/O stream wrapper
WMPStream *pDecodeStream = (WMPStream*)data;
if(!handle || !pDecodeStream) {
return NULL;
}
BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
try {
int width, height; // image dimensions (in pixels)
// create a JXR decoder interface and initialize function pointers with *_WMP functions
error_code = PKImageDecode_Create_WMP(&pDecoder);
JXR_CHECK(error_code);
// attach the stream to the decoder ...
// ... then read the image container and the metadata
error_code = pDecoder->Initialize(pDecoder, pDecodeStream);
JXR_CHECK(error_code);
// set decoder parameters
SetDecoderParameters(pDecoder, flags);
// get dst image format specifications
unsigned red_mask = 0, green_mask = 0, blue_mask = 0;
error_code = GetInputPixelFormat(pDecoder, &guid_format, &image_type, &bpp, &red_mask, &green_mask, &blue_mask);
JXR_CHECK(error_code);
// get image dimensions
pDecoder->GetSize(pDecoder, &width, &height);
// allocate dst image
{
dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, bpp, red_mask, green_mask, blue_mask);
if(!dib) {
throw FI_MSG_ERROR_DIB_MEMORY;
}
if(FreeImage_GetBPP(dib) == 1) {
// BD_1 - build a FIC_MINISBLACK palette
RGBQUAD *pal = FreeImage_GetPalette(dib);
pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
}
}
// get image resolution
{
float resX, resY; // image resolution (in dots per inch)
// convert from English units, i.e. dots per inch to universal units, i.e. dots per meter
pDecoder->GetResolution(pDecoder, &resX, &resY);
FreeImage_SetDotsPerMeterX(dib, (unsigned)(resX / 0.0254F + 0.5F));
FreeImage_SetDotsPerMeterY(dib, (unsigned)(resY / 0.0254F + 0.5F));
}
// get metadata & ICC profile
error_code = ReadMetadata(pDecoder, dib);
JXR_CHECK(error_code);
if(header_only) {
// header only mode ...
// free the decoder
pDecoder->Release(&pDecoder);
assert(pDecoder == NULL);
return dib;
}
// copy pixels into the dib, perform pixel conversion if needed
error_code = CopyPixels(pDecoder, guid_format, dib, width, height);
JXR_CHECK(error_code);
// free the decoder
pDecoder->Release(&pDecoder);
assert(pDecoder == NULL);
return dib;
} catch (const char *message) {
// unload the dib
FreeImage_Unload(dib);
// free the decoder
pDecoder->Release(&pDecoder);
if(NULL != message) {
FreeImage_OutputMessageProc(s_format_id, message);
}
}
return NULL;
}
// ==========================================================
// Save
// ==========================================================
src/Source/FreeImage/PluginJXR.cpp view on Meta::CPAN
wmiSCP->sbSubband = SB_ALL; // keep all subbands
wmiSCP->uAlphaMode = 0; // 0:no alpha 1: alpha only else: something + alpha
wmiSCP->uiDefaultQPIndex = 1; // quantization for grey or rgb layer(s), 1: lossless
wmiSCP->uiDefaultQPIndexAlpha = 1; // quantization for alpha layer, 1: lossless
// process the flags
// -----------------
// progressive mode
if((flags & JXR_PROGRESSIVE) == JXR_PROGRESSIVE) {
// turn on progressive mode (instead of sequential mode)
wmiSCP->bProgressiveMode = TRUE;
}
// quality in [0.01 - 1.0), 1.0 means lossless - default is 0.80
int quality = flags & 0x7F;
if(quality == 0) {
// defaut to 0.80
fltImageQuality = 0.8F;
} else if((flags & JXR_LOSSLESS) == JXR_LOSSLESS) {
fltImageQuality = 1.0F;
} else {
quality = (quality >= 100) ? 100 : quality;
fltImageQuality = quality / 100.0F;
}
SetCompression(wmiSCP, pixelInfo, fltImageQuality);
// alpha compression
if(bHasAlpha) {
wmiSCP->uAlphaMode = 2; // encode with a planar alpha channel
}
}
// --------------------------------------------------------------------------
static BOOL DLL_CALLCONV
Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
BOOL bIsFlipped = FALSE; // FreeImage DIB are upside-down relative to usual graphic conventions
PKPixelFormatGUID guid_format; // image format
PKPixelInfo pixelInfo; // image specifications
BOOL bHasAlpha = FALSE; // is alpha layer present ?
PKImageEncode *pEncoder = NULL; // encoder interface
ERR error_code = 0; // error code as returned by the interface
// get the I/O stream wrapper
WMPStream *pEncodeStream = (WMPStream*)data;
if(!dib || !handle || !pEncodeStream) {
return FALSE;
}
try {
// get image dimensions
unsigned width = FreeImage_GetWidth(dib);
unsigned height = FreeImage_GetHeight(dib);
// check JPEG-XR limits
if((width < MB_WIDTH_PIXEL) || (height < MB_HEIGHT_PIXEL)) {
FreeImage_OutputMessageProc(s_format_id, "Unsupported image size: width x height = %d x %d", width, height);
throw (const char*)NULL;
}
// get output pixel format
error_code = GetOutputPixelFormat(dib, &guid_format, &bHasAlpha);
JXR_CHECK(error_code);
pixelInfo.pGUIDPixFmt = &guid_format;
error_code = PixelFormatLookup(&pixelInfo, LOOKUP_FORWARD);
JXR_CHECK(error_code);
// create a JXR encoder interface and initialize function pointers with *_WMP functions
error_code = PKImageEncode_Create_WMP(&pEncoder);
JXR_CHECK(error_code);
// attach the stream to the encoder and set all encoder parameters to zero ...
error_code = pEncoder->Initialize(pEncoder, pEncodeStream, &pEncoder->WMP.wmiSCP, sizeof(CWMIStrCodecParam));
JXR_CHECK(error_code);
// ... then configure the encoder
SetEncoderParameters(&pEncoder->WMP.wmiSCP, &pixelInfo, flags, bHasAlpha);
// set pixel format
pEncoder->SetPixelFormat(pEncoder, guid_format);
// set image size
pEncoder->SetSize(pEncoder, width, height);
// set resolution (convert from universal units to English units)
float resX = (float)(unsigned)(0.5F + 0.0254F * FreeImage_GetDotsPerMeterX(dib));
float resY = (float)(unsigned)(0.5F + 0.0254F * FreeImage_GetDotsPerMeterY(dib));
pEncoder->SetResolution(pEncoder, resX, resY);
// set metadata
WriteMetadata(pEncoder, dib);
// write metadata & pixels
// -----------------------
// dib coordinates are upside-down relative to usual conventions
bIsFlipped = FreeImage_FlipVertical(dib);
// get a pointer to dst pixel data
BYTE *dib_bits = FreeImage_GetBits(dib);
// get dst pitch (count of BYTE for stride)
const unsigned cbStride = FreeImage_GetPitch(dib);
// write metadata + pixels on output
error_code = pEncoder->WritePixels(pEncoder, height, dib_bits, cbStride);
JXR_CHECK(error_code);
// recover dib coordinates
FreeImage_FlipVertical(dib);
// free the encoder
pEncoder->Release(&pEncoder);
assert(pEncoder == NULL);
return TRUE;
} catch (const char *message) {
( run in 0.465 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )