opj_image_t* ossimOpjCompressor::createOpjImage( ossimScalarType scalar, ossim_uint32 bands, const ossimIrect& imageRect ) const { opj_image_t* image = 0; // image component definitions: opj_image_cmptparm_t* imageParams = new opj_image_cmptparm_t[bands]; opj_image_cmptparm_t* imageParam = imageParams; for (ossim_uint32 i = 0; i < bands; ++i) { imageParam->dx = 1; imageParam->dy = 1; imageParam->h = imageRect.height(); imageParam->w = imageRect.width(); imageParam->sgnd = (OPJ_UINT32)ossim::isSigned(scalar); imageParam->prec = ossim::getActualBitsPerPixel(scalar); imageParam->bpp = ossim::getBitsPerPixel(scalar); imageParam->x0 = 0; imageParam->y0 = 0; ++imageParam; } OPJ_COLOR_SPACE clrspc; if ( bands == 3 ) { clrspc = OPJ_CLRSPC_SRGB; } else // if ( bands == 1 ) { // Anything other than 3 band. Not sure if this is correct way yet?(drb) clrspc = OPJ_CLRSPC_GRAY; } if ( clrspc != OPJ_CLRSPC_UNKNOWN ) { image = opj_image_tile_create( bands, imageParams, clrspc ); if ( image ) { image->x0 = 0; image->y0 = 0; image->x1 = imageRect.width(); image->y1 = imageRect.height(); image->color_space = clrspc; } } delete [] imageParams; imageParams = 0; if ( traceDebug() ) { ossimNotify(ossimNotifyLevel_DEBUG) << "ossimOpjCompressor::createOpjImage DEBUG:\n"; if ( image ) { ossim::print( ossimNotify(ossimNotifyLevel_DEBUG), *image ); } else { ossimNotify(ossimNotifyLevel_WARN) << "ossimOpjCompressor::createOpjImage DEBUG image not created!" << std::endl; } } return image; } // End: ossimOpjCompressor::createOpjImage( ... )
int main (int argc, char *argv[]) { opj_cparameters_t l_param; opj_codec_t * l_codec; opj_image_t * l_image; opj_image_cmptparm_t l_params [NUM_COMPS_MAX]; opj_stream_t * l_stream; OPJ_UINT32 l_nb_tiles; OPJ_UINT32 l_data_size; unsigned char len; #ifdef USING_MCT const OPJ_FLOAT32 l_mct [] = { 1 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 }; const OPJ_INT32 l_offsets [] = { 128 , 128 , 128 }; #endif opj_image_cmptparm_t * l_current_param_ptr; OPJ_UINT32 i; OPJ_BYTE *l_data; OPJ_UINT32 num_comps; int image_width; int image_height; int tile_width; int tile_height; int comp_prec; int irreversible; char output_file[64]; /* should be test_tile_encoder 3 2000 2000 1000 1000 8 tte1.j2k */ if( argc == 9 ) { num_comps = (OPJ_UINT32)atoi( argv[1] ); image_width = atoi( argv[2] ); image_height = atoi( argv[3] ); tile_width = atoi( argv[4] ); tile_height = atoi( argv[5] ); comp_prec = atoi( argv[6] ); irreversible = atoi( argv[7] ); strcpy(output_file, argv[8] ); } else { num_comps = 3; image_width = 2000; image_height = 2000; tile_width = 1000; tile_height = 1000; comp_prec = 8; irreversible = 1; strcpy(output_file, "test.j2k" ); } if( num_comps > NUM_COMPS_MAX ) { return 1; } l_nb_tiles = (OPJ_UINT32)(image_width/tile_width) * (OPJ_UINT32)(image_height/tile_height); l_data_size = (OPJ_UINT32)tile_width * (OPJ_UINT32)tile_height * (OPJ_UINT32)num_comps * (OPJ_UINT32)(comp_prec/8); l_data = (OPJ_BYTE*) malloc(l_data_size * sizeof(OPJ_BYTE)); fprintf(stdout, "Encoding random values -> keep in mind that this is very hard to compress\n"); for (i=0;i<l_data_size;++i) { l_data[i] = (OPJ_BYTE)i; /*rand();*/ } opj_set_default_encoder_parameters(&l_param); /** you may here add custom encoding parameters */ /* rate specifications */ /** number of quality layers in the stream */ l_param.tcp_numlayers = 1; l_param.cp_fixed_quality = 1; l_param.tcp_distoratio[0] = 20; /* is using others way of calculation */ /* l_param.cp_disto_alloc = 1 or l_param.cp_fixed_alloc = 1 */ /* l_param.tcp_rates[0] = ... */ /* tile definitions parameters */ /* position of the tile grid aligned with the image */ l_param.cp_tx0 = 0; l_param.cp_ty0 = 0; /* tile size, we are using tile based encoding */ l_param.tile_size_on = OPJ_TRUE; l_param.cp_tdx = tile_width; l_param.cp_tdy = tile_height; /* use irreversible encoding ?*/ l_param.irreversible = irreversible; /* do not bother with mct, the rsiz is set when calling opj_set_MCT*/ /*l_param.cp_rsiz = OPJ_STD_RSIZ;*/ /* no cinema */ /*l_param.cp_cinema = 0;*/ /* no not bother using SOP or EPH markers, do not use custom size precinct */ /* number of precincts to specify */ /* l_param.csty = 0;*/ /* l_param.res_spec = ... */ /* l_param.prch_init[i] = .. */ /* l_param.prcw_init[i] = .. */ /* do not use progression order changes */ /*l_param.numpocs = 0;*/ /* l_param.POC[i].... */ /* do not restrain the size for a component.*/ /* l_param.max_comp_size = 0; */ /** block encoding style for each component, do not use at the moment */ /** J2K_CCP_CBLKSTY_TERMALL, J2K_CCP_CBLKSTY_LAZY, J2K_CCP_CBLKSTY_VSC, J2K_CCP_CBLKSTY_SEGSYM, J2K_CCP_CBLKSTY_RESET */ /* l_param.mode = 0;*/ /** number of resolutions */ l_param.numresolution = 6; /** progression order to use*/ /** OPJ_LRCP, OPJ_RLCP, OPJ_RPCL, PCRL, CPRL */ l_param.prog_order = OPJ_LRCP; /** no "region" of interest, more precisally component */ /* l_param.roi_compno = -1; */ /* l_param.roi_shift = 0; */ /* we are not using multiple tile parts for a tile. */ /* l_param.tp_on = 0; */ /* l_param.tp_flag = 0; */ /* if we are using mct */ #ifdef USING_MCT opj_set_MCT(&l_param,l_mct,l_offsets,NUM_COMPS); #endif /* image definition */ l_current_param_ptr = l_params; for (i=0;i<num_comps;++i) { /* do not bother bpp useless */ /*l_current_param_ptr->bpp = COMP_PREC;*/ l_current_param_ptr->dx = 1; l_current_param_ptr->dy = 1; l_current_param_ptr->h = (OPJ_UINT32)image_height; l_current_param_ptr->w = (OPJ_UINT32)image_width; l_current_param_ptr->sgnd = 0; l_current_param_ptr->prec = (OPJ_UINT32)comp_prec; l_current_param_ptr->x0 = 0; l_current_param_ptr->y0 = 0; ++l_current_param_ptr; } /* should we do j2k or jp2 ?*/ len = (unsigned char)strlen( output_file ); if( strcmp( output_file + len - 4, ".jp2" ) == 0 ) { l_codec = opj_create_compress(OPJ_CODEC_JP2); } else { l_codec = opj_create_compress(OPJ_CODEC_J2K); } if (!l_codec) { return 1; } /* catch events using our callbacks and give a local context */ opj_set_info_handler(l_codec, info_callback,00); opj_set_warning_handler(l_codec, warning_callback,00); opj_set_error_handler(l_codec, error_callback,00); l_image = opj_image_tile_create(num_comps,l_params,OPJ_CLRSPC_SRGB); if (! l_image) { opj_destroy_codec(l_codec); return 1; } l_image->x0 = 0; l_image->y0 = 0; l_image->x1 = (OPJ_UINT32)image_width; l_image->y1 = (OPJ_UINT32)image_height; l_image->color_space = OPJ_CLRSPC_SRGB; if (! opj_setup_encoder(l_codec,&l_param,l_image)) { fprintf(stderr, "ERROR -> test_tile_encoder: failed to setup the codec!\n"); opj_destroy_codec(l_codec); opj_image_destroy(l_image); return 1; } l_stream = opj_stream_create_default_file_stream_v3(output_file, OPJ_FALSE); if (! l_stream) { fprintf(stderr, "ERROR -> test_tile_encoder: failed to create the stream from the output file %s !\n",output_file ); opj_destroy_codec(l_codec); opj_image_destroy(l_image); return 1; } if (! opj_start_compress(l_codec,l_image,l_stream)) { fprintf(stderr, "ERROR -> test_tile_encoder: failed to start compress!\n"); opj_stream_destroy_v3(l_stream); opj_destroy_codec(l_codec); opj_image_destroy(l_image); return 1; } for (i=0;i<l_nb_tiles;++i) { if (! opj_write_tile(l_codec,i,l_data,l_data_size,l_stream)) { fprintf(stderr, "ERROR -> test_tile_encoder: failed to write the tile %d!\n",i); opj_stream_destroy_v3(l_stream); opj_destroy_codec(l_codec); opj_image_destroy(l_image); return 1; } } if (! opj_end_compress(l_codec,l_stream)) { fprintf(stderr, "ERROR -> test_tile_encoder: failed to end compress!\n"); opj_stream_destroy_v3(l_stream); opj_destroy_codec(l_codec); opj_image_destroy(l_image); return 1; } opj_stream_destroy_v3(l_stream); opj_destroy_codec(l_codec); opj_image_destroy(l_image); free(l_data); /* Print profiling*/ /*PROFPRINT();*/ return 0; }
J2KPRIV( NRT_BOOL) OpenJPEG_initImage(OpenJPEGWriterImpl *impl, j2k_WriterOptions *writerOps, nrt_Error *error) { NRT_BOOL rc = NRT_SUCCESS; nrt_Uint32 i, nComponents, height, width, tileHeight, tileWidth; nrt_Uint32 nBytes; j2k_Component *component = NULL; size_t uncompressedSize; int imageType; opj_cparameters_t encoderParams; opj_image_cmptparm_t *cmptParams; OPJ_COLOR_SPACE colorSpace; nComponents = j2k_Container_getNumComponents(impl->container, error); width = j2k_Container_getWidth(impl->container, error); height = j2k_Container_getHeight(impl->container, error); tileWidth = j2k_Container_getTileWidth(impl->container, error); tileHeight = j2k_Container_getTileHeight(impl->container, error); imageType = j2k_Container_getImageType(impl->container, error); /* Set up the encoder parameters. This defaults to lossless. */ /* TODO allow overrides somehow? */ opj_set_default_encoder_parameters(&encoderParams); /* For now we are enforcing lossless compression. If we have a better * way to allow overrides in the future, uncomment out the tcp_rates logic * below (tcp_rates[0] == 0 via opj_set_default_encoder_parameters()). * Also consider setting encoderParams.irreversible = 1; to use the * lossy DWT 9-7 instead of the reversible 5-3. */ /*if (writerOps && writerOps->compressionRatio > 0.0001) encoderParams.tcp_rates[0] = 1.0 / writerOps->compressionRatio; else encoderParams.tcp_rates[0] = 4.0; */ /* TODO: These two lines should not be necessary when using lossless * encoding but appear to be needed (at least in OpenJPEG 2.0) - * otherwise we get a seg fault. * The sample opj_compress.c is doing the same thing with a comment * indicating that it's a bug. */ ++encoderParams.tcp_numlayers; encoderParams.cp_disto_alloc = 1; if (writerOps && writerOps->numResolutions > 0) { encoderParams.numresolution = writerOps->numResolutions; /* Note, if this isn't set right (see below) it will error out */ } else { /* OpenJPEG defaults this to 6, but that causes the compressor to fail if the tile sizes are less than 2^6. So we adjust this down if necessary. */ const double logTwo = log(2); const OPJ_UINT32 minX = (OPJ_UINT32)floor(log(tileWidth) / logTwo); const OPJ_UINT32 minY = (OPJ_UINT32)floor(log(tileHeight) / logTwo); const OPJ_UINT32 minXY = (minX < minY) ? minX : minY; if (minXY < encoderParams.numresolution) { encoderParams.numresolution = minXY; } } /* Turn on tiling */ encoderParams.tile_size_on = 1; encoderParams.cp_tx0 = 0; encoderParams.cp_ty0 = 0; encoderParams.cp_tdx = tileWidth; encoderParams.cp_tdy = tileHeight; if (!(cmptParams = (opj_image_cmptparm_t*)J2K_MALLOC(sizeof( opj_image_cmptparm_t) * nComponents))) { nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT, NRT_ERR_MEMORY); goto CATCH_ERROR; } memset(cmptParams, 0, sizeof(opj_image_cmptparm_t) * nComponents); for(i = 0; i < nComponents; ++i) { component = j2k_Container_getComponent(impl->container, i, error); cmptParams[i].w = j2k_Component_getWidth(component, error); cmptParams[i].h = j2k_Component_getHeight(component, error); cmptParams[i].prec = j2k_Component_getPrecision(component, error); cmptParams[i].x0 = j2k_Component_getOffsetX(component, error); cmptParams[i].y0 = j2k_Component_getOffsetY(component, error); cmptParams[i].dx = j2k_Component_getSeparationX(component, error); cmptParams[i].dy = j2k_Component_getSeparationY(component, error); cmptParams[i].sgnd = j2k_Component_isSigned(component, error); } nBytes = (j2k_Container_getPrecision(impl->container, error) - 1) / 8 + 1; uncompressedSize = width * height * nComponents * nBytes; /* this is not ideal, but there is really no other way */ if (!(impl->compressedBuf = (char*)J2K_MALLOC(uncompressedSize))) { nrt_Error_init(error, NRT_STRERROR(NRT_ERRNO), NRT_CTXT, NRT_ERR_MEMORY); goto CATCH_ERROR; } if (!(impl->compressed = nrt_BufferAdapter_construct(impl->compressedBuf, uncompressedSize, 1, error))) { goto CATCH_ERROR; } if (!(impl->stream = OpenJPEG_createIO(impl->compressed, &impl->userData, 0, 0, error))) { goto CATCH_ERROR; } switch(imageType) { case J2K_TYPE_RGB: colorSpace = OPJ_CLRSPC_SRGB; break; default: colorSpace = OPJ_CLRSPC_GRAY; } if (!(impl->codec = opj_create_compress(OPJ_CODEC_J2K))) { nrt_Error_init(error, "Error creating OpenJPEG codec", NRT_CTXT, NRT_ERR_INVALID_OBJECT); goto CATCH_ERROR; } if (!(impl->image = opj_image_tile_create(nComponents, cmptParams, colorSpace))) { nrt_Error_init(error, "Error creating OpenJPEG image", NRT_CTXT, NRT_ERR_INVALID_OBJECT); goto CATCH_ERROR; } /* for some reason we must also explicitly specify these in the image... */ impl->image->numcomps = nComponents; impl->image->x0 = 0; impl->image->y0 = 0; impl->image->x1 = width; impl->image->y1 = height; impl->image->color_space = colorSpace; memset(error->message, 0, NRT_MAX_EMESSAGE); if(!opj_set_error_handler(impl->codec, OpenJPEG_errorHandler, error)) { nrt_Error_init(error, "Unable to set OpenJPEG error handler", NRT_CTXT, NRT_ERR_UNK); goto CATCH_ERROR; } if (!opj_setup_encoder(impl->codec, &encoderParams, impl->image)) { /*nrt_Error_init(error, "Error setting up OpenJPEG decoder", NRT_CTXT, NRT_ERR_INVALID_OBJECT);*/ goto CATCH_ERROR; } if (!opj_start_compress(impl->codec, impl->image, impl->stream)) { /*nrt_Error_init(error, "Error starting OpenJPEG compression", NRT_CTXT, NRT_ERR_INVALID_OBJECT);*/ goto CATCH_ERROR; } goto CLEANUP; CATCH_ERROR: { rc = NRT_FAILURE; } CLEANUP: { if (cmptParams) J2K_FREE(cmptParams); } return rc; }