X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmJpeg2000.cxx;h=3e65fed2809920783620bd74a6fc6626fd97dcb2;hb=b06cbd9177331d793223eac6bf8b2bccf874e7e3;hp=ed0f09f2d19e9a808ccb09c82fdd38f80e8e629c;hpb=8fd45dc6d321d1419854dc0e4fa6a37d6826b655;p=gdcm.git diff --git a/src/gdcmJpeg2000.cxx b/src/gdcmJpeg2000.cxx index ed0f09f2..3e65fed2 100644 --- a/src/gdcmJpeg2000.cxx +++ b/src/gdcmJpeg2000.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmJpeg2000.cxx,v $ Language: C++ - Date: $Date: 2007/05/23 14:18:10 $ - Version: $Revision: 1.43 $ + Date: $Date: 2007/08/22 16:14:04 $ + Version: $Revision: 1.45 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -59,6 +59,24 @@ namespace GDCM_NAME_SPACE * @return 1 on success, 0 on error */ +/** +sample error callback expecting a FILE* client object +*/ +void error_callback(const char *msg, void *) { + std::cerr << "Error in gdcmopenjpeg" << msg << std::endl; +} +/** +sample warning callback expecting a FILE* client object +*/ +void warning_callback(const char *msg, void *) { + std::cerr << "Warning in gdcmopenjpeg" << msg << std::endl; +} +/** +sample debug callback expecting no client object +*/ +void info_callback(const char *msg, void *) { + std::cerr << "Info in gdcmopenjpeg" << msg << std::endl; +} #define J2K_CFMT 0 #define JP2_CFMT 1 @@ -89,7 +107,7 @@ bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength) opj_dinfo_t* dinfo; /* handle to a decompressor */ opj_cio_t *cio; unsigned char *src = (unsigned char*)inputdata; - int file_length = inputlength; + int file_length = static_cast< int >( inputlength ); /* configure the event callbacks (not required) */ memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); @@ -114,9 +132,9 @@ bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength) /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_J2K); - + /* catch events using our callbacks and give a local context */ - opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL); + opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); @@ -142,43 +160,46 @@ bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength) for (int compno = 0; compno < image->numcomps; compno++) { opj_image_comp_t *comp = &image->comps[compno]; - + int w = image->comps[compno].w; int wr = int_ceildivpow2(image->comps[compno].w, image->comps[compno].factor); - + //int h = image.comps[compno].h; int hr = int_ceildivpow2(image->comps[compno].h, image->comps[compno].factor); - + if (comp->prec <= 8) { - uint8_t *data8 = (uint8_t*)raw; - for (int i = 0; i < wr * hr; i++) + uint8_t *data8 = (uint8_t*)raw + compno; + for (int i = 0; i < wr * hr; i++) { int v = image->comps[compno].data[i / wr * w + i % wr]; - *data8++ = (uint8_t)v; + *data8 = (uint8_t)v; + data8 += image->numcomps; } } else if (comp->prec <= 16) { - uint16_t *data16 = (uint16_t*)raw; - for (int i = 0; i < wr * hr; i++) + uint16_t *data16 = (uint16_t*)raw + compno; + for (int i = 0; i < wr * hr; i++) { int v = image->comps[compno].data[i / wr * w + i % wr]; - *data16++ = (uint16_t)v; + *data16 = (uint16_t)v; + data16 += image->numcomps; } } else { - uint32_t *data32 = (uint32_t*)raw; - for (int i = 0; i < wr * hr; i++) + uint32_t *data32 = (uint32_t*)raw + compno; + for (int i = 0; i < wr * hr; i++) { int v = image->comps[compno].data[i / wr * w + i % wr]; - *data32++ = (uint32_t)v; + *data32 = (uint32_t)v; + data32 += image->numcomps; } } //free(image.comps[compno].data); } - + /* free remaining structures */ if(dinfo) { @@ -188,6 +209,247 @@ bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength) /* free image data structure */ opj_image_destroy(image); + return true; +} + +template +void rawtoimage_fill(T *inputbuffer, int w, int h, int numcomps, opj_image_t *image) +{ + T *p = inputbuffer; + for (int i = 0; i < w * h; i++) + { + for(int compno = 0; compno < numcomps; compno++) + { + /* compno : 0 = GREY, (0, 1, 2) = (R, G, B) */ + image->comps[compno].data[i] = *p; + ++p; + } + } +} + +opj_image_t* rawtoimage(char *inputbuffer, opj_cparameters_t *parameters, + int fragment_size, int image_width, int image_height, int sample_pixel, + int bitsallocated, int sign, int quality) +{ + (void)quality; + (void)fragment_size; + int w, h; + int numcomps; + OPJ_COLOR_SPACE color_space; + opj_image_cmptparm_t cmptparm[3]; /* maximum of 3 components */ + opj_image_t * image = NULL; + + assert( sample_pixel == 1 || sample_pixel == 3 ); + if( sample_pixel == 1 ) + { + numcomps = 1; + color_space = CLRSPC_GRAY; + } + else // sample_pixel == 3 + { + numcomps = 3; + color_space = CLRSPC_SRGB; + } + int subsampling_dx = parameters->subsampling_dx; + int subsampling_dy = parameters->subsampling_dy; + + // FIXME + w = image_width; + h = image_height; + + /* initialize image components */ + memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t)); + //assert( bitsallocated == 8 ); + for(int i = 0; i < numcomps; i++) { + cmptparm[i].prec = bitsallocated; + cmptparm[i].bpp = bitsallocated; + cmptparm[i].sgnd = sign; + cmptparm[i].dx = subsampling_dx; + cmptparm[i].dy = subsampling_dy; + cmptparm[i].w = w; + cmptparm[i].h = h; + } + + /* create the image */ + image = opj_image_create(numcomps, &cmptparm[0], color_space); + if(!image) { + return NULL; + } + /* set image offset and reference grid */ + image->x0 = parameters->image_offset_x0; + image->y0 = parameters->image_offset_y0; + image->x1 = parameters->image_offset_x0 + (w - 1) * subsampling_dx + 1; + image->y1 = parameters->image_offset_y0 + (h - 1) * subsampling_dy + 1; + + /* set image data */ + + //assert( fragment_size == numcomps*w*h*(bitsallocated/8) ); + if (bitsallocated <= 8) + { + if( sign ) + { + rawtoimage_fill((int8_t*)inputbuffer,w,h,numcomps,image); + } + else + { + rawtoimage_fill((uint8_t*)inputbuffer,w,h,numcomps,image); + } + } + else if (bitsallocated <= 16) + { + if( sign ) + { + rawtoimage_fill((int16_t*)inputbuffer,w,h,numcomps,image); + } + else + { + rawtoimage_fill((uint16_t*)inputbuffer,w,h,numcomps,image); + } + } + else if (bitsallocated <= 32) + { + if( sign ) + { + rawtoimage_fill((int32_t*)inputbuffer,w,h,numcomps,image); + } + else + { + rawtoimage_fill((uint32_t*)inputbuffer,w,h,numcomps,image); + } + } + else + { + abort(); + } + + return image; +} + +/* + * The following function was copy paste from image_to_j2k.c with part from convert.c + */ +bool gdcm_write_JPEG2000_file (std::ostream *fp, char *inputdata, size_t inputlength, + int image_width, int image_height, int numZ, int sample_pixel, int bitsallocated, + int sign, int quality) +{ +//// input_buffer is ONE image +//// fragment_size is the size of this image (fragment) + (void)numZ; + bool bSuccess; + //bool delete_comment = true; + opj_cparameters_t parameters; /* compression parameters */ + opj_event_mgr_t event_mgr; /* event manager */ + opj_image_t *image = NULL; + //quality = 100; + + /* + configure the event callbacks (not required) + setting of each callback is optionnal + */ + memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); + event_mgr.error_handler = error_callback; + event_mgr.warning_handler = warning_callback; + event_mgr.info_handler = info_callback; + + /* set encoding parameters to default values */ + memset(¶meters, 0, sizeof(parameters)); + opj_set_default_encoder_parameters(¶meters); + + /* if no rate entered, lossless by default */ + parameters.tcp_rates[0] = 0; + parameters.tcp_numlayers = 1; + parameters.cp_disto_alloc = 1; + + if(parameters.cp_comment == NULL) { + const char comment[] = "Created by GDCM/OpenJPEG version 1.0"; + parameters.cp_comment = (char*)malloc(strlen(comment) + 1); + strcpy(parameters.cp_comment, comment); + /* no need to delete parameters.cp_comment on exit */ + //delete_comment = false; + } + + + /* decode the source image */ + /* ----------------------- */ + + image = rawtoimage((char*)inputdata, ¶meters, + static_cast( inputlength ), + image_width, image_height, + sample_pixel, bitsallocated, sign, quality); + if (!image) { + return 1; + } + + /* encode the destination image */ + /* ---------------------------- */ + parameters.cod_format = J2K_CFMT; /* J2K format output */ + int codestream_length; + opj_cio_t *cio = NULL; + //FILE *f = NULL; + + /* get a J2K compressor handle */ + opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K); + + /* catch events using our callbacks and give a local context */ + opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr); + + /* 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, parameters.index); + if (!bSuccess) { + opj_cio_close(cio); + fprintf(stderr, "failed to encode image\n"); + return 1; + } + codestream_length = cio_tell(cio); + + /* write the buffer to disk */ + //f = fopen(parameters.outfile, "wb"); + //if (!f) { + // fprintf(stderr, "failed to open %s for writing\n", parameters.outfile); + // return 1; + //} + //fwrite(cio->buffer, 1, codestream_length, f); +//#define MDEBUG +#ifdef MDEBUG + static int c = 0; + std::ostringstream os; + os << "/tmp/debug"; + os << c; + c++; + os << ".j2k"; + std::ofstream debug(os.str().c_str()); + debug.write((char*)(cio->buffer), codestream_length); + debug.close(); +#endif + fp->write((char*)(cio->buffer), codestream_length); + //fclose(f); + + /* close and free the byte stream */ + opj_cio_close(cio); + + /* free remaining compression structures */ + opj_destroy_compress(cinfo); + + + /* free user parameters structure */ + //if(delete_comment) { + if(parameters.cp_comment) free(parameters.cp_comment); + //} + if(parameters.cp_matrice) free(parameters.cp_matrice); + + /* free image data */ + opj_image_destroy(image); + + + + return true; }