PageRenderTime 39ms CodeModel.GetById 13ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 0ms

/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
  1// ==========================================================
  2// JPEG2000 JP2 file format Loader and Writer
  3//
  4// Design and implementation by
  5// - Hervé Drolon (drolon@infonie.fr)
  6//
  7// This file is part of FreeImage 3
  8//
  9// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
 10// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
 11// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
 12// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
 13// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
 14// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
 15// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
 16// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
 17// THIS DISCLAIMER.
 18//
 19// Use at your own risk!
 20// ==========================================================
 21
 22#include "FreeImage.h"
 23#include "Utilities.h"
 24#include "../LibOpenJPEG/openjpeg.h"
 25
 26// ==========================================================
 27// Plugin Interface
 28// ==========================================================
 29
 30static int s_format_id;
 31
 32// ==========================================================
 33// Helper functions (see J2KHelper.cpp)
 34// ==========================================================
 35
 36FIBITMAP* J2KImageToFIBITMAP(int format_id, const opj_image_t *image);
 37opj_image_t* FIBITMAPToJ2KImage(int format_id, FIBITMAP *dib, const opj_cparameters_t *parameters);
 38
 39// ==========================================================
 40// Internal functions
 41// ==========================================================
 42
 43/**
 44OpenJPEG Error callback 
 45*/
 46static void jp2_error_callback(const char *msg, void *client_data) {
 47	FreeImage_OutputMessageProc(s_format_id, "Error: %s", msg);
 48}
 49/**
 50OpenJPEG Warning callback 
 51*/
 52static void jp2_warning_callback(const char *msg, void *client_data) {
 53	FreeImage_OutputMessageProc(s_format_id, "Warning: %s", msg);
 54}
 55
 56// ==========================================================
 57// Plugin Implementation
 58// ==========================================================
 59
 60static const char * DLL_CALLCONV
 61Format() {
 62	return "JP2";
 63}
 64
 65static const char * DLL_CALLCONV
 66Description() {
 67	return "JPEG-2000 File Format";
 68}
 69
 70static const char * DLL_CALLCONV
 71Extension() {
 72	return "jp2";
 73}
 74
 75static const char * DLL_CALLCONV
 76RegExpr() {
 77	return NULL;
 78}
 79
 80static const char * DLL_CALLCONV
 81MimeType() {
 82	return "image/jp2";
 83}
 84
 85static BOOL DLL_CALLCONV
 86Validate(FreeImageIO *io, fi_handle handle) {
 87	BYTE jp2_signature[] = { 0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A };
 88	BYTE signature[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 89
 90	long tell = io->tell_proc(handle);
 91	io->read_proc(signature, 1, sizeof(jp2_signature), handle);
 92	io->seek_proc(handle, tell, SEEK_SET);
 93
 94	return (memcmp(jp2_signature, signature, sizeof(jp2_signature)) == 0);
 95}
 96
 97static BOOL DLL_CALLCONV
 98SupportsExportDepth(int depth) {
 99	return (
100		(depth == 8) ||
101		(depth == 24) || 
102		(depth == 32)
103	);
104}
105
106static BOOL DLL_CALLCONV 
107SupportsExportType(FREE_IMAGE_TYPE type) {
108	return (
109		(type == FIT_BITMAP)  ||
110		(type == FIT_UINT16)  ||
111		(type == FIT_RGB16) || 
112		(type == FIT_RGBA16)
113	);
114}
115
116// ----------------------------------------------------------
117
118static void * DLL_CALLCONV
119Open(FreeImageIO *io, fi_handle handle, BOOL read) {
120	return NULL;
121}
122
123static void DLL_CALLCONV
124Close(FreeImageIO *io, fi_handle handle, void *data) {
125}
126
127// ----------------------------------------------------------
128
129static FIBITMAP * DLL_CALLCONV
130Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
131	if (handle) {
132		opj_dparameters_t parameters;	// decompression parameters 
133		opj_event_mgr_t event_mgr;		// event manager 
134		opj_image_t *image = NULL;		// decoded image 
135
136		BYTE *src = NULL; 
137		long file_length;
138
139		opj_dinfo_t* dinfo = NULL;	// handle to a decompressor 
140		opj_cio_t *cio = NULL;
141
142		FIBITMAP *dib = NULL;
143
144		// check the file format
145		if(!Validate(io, handle)) {
146			return NULL;
147		}
148
149		// configure the event callbacks
150		memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
151		event_mgr.error_handler = jp2_error_callback;
152		event_mgr.warning_handler = jp2_warning_callback;
153		event_mgr.info_handler = NULL;
154
155		// set decoding parameters to default values 
156		opj_set_default_decoder_parameters(&parameters);
157
158		try {
159			// read the input file and put it in memory
160
161			long start_pos = io->tell_proc(handle);
162			io->seek_proc(handle, 0, SEEK_END);
163			file_length = io->tell_proc(handle) - start_pos;
164			io->seek_proc(handle, start_pos, SEEK_SET);
165			src = (BYTE*)malloc(file_length * sizeof(BYTE));
166			if(!src) {
167				throw FI_MSG_ERROR_MEMORY;
168			}
169			if(io->read_proc(src, 1, file_length, handle) < 1) {
170				throw "Error while reading input stream";
171			}
172
173			// decode the JPEG-2000 file
174
175			// get a decoder handle 
176			dinfo = opj_create_decompress(CODEC_JP2);
177			
178			// catch events using our callbacks
179			opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL);			
180
181			// setup the decoder decoding parameters using user parameters 
182			opj_setup_decoder(dinfo, &parameters);
183
184			// open a byte stream 
185			cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
186
187			// decode the stream and fill the image structure 
188			image = opj_decode(dinfo, cio);
189			if(!image) {
190				throw "Failed to decode image!\n";
191			}
192			
193			// close the byte stream 
194			opj_cio_close(cio);
195			cio = NULL;
196
197			// free the memory containing the code-stream 
198			free(src);
199			src = NULL;
200
201			// free the codec context
202			opj_destroy_decompress(dinfo);
203
204			// create output image 
205			dib = J2KImageToFIBITMAP(s_format_id, image);
206			if(!dib) throw "Failed to import JPEG2000 image";
207
208			// free image data structure
209			opj_image_destroy(image);
210
211			return dib;
212
213		} catch (const char *text) {
214			if(src) free(src);
215			if(dib) FreeImage_Unload(dib);
216			// free remaining structures
217			opj_destroy_decompress(dinfo);
218			opj_image_destroy(image);
219			// close the byte stream
220			if(cio) opj_cio_close(cio);
221
222			FreeImage_OutputMessageProc(s_format_id, text);
223
224			return NULL;
225		}
226	}
227
228	return NULL;
229}
230
231static BOOL DLL_CALLCONV
232Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
233	if ((dib) && (handle)) {
234		BOOL bSuccess;
235		opj_cparameters_t parameters;		// compression parameters 
236		opj_event_mgr_t event_mgr;			// event manager 
237		opj_image_t *image = NULL;			// image to encode
238		opj_cinfo_t* cinfo = NULL;			// codec context
239		opj_cio_t *cio = NULL;				// memory byte stream
240
241		// configure the event callbacks
242		memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
243		event_mgr.error_handler = jp2_error_callback;
244		event_mgr.warning_handler = jp2_warning_callback;
245		event_mgr.info_handler = NULL;
246
247		// set encoding parameters to default values
248		opj_set_default_encoder_parameters(&parameters);
249
250		parameters.tcp_numlayers = 0;
251		// if no rate entered, apply a 16:1 rate by default
252		if(flags == JP2_DEFAULT) {
253			parameters.tcp_rates[0] = (float)16;
254		} else {
255			// for now, the flags parameter is only used to specify the rate
256			parameters.tcp_rates[0] = (float)flags;
257		}
258		parameters.tcp_numlayers++;
259		parameters.cp_disto_alloc = 1;
260
261		try {
262			// convert the dib to a OpenJPEG image
263			image = FIBITMAPToJ2KImage(s_format_id, dib, &parameters);
264			if(!image) return FALSE;
265
266			// decide if MCT should be used
267			parameters.tcp_mct = (image->numcomps == 3) ? 1 : 0;
268
269			// encode the destination image
270
271			// get a J2K compressor handle
272			cinfo = opj_create_compress(CODEC_JP2);
273
274			// catch events using our callbacks
275			opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, NULL);			
276
277			// setup the encoder parameters using the current image and using user parameters
278			opj_setup_encoder(cinfo, &parameters, image);
279
280			// open a byte stream for writing, allocate memory for all tiles
281			cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
282
283			// encode the image
284			bSuccess = opj_encode(cinfo, cio, image, NULL/*parameters.index*/);
285			if (!bSuccess) {
286				throw "Failed to encode image";
287			}
288			int codestream_length = cio_tell(cio);
289
290			// write the buffer to user's IO handle
291			io->write_proc(cio->buffer, 1, codestream_length, handle);
292
293			// close and free the byte stream 
294			opj_cio_close(cio);
295
296			// free remaining compression structures
297			opj_destroy_compress(cinfo);
298			
299			// free image data
300			opj_image_destroy(image);
301
302			return TRUE;
303
304		} catch (const char *text) {
305			if(cio) opj_cio_close(cio);
306			if(cinfo) opj_destroy_compress(cinfo);
307			if(image) opj_image_destroy(image);
308			FreeImage_OutputMessageProc(s_format_id, text);
309			return FALSE;
310		}
311	}
312
313	return FALSE;
314}
315
316// ==========================================================
317//   Init
318// ==========================================================
319
320void DLL_CALLCONV
321InitJP2(Plugin *plugin, int format_id) {
322	s_format_id = format_id;
323
324	plugin->format_proc = Format;
325	plugin->description_proc = Description;
326	plugin->extension_proc = Extension;
327	plugin->regexpr_proc = RegExpr;
328	plugin->open_proc = Open;
329	plugin->close_proc = Close;
330	plugin->pagecount_proc = NULL;
331	plugin->pagecapability_proc = NULL;
332	plugin->load_proc = Load;
333	plugin->save_proc = Save;
334	plugin->validate_proc = Validate;
335	plugin->mime_proc = MimeType;
336	plugin->supports_export_bpp_proc = SupportsExportDepth;
337	plugin->supports_export_type_proc = SupportsExportType;
338	plugin->supports_icc_profiles_proc = NULL;
339}