/src/FreeImage/Source/FreeImage/PluginJP2.cpp
https://bitbucket.org/cabalistic/ogredeps/ · C++ · 339 lines · 194 code · 69 blank · 76 comment · 30 complexity · ca615216ed4900436a17e17539217777 MD5 · raw file
- // ==========================================================
- // JPEG2000 JP2 file format Loader and Writer
- //
- // Design and implementation by
- // - Hervé Drolon (drolon@infonie.fr)
- //
- // This file is part of FreeImage 3
- //
- // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
- // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
- // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
- // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
- // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
- // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
- // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
- // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
- // THIS DISCLAIMER.
- //
- // Use at your own risk!
- // ==========================================================
- #include "FreeImage.h"
- #include "Utilities.h"
- #include "../LibOpenJPEG/openjpeg.h"
- // ==========================================================
- // Plugin Interface
- // ==========================================================
- static int s_format_id;
- // ==========================================================
- // Helper functions (see J2KHelper.cpp)
- // ==========================================================
- FIBITMAP* J2KImageToFIBITMAP(int format_id, const opj_image_t *image);
- opj_image_t* FIBITMAPToJ2KImage(int format_id, FIBITMAP *dib, const opj_cparameters_t *parameters);
- // ==========================================================
- // Internal functions
- // ==========================================================
- /**
- OpenJPEG Error callback
- */
- static void jp2_error_callback(const char *msg, void *client_data) {
- FreeImage_OutputMessageProc(s_format_id, "Error: %s", msg);
- }
- /**
- OpenJPEG Warning callback
- */
- static void jp2_warning_callback(const char *msg, void *client_data) {
- FreeImage_OutputMessageProc(s_format_id, "Warning: %s", msg);
- }
- // ==========================================================
- // Plugin Implementation
- // ==========================================================
- static const char * DLL_CALLCONV
- Format() {
- return "JP2";
- }
- static const char * DLL_CALLCONV
- Description() {
- return "JPEG-2000 File Format";
- }
- static const char * DLL_CALLCONV
- Extension() {
- return "jp2";
- }
- static const char * DLL_CALLCONV
- RegExpr() {
- return NULL;
- }
- static const char * DLL_CALLCONV
- MimeType() {
- return "image/jp2";
- }
- static BOOL DLL_CALLCONV
- Validate(FreeImageIO *io, fi_handle handle) {
- BYTE jp2_signature[] = { 0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A };
- BYTE signature[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- long tell = io->tell_proc(handle);
- io->read_proc(signature, 1, sizeof(jp2_signature), handle);
- io->seek_proc(handle, tell, SEEK_SET);
- return (memcmp(jp2_signature, signature, sizeof(jp2_signature)) == 0);
- }
- static BOOL DLL_CALLCONV
- SupportsExportDepth(int depth) {
- return (
- (depth == 8) ||
- (depth == 24) ||
- (depth == 32)
- );
- }
- static BOOL DLL_CALLCONV
- SupportsExportType(FREE_IMAGE_TYPE type) {
- return (
- (type == FIT_BITMAP) ||
- (type == FIT_UINT16) ||
- (type == FIT_RGB16) ||
- (type == FIT_RGBA16)
- );
- }
- // ----------------------------------------------------------
- static void * DLL_CALLCONV
- Open(FreeImageIO *io, fi_handle handle, BOOL read) {
- return NULL;
- }
- static void DLL_CALLCONV
- Close(FreeImageIO *io, fi_handle handle, void *data) {
- }
- // ----------------------------------------------------------
- static FIBITMAP * DLL_CALLCONV
- Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
- if (handle) {
- opj_dparameters_t parameters; // decompression parameters
- opj_event_mgr_t event_mgr; // event manager
- opj_image_t *image = NULL; // decoded image
- BYTE *src = NULL;
- long file_length;
- opj_dinfo_t* dinfo = NULL; // handle to a decompressor
- opj_cio_t *cio = NULL;
- FIBITMAP *dib = NULL;
- // check the file format
- if(!Validate(io, handle)) {
- return NULL;
- }
- // configure the event callbacks
- memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
- event_mgr.error_handler = jp2_error_callback;
- event_mgr.warning_handler = jp2_warning_callback;
- event_mgr.info_handler = NULL;
- // set decoding parameters to default values
- opj_set_default_decoder_parameters(¶meters);
- try {
- // read the input file and put it in memory
- long start_pos = io->tell_proc(handle);
- io->seek_proc(handle, 0, SEEK_END);
- file_length = io->tell_proc(handle) - start_pos;
- io->seek_proc(handle, start_pos, SEEK_SET);
- src = (BYTE*)malloc(file_length * sizeof(BYTE));
- if(!src) {
- throw FI_MSG_ERROR_MEMORY;
- }
- if(io->read_proc(src, 1, file_length, handle) < 1) {
- throw "Error while reading input stream";
- }
- // decode the JPEG-2000 file
- // get a decoder handle
- dinfo = opj_create_decompress(CODEC_JP2);
-
- // catch events using our callbacks
- opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL);
- // setup the decoder decoding parameters using user parameters
- opj_setup_decoder(dinfo, ¶meters);
- // open a byte stream
- cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
- // decode the stream and fill the image structure
- image = opj_decode(dinfo, cio);
- if(!image) {
- throw "Failed to decode image!\n";
- }
-
- // close the byte stream
- opj_cio_close(cio);
- cio = NULL;
- // free the memory containing the code-stream
- free(src);
- src = NULL;
- // free the codec context
- opj_destroy_decompress(dinfo);
- // create output image
- dib = J2KImageToFIBITMAP(s_format_id, image);
- if(!dib) throw "Failed to import JPEG2000 image";
- // free image data structure
- opj_image_destroy(image);
- return dib;
- } catch (const char *text) {
- if(src) free(src);
- if(dib) FreeImage_Unload(dib);
- // free remaining structures
- opj_destroy_decompress(dinfo);
- opj_image_destroy(image);
- // close the byte stream
- if(cio) opj_cio_close(cio);
- FreeImage_OutputMessageProc(s_format_id, text);
- return NULL;
- }
- }
- return NULL;
- }
- static BOOL DLL_CALLCONV
- Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
- if ((dib) && (handle)) {
- BOOL bSuccess;
- opj_cparameters_t parameters; // compression parameters
- opj_event_mgr_t event_mgr; // event manager
- opj_image_t *image = NULL; // image to encode
- opj_cinfo_t* cinfo = NULL; // codec context
- opj_cio_t *cio = NULL; // memory byte stream
- // configure the event callbacks
- memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
- event_mgr.error_handler = jp2_error_callback;
- event_mgr.warning_handler = jp2_warning_callback;
- event_mgr.info_handler = NULL;
- // set encoding parameters to default values
- opj_set_default_encoder_parameters(¶meters);
- parameters.tcp_numlayers = 0;
- // if no rate entered, apply a 16:1 rate by default
- if(flags == JP2_DEFAULT) {
- parameters.tcp_rates[0] = (float)16;
- } else {
- // for now, the flags parameter is only used to specify the rate
- parameters.tcp_rates[0] = (float)flags;
- }
- parameters.tcp_numlayers++;
- parameters.cp_disto_alloc = 1;
- try {
- // convert the dib to a OpenJPEG image
- image = FIBITMAPToJ2KImage(s_format_id, dib, ¶meters);
- if(!image) return FALSE;
- // decide if MCT should be used
- parameters.tcp_mct = (image->numcomps == 3) ? 1 : 0;
- // encode the destination image
- // get a J2K compressor handle
- cinfo = opj_create_compress(CODEC_JP2);
- // catch events using our callbacks
- opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, NULL);
- // setup the encoder parameters using the current image and using user parameters
- opj_setup_encoder(cinfo, ¶meters, image);
- // open a byte stream for writing, allocate memory for all tiles
- cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
- // encode the image
- bSuccess = opj_encode(cinfo, cio, image, NULL/*parameters.index*/);
- if (!bSuccess) {
- throw "Failed to encode image";
- }
- int codestream_length = cio_tell(cio);
- // write the buffer to user's IO handle
- io->write_proc(cio->buffer, 1, codestream_length, handle);
- // close and free the byte stream
- opj_cio_close(cio);
- // free remaining compression structures
- opj_destroy_compress(cinfo);
-
- // free image data
- opj_image_destroy(image);
- return TRUE;
- } catch (const char *text) {
- if(cio) opj_cio_close(cio);
- if(cinfo) opj_destroy_compress(cinfo);
- if(image) opj_image_destroy(image);
- FreeImage_OutputMessageProc(s_format_id, text);
- return FALSE;
- }
- }
- return FALSE;
- }
- // ==========================================================
- // Init
- // ==========================================================
- void DLL_CALLCONV
- InitJP2(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 = Open;
- plugin->close_proc = Close;
- plugin->pagecount_proc = NULL;
- plugin->pagecapability_proc = NULL;
- plugin->load_proc = Load;
- plugin->save_proc = Save;
- plugin->validate_proc = Validate;
- plugin->mime_proc = MimeType;
- plugin->supports_export_bpp_proc = SupportsExportDepth;
- plugin->supports_export_type_proc = SupportsExportType;
- plugin->supports_icc_profiles_proc = NULL;
- }