diff --git a/bin/openjpeg-dotnet.dll b/bin/openjpeg-dotnet.dll index ad6a14b1..50a6b454 100644 Binary files a/bin/openjpeg-dotnet.dll and b/bin/openjpeg-dotnet.dll differ diff --git a/openjpeg-dotnet/dotnet/dotnet.cpp b/openjpeg-dotnet/dotnet/dotnet.cpp index a1e998fc..e3c78745 100644 --- a/openjpeg-dotnet/dotnet/dotnet.cpp +++ b/openjpeg-dotnet/dotnet/dotnet.cpp @@ -7,102 +7,15 @@ extern "C" { #include -struct image_wrapper -{ - opj_image* image; - - image_wrapper(int numcmpts, opj_image_cmptparm_t* cmptparms, OPJ_COLOR_SPACE clrspc) - { - image = opj_image_create(numcmpts, cmptparms, clrspc); - - if (image == NULL) - throw "opj_image_create failed"; - } - - image_wrapper(opj_dinfo* dinfo, opj_cio* cio) - { - image = opj_decode(dinfo,cio); - - if (image == NULL) - throw "opj_decode failed"; - } - - ~image_wrapper() - { - opj_image_destroy(image); - } -}; - -struct cinfo_wrapper -{ - opj_cinfo* cinfo; - - cinfo_wrapper(CODEC_FORMAT format) - { - cinfo = opj_create_compress(format); - - if (cinfo == NULL) - throw "opj_create_compress failed"; - } - - ~cinfo_wrapper() - { - opj_destroy_compress(cinfo); - } -}; - -struct dinfo_wrapper -{ - opj_dinfo* dinfo; - - dinfo_wrapper(CODEC_FORMAT format) - { - dinfo = opj_create_decompress(format); - - if (dinfo == NULL) - throw "opj_create_decompress failed"; - } - - ~dinfo_wrapper() - { - opj_destroy_decompress(dinfo); - } -}; - -struct cio_wrapper -{ - opj_cio* cio; - - cio_wrapper(opj_cinfo* cinfo, unsigned char* buffer, int length) - { - cio = opj_cio_open((opj_common_ptr)cinfo,buffer,length); - - if (cio == NULL) - throw "opj_cio_open failed"; - } - - cio_wrapper(opj_dinfo* dinfo, unsigned char* buffer, int length) - { - cio = opj_cio_open((opj_common_ptr)dinfo,buffer,length); - - if (cio == NULL) - throw "opj_cio_open failed"; - } - - ~cio_wrapper() - { - opj_cio_close(cio); - } -}; - bool DotNetAllocEncoded(MarshalledImage* image) { + DotNetFree(image); + try { image->encoded = new unsigned char[image->length]; image->decoded = 0; } - catch (...) { return false; @@ -113,12 +26,13 @@ bool DotNetAllocEncoded(MarshalledImage* image) bool DotNetAllocDecoded(MarshalledImage* image) { + DotNetFree(image); + try { image->decoded = new unsigned char[image->width * image->height * image->components]; image->encoded = 0; } - catch (...) { return false; @@ -179,27 +93,36 @@ bool DotNetEncode(MarshalledImage* image, bool lossless) comptparm[i].h = image->height; } - image_wrapper cimage(image->components,comptparm,CLRSPC_SRGB); - cimage.image->x0 = 0; - cimage.image->y0 = 0; - cimage.image->x1 = image->width; - cimage.image->y1 = image->height; + opj_image_t* jp2_image = opj_image_create(image->components, comptparm, CLRSPC_SRGB); + if (image == NULL) + throw "opj_image_create failed"; + + jp2_image->x0 = 0; + jp2_image->y0 = 0; + jp2_image->x1 = image->width; + jp2_image->y1 = image->height; int n = image->width * image->height; for (int i = 0; i < image->components; i++) - std::copy(image->decoded+i*n,image->decoded+(i+1)*n,cimage.image->comps[i].data); + std::copy(image->decoded + i * n, image->decoded + (i + 1) * n, jp2_image->comps[i].data); - cinfo_wrapper cinfo(CODEC_J2K); - opj_setup_encoder(cinfo.cinfo,&cparameters,cimage.image); - cio_wrapper cio(cinfo.cinfo,NULL,0); + opj_cinfo* cinfo = opj_create_compress(CODEC_J2K); + opj_setup_encoder(cinfo, &cparameters, jp2_image); + opj_cio* cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0); + if (cio == NULL) + throw "opj_cio_open failed"; - if (!opj_encode(cinfo.cinfo,cio.cio,cimage.image,cparameters.index)) + if (!opj_encode(cinfo, cio, jp2_image, cparameters.index)) return false; - image->length = cio_tell(cio.cio); + image->length = cio_tell(cio); image->encoded = new unsigned char[image->length]; - std::copy(cio.cio->buffer,cio.cio->buffer+image->length,image->encoded); + std::copy(cio->buffer, cio->buffer + image->length, image->encoded); + opj_image_destroy(jp2_image); + opj_destroy_compress(cinfo); + opj_cio_close(cio); + return true; } @@ -216,23 +139,78 @@ bool DotNetDecode(MarshalledImage* image) try { opj_set_default_decoder_parameters(&dparameters); - dinfo_wrapper dinfo(CODEC_J2K); - opj_setup_decoder(dinfo.dinfo, &dparameters); - cio_wrapper cio(dinfo.dinfo,image->encoded,image->length); - image_wrapper cimage(dinfo.dinfo, cio.cio); // decode happens here + opj_dinfo_t* dinfo = opj_create_decompress(CODEC_J2K); + opj_setup_decoder(dinfo, &dparameters); + opj_cio* cio = opj_cio_open((opj_common_ptr)dinfo, image->encoded, image->length); - image->width = cimage.image->x1 - cimage.image->x0; - image->height = cimage.image->y1 - cimage.image->y0; - image->components = cimage.image->numcomps; + opj_image* jp2_image = opj_decode(dinfo, cio); // decode happens here + if (image == NULL) + throw "opj_decode failed"; + + image->width = jp2_image->x1 - jp2_image->x0; + image->height = jp2_image->y1 - jp2_image->y0; + image->components = jp2_image->numcomps; int n = image->width * image->height; - image->decoded = new unsigned char[n*image->components]; + image->decoded = new unsigned char[n * image->components]; for (int i = 0; i < image->components; i++) - std::copy(cimage.image->comps[i].data,cimage.image->comps[i].data+n,image->decoded+i*n); + std::copy(jp2_image->comps[i].data, jp2_image->comps[i].data + n, image->decoded + i * n); + + opj_image_destroy(jp2_image); + opj_destroy_decompress(dinfo); + opj_cio_close(cio); + + return true; + } + catch (...) + { + return false; + } +} + +bool DotNetDecodeWithInfo(MarshalledImage* image) +{ + opj_dparameters dparameters; + opj_codestream_info_t info; + + try + { + opj_set_default_decoder_parameters(&dparameters); + opj_dinfo_t* dinfo = opj_create_decompress(CODEC_J2K); + opj_setup_decoder(dinfo, &dparameters); + opj_cio* cio = opj_cio_open((opj_common_ptr)dinfo, image->encoded, image->length); + + opj_image* jp2_image = opj_decode_with_info(dinfo, cio, &info); // decode happens here + if (image == NULL) + throw "opj_decode failed"; + + // maximum number of decompositions + int max_numdecompos = 0; + for (int compno = 0; compno < info.numcomps; compno++) + { + if (max_numdecompos < info.numdecompos[compno]) + max_numdecompos = info.numdecompos[compno]; + } + + image->width = jp2_image->x1 - jp2_image->x0; + image->height = jp2_image->y1 - jp2_image->y0; + image->layers = info.numlayers; + image->resolutions = max_numdecompos + 1; + image->components = info.numcomps; + image->packet_count = info.packno; + image->packets = info.tile->packet; + int n = image->width * image->height; + image->decoded = new unsigned char[n * image->components]; + + for (int i = 0; i < image->components; i++) + std::copy(jp2_image->comps[i].data, jp2_image->comps[i].data + n, image->decoded + i * n); + + opj_image_destroy(jp2_image); + opj_destroy_decompress(dinfo); + opj_cio_close(cio); return true; } - catch (...) { return false; diff --git a/openjpeg-dotnet/dotnet/dotnet.h b/openjpeg-dotnet/dotnet/dotnet.h index c9e4b8b7..122405bb 100644 --- a/openjpeg-dotnet/dotnet/dotnet.h +++ b/openjpeg-dotnet/dotnet/dotnet.h @@ -1,8 +1,9 @@ - #ifndef LIBSL_H #define LIBSL_H +#include "../libopenjpeg/openjpeg.h" + struct MarshalledImage { unsigned char* encoded; @@ -12,7 +13,11 @@ struct MarshalledImage unsigned char* decoded; int width; int height; + int layers; + int resolutions; int components; + int packet_count; + opj_packet_info_t* packets; }; #ifdef WIN32 @@ -24,6 +29,7 @@ struct MarshalledImage // uncompresed images are raw RGBA 8bit/channel DLLEXPORT bool DotNetEncode(MarshalledImage* image, bool lossless); DLLEXPORT bool DotNetDecode(MarshalledImage* image); +DLLEXPORT bool DotNetDecodeWithInfo(MarshalledImage* image); DLLEXPORT bool DotNetAllocEncoded(MarshalledImage* image); DLLEXPORT bool DotNetAllocDecoded(MarshalledImage* image); DLLEXPORT void DotNetFree(MarshalledImage* image);