Alien-FreeImage

 view release on metacpan or  search on metacpan

src/Source/FreeImage/J2KHelper.cpp  view on Meta::CPAN

// ==========================================================
// JPEG2000 helpers
//
// 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"
#include "J2KHelper.h"

// --------------------------------------------------------------------------

static OPJ_UINT64 
_LengthProc(J2KFIO_t *fio) {
	long start_pos = fio->io->tell_proc(fio->handle);
	fio->io->seek_proc(fio->handle, 0, SEEK_END);
	unsigned file_length = fio->io->tell_proc(fio->handle) - start_pos;
	fio->io->seek_proc(fio->handle, start_pos, SEEK_SET);
	return (OPJ_UINT64)file_length;
}

static OPJ_SIZE_T 
_ReadProc(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) {
	J2KFIO_t *fio = (J2KFIO_t*)p_user_data;
	OPJ_SIZE_T l_nb_read = fio->io->read_proc(p_buffer, 1, (unsigned)p_nb_bytes, fio->handle);
	return l_nb_read ? l_nb_read : (OPJ_SIZE_T)-1;
}

static OPJ_SIZE_T 
_WriteProc(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) {
	J2KFIO_t *fio = (J2KFIO_t*)p_user_data;  
	return fio->io->write_proc(p_buffer, 1, (unsigned)p_nb_bytes, fio->handle);
}

static OPJ_OFF_T 
_SkipProc(OPJ_OFF_T p_nb_bytes, void *p_user_data) {
	J2KFIO_t *fio = (J2KFIO_t*)p_user_data;
	if( fio->io->seek_proc(fio->handle, (long)p_nb_bytes, SEEK_CUR) ) {
		return -1;
	}
	return p_nb_bytes;
}

static OPJ_BOOL 
_SeekProc(OPJ_OFF_T p_nb_bytes, FILE * p_user_data) {
	J2KFIO_t *fio = (J2KFIO_t*)p_user_data;
	if( fio->io->seek_proc(fio->handle, (long)p_nb_bytes, SEEK_SET) ) {
		return OPJ_FALSE;
	}
	return OPJ_TRUE;
}

// --------------------------------------------------------------------------

J2KFIO_t* 
opj_freeimage_stream_create(FreeImageIO *io, fi_handle handle, BOOL bRead) {
	if(!handle) {
		return NULL;
	}
	J2KFIO_t *fio = (J2KFIO_t*)malloc(sizeof(J2KFIO_t));
	if(fio) {
		fio->io = io;
		fio->handle = handle;

		opj_stream_t *l_stream = opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, bRead ? OPJ_TRUE : OPJ_FALSE);
		if (l_stream) {
			opj_stream_set_user_data(l_stream, fio, NULL);
			opj_stream_set_user_data_length(l_stream, _LengthProc(fio));
			opj_stream_set_read_function(l_stream, (opj_stream_read_fn)_ReadProc);
			opj_stream_set_write_function(l_stream, (opj_stream_write_fn)_WriteProc);
			opj_stream_set_skip_function(l_stream, (opj_stream_skip_fn)_SkipProc);
			opj_stream_set_seek_function(l_stream, (opj_stream_seek_fn)_SeekProc);
			fio->stream = l_stream;
			return fio;
		} else {
			free(fio);
		}
	}

	return NULL;		
}

void 
opj_freeimage_stream_destroy(J2KFIO_t* fio) {
	if(fio) {
		if(fio->stream) {
			opj_stream_destroy(fio->stream);
		}
		free(fio);
	}
}

// --------------------------------------------------------------------------

/**
Divide an integer by a power of 2 and round upwards
@return Returns a divided by 2^b
*/
static int int_ceildivpow2(int a, int b) {
	return (a + (1 << b) - 1) >> b;
}

/**
Convert a OpenJPEG image to a FIBITMAP
@param format_id Plugin ID
@param image OpenJPEG image
@param header_only If TRUE, allocate a 'header only' FIBITMAP, otherwise allocate a full FIBITMAP
@return Returns the converted image if successful, returns NULL otherwise
*/
FIBITMAP* J2KImageToFIBITMAP(int format_id, const opj_image_t *image, BOOL header_only) {
	FIBITMAP *dib = NULL;

	try {
		// compute image width and height

		//int w = int_ceildiv(image->x1 - image->x0, image->comps[0].dx);
		int wr = image->comps[0].w;
		int wrr = int_ceildivpow2(image->comps[0].w, image->comps[0].factor);
		
		//int h = int_ceildiv(image->y1 - image->y0, image->comps[0].dy);
		//int hr = image->comps[0].h;
		int hrr = int_ceildivpow2(image->comps[0].h, image->comps[0].factor);

		// check the number of components

		int numcomps = image->numcomps;

		BOOL bIsValid = TRUE;



( run in 0.434 second using v1.01-cache-2.11-cpan-119454b85a5 )