void J2KReader::decode(bool headeronly) { if( !_fileData || !_dataLength ) { BOOST_THROW_EXCEPTION( exception::Bug() << exception::dev( "Need to open the file before decoding." ) ); } opj_dparameters_t parameters; // decompression parameters opj_dinfo_t *dinfo = NULL; // handle to a decompressor opj_cio_t *cio = NULL; _openjpeg.event_mgr.error_handler = NULL; _openjpeg.event_mgr.warning_handler = NULL; _openjpeg.event_mgr.info_handler = NULL; opj_set_default_decoder_parameters(¶meters); if (headeronly) { parameters.cp_limit_decoding = LIMIT_TO_MAIN_HEADER; } // Decompress a JPEG-2000 codestream // 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, &_openjpeg.event_mgr, stderr ); // setup the decoder decoding parameters using user parameters opj_setup_decoder(dinfo, ¶meters); if( !dinfo ) { BOOST_THROW_EXCEPTION( exception::Unknown() << exception::dev( "Failed to open decoder for image." ) ); } // open a byte stream cio = opj_cio_open((opj_common_ptr)dinfo, _fileData, _dataLength); if( !cio ) { opj_destroy_decompress( dinfo ); BOOST_THROW_EXCEPTION( exception::Unknown() << exception::dev( "Failed to open decoder for image." ) ); } // Start decoding to get an image if( _openjpeg.image ) { opj_image_destroy( _openjpeg.image ); } _openjpeg.image = opj_decode( dinfo, cio ); // close the byte stream opj_destroy_decompress( dinfo ); opj_cio_close( cio ); if( !_openjpeg.image ) { BOOST_THROW_EXCEPTION( exception::Unknown() << exception::dev( "Failed to decode image." ) ); } }
bool DotNetDecode(MarshalledImage* image) { opj_dparameters dparameters; 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(dinfo, cio); // decode happens here if (jp2_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]; 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; } }
JP2KImage read_jp2k_data(unsigned char* data, int len, int format) { JP2KImage jp; init_jp2k(&jp); opj_dinfo_t* codec = NULL; opj_cio_t* stream = NULL; opj_dparameters_t parameters; opj_set_default_decoder_parameters(¶meters); if (format==JP2K_FMT_J2K) { // JPEG 2000 codestream codec = opj_create_decompress(CODEC_J2K); } else if (format==JP2K_FMT_JP2) { // JPEG 2000 compressed image data codec = opj_create_decompress(CODEC_JP2); } else if (format==JP2K_FMT_JPT) { // JPEG 2000 JPIP codec = opj_create_decompress(CODEC_JPT); } else { print_message("JBXL::readJPEG2KData: ERROR: unknown file format!\n"); jp.state = ERROR_GRAPH_NODATA; return jp; } opj_setup_decoder(codec, ¶meters); stream = opj_cio_open((opj_common_ptr)codec, data, len); jp.image = opj_decode(codec, stream); if (jp.image==NULL) { opj_cio_close(stream); opj_destroy_decompress(codec); jp.state = ERROR_GRAPH_IVDDATA; return jp; } setup_jp2k(&jp); opj_cio_close(stream); opj_destroy_decompress(codec); return jp; }
void JPXStream::close() { if (image != NULL) { opj_image_destroy(image); image = NULL; } if (dinfo != NULL) { opj_destroy_decompress(dinfo); dinfo = NULL; } }
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 (jp2_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; } }
int main(int argc, char **argv) { opj_dparameters_t parameters; /* decompression parameters */ img_fol_t img_fol; opj_event_mgr_t event_mgr; /* event manager */ opj_image_t *image = NULL; FILE *fsrc = NULL; unsigned char *src = NULL; int file_length; int num_images; int i,imageno; dircnt_t *dirptr = NULL; opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ opj_cio_t *cio = NULL; opj_codestream_info_t cstr_info; /* Codestream information structure */ char indexfilename[OPJ_PATH_LEN]; /* index file name */ /* configure the event callbacks (not required) */ 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 decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); /* Initialize indexfilename and img_fol */ *indexfilename = 0; memset(&img_fol,0,sizeof(img_fol_t)); /* parse input and get user encoding parameters */ if(parse_cmdline_decoder(argc, argv, ¶meters,&img_fol, indexfilename) == 1) { return 1; } /* Initialize reading of directory */ if(img_fol.set_imgdir==1){ num_images=get_num_images(img_fol.imgdirpath); dirptr=(dircnt_t*)malloc(sizeof(dircnt_t)); if(dirptr){ dirptr->filename_buf = (char*)malloc(num_images*OPJ_PATH_LEN*sizeof(char)); /* Stores at max 10 image file names*/ dirptr->filename = (char**) malloc(num_images*sizeof(char*)); if(!dirptr->filename_buf){ return 1; } for(i=0;i<num_images;i++){ dirptr->filename[i] = dirptr->filename_buf + i*OPJ_PATH_LEN; } } if(load_images(dirptr,img_fol.imgdirpath)==1){ return 1; } if (num_images==0){ fprintf(stdout,"Folder is empty\n"); return 1; } }else{ num_images=1; } /*Encoding image one by one*/ for(imageno = 0; imageno < num_images ; imageno++) { image = NULL; fprintf(stderr,"\n"); if(img_fol.set_imgdir==1){ if (get_next_file(imageno, dirptr,&img_fol, ¶meters)) { fprintf(stderr,"skipping file...\n"); continue; } } /* read the input file and put it in memory */ /* ---------------------------------------- */ fsrc = fopen(parameters.infile, "rb"); if (!fsrc) { fprintf(stderr, "ERROR -> failed to open %s for reading\n", parameters.infile); return 1; } fseek(fsrc, 0, SEEK_END); file_length = ftell(fsrc); fseek(fsrc, 0, SEEK_SET); src = (unsigned char *) malloc(file_length); if (fread(src, 1, file_length, fsrc) != (size_t)file_length) { free(src); fclose(fsrc); fprintf(stderr, "\nERROR: fread return a number of element different from the expected.\n"); return 1; } fclose(fsrc); /* decode the code-stream */ /* ---------------------- */ switch(parameters.decod_format) { case J2K_CFMT: { /* JPEG-2000 codestream */ /* 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, stderr); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); /* decode the stream and fill the image structure */ if (*indexfilename) /* If need to extract codestream information*/ image = opj_decode_with_info(dinfo, cio, &cstr_info); else image = opj_decode(dinfo, cio); if(!image) { fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); opj_destroy_decompress(dinfo); opj_cio_close(cio); free(src); return 1; } /* close the byte stream */ opj_cio_close(cio); /* Write the index to disk */ if (*indexfilename) { opj_bool bSuccess; bSuccess = write_index_file(&cstr_info, indexfilename); if (bSuccess) { fprintf(stderr, "Failed to output index file\n"); } } } break; case JP2_CFMT: { /* JPEG 2000 compressed image data */ /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_JP2); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); /* setup the decoder decoding parameters using the current image and user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); /* decode the stream and fill the image structure */ if (*indexfilename) /* If need to extract codestream information*/ image = opj_decode_with_info(dinfo, cio, &cstr_info); else image = opj_decode(dinfo, cio); if(!image) { fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); opj_destroy_decompress(dinfo); opj_cio_close(cio); free(src); return 1; } /* close the byte stream */ opj_cio_close(cio); /* Write the index to disk */ if (*indexfilename) { opj_bool bSuccess; bSuccess = write_index_file(&cstr_info, indexfilename); if (bSuccess) { fprintf(stderr, "Failed to output index file\n"); } } } break; case JPT_CFMT: { /* JPEG 2000, JPIP */ /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_JPT); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); /* decode the stream and fill the image structure */ if (*indexfilename) /* If need to extract codestream information*/ image = opj_decode_with_info(dinfo, cio, &cstr_info); else image = opj_decode(dinfo, cio); if(!image) { fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); opj_destroy_decompress(dinfo); opj_cio_close(cio); free(src); return 1; } /* close the byte stream */ opj_cio_close(cio); /* Write the index to disk */ if (*indexfilename) { opj_bool bSuccess; bSuccess = write_index_file(&cstr_info, indexfilename); if (bSuccess) { fprintf(stderr, "Failed to output index file\n"); } } } break; default: fprintf(stderr, "skipping file..\n"); continue; } /* free the memory containing the code-stream */ free(src); src = NULL; if(image->color_space == CLRSPC_SYCC) { color_sycc_to_rgb(image); } if(image->icc_profile_buf) { #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) color_apply_icc_profile(image); #endif free(image->icc_profile_buf); image->icc_profile_buf = NULL; image->icc_profile_len = 0; } /* create output image */ /* ------------------- */ switch (parameters.cod_format) { case PXM_DFMT: /* PNM PGM PPM */ if (imagetopnm(image, parameters.outfile)) { fprintf(stdout,"Outfile %s not generated\n",parameters.outfile); } else { fprintf(stdout,"Generated Outfile %s\n",parameters.outfile); } break; case PGX_DFMT: /* PGX */ if(imagetopgx(image, parameters.outfile)){ fprintf(stdout,"Outfile %s not generated\n",parameters.outfile); } else { fprintf(stdout,"Generated Outfile %s\n",parameters.outfile); } break; case BMP_DFMT: /* BMP */ if(imagetobmp(image, parameters.outfile)){ fprintf(stdout,"Outfile %s not generated\n",parameters.outfile); } else { fprintf(stdout,"Generated Outfile %s\n",parameters.outfile); } break; #ifdef HAVE_LIBTIFF case TIF_DFMT: /* TIFF */ if(imagetotif(image, parameters.outfile)){ fprintf(stdout,"Outfile %s not generated\n",parameters.outfile); } else { fprintf(stdout,"Generated Outfile %s\n",parameters.outfile); } break; #endif /* HAVE_LIBTIFF */ case RAW_DFMT: /* RAW */ if(imagetoraw(image, parameters.outfile)){ fprintf(stdout,"Error generating raw file. Outfile %s not generated\n",parameters.outfile); } else { fprintf(stdout,"Successfully generated Outfile %s\n",parameters.outfile); } break; case TGA_DFMT: /* TGA */ if(imagetotga(image, parameters.outfile)){ fprintf(stdout,"Error generating tga file. Outfile %s not generated\n",parameters.outfile); } else { fprintf(stdout,"Successfully generated Outfile %s\n",parameters.outfile); } break; #ifdef HAVE_LIBPNG case PNG_DFMT: /* PNG */ if(imagetopng(image, parameters.outfile)){ fprintf(stdout,"Error generating png file. Outfile %s not generated\n",parameters.outfile); } else { fprintf(stdout,"Successfully generated Outfile %s\n",parameters.outfile); } break; #endif /* HAVE_LIBPNG */ /* Can happen if output file is TIFF or PNG * and HAVE_LIBTIF or HAVE_LIBPNG is undefined */ default: fprintf(stderr,"Outfile %s not generated\n",parameters.outfile); } /* free remaining structures */ if(dinfo) { opj_destroy_decompress(dinfo); } /* free codestream information structure */ if (*indexfilename) opj_destroy_cstr_info(&cstr_info); /* free image data structure */ opj_image_destroy(image); } return 0; }
int main(int argc, char *argv[]) { opj_dparameters_t parameters; /* decompression parameters */ img_fol_t img_fol; opj_event_mgr_t event_mgr; /* event manager */ opj_image_t *image = NULL; FILE *fsrc = NULL, *fout = NULL; unsigned char *src = NULL; int file_length; int num_images; int i,imageno; dircnt_t *dirptr = NULL; opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ opj_cio_t *cio = NULL; opj_codestream_info_t cstr_info; /* Codestream information structure */ char indexfilename[OPJ_PATH_LEN]; /* index file name */ /* configure the event callbacks (not required) */ 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 decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); /* Initialize indexfilename and img_fol */ *indexfilename = 0; memset(&img_fol,0,sizeof(img_fol_t)); /* parse input and get user encoding parameters */ if(parse_cmdline_decoder(argc, argv, ¶meters,&img_fol, indexfilename) == 1) { return 1; } /* Initialize reading of directory */ if(img_fol.set_imgdir==1){ num_images=get_num_images(img_fol.imgdirpath); dirptr=(dircnt_t*)malloc(sizeof(dircnt_t)); if(dirptr){ dirptr->filename_buf = (char*)malloc(num_images*OPJ_PATH_LEN*sizeof(char)); /* Stores at max 10 image file names*/ dirptr->filename = (char**) malloc(num_images*sizeof(char*)); if(!dirptr->filename_buf){ return 1; } for(i=0;i<num_images;i++){ dirptr->filename[i] = dirptr->filename_buf + i*OPJ_PATH_LEN; } } if(load_images(dirptr,img_fol.imgdirpath)==1){ return 1; } if (num_images==0){ fprintf(stdout,"Folder is empty\n"); return 1; } }else{ num_images=1; } /* */ if (parameters.outfile[0] != 0) { fout = fopen(parameters.outfile,"w"); if (!fout) { fprintf(stderr, "ERROR -> failed to open %s for reading\n", parameters.outfile); return 1; } } else fout = stdout; /*Encoding image one by one*/ for(imageno = 0; imageno < num_images ; imageno++) { image = NULL; fprintf(stderr,"\n"); if(img_fol.set_imgdir==1){ if (get_next_file(imageno, dirptr,&img_fol, ¶meters)) { fprintf(stderr,"skipping file...\n"); continue; } } /* read the input file and put it in memory */ /* ---------------------------------------- */ fsrc = fopen(parameters.infile, "rb"); if (!fsrc) { fprintf(stderr, "ERROR -> failed to open %s for reading\n", parameters.infile); return 1; } fseek(fsrc, 0, SEEK_END); file_length = ftell(fsrc); fseek(fsrc, 0, SEEK_SET); src = (unsigned char *) malloc(file_length); if (fread(src, 1, file_length, fsrc) != (size_t)file_length) { free(src); fclose(fsrc); fclose(fout); fprintf(stderr, "\nERROR: fread return a number of element different from the expected.\n"); return 1; } fclose(fsrc); /* decode the code-stream */ /* ---------------------- */ switch(parameters.decod_format) { case J2K_CFMT: { /* JPEG-2000 codestream */ /* 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, stderr); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); /* decode the stream and fill the image structure */ if (*indexfilename) /* If need to extract codestream information*/ image = opj_decode_with_info(dinfo, cio, &cstr_info); else image = opj_decode(dinfo, cio); if(!image) { fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); opj_destroy_decompress(dinfo); opj_cio_close(cio); fclose(fout); free(src); return 1; } /* dump image */ j2k_dump_image(fout, image); /* dump cp */ j2k_dump_cp(fout, image, ((opj_j2k_t*)dinfo->j2k_handle)->cp); /* close the byte stream */ opj_cio_close(cio); /* Write the index to disk */ if (*indexfilename) { opj_bool bSuccess; bSuccess = write_index_file(&cstr_info, indexfilename); if (bSuccess) { fprintf(stderr, "Failed to output index file\n"); } } } break; case JP2_CFMT: { /* JPEG 2000 compressed image data */ /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_JP2); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); /* setup the decoder decoding parameters using the current image and user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); /* decode the stream and fill the image structure */ if (*indexfilename) /* If need to extract codestream information*/ image = opj_decode_with_info(dinfo, cio, &cstr_info); else image = opj_decode(dinfo, cio); if(!image) { fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); opj_destroy_decompress(dinfo); opj_cio_close(cio); fclose(fout); free(src); return 1; } /* dump image */ if(image->icc_profile_buf) { free(image->icc_profile_buf); image->icc_profile_buf = NULL; } j2k_dump_image(fout, image); /* dump cp */ j2k_dump_cp(fout, image, ((opj_jp2_t*)dinfo->jp2_handle)->j2k->cp); /* close the byte stream */ opj_cio_close(cio); /* Write the index to disk */ if (*indexfilename) { opj_bool bSuccess; bSuccess = write_index_file(&cstr_info, indexfilename); if (bSuccess) { fprintf(stderr, "Failed to output index file\n"); } } } break; case JPT_CFMT: { /* JPEG 2000, JPIP */ /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_JPT); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); /* decode the stream and fill the image structure */ if (*indexfilename) /* If need to extract codestream information*/ image = opj_decode_with_info(dinfo, cio, &cstr_info); else image = opj_decode(dinfo, cio); if(!image) { fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); opj_destroy_decompress(dinfo); opj_cio_close(cio); fclose(fout); free(src); return 1; } /* close the byte stream */ opj_cio_close(cio); /* Write the index to disk */ if (*indexfilename) { opj_bool bSuccess; bSuccess = write_index_file(&cstr_info, indexfilename); if (bSuccess) { fprintf(stderr, "Failed to output index file\n"); } } } break; default: fprintf(stderr, "skipping file..\n"); continue; } /* free the memory containing the code-stream */ free(src); src = NULL; /* free remaining structures */ if(dinfo) { opj_destroy_decompress(dinfo); } /* free codestream information structure */ if (*indexfilename) opj_destroy_cstr_info(&cstr_info); /* free image data structure */ opj_image_destroy(image); } fclose(fout); return EXIT_SUCCESS; }
// load the jpeg2000 file format bool wxJPEG2000Handler::LoadFile(wxImage *image, wxInputStream& stream, bool verbose, int index) { opj_dparameters_t parameters; /* decompression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_image_t *opjimage = NULL; unsigned char *src = NULL; unsigned char *ptr; int file_length, jp2c_point, jp2h_point; unsigned long int jp2hboxlen, jp2cboxlen; opj_codestream_info_t cstr_info; /* Codestream information structure */ unsigned char hdr[24]; int jpfamform; // destroy the image image->Destroy(); /* read the beginning of the file to check the type */ if (!stream.Read(hdr, WXSIZEOF(hdr))) return false; if ((jpfamform = jpeg2000familytype(hdr, WXSIZEOF(hdr))) < 0) return false; stream.SeekI(0, wxFromStart); /* handle to a decompressor */ opj_dinfo_t* dinfo = NULL; opj_cio_t *cio = NULL; /* configure the event callbacks */ memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); event_mgr.error_handler = jpeg2000_error_callback; event_mgr.warning_handler = jpeg2000_warning_callback; event_mgr.info_handler = jpeg2000_info_callback; /* set decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); /* prepare parameters */ strncpy(parameters.infile, "", sizeof(parameters.infile) - 1); strncpy(parameters.outfile, "", sizeof(parameters.outfile) - 1); parameters.decod_format = jpfamform; parameters.cod_format = BMP_DFMT; if (m_reducefactor) parameters.cp_reduce = m_reducefactor; if (m_qualitylayers) parameters.cp_layer = m_qualitylayers; /*if (n_components) parameters. = n_components;*/ /* JPWL only */ #ifdef USE_JPWL parameters.jpwl_exp_comps = m_expcomps; parameters.jpwl_max_tiles = m_maxtiles; parameters.jpwl_correct = m_enablejpwl; #endif /* USE_JPWL */ /* get a decoder handle */ if (jpfamform == JP2_CFMT || jpfamform == MJ2_CFMT) dinfo = opj_create_decompress(CODEC_JP2); else if (jpfamform == J2K_CFMT) dinfo = opj_create_decompress(CODEC_J2K); else return false; /* find length of the stream */ stream.SeekI(0, wxFromEnd); file_length = (int) stream.TellI(); /* it's a movie */ if (jpfamform == MJ2_CFMT) { /* search for the first codestream box and the movie header box */ jp2c_point = searchjpeg2000c(stream, file_length, m_framenum); jp2h_point = searchjpeg2000headerbox(stream, file_length); // read the jp2h box and store it stream.SeekI(jp2h_point, wxFromStart); stream.Read(&jp2hboxlen, sizeof(unsigned long int)); jp2hboxlen = BYTE_SWAP4(jp2hboxlen); // read the jp2c box and store it stream.SeekI(jp2c_point, wxFromStart); stream.Read(&jp2cboxlen, sizeof(unsigned long int)); jp2cboxlen = BYTE_SWAP4(jp2cboxlen); // malloc memory source src = (unsigned char *) malloc(jpeg2000headSIZE + jp2hboxlen + jp2cboxlen); // copy the jP and ftyp memcpy(src, jpeg2000head, jpeg2000headSIZE); // copy the jp2h stream.SeekI(jp2h_point, wxFromStart); stream.Read(&src[jpeg2000headSIZE], jp2hboxlen); // copy the jp2c stream.SeekI(jp2c_point, wxFromStart); stream.Read(&src[jpeg2000headSIZE + jp2hboxlen], jp2cboxlen); } else if (jpfamform == JP2_CFMT || jpfamform == J2K_CFMT) { /* It's a plain image */ /* get data */ stream.SeekI(0, wxFromStart); src = (unsigned char *) malloc(file_length); stream.Read(src, file_length); } else return false; /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ if (jpfamform == MJ2_CFMT) cio = opj_cio_open((opj_common_ptr)dinfo, src, jpeg2000headSIZE + jp2hboxlen + jp2cboxlen); else if (jpfamform == JP2_CFMT || jpfamform == J2K_CFMT) cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); else { free(src); return false; } /* decode the stream and fill the image structure */ opjimage = opj_decode_with_info(dinfo, cio, &cstr_info); if (!opjimage) { wxMutexGuiEnter(); wxLogError(wxT("JPEG 2000 failed to decode image!")); wxMutexGuiLeave(); opj_destroy_decompress(dinfo); opj_cio_close(cio); free(src); return false; } /* close the byte stream */ opj_cio_close(cio); /* - At this point, we have the structure "opjimage" that is filled with decompressed data, as processed by the OpenJPEG decompression engine - We need to fill the class "image" with the proper pixel sample values */ { int shiftbpp; int c, tempcomps; // check components number if (m_components > opjimage->numcomps) m_components = opjimage->numcomps; // check image depth (only on the first one, for now) if (m_components) shiftbpp = opjimage->comps[m_components - 1].prec - 8; else shiftbpp = opjimage->comps[0].prec - 8; // prepare image size if (m_components) image->Create(opjimage->comps[m_components - 1].w, opjimage->comps[m_components - 1].h, true); else image->Create(opjimage->comps[0].w, opjimage->comps[0].h, true); // access image raw data image->SetMask(false); ptr = image->GetData(); // workaround for components different from 1 or 3 if ((opjimage->numcomps != 1) && (opjimage->numcomps != 3)) { #ifndef __WXGTK__ wxMutexGuiEnter(); #endif /* __WXGTK__ */ wxLogMessage(wxT("JPEG2000: weird number of components")); #ifndef __WXGTK__ wxMutexGuiLeave(); #endif /* __WXGTK__ */ tempcomps = 1; } else tempcomps = opjimage->numcomps; // workaround for subsampled components for (c = 1; c < tempcomps; c++) { if ((opjimage->comps[c].w != opjimage->comps[c - 1].w) || (opjimage->comps[c].h != opjimage->comps[c - 1].h)) { tempcomps = 1; break; } } // workaround for different precision components for (c = 1; c < tempcomps; c++) { if (opjimage->comps[c].bpp != opjimage->comps[c - 1].bpp) { tempcomps = 1; break; } } // only one component selected if (m_components) tempcomps = 1; // RGB color picture if (tempcomps == 3) { int row, col; int *r = opjimage->comps[0].data; int *g = opjimage->comps[1].data; int *b = opjimage->comps[2].data; if (shiftbpp > 0) { for (row = 0; row < opjimage->comps[0].h; row++) { for (col = 0; col < opjimage->comps[0].w; col++) { *(ptr++) = (*(r++)) >> shiftbpp; *(ptr++) = (*(g++)) >> shiftbpp; *(ptr++) = (*(b++)) >> shiftbpp; } } } else if (shiftbpp < 0) { for (row = 0; row < opjimage->comps[0].h; row++) { for (col = 0; col < opjimage->comps[0].w; col++) { *(ptr++) = (*(r++)) << -shiftbpp; *(ptr++) = (*(g++)) << -shiftbpp; *(ptr++) = (*(b++)) << -shiftbpp; } } } else { for (row = 0; row < opjimage->comps[0].h; row++) { for (col = 0; col < opjimage->comps[0].w; col++) { *(ptr++) = *(r++); *(ptr++) = *(g++); *(ptr++) = *(b++); } } } }
BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) { LLTimer decode_timer; /* Extract metadata */ /* ---------------- */ U8* c_data = base.getData(); size_t c_size = base.getDataSize(); size_t position = 0; while (position < 1024 && position < (c_size - 7)) // the comment field should be in the first 1024 bytes. { if (c_data[position] == 0xff && c_data[position + 1] == 0x64) { U8 high_byte = c_data[position + 2]; U8 low_byte = c_data[position + 3]; S32 c_length = (high_byte * 256) + low_byte; // This size also counts the markers, 00 01 and itself if (c_length > 200) // sanity check { // While comments can be very long, anything longer then 200 is suspect. break; } if (position + 2 + c_length > c_size) { // comment extends past end of data, corruption, or all data not retrived yet. break; } // if the comment block does not end at the end of data, check to see if the next // block starts with 0xFF if (position + 2 + c_length < c_size && c_data[position + 2 + c_length] != 0xff) { // invalied comment block break; } // extract the comment minus the markers, 00 01 raw_image.mComment.assign((char*)c_data + position + 6, c_length - 4); break; } ++position; } opj_dparameters_t parameters; /* decompression parameters */ opj_event_mgr_t event_mgr = { }; /* event manager */ opj_image_t *image = nullptr; opj_dinfo_t* dinfo = nullptr; /* handle to a decompressor */ opj_cio_t *cio = nullptr; /* configure the event callbacks (not required) */ event_mgr.error_handler = error_callback; event_mgr.warning_handler = warning_callback; event_mgr.info_handler = info_callback; /* set decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); parameters.cp_reduce = base.getRawDiscardLevel(); if(parameters.cp_reduce == 0 && *(U16*)(base.getData() + base.getDataSize() - 2) != 0xD9FF) { bool failed = true; for(S32 i = base.getDataSize()-1; i > 42; --i) { if(base.getData()[i] != 0x00) { failed = *(U16*)(base.getData()+i-1) != 0xD9FF; break; } } if(failed) { opj_image_destroy(image); base.decodeFailed(); return TRUE; } } /* decode the code-stream */ /* ---------------------- */ /* JPEG-2000 codestream */ /* 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, stderr); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize()); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); /* close the byte stream */ opj_cio_close(cio); /* free remaining structures */ if(dinfo) { opj_destroy_decompress(dinfo); } // The image decode failed if the return was NULL or the component // count was zero. The latter is just a sanity check before we // dereference the array. if(!image || !image->numcomps) { LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image!" << LL_ENDL; if (image) { opj_image_destroy(image); } base.decodeFailed(); return TRUE; // done } // sometimes we get bad data out of the cache - check to see if the decode succeeded for (S32 i = 0; i < image->numcomps; i++) { if (image->comps[i].factor != base.getRawDiscardLevel()) { // if we didn't get the discard level we're expecting, fail opj_image_destroy(image); base.decodeFailed(); return TRUE; } } if(image->numcomps <= first_channel) { LL_WARNS("Texture") << "trying to decode more channels than are present in image: numcomps: " << image->numcomps << " first_channel: " << first_channel << LL_ENDL; if (image) { opj_image_destroy(image); } base.decodeFailed(); return TRUE; } // Copy image data into our raw image format (instead of the separate channel format S32 img_components = image->numcomps; S32 channels = img_components - first_channel; if( channels > max_channel_count ) channels = max_channel_count; // Component buffers are allocated in an image width by height buffer. // The image placed in that buffer is ceil(width/2^factor) by // ceil(height/2^factor) and if the factor isn't zero it will be at the // top left of the buffer with black filled in the rest of the pixels. // It is integer math so the formula is written in ceildivpo2. // (Assuming all the components have the same width, height and // factor.) S32 comp_width = image->comps[0].w; S32 f=image->comps[0].factor; S32 width = ceildivpow2(image->x1 - image->x0, f); S32 height = ceildivpow2(image->y1 - image->y0, f); raw_image.resize(width, height, channels); U8 *rawp = raw_image.getData(); if (!rawp) { opj_image_destroy(image); base.setLastError("Memory error"); base.decodeFailed(); return true; // done } // first_channel is what channel to start copying from // dest is what channel to copy to. first_channel comes from the // argument, dest always starts writing at channel zero. for (S32 comp = first_channel, dest=0; comp < first_channel + channels; comp++, dest++) { if (image->comps[comp].data) { S32 offset = dest; for (S32 y = (height - 1); y >= 0; y--) { for (S32 x = 0; x < width; x++) { rawp[offset] = image->comps[comp].data[y*comp_width + x]; offset += channels; } } } else // Some rare OpenJPEG versions have this bug. { LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << LL_ENDL; if (image) { opj_image_destroy(image); } base.decodeFailed(); return TRUE; // done } } /* free image data structure */ opj_image_destroy(image); return TRUE; // done }
struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags) { struct ImBuf *ibuf = 0; int use_float = 0; /* for precision higher then 8 use float */ long signed_offsets[4]= {0, 0, 0, 0}; int float_divs[4]= {1, 1, 1, 1}; int index; int w, h, depth; opj_dparameters_t parameters; /* decompression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_image_t *image = NULL; int i; opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ opj_cio_t *cio = NULL; if (check_jp2(mem) == 0) return(0); /* configure the event callbacks (not required) */ 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 decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); /* JPEG 2000 compressed image data */ /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_JP2); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); /* setup the decoder decoding parameters using the current image and user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, mem, size); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); if(!image) { fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); opj_destroy_decompress(dinfo); opj_cio_close(cio); return NULL; } /* close the byte stream */ opj_cio_close(cio); if((image->numcomps * image->x1 * image->y1) == 0) { fprintf(stderr,"\nError: invalid raw image parameters\n"); return NULL; } w = image->comps[0].w; h = image->comps[0].h; switch (image->numcomps) { case 1: /* Greyscale */ case 3: /* Color */ depth= 24; break; default: /* 2 or 4 - Greyscale or Color + alpha */ depth= 32; /* greyscale + alpha */ break; } i = image->numcomps; if (i>4) i= 4; while (i) { i--; if (image->comps[i].prec > 8) use_float = 1; if (image->comps[i].sgnd) signed_offsets[i]= 1 << (image->comps[i].prec - 1); /* only needed for float images but dosnt hurt to calc this */ float_divs[i]= (1<<image->comps[i].prec)-1; } ibuf= IMB_allocImBuf(w, h, depth, use_float ? IB_rectfloat : IB_rect); if (ibuf==NULL) { if(dinfo) opj_destroy_decompress(dinfo); return NULL; } ibuf->ftype = JP2; if (use_float) { float *rect_float= ibuf->rect_float; if (image->numcomps < 3) { /* greyscale 12bits+ */ for (i = 0; i < w * h; i++, rect_float+=4) { index = w * h - ((i) / (w) + 1) * w + (i) % (w); rect_float[0]= rect_float[1]= rect_float[2]= (float)(image->comps[0].data[index] + signed_offsets[0]) / float_divs[0]; if (image->numcomps == 2) rect_float[3]= (image->comps[1].data[index] + signed_offsets[1]) / float_divs[1]; else rect_float[3]= 1.0f; } } else { /* rgb or rgba 12bits+ */ for (i = 0; i < w * h; i++, rect_float+=4) { index = w * h - ((i) / (w) + 1) * w + (i) % (w); rect_float[0]= (float)(image->comps[0].data[index] + signed_offsets[0]) / float_divs[0]; rect_float[1]= (float)(image->comps[1].data[index] + signed_offsets[1]) / float_divs[1]; rect_float[2]= (float)(image->comps[2].data[index] + signed_offsets[2]) / float_divs[2]; if (image->numcomps >= 4) rect_float[3]= (float)(image->comps[3].data[index] + signed_offsets[3]) / float_divs[3]; else rect_float[3]= 1.0f; } } } else { unsigned char *rect= (unsigned char *)ibuf->rect; if (image->numcomps < 3) { /* greyscale */ for (i = 0; i < w * h; i++, rect+=4) { index = w * h - ((i) / (w) + 1) * w + (i) % (w); rect[0]= rect[1]= rect[2]= (image->comps[0].data[index] + signed_offsets[0]); if (image->numcomps == 2) rect[3]= image->comps[1].data[index] + signed_offsets[1]; else rect[3]= 255; } } else { /* 8bit rgb or rgba */ for (i = 0; i < w * h; i++, rect+=4) { int index = w * h - ((i) / (w) + 1) * w + (i) % (w); rect[0]= image->comps[0].data[index] + signed_offsets[0]; rect[1]= image->comps[1].data[index] + signed_offsets[1]; rect[2]= image->comps[2].data[index] + signed_offsets[2]; if (image->numcomps >= 4) rect[3]= image->comps[3].data[index] + signed_offsets[3]; else rect[3]= 255; } } } /* free remaining structures */ if(dinfo) { opj_destroy_decompress(dinfo); } /* free image data structure */ opj_image_destroy(image); if (flags & IB_rect) { IMB_rect_from_float(ibuf); } return(ibuf); }
BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base) { // // FIXME: We get metadata by decoding the ENTIRE image. // // Update the raw discard level base.updateRawDiscardLevel(); opj_dparameters_t parameters; /* decompression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_image_t *image = NULL; opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ opj_cio_t *cio = NULL; /* configure the event callbacks (not required) */ 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 decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); // Only decode what's required to get the size data. parameters.cp_limit_decoding=LIMIT_TO_MAIN_HEADER; //parameters.cp_reduce = mRawDiscardLevel; /* decode the code-stream */ /* ---------------------- */ /* JPEG-2000 codestream */ /* 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, stderr); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize()); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); /* close the byte stream */ opj_cio_close(cio); /* free remaining structures */ if(dinfo) { opj_destroy_decompress(dinfo); } if(!image) { llwarns << "ERROR -> getMetadata: failed to decode image!" << llendl; return FALSE; } // Copy image data into our raw image format (instead of the separate channel format S32 width = 0; S32 height = 0; S32 img_components = image->numcomps; width = image->x1 - image->x0; height = image->y1 - image->y0; base.setSize(width, height, img_components); /* free image data structure */ opj_image_destroy(image); return TRUE; }
int main(int argc, char **argv) { opj_dparameters_t parameters; /* decompression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_image_t *image = NULL; FILE *fsrc = NULL; unsigned char *src = NULL; int file_length; opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ opj_cio_t *cio = NULL; /* configure the event callbacks (not required) */ 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 decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); /* parse input and get user decoding parameters */ if(parse_cmdline_decoder(argc, argv, ¶meters) == 1) { return 0; } /* read the input file and put it in memory */ /* ---------------------------------------- */ fsrc = fopen(parameters.infile, "rb"); if (!fsrc) { fprintf(stderr, "ERROR -> failed to open %s for reading\n", parameters.infile); return 1; } fseek(fsrc, 0, SEEK_END); file_length = ftell(fsrc); fseek(fsrc, 0, SEEK_SET); src = (unsigned char *) malloc(file_length); fread(src, 1, file_length, fsrc); fclose(fsrc); /* decode the code-stream */ /* ---------------------- */ switch(parameters.decod_format) { case J2K_CFMT: { /* JPEG-2000 codestream */ /* 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, stderr); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); if(!image) { fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); opj_destroy_decompress(dinfo); opj_cio_close(cio); return 1; } /* close the byte stream */ opj_cio_close(cio); } break; case JP2_CFMT: { /* JPEG 2000 compressed image data */ /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_JP2); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); /* setup the decoder decoding parameters using the current image and user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); if(!image) { fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); opj_destroy_decompress(dinfo); opj_cio_close(cio); return 1; } /* close the byte stream */ opj_cio_close(cio); } break; case JPT_CFMT: { /* JPEG 2000, JPIP */ /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_JPT); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); if(!image) { fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); opj_destroy_decompress(dinfo); opj_cio_close(cio); return 1; } /* close the byte stream */ opj_cio_close(cio); } break; default: fprintf(stderr, "ERROR -> j2k_to_image : Unknown input image format\n"); return 1; } /* free the memory containing the code-stream */ free(src); src = NULL; /* create output image */ /* ------------------- */ switch (parameters.cod_format) { case PXM_DFMT: /* PNM PGM PPM */ imagetopnm(image, parameters.outfile); break; case PGX_DFMT: /* PGX */ imagetopgx(image, parameters.outfile); break; case BMP_DFMT: /* BMP */ imagetobmp(image, parameters.outfile); break; } /* free remaining structures */ if(dinfo) { opj_destroy_decompress(dinfo); } /* free image data structure */ opj_image_destroy(image); return 0; }
bool _openslide_jp2k_decode_buffer(uint32_t *dest, int32_t w, int32_t h, void *data, int32_t datalen, enum _openslide_jp2k_colorspace space, GError **err) { GError *tmp_err = NULL; bool success = false; // opj_cio_open interprets a NULL buffer as opening for write g_assert(data != NULL); // init decompressor opj_cio_t *stream = NULL; opj_dinfo_t *dinfo = NULL; opj_image_t *image = NULL; // note: don't use info_handler, it outputs lots of junk opj_event_mgr_t event_callbacks = { .error_handler = error_callback, .warning_handler = warning_callback, }; opj_dparameters_t parameters; dinfo = opj_create_decompress(CODEC_J2K); opj_set_default_decoder_parameters(¶meters); opj_setup_decoder(dinfo, ¶meters); stream = opj_cio_open((opj_common_ptr) dinfo, data, datalen); opj_set_event_mgr((opj_common_ptr) dinfo, &event_callbacks, &tmp_err); // decode image = opj_decode(dinfo, stream); // check error if (tmp_err) { g_propagate_error(err, tmp_err); goto DONE; } // sanity check if (image->numcomps != 3) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FAILED, "image->numcomps != 3"); goto DONE; } // TODO more checks? unpack_argb(space, image->comps, dest, w, h); success = true; DONE: if (image) { opj_image_destroy(image); } if (stream) { opj_cio_close(stream); } if (dinfo) { opj_destroy_decompress(dinfo); } return success; }
fz_pixmap * fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *defcs) { fz_pixmap *img; opj_event_mgr_t evtmgr; opj_dparameters_t params; opj_dinfo_t *info; opj_cio_t *cio; opj_image_t *jpx; fz_colorspace *colorspace; unsigned char *p; int format; int a, n, w, h, depth, sgnd; int x, y, k, v; if (size < 2) fz_throw(ctx, "not enough data to determine image format"); /* Check for SOC marker -- if found we have a bare J2K stream */ if (data[0] == 0xFF && data[1] == 0x4F) format = CODEC_J2K; else format = CODEC_JP2; memset(&evtmgr, 0, sizeof(evtmgr)); evtmgr.error_handler = fz_opj_error_callback; evtmgr.warning_handler = fz_opj_warning_callback; evtmgr.info_handler = fz_opj_info_callback; opj_set_default_decoder_parameters(¶ms); info = opj_create_decompress(format); opj_set_event_mgr((opj_common_ptr)info, &evtmgr, ctx); opj_setup_decoder(info, ¶ms); cio = opj_cio_open((opj_common_ptr)info, data, size); jpx = opj_decode(info, cio); opj_cio_close(cio); opj_destroy_decompress(info); if (!jpx) fz_throw(ctx, "opj_decode failed"); for (k = 1; k < jpx->numcomps; k++) { if (jpx->comps[k].w != jpx->comps[0].w) fz_throw(ctx, "image components have different width"); if (jpx->comps[k].h != jpx->comps[0].h) fz_throw(ctx, "image components have different height"); if (jpx->comps[k].prec != jpx->comps[0].prec) fz_throw(ctx, "image components have different precision"); } n = jpx->numcomps; w = jpx->comps[0].w; h = jpx->comps[0].h; depth = jpx->comps[0].prec; sgnd = jpx->comps[0].sgnd; if (jpx->color_space == CLRSPC_SRGB && n == 4) { n = 3; a = 1; } else if (jpx->color_space == CLRSPC_SYCC && n == 4) { n = 3; a = 1; } else if (n == 2) { n = 1; a = 1; } else if (n > 4) { n = 4; a = 1; } else { a = 0; } if (defcs) { if (defcs->n == n) { colorspace = defcs; } else { fz_warn(ctx, "jpx file and dict colorspaces do not match"); defcs = NULL; } } if (!defcs) { switch (n) { case 1: colorspace = fz_device_gray; break; case 3: colorspace = fz_device_rgb; break; case 4: colorspace = fz_device_cmyk; break; } } fz_try(ctx) { img = fz_new_pixmap(ctx, colorspace, w, h); } fz_catch(ctx) { opj_image_destroy(jpx); fz_throw(ctx, "out of memory"); } p = img->samples; for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { for (k = 0; k < n + a; k++) { v = jpx->comps[k].data[y * w + x]; if (sgnd) v = v + (1 << (depth - 1)); if (depth > 8) v = v >> (depth - 8); *p++ = v; } if (!a) *p++ = 255; } } if (a) { if (n == 4) { fz_pixmap *tmp = fz_new_pixmap(ctx, fz_device_rgb, w, h); fz_convert_pixmap(ctx, img, tmp); fz_drop_pixmap(ctx, img); img = tmp; } fz_premultiply_pixmap(ctx, img); } opj_image_destroy(jpx); return img; }
int openjpeg2k_decode_mem(IMG_DAT **oimg_dat, int *lossyflag, unsigned char *idata, const int ilen) { IMG_DAT *img_dat; opj_image_t *image = NULL; opj_event_mgr_t event_mgr; opj_dinfo_t* dinfo = NULL; opj_cio_t *cio = NULL; opj_dparameters_t parameters; opj_codestream_info_t cstr_info; signed char* sgnd_buf = NULL; unsigned char* unsgnd_buf = NULL; int size; /* configure the event handler */ memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); /* set decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); /* set the decode and encode format */ parameters.decod_format = get_file_format("b.jp2"); parameters.cod_format = get_file_format("a.raw"); /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_JP2); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, idata, ilen); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); if (!image) { fprintf(stderr, "ERROR -> failed to decode image!\n"); opj_destroy_decompress(dinfo); opj_cio_close(cio); return(-1); } opj_cio_close(cio); if (dinfo) { opj_destroy_decompress(dinfo); } size = image->numcomps * image->comps[0].w * image->comps[0].h; /* only support unsigned jp2 image */ if (image->comps[0].sgnd == 1) { fprintf(stderr, "ERROR -> Can't decode signed buffer!\n"); opj_image_destroy(image); return(-2); } /* allocate buf for the Raw image */ unsgnd_buf = (unsigned char *) malloc(size * sizeof(unsigned char)); /* convert JP2 to Raw */ if (image_to_raw(image, unsgnd_buf)) { fprintf(stderr, "ERROR -> image_to_raw!\n"); opj_image_destroy(image); return(-3); } /* consturct img_dat format */ if ((img_dat_generate_openjpeg(&img_dat, image, unsgnd_buf)) != 0){ free(unsgnd_buf); opj_image_destroy(image); fprintf(stderr, "ERROR : openjpeg2k_decode_mem: failed to generate img_dat\n"); return(-4); } free(unsgnd_buf); opj_image_destroy(image); *oimg_dat = img_dat; *lossyflag = 0; return(0); }
struct redcode_frame_raw * redcode_decode_video_raw( struct redcode_frame * frame, int scale) { struct redcode_frame_raw * rv = NULL; opj_dparameters_t parameters; /* decompression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_image_t *image = NULL; opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ opj_cio_t *cio = NULL; 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; opj_set_default_decoder_parameters(¶meters); parameters.decod_format = JP2_CFMT; if (scale == 2) { parameters.cp_reduce = 1; } else if (scale == 4) { parameters.cp_reduce = 2; } else if (scale == 8) { parameters.cp_reduce = 3; } /* JPEG 2000 compressed image data */ /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_JP2); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); /* setup the decoder decoding parameters using the current image and user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, frame->data + frame->offset, frame->length); image = opj_decode(dinfo, cio); if(!image) { fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); opj_destroy_decompress(dinfo); opj_cio_close(cio); return 0; } /* close the byte stream */ opj_cio_close(cio); /* free remaining structures */ if(dinfo) { opj_destroy_decompress(dinfo); } if((image->numcomps * image->x1 * image->y1) == 0) { opj_image_destroy(image); return 0; } rv = (struct redcode_frame_raw *) calloc( 1, sizeof(struct redcode_frame_raw)); rv->data = image; rv->width = image->comps[0].w; rv->height = image->comps[0].h; return rv; }
static GstFlowReturn gst_openjpeg_dec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame) { GstOpenJPEGDec *self = GST_OPENJPEG_DEC (decoder); GstFlowReturn ret = GST_FLOW_OK; gint64 deadline; GstMapInfo map; opj_dinfo_t *dec; opj_event_mgr_t callbacks; opj_cio_t *io; opj_image_t *image; GstVideoFrame vframe; opj_dparameters_t params; GST_DEBUG_OBJECT (self, "Handling frame"); deadline = gst_video_decoder_get_max_decode_time (decoder, frame); if (deadline < 0) { GST_LOG_OBJECT (self, "Dropping too late frame: deadline %" G_GINT64_FORMAT, deadline); ret = gst_video_decoder_drop_frame (decoder, frame); return ret; } dec = opj_create_decompress (self->codec_format); if (!dec) goto initialization_error; if (G_UNLIKELY (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_TRACE)) { callbacks.error_handler = gst_openjpeg_dec_opj_error; callbacks.warning_handler = gst_openjpeg_dec_opj_warning; callbacks.info_handler = gst_openjpeg_dec_opj_info; opj_set_event_mgr ((opj_common_ptr) dec, &callbacks, self); } else { opj_set_event_mgr ((opj_common_ptr) dec, NULL, NULL); } params = self->params; if (self->ncomps) params.jpwl_exp_comps = self->ncomps; opj_setup_decoder (dec, ¶ms); if (!gst_buffer_map (frame->input_buffer, &map, GST_MAP_READ)) goto map_read_error; io = opj_cio_open ((opj_common_ptr) dec, map.data + (self->is_jp2c ? 8 : 0), map.size - (self->is_jp2c ? 8 : 0)); if (!io) goto open_error; image = opj_decode (dec, io); if (!image) goto decode_error; gst_buffer_unmap (frame->input_buffer, &map); ret = gst_openjpeg_dec_negotiate (self, image); if (ret != GST_FLOW_OK) goto negotiate_error; ret = gst_video_decoder_allocate_output_frame (decoder, frame); if (ret != GST_FLOW_OK) goto allocate_error; if (!gst_video_frame_map (&vframe, &self->output_state->info, frame->output_buffer, GST_MAP_WRITE)) goto map_write_error; self->fill_frame (&vframe, image); gst_video_frame_unmap (&vframe); opj_image_destroy (image); opj_cio_close (io); opj_destroy_decompress (dec); ret = gst_video_decoder_finish_frame (decoder, frame); return ret; initialization_error: { gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, LIBRARY, INIT, ("Failed to initialize OpenJPEG decoder"), (NULL)); return GST_FLOW_ERROR; } map_read_error: { opj_destroy_decompress (dec); gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, CORE, FAILED, ("Failed to map input buffer"), (NULL)); return GST_FLOW_ERROR; } open_error: { opj_destroy_decompress (dec); gst_buffer_unmap (frame->input_buffer, &map); gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, LIBRARY, INIT, ("Failed to open OpenJPEG stream"), (NULL)); return GST_FLOW_ERROR; } decode_error: { opj_cio_close (io); opj_destroy_decompress (dec); gst_buffer_unmap (frame->input_buffer, &map); gst_video_codec_frame_unref (frame); GST_VIDEO_DECODER_ERROR (self, 1, STREAM, DECODE, ("Failed to decode OpenJPEG stream"), (NULL), ret); return ret; } negotiate_error: { opj_image_destroy (image); opj_cio_close (io); opj_destroy_decompress (dec); gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, CORE, NEGOTIATION, ("Failed to negotiate"), (NULL)); return ret; } allocate_error: { opj_image_destroy (image); opj_cio_close (io); opj_destroy_decompress (dec); gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, CORE, FAILED, ("Failed to allocate output buffer"), (NULL)); return ret; } map_write_error: { opj_image_destroy (image); opj_cio_close (io); opj_destroy_decompress (dec); gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, CORE, FAILED, ("Failed to map output buffer"), (NULL)); return GST_FLOW_ERROR; } }
static void aperio_tiff_tilereader(openslide_t *osr, TIFF *tiff, uint32_t *dest, int64_t x, int64_t y, int32_t w, int32_t h) { // which compression? uint16_t compression_mode; TIFFGetField(tiff, TIFFTAG_COMPRESSION, &compression_mode); // not for us? fallback if ((compression_mode != APERIO_COMPRESSION_JP2K_YCBCR) && (compression_mode != APERIO_COMPRESSION_JP2K_RGB)) { _openslide_generic_tiff_tilereader(osr, tiff, dest, x, y, w, h); return; } // else, JPEG 2000! opj_cio_t *stream = NULL; opj_dinfo_t *dinfo = NULL; opj_image_t *image = NULL; opj_image_comp_t *comps = NULL; // note: don't use info_handler, it outputs lots of junk opj_event_mgr_t event_callbacks = { .error_handler = error_callback, .warning_handler = warning_callback, }; // get tile number ttile_t tile_no = TIFFComputeTile(tiff, x, y, 0, 0); // g_debug("aperio reading tile_no: %d", tile_no); // get tile size toff_t *sizes; if (TIFFGetField(tiff, TIFFTAG_TILEBYTECOUNTS, &sizes) == 0) { _openslide_set_error(osr, "Cannot get tile size"); return; // ok, haven't allocated anything yet } tsize_t tile_size = sizes[tile_no]; // a slide with zero-length tiles has been seen in the wild if (!tile_size) { // fill with transparent memset(dest, 0, w * h * 4); //g_debug("skipping tile %d", tile_no); return; // ok, haven't allocated anything yet } // get raw tile tdata_t buf = g_slice_alloc(tile_size); tsize_t size = TIFFReadRawTile(tiff, tile_no, buf, tile_size); if (size == -1) { _openslide_set_error(osr, "Cannot get raw tile"); goto DONE; } // init decompressor opj_dparameters_t parameters; dinfo = opj_create_decompress(CODEC_J2K); opj_set_default_decoder_parameters(¶meters); opj_setup_decoder(dinfo, ¶meters); stream = opj_cio_open((opj_common_ptr) dinfo, buf, size); opj_set_event_mgr((opj_common_ptr) dinfo, &event_callbacks, osr); // decode image = opj_decode(dinfo, stream); // check error if (openslide_get_error(osr)) { goto DONE; } comps = image->comps; // sanity check if (image->numcomps != 3) { _openslide_set_error(osr, "image->numcomps != 3"); goto DONE; } // TODO more checks? copy_aperio_tile(compression_mode, comps, dest, w, h, w / comps[0].w, h / comps[0].h, w / comps[1].w, h / comps[1].h, w / comps[2].w, h / comps[2].h); DONE: // erase g_slice_free1(tile_size, buf); if (image) opj_image_destroy(image); if (stream) opj_cio_close(stream); if (dinfo) opj_destroy_decompress(dinfo); }
int dt_imageio_j2k_read_profile(const char *filename, uint8_t **out) { #ifdef HAVE_OPENJPEG_ICC opj_dparameters_t parameters; /* decompression parameters */ opj_image_t *image = NULL; FILE *fsrc = NULL; unsigned char *src = NULL; int file_length; opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ opj_cio_t *cio = NULL; OPJ_CODEC_FORMAT codec; gboolean res = FALSE; unsigned int length = 0; *out = NULL; /* read the input file and put it in memory */ /* ---------------------------------------- */ fsrc = fopen(filename, "rb"); if(!fsrc) { fprintf(stderr, "[j2k_open] Error: failed to open `%s' for reading\n", filename); goto another_end_of_the_world; } fseek(fsrc, 0, SEEK_END); file_length = ftell(fsrc); fseek(fsrc, 0, SEEK_SET); src = (unsigned char *) malloc(file_length); if(fread(src, 1, file_length, fsrc) != (size_t)file_length) { free(src); fclose(fsrc); fprintf(stderr, "[j2k_open] Error: fread returned a number of elements different from the expected.\n"); goto another_end_of_the_world; } fclose(fsrc); if(memcmp(JP2_HEAD, src, sizeof(JP2_HEAD)) == 0) { codec = CODEC_JP2; } else if(memcmp(J2K_HEAD, src, sizeof(J2K_HEAD)) == 0) { codec = CODEC_J2K; } else // this will also reject jpt files. { free(src); fprintf(stderr, "[j2k_open] Error: `%s' has unsupported file format.\n", filename); goto another_end_of_the_world; } /* set decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); parameters.cp_limit_decoding = LIMIT_TO_MAIN_HEADER; /* decode the code-stream */ /* ---------------------- */ /* get a decoder handle */ dinfo = opj_create_decompress(codec); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); /* close the byte stream */ opj_cio_close(cio); /* free the memory containing the code-stream */ free(src); if(!image) { fprintf(stderr, "[j2k_open] Error: failed to decode image `%s'\n", filename); goto another_end_of_the_world; } if(image->icc_profile_buf) { res = TRUE; length = image->icc_profile_len; *out = image->icc_profile_buf; image->icc_profile_buf = NULL; image->icc_profile_len = 0; } another_end_of_the_world: /* free remaining structures */ if(dinfo) opj_destroy_decompress(dinfo); /* free image data structure */ opj_image_destroy(image); return res?length:0; #else return 0; #endif }
static int libopenjpeg_decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; LibOpenJPEGContext *ctx = avctx->priv_data; AVFrame *picture = &ctx->image, *output = data; opj_dinfo_t *dec; opj_cio_t *stream; opj_image_t *image; int width, height, has_alpha = 0, ret = -1; int x, y, index; uint8_t *img_ptr; int adjust[4]; *data_size = 0; // Check if input is a raw jpeg2k codestream or in jp2 wrapping if((AV_RB32(buf) == 12) && (AV_RB32(buf + 4) == JP2_SIG_TYPE) && (AV_RB32(buf + 8) == JP2_SIG_VALUE)) { dec = opj_create_decompress(CODEC_JP2); } else { // If the AVPacket contains a jp2c box, then skip to // the starting byte of the codestream. if (AV_RB32(buf + 4) == AV_RB32("jp2c")) buf += 8; dec = opj_create_decompress(CODEC_J2K); } if(!dec) { av_log(avctx, AV_LOG_ERROR, "Error initializing decoder.\n"); return -1; } opj_set_event_mgr((opj_common_ptr)dec, NULL, NULL); ctx->dec_params.cp_reduce = avctx->lowres; // Tie decoder with decoding parameters opj_setup_decoder(dec, &ctx->dec_params); stream = opj_cio_open((opj_common_ptr)dec, buf, buf_size); if(!stream) { av_log(avctx, AV_LOG_ERROR, "Codestream could not be opened for reading.\n"); opj_destroy_decompress(dec); return -1; } // Decode the codestream image = opj_decode_with_info(dec, stream, NULL); opj_cio_close(stream); if(!image) { av_log(avctx, AV_LOG_ERROR, "Error decoding codestream.\n"); opj_destroy_decompress(dec); return -1; } width = image->comps[0].w << avctx->lowres; height = image->comps[0].h << avctx->lowres; if(av_check_image_size(width, height, 0, avctx) < 0) { av_log(avctx, AV_LOG_ERROR, "%dx%d dimension invalid.\n", width, height); goto done; } avcodec_set_dimensions(avctx, width, height); switch(image->numcomps) { case 1: avctx->pix_fmt = PIX_FMT_GRAY8; break; case 3: if(check_image_attributes(image)) { avctx->pix_fmt = PIX_FMT_RGB24; } else { avctx->pix_fmt = PIX_FMT_GRAY8; av_log(avctx, AV_LOG_ERROR, "Only first component will be used.\n"); } break; case 4: has_alpha = 1; avctx->pix_fmt = PIX_FMT_RGBA; break; default: av_log(avctx, AV_LOG_ERROR, "%d components unsupported.\n", image->numcomps); goto done; } if(picture->data[0]) avctx->release_buffer(avctx, picture); if(avctx->get_buffer(avctx, picture) < 0) { av_log(avctx, AV_LOG_ERROR, "Couldn't allocate image buffer.\n"); return -1; } for(x = 0; x < image->numcomps; x++) { adjust[x] = FFMAX(image->comps[x].prec - 8, 0); } for(y = 0; y < avctx->height; y++) { index = y*avctx->width; img_ptr = picture->data[0] + y*picture->linesize[0]; for(x = 0; x < avctx->width; x++, index++) { *img_ptr++ = image->comps[0].data[index] >> adjust[0]; if(image->numcomps > 2 && check_image_attributes(image)) { *img_ptr++ = image->comps[1].data[index] >> adjust[1]; *img_ptr++ = image->comps[2].data[index] >> adjust[2]; if(has_alpha) *img_ptr++ = image->comps[3].data[index] >> adjust[3]; } } }
dt_imageio_retval_t dt_imageio_open_j2k(dt_image_t *img, const char *filename, dt_mipmap_cache_allocator_t a) { opj_dparameters_t parameters; /* decompression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_image_t *image = NULL; FILE *fsrc = NULL; unsigned char *src = NULL; int file_length; opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ opj_cio_t *cio = NULL; OPJ_CODEC_FORMAT codec; int ret = DT_IMAGEIO_FILE_CORRUPTED; int file_format = get_file_format(filename); if(file_format == -1) return DT_IMAGEIO_FILE_CORRUPTED; if(!img->exif_inited) (void) dt_exif_read(img, filename); /* read the input file and put it in memory */ /* ---------------------------------------- */ fsrc = fopen(filename, "rb"); if(!fsrc) { fprintf(stderr, "[j2k_open] Error: failed to open `%s' for reading\n", filename); return DT_IMAGEIO_FILE_NOT_FOUND; } fseek(fsrc, 0, SEEK_END); file_length = ftell(fsrc); fseek(fsrc, 0, SEEK_SET); src = (unsigned char *) malloc(file_length); if(fread(src, 1, file_length, fsrc) != (size_t)file_length) { free(src); fclose(fsrc); fprintf(stderr, "[j2k_open] Error: fread returned a number of elements different from the expected.\n"); return DT_IMAGEIO_FILE_NOT_FOUND; } fclose(fsrc); if(memcmp(JP2_HEAD, src, sizeof(JP2_HEAD)) == 0) { file_format = JP2_CFMT; // just in case someone used the wrong extension } else if(memcmp(J2K_HEAD, src, sizeof(J2K_HEAD)) == 0) { file_format = J2K_CFMT; // just in case someone used the wrong extension } else // this will also reject jpt files. { free(src); fprintf(stderr, "[j2k_open] Error: `%s' has unsupported file format.\n", filename); return DT_IMAGEIO_FILE_CORRUPTED; } /* configure the event callbacks (not required) */ 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 decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); /* decode the code-stream */ /* ---------------------- */ if(file_format == J2K_CFMT) /* JPEG-2000 codestream */ codec = CODEC_J2K; else if(file_format == JP2_CFMT) /* JPEG 2000 compressed image data */ codec = CODEC_JP2; else if(file_format == JPT_CFMT) /* JPEG 2000, JPIP */ codec = CODEC_JPT; else { free(src); return DT_IMAGEIO_FILE_CORRUPTED; // can't happen } /* get a decoder handle */ dinfo = opj_create_decompress(codec); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); /* close the byte stream */ opj_cio_close(cio); /* free the memory containing the code-stream */ free(src); if(!image) { fprintf(stderr, "[j2k_open] Error: failed to decode image `%s'\n", filename); ret = DT_IMAGEIO_FILE_CORRUPTED; goto end_of_the_world; } if(image->color_space == CLRSPC_SYCC) { color_sycc_to_rgb(image); } //FIXME: openjpeg didn't have support for icc profiles before version 1.5 // this needs some #ifdef magic and proper implementation #ifdef HAVE_OPENJPEG_ICC if(image->icc_profile_buf) { #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) color_apply_icc_profile(image); #endif free(image->icc_profile_buf); image->icc_profile_buf = NULL; image->icc_profile_len = 0; } #endif /* create output image */ /* ------------------- */ long signed_offsets[4] = {0, 0, 0, 0}; int float_divs[4] = {1, 1, 1, 1}; // some sanity checks if(image->numcomps == 0 || image->x1 == 0 || image->y1 == 0) { fprintf(stderr, "[j2k_open] Error: invalid raw image parameters in `%s'\n", filename); ret = DT_IMAGEIO_FILE_CORRUPTED; goto end_of_the_world; } for(int i = 0; i < image->numcomps; i++) { if(image->comps[i].w != image->x1 || image->comps[i].h != image->y1) { fprintf(stderr, "[j2k_open] Error: some component has different size in `%s'\n", filename); ret = DT_IMAGEIO_FILE_CORRUPTED; goto end_of_the_world; } if(image->comps[i].prec > 16) { fprintf(stderr,"[j2k_open] Error: precision %d is larger than 16 in `%s'\n", image->comps[1].prec, filename); ret = DT_IMAGEIO_FILE_CORRUPTED; goto end_of_the_world; } } img->width = image->x1; img->height = image->y1; img->bpp = 4*sizeof(float); float *buf = (float *)dt_mipmap_cache_alloc(img, DT_MIPMAP_FULL, a); if(!buf) { ret = DT_IMAGEIO_CACHE_FULL; goto end_of_the_world; } int i = image->numcomps; if(i > 4) i = 4; while(i) { i--; if(image->comps[i].sgnd) signed_offsets[i] = 1 << (image->comps[i].prec - 1); float_divs[i] = (1 << image->comps[i].prec) - 1; } // numcomps == 1 : grey -> r = grey, g = grey, b = grey // numcomps == 2 : grey, alpha -> r = grey, g = grey, b = grey. put alpha into the mix? // numcomps == 3 : rgb -> rgb // numcomps == 4 : rgb, alpha -> rgb. put alpha into the mix? // first try: ignore alpha. if(image->numcomps < 3) // 1, 2 => grayscale { for(int i = 0; i < img->width * img->height; i++) buf[i*4 + 0] = buf[i*4 + 1] = buf[i*4 + 2] = (float)(image->comps[0].data[i] + signed_offsets[0]) / float_divs[0]; } else // 3, 4 => rgb { for(int i = 0; i < img->width * img->height; i++) for(int k = 0; k < 3; k++) buf[i*4 + k] = (float)(image->comps[k].data[i] + signed_offsets[k]) / float_divs[k]; } ret = DT_IMAGEIO_OK; end_of_the_world: /* free remaining structures */ if(dinfo) opj_destroy_decompress(dinfo); /* free image data structure */ opj_image_destroy(image); return ret; }
static GF_Err JP2_ProcessData(GF_MediaDecoder *ifcg, char *inBuffer, u32 inBufferLength, u16 ES_ID, char *outBuffer, u32 *outBufferLength, u8 PaddingBits, u32 mmlevel) { u32 i, w, wr, h, hr, wh; opj_dparameters_t parameters; /* decompression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ opj_cio_t *cio = NULL; opj_codestream_info_t cinfo; JP2CTX(); #if 1 switch (mmlevel) { case GF_CODEC_LEVEL_SEEK: case GF_CODEC_LEVEL_DROP: *outBufferLength = 0; return GF_OK; } #endif if (!ctx->image) { /* configure the event callbacks (not required) */ 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 decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_JP2); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); /* setup the decoder decoding parameters using the current image and user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ if (ctx->dsi) { char *data; data = gf_malloc(sizeof(char) * (ctx->dsi_size+inBufferLength)); memcpy(data, ctx->dsi, ctx->dsi_size); memcpy(data+ctx->dsi_size, inBuffer, inBufferLength); cio = opj_cio_open((opj_common_ptr)dinfo, data, ctx->dsi_size+inBufferLength); /* decode the stream and fill the image structure */ ctx->image = opj_decode(dinfo, cio); gf_free(data); } else { cio = opj_cio_open((opj_common_ptr)dinfo, inBuffer, inBufferLength); /* decode the stream and fill the image structure */ ctx->image = opj_decode_with_info(dinfo, cio, &cinfo); } //Fill the ctx info because dsi was not present if (ctx->image) { ctx->nb_comp = cinfo.numcomps; ctx->width = cinfo.image_w; ctx->height = cinfo.image_h; ctx->bpp = ctx->nb_comp * 8; ctx->out_size = ctx->width * ctx->height * ctx->nb_comp /* * ctx->bpp / 8 */; switch (ctx->nb_comp) { case 1: ctx->pixel_format = GF_PIXEL_GREYSCALE; break; case 2: ctx->pixel_format = GF_PIXEL_ALPHAGREY; break; case 3: ctx->pixel_format = GF_PIXEL_RGB_24; break; case 4: ctx->pixel_format = GF_PIXEL_RGBA; break; default: return GF_NOT_SUPPORTED; } if ( *outBufferLength < ctx->out_size ) { *outBufferLength = ctx->out_size; opj_destroy_decompress(dinfo); opj_cio_close(cio); return GF_BUFFER_TOO_SMALL; } } if(!ctx->image) { opj_destroy_decompress(dinfo); opj_cio_close(cio); return GF_IO_ERR; } /* close the byte stream */ opj_cio_close(cio); cio = NULL; /* gf_free( remaining structures */ if(dinfo) { opj_destroy_decompress(dinfo); dinfo = NULL; } } w = ctx->image->comps[0].w; wr = int_ceildivpow2(ctx->image->comps[0].w, ctx->image->comps[0].factor); h = ctx->image->comps[0].h; hr = int_ceildivpow2(ctx->image->comps[0].h, ctx->image->comps[0].factor); wh = wr*hr; if (ctx->nb_comp==1) { if ((w==wr) && (h==hr)) { for (i=0; i<wh; i++) { outBuffer[i] = ctx->image->comps[0].data[i]; } } else { for (i=0; i<wh; i++) { outBuffer[i] = ctx->image->comps[0].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)]; } } } else if (ctx->nb_comp==3) { if ((ctx->image->comps[0].w==2*ctx->image->comps[1].w) && (ctx->image->comps[1].w==ctx->image->comps[2].w) && (ctx->image->comps[0].h==2*ctx->image->comps[1].h) && (ctx->image->comps[1].h==ctx->image->comps[2].h)) { if (ctx->pixel_format != GF_PIXEL_YV12) { ctx->pixel_format = GF_PIXEL_YV12; ctx->out_size = 3*ctx->width*ctx->height/2; *outBufferLength = ctx->out_size; return GF_BUFFER_TOO_SMALL; } if ((w==wr) && (h==hr)) { for (i=0; i<wh; i++) { *outBuffer = ctx->image->comps[0].data[i]; outBuffer++; } w = ctx->image->comps[1].w; wr = int_ceildivpow2(ctx->image->comps[1].w, ctx->image->comps[1].factor); h = ctx->image->comps[1].h; hr = int_ceildivpow2(ctx->image->comps[1].h, ctx->image->comps[1].factor); wh = wr*hr; for (i=0; i<wh; i++) { *outBuffer = ctx->image->comps[1].data[i]; outBuffer++; } for (i=0; i<wh; i++) { *outBuffer = ctx->image->comps[2].data[i]; outBuffer++; } } else { for (i=0; i<wh; i++) { *outBuffer = ctx->image->comps[0].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)]; } w = ctx->image->comps[1].w; wr = int_ceildivpow2(ctx->image->comps[1].w, ctx->image->comps[1].factor); h = ctx->image->comps[1].h; hr = int_ceildivpow2(ctx->image->comps[1].h, ctx->image->comps[1].factor); wh = wr*hr; for (i=0; i<wh; i++) { *outBuffer = ctx->image->comps[1].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)]; } for (i=0; i<wh; i++) { *outBuffer = ctx->image->comps[2].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)]; } } } else if ((ctx->image->comps[0].w==ctx->image->comps[1].w) && (ctx->image->comps[1].w==ctx->image->comps[2].w) && (ctx->image->comps[0].h==ctx->image->comps[1].h) && (ctx->image->comps[1].h==ctx->image->comps[2].h)) { if ((w==wr) && (h==hr)) { for (i=0; i<wh; i++) { u32 idx = 3*i; outBuffer[idx] = ctx->image->comps[0].data[i]; outBuffer[idx+1] = ctx->image->comps[1].data[i]; outBuffer[idx+2] = ctx->image->comps[2].data[i]; } } else { for (i=0; i<wh; i++) { u32 idx = 3*i; outBuffer[idx] = ctx->image->comps[0].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)]; outBuffer[idx+1] = ctx->image->comps[1].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)]; outBuffer[idx+2] = ctx->image->comps[2].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)]; } } } } else if (ctx->nb_comp==4) { if ((ctx->image->comps[0].w==ctx->image->comps[1].w) && (ctx->image->comps[1].w==ctx->image->comps[2].w) && (ctx->image->comps[2].w==ctx->image->comps[3].w) && (ctx->image->comps[0].h==ctx->image->comps[1].h) && (ctx->image->comps[1].h==ctx->image->comps[2].h) && (ctx->image->comps[2].h==ctx->image->comps[3].h)) { if ((w==wr) && (h==hr)) { for (i=0; i<wh; i++) { u32 idx = 4*i; outBuffer[idx] = ctx->image->comps[0].data[i]; outBuffer[idx+1] = ctx->image->comps[1].data[i]; outBuffer[idx+2] = ctx->image->comps[2].data[i]; outBuffer[idx+3] = ctx->image->comps[3].data[i]; } } else { for (i=0; i<wh; i++) { u32 idx = 4*i; outBuffer[idx] = ctx->image->comps[0].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)]; outBuffer[idx+1] = ctx->image->comps[1].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)]; outBuffer[idx+2] = ctx->image->comps[2].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)]; outBuffer[idx+3] = ctx->image->comps[3].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)]; } } } } /* gf_free( image data structure */ if (ctx->image) { opj_image_destroy(ctx->image); ctx->image = NULL; } *outBufferLength = ctx->out_size; return GF_OK; }
/* -------------------------------------------------------------------------- -------------------- MAIN METHOD, CALLED BY JAVA -----------------------*/ JNIEXPORT jint JNICALL Java_org_openJpeg_OpenJPEGJavaDecoder_internalDecodeJ2KtoImage(JNIEnv *env, jobject obj, jobjectArray javaParameters) { int argc; /* To simulate the command line parameters (taken from the javaParameters variable) and be able to re-use the */ char **argv; /* 'parse_cmdline_decoder' method taken from the j2k_to_image project */ opj_dparameters_t parameters; /* decompression parameters */ img_fol_t img_fol; opj_event_mgr_t event_mgr; /* event manager */ opj_image_t *image = NULL; FILE *fsrc = NULL; unsigned char *src = NULL; int file_length; int num_images; int i,j,imageno; opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ opj_cio_t *cio = NULL; int w,h; long min_value, max_value; short tempS; unsigned char tempUC, tempUC1, tempUC2; /* ==> Access variables to the Java member variables*/ jsize arraySize; jclass cls; jobject object; jboolean isCopy; jfieldID fid; jbyteArray jba; jshortArray jsa; jintArray jia; jbyte *jbBody, *ptrBBody; jshort *jsBody, *ptrSBody; jint *jiBody, *ptrIBody; callback_variables_t msgErrorCallback_vars; /* <=== access variable to Java member variables */ int *ptr, *ptr1, *ptr2; /* <== To transfer the decoded image to Java*/ /* configure the event callbacks */ 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; /* JNI reference to the calling class*/ cls = (*env)->GetObjectClass(env, obj); /* Pointers to be able to call a Java method for all the info and error messages*/ msgErrorCallback_vars.env = env; msgErrorCallback_vars.jobj = &obj; msgErrorCallback_vars.message_mid = (*env)->GetMethodID(env, cls, "logMessage", "(Ljava/lang/String;)V"); msgErrorCallback_vars.error_mid = (*env)->GetMethodID(env, cls, "logError", "(Ljava/lang/String;)V"); /* Get the String[] containing the parameters, and converts it into a char** to simulate command line arguments.*/ arraySize = (*env)->GetArrayLength(env, javaParameters); argc = (int) arraySize +1; argv = opj_malloc(argc*sizeof(char*)); argv[0] = "ProgramName.exe"; /* The program name: useless*/ j=0; for (i=1; i<argc; i++) { object = (*env)->GetObjectArrayElement(env, javaParameters, i-1); argv[i] = (char*)(*env)->GetStringUTFChars(env, object, &isCopy); } /*printf("C: decoder params = "); for (i=0; i<argc; i++) { printf("[%s]",argv[i]); } printf("\n");*/ /* set decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); parameters.decod_format = J2K_CFMT; /* parse input and get user encoding parameters */ if(parse_cmdline_decoder(argc, argv, ¶meters,&img_fol) == 1) { /* Release the Java arguments array*/ for (i=1; i<argc; i++) (*env)->ReleaseStringUTFChars(env, (*env)->GetObjectArrayElement(env, javaParameters, i-1), argv[i]); return -1; } /* Release the Java arguments array*/ for (i=1; i<argc; i++) (*env)->ReleaseStringUTFChars(env, (*env)->GetObjectArrayElement(env, javaParameters, i-1), argv[i]); num_images=1; /* Get additional information from the Java object variables*/ fid = (*env)->GetFieldID(env, cls,"skippedResolutions", "I"); parameters.cp_reduce = (short) (*env)->GetIntField(env, obj, fid); /*Decoding image one by one*/ for(imageno = 0; imageno < num_images ; imageno++) { image = NULL; fprintf(stderr,"\n"); /* read the input file and put it in memory into the 'src' object, if the -i option is given in JavaParameters. Implemented for debug purpose. */ /* -------------------------------------------------------------- */ if (parameters.infile && parameters.infile[0]!='\0') { /*printf("C: opening [%s]\n", parameters.infile);*/ fsrc = fopen(parameters.infile, "rb"); if (!fsrc) { fprintf(stderr, "ERROR -> failed to open %s for reading\n", parameters.infile); return 1; } fseek(fsrc, 0, SEEK_END); file_length = ftell(fsrc); fseek(fsrc, 0, SEEK_SET); src = (unsigned char *) opj_malloc(file_length); fread(src, 1, file_length, fsrc); fclose(fsrc); /*printf("C: %d bytes read from file\n",file_length);*/ } else { /* Preparing the transfer of the codestream from Java to C*/ /*printf("C: before transfering codestream\n");*/ fid = (*env)->GetFieldID(env, cls,"compressedStream", "[B"); jba = (*env)->GetObjectField(env, obj, fid); file_length = (*env)->GetArrayLength(env, jba); jbBody = (*env)->GetByteArrayElements(env, jba, &isCopy); src = (unsigned char*)jbBody; } /* decode the code-stream */ /* ---------------------- */ switch(parameters.decod_format) { case J2K_CFMT: { /* JPEG-2000 codestream */ /* 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, &msgErrorCallback_vars); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); if(!image) { fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); opj_destroy_decompress(dinfo); opj_cio_close(cio); return 1; } /* close the byte stream */ opj_cio_close(cio); } break; case JP2_CFMT: { /* JPEG 2000 compressed image data */ /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_JP2); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, &msgErrorCallback_vars); /* setup the decoder decoding parameters using the current image and user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); if(!image) { fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); opj_destroy_decompress(dinfo); opj_cio_close(cio); return 1; } /* close the byte stream */ opj_cio_close(cio); } break; case JPT_CFMT: { /* JPEG 2000, JPIP */ /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_JPT); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, &msgErrorCallback_vars); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); if(!image) { fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); opj_destroy_decompress(dinfo); opj_cio_close(cio); return 1; } /* close the byte stream */ opj_cio_close(cio); } break; default: fprintf(stderr, "skipping file..\n"); continue; } /* free the memory containing the code-stream */ if (parameters.infile && parameters.infile[0]!='\0') { opj_free(src); } else { (*env)->ReleaseByteArrayElements(env, jba, jbBody, 0); } src = NULL; /* create output image. If the -o parameter is given in the JavaParameters, write the decoded version into a file. Implemented for debug purpose. */ /* ---------------------------------- */ switch (parameters.cod_format) { case PXM_DFMT: /* PNM PGM PPM */ if (imagetopnm(image, parameters.outfile)) { fprintf(stdout,"Outfile %s not generated\n",parameters.outfile); } else { fprintf(stdout,"Generated Outfile %s\n",parameters.outfile); } break; case PGX_DFMT: /* PGX */ if(imagetopgx(image, parameters.outfile)){ fprintf(stdout,"Outfile %s not generated\n",parameters.outfile); } else { fprintf(stdout,"Generated Outfile %s\n",parameters.outfile); } break; case BMP_DFMT: /* BMP */ if(imagetobmp(image, parameters.outfile)){ fprintf(stdout,"Outfile %s not generated\n",parameters.outfile); } else { fprintf(stdout,"Generated Outfile %s\n",parameters.outfile); } break; } /* ========= Return the image to the Java structure ===============*/ #ifdef CHECK_THRESHOLDS printf("C: checking thresholds\n"); #endif /* First compute the real with and height, in function of the resolutions decoded.*/ /*wr = (image->comps[0].w + (1 << image->comps[0].factor) -1) >> image->comps[0].factor;*/ /*hr = (image->comps[0].h + (1 << image->comps[0].factor) -1) >> image->comps[0].factor;*/ w = image->comps[0].w; h = image->comps[0].h; if (image->numcomps==3) { /* 3 components color image*/ ptr = image->comps[0].data; ptr1 = image->comps[1].data; ptr2 = image->comps[2].data; #ifdef CHECK_THRESHOLDS if (image->comps[0].sgnd) { min_value = -128; max_value = 127; } else { min_value = 0; max_value = 255; } #endif /* Get the pointer to the Java structure where the data must be copied*/ fid = (*env)->GetFieldID(env, cls,"image24", "[I"); jia = (*env)->GetObjectField(env, obj, fid); jiBody = (*env)->GetIntArrayElements(env, jia, 0); ptrIBody = jiBody; printf("C: transfering image24: %d int to Java pointer=%d\n",image->numcomps*w*h, ptrIBody); for (i=0; i<w*h; i++) { tempUC = (unsigned char)(ptr[i]); tempUC1 = (unsigned char)(ptr1[i]); tempUC2 = (unsigned char)(ptr2[i]); #ifdef CHECK_THRESHOLDS if (tempUC < min_value) tempUC=min_value; else if (tempUC > max_value) tempUC=max_value; if (tempUC1 < min_value) tempUC1=min_value; else if (tempUC1 > max_value) tempUC1=max_value; if (tempUC2 < min_value) tempUC2=min_value; else if (tempUC2 > max_value) tempUC2=max_value; #endif *(ptrIBody++) = (int) ( (tempUC2<<16) + (tempUC1<<8) + tempUC ); } (*env)->ReleaseIntArrayElements(env, jia, jiBody, 0); } else { /* 1 component 8 or 16 bpp image*/ ptr = image->comps[0].data; printf("C: before transfering a %d bpp image to java (length = %d)\n",image->comps[0].prec ,w*h); if (image->comps[0].prec<=8) { fid = (*env)->GetFieldID(env, cls,"image8", "[B"); jba = (*env)->GetObjectField(env, obj, fid); jbBody = (*env)->GetByteArrayElements(env, jba, 0); ptrBBody = jbBody; #ifdef CHECK_THRESHOLDS if (image->comps[0].sgnd) { min_value = -128; max_value = 127; } else { min_value = 0; max_value = 255; } #endif /*printf("C: transfering %d shorts to Java image8 pointer = %d\n", wr*hr,ptrSBody);*/ for (i=0; i<w*h; i++) { tempUC = (unsigned char) (ptr[i]); #ifdef CHECK_THRESHOLDS if (tempUC<min_value) tempUC = min_value; else if (tempUC > max_value) tempUC = max_value; #endif *(ptrBBody++) = tempUC; } (*env)->ReleaseByteArrayElements(env, jba, jbBody, 0); printf("C: image8 transfered to Java\n"); } else { fid = (*env)->GetFieldID(env, cls,"image16", "[S"); jsa = (*env)->GetObjectField(env, obj, fid); jsBody = (*env)->GetShortArrayElements(env, jsa, 0); ptrSBody = jsBody; #ifdef CHECK_THRESHOLDS if (image->comps[0].sgnd) { min_value = -32768; max_value = 32767; } else { min_value = 0; max_value = 65535; } printf("C: minValue = %d, maxValue = %d\n", min_value, max_value); #endif printf("C: transfering %d shorts to Java image16 pointer = %d\n", w*h,ptrSBody); for (i=0; i<w*h; i++) { tempS = (short) (ptr[i]); #ifdef CHECK_THRESHOLDS if (tempS<min_value) { printf("C: value %d truncated to %d\n", tempS, min_value); tempS = min_value; } else if (tempS > max_value) { printf("C: value %d truncated to %d\n", tempS, max_value); tempS = max_value; } #endif *(ptrSBody++) = tempS; } (*env)->ReleaseShortArrayElements(env, jsa, jsBody, 0); printf("C: image16 completely filled\n"); } } /* free remaining structures */ if(dinfo) { opj_destroy_decompress(dinfo); } /* free image data structure */ opj_image_destroy(image); } return 1; /* OK */ }
void OpenJpegDecoder::PerformDecode(DecodeRequestPtr request) { if (!request) return; DecodeResultPtr result(new DecodeResult()); result->id_ = request->id_; result->level_ = -1; // no level decoded yet result->max_levels_ = 5; result->original_width_ = 0; result->original_height_ = 0; result->components_ = 0; result->tag_ = request->tag_; // Guard against OpenJpeg crash on illegal data at an early phase unsigned char *data = (unsigned char *)request->source_->GetData(); if (data[0] != 0xFF) { TextureDecoderModule::LogError("Invalid data passed to PerformDecode!"); QueueResult<DecodeResult>(result); return; } opj_dinfo_t* dinfo = 0; // decoder opj_image_t *image = 0; // decoded image opj_dparameters_t parameters; // decoder parameters opj_cio_t *cio = 0; // decode stream opj_codestream_info_t cstr_info; // codestream info memset(&cstr_info, 0, sizeof(opj_codestream_info_t)); opj_event_mgr_t event_mgr; // decode event manager memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); event_mgr.error_handler = HandleError; //event_mgr.warning_handler = HandleWarning; //event_mgr.info_handler = HandleInfo; opj_set_default_decoder_parameters(¶meters); parameters.cp_reduce = request->level_; dinfo = opj_create_decompress(CODEC_J2K); opj_setup_decoder(dinfo, ¶meters); opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, this); cio = opj_cio_open((opj_common_ptr)dinfo, (unsigned char *)request->source_->GetData(), request->source_->GetSize()); image = opj_decode_with_info(dinfo, cio, &cstr_info); result->max_levels_ = cstr_info.numlayers; opj_cio_close(cio); opj_destroy_decompress(dinfo); if ((image) && (image->numcomps)) { result->original_width_ = image->x1 - image->x0; result->original_height_ = image->y1 - image->y0; result->components_ = image->numcomps; result->level_ = request->level_; // Assume all components are same size int actual_width = image->comps[0].w; int actual_height = image->comps[0].h; // Create a (possibly temporary, if no-one stores the pointer) raw texture resource Foundation::ResourcePtr resource(new TextureResource(request->source_->GetId(), actual_width, actual_height, image->numcomps)); TextureResource* texture = checked_static_cast<TextureResource*>(resource.get()); u8* data = texture->GetData(); texture->SetLevel(request->level_); for (int y = 0; y < actual_height; ++y) { for (int x = 0; x < actual_width; ++x) { for (int c = 0; c < image->numcomps; ++c) { *data = image->comps[c].data[y * actual_width + x]; data++; } } } result->texture_ = resource; } if (image) opj_image_destroy(image); QueueResult<DecodeResult>(result); }
J2kImageDecoder::~J2kImageDecoder() { opj_destroy_decompress(dinfo); }
static int libopenjpeg_decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) { uint8_t *buf = avpkt->data; int buf_size = avpkt->size; LibOpenJPEGContext *ctx = avctx->priv_data; AVFrame *picture = &ctx->image, *output = data; opj_dinfo_t *dec; opj_cio_t *stream; opj_image_t *image; int width, height, ret = -1; int pixel_size = 0; int ispacked = 0; *data_size = 0; // Check if input is a raw jpeg2k codestream or in jp2 wrapping if((AV_RB32(buf) == 12) && (AV_RB32(buf + 4) == JP2_SIG_TYPE) && (AV_RB32(buf + 8) == JP2_SIG_VALUE)) { dec = opj_create_decompress(CODEC_JP2); } else { // If the AVPacket contains a jp2c box, then skip to // the starting byte of the codestream. if (AV_RB32(buf + 4) == AV_RB32("jp2c")) buf += 8; dec = opj_create_decompress(CODEC_J2K); } if(!dec) { av_log(avctx, AV_LOG_ERROR, "Error initializing decoder.\n"); return -1; } opj_set_event_mgr((opj_common_ptr)dec, NULL, NULL); ctx->dec_params.cp_limit_decoding = LIMIT_TO_MAIN_HEADER; // Tie decoder with decoding parameters opj_setup_decoder(dec, &ctx->dec_params); stream = opj_cio_open((opj_common_ptr)dec, buf, buf_size); if(!stream) { av_log(avctx, AV_LOG_ERROR, "Codestream could not be opened for reading.\n"); opj_destroy_decompress(dec); return -1; } // Decode the header only image = opj_decode_with_info(dec, stream, NULL); opj_cio_close(stream); if(!image) { av_log(avctx, AV_LOG_ERROR, "Error decoding codestream.\n"); opj_destroy_decompress(dec); return -1; } width = image->x1 - image->x0; height = image->y1 - image->y0; if(av_image_check_size(width, height, 0, avctx) < 0) { av_log(avctx, AV_LOG_ERROR, "%dx%d dimension invalid.\n", width, height); goto done; } avcodec_set_dimensions(avctx, width, height); if (avctx->pix_fmt != PIX_FMT_NONE) { if (!libopenjpeg_matches_pix_fmt(image, avctx->pix_fmt)) { avctx->pix_fmt = PIX_FMT_NONE; } } if (avctx->pix_fmt == PIX_FMT_NONE) { avctx->pix_fmt = libopenjpeg_guess_pix_fmt(image); } if (avctx->pix_fmt == PIX_FMT_NONE) { av_log(avctx, AV_LOG_ERROR, "Unable to determine pixel format\n"); goto done; } if(picture->data[0]) ff_thread_release_buffer(avctx, picture); if(ff_thread_get_buffer(avctx, picture) < 0){ av_log(avctx, AV_LOG_ERROR, "ff_thread_get_buffer() failed\n"); goto done; } ctx->dec_params.cp_limit_decoding = NO_LIMITATION; ctx->dec_params.cp_reduce = avctx->lowres; // Tie decoder with decoding parameters opj_setup_decoder(dec, &ctx->dec_params); stream = opj_cio_open((opj_common_ptr)dec, buf, buf_size); if(!stream) { av_log(avctx, AV_LOG_ERROR, "Codestream could not be opened for reading.\n"); goto done; } opj_image_destroy(image); // Decode the codestream image = opj_decode_with_info(dec, stream, NULL); opj_cio_close(stream); if(!image) { av_log(avctx, AV_LOG_ERROR, "Error decoding codestream.\n"); goto done; } pixel_size = av_pix_fmt_descriptors[avctx->pix_fmt].comp[0].step_minus1 + 1; ispacked = libopenjpeg_ispacked(avctx->pix_fmt); switch (pixel_size) { case 1: if (ispacked) { libopenjpeg_copy_to_packed8(picture, image); } else { libopenjpeg_copyto8(picture, image); } break; case 2: if (ispacked) { libopenjpeg_copy_to_packed8(picture, image); } else { libopenjpeg_copyto16(picture, image); } break; case 3: case 4: if (ispacked) { libopenjpeg_copy_to_packed8(picture, image); } break; case 6: case 8: if (ispacked) { libopenjpeg_copy_to_packed16(picture, image); } break; default: av_log(avctx, AV_LOG_ERROR, "unsupported pixel size %d\n", pixel_size); goto done; } *output = ctx->image; *data_size = sizeof(AVPicture); ret = buf_size; done: opj_image_destroy(image); opj_destroy_decompress(dec); return ret; }
BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) { // // FIXME: Get the comment field out of the texture // LLTimer decode_timer; opj_dparameters_t parameters; /* decompression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_image_t *image = NULL; opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ opj_cio_t *cio = NULL; /* configure the event callbacks (not required) */ 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 decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); parameters.cp_reduce = base.getRawDiscardLevel(); /* decode the code-stream */ /* ---------------------- */ /* JPEG-2000 codestream */ /* 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, stderr); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize()); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); /* close the byte stream */ opj_cio_close(cio); /* free remaining structures */ if(dinfo) { opj_destroy_decompress(dinfo); } // The image decode failed if the return was NULL or the component // count was zero. The latter is just a sanity check before we // dereference the array. if(!image || !image->numcomps) { LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image!" << LL_ENDL; if (image) { opj_image_destroy(image); } return TRUE; // done } // sometimes we get bad data out of the cache - check to see if the decode succeeded for (S32 i = 0; i < image->numcomps; i++) { if (image->comps[i].factor != base.getRawDiscardLevel()) { // if we didn't get the discard level we're expecting, fail opj_image_destroy(image); base.mDecoding = FALSE; return TRUE; } } if(image->numcomps <= first_channel) { llwarns << "trying to decode more channels than are present in image: numcomps: " << image->numcomps << " first_channel: " << first_channel << llendl; if (image) { opj_image_destroy(image); } return TRUE; } // Copy image data into our raw image format (instead of the separate channel format S32 img_components = image->numcomps; S32 channels = img_components - first_channel; if( channels > max_channel_count ) channels = max_channel_count; // Component buffers are allocated in an image width by height buffer. // The image placed in that buffer is ceil(width/2^factor) by // ceil(height/2^factor) and if the factor isn't zero it will be at the // top left of the buffer with black filled in the rest of the pixels. // It is integer math so the formula is written in ceildivpo2. // (Assuming all the components have the same width, height and // factor.) S32 comp_width = image->comps[0].w; S32 f=image->comps[0].factor; S32 width = ceildivpow2(image->x1 - image->x0, f); S32 height = ceildivpow2(image->y1 - image->y0, f); raw_image.resize(width, height, channels); U8 *rawp = raw_image.getData(); // first_channel is what channel to start copying from // dest is what channel to copy to. first_channel comes from the // argument, dest always starts writing at channel zero. for (S32 comp = first_channel, dest=0; comp < first_channel + channels; comp++, dest++) { if (image->comps[comp].data) { S32 offset = dest; for (S32 y = (height - 1); y >= 0; y--) { for (S32 x = 0; x < width; x++) { rawp[offset] = image->comps[comp].data[y*comp_width + x]; offset += channels; } } } else // Some rare OpenJPEG versions have this bug. { LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << LL_ENDL; opj_image_destroy(image); return TRUE; // done } } /* free image data structure */ opj_image_destroy(image); return TRUE; // done }
struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { struct ImBuf *ibuf = NULL; bool use_float = false; /* for precision higher then 8 use float */ bool use_alpha = false; long signed_offsets[4] = {0, 0, 0, 0}; int float_divs[4] = {1, 1, 1, 1}; unsigned int i, i_next, w, h, planes; unsigned int y; int *r, *g, *b, *a; /* matching 'opj_image_comp.data' type */ int is_jp2, is_j2k; opj_dparameters_t parameters; /* decompression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_image_t *image = NULL; opj_dinfo_t *dinfo = NULL; /* handle to a decompressor */ opj_cio_t *cio = NULL; is_jp2 = check_jp2(mem); is_j2k = check_j2k(mem); if (!is_jp2 && !is_j2k) return(NULL); /* both 8, 12 and 16 bit JP2Ks are default to standard byte colorspace */ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); /* configure the event callbacks (not required) */ 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 decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); /* JPEG 2000 compressed image data */ /* get a decoder handle */ dinfo = opj_create_decompress(is_jp2 ? CODEC_JP2 : CODEC_J2K); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); /* setup the decoder decoding parameters using the current image and user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, mem, size); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); if (!image) { fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); opj_destroy_decompress(dinfo); opj_cio_close(cio); return NULL; } /* close the byte stream */ opj_cio_close(cio); if ((image->numcomps * image->x1 * image->y1) == 0) { fprintf(stderr, "\nError: invalid raw image parameters\n"); return NULL; } w = image->comps[0].w; h = image->comps[0].h; switch (image->numcomps) { case 1: /* Grayscale */ case 3: /* Color */ planes = 24; use_alpha = false; break; default: /* 2 or 4 - Grayscale or Color + alpha */ planes = 32; /* grayscale + alpha */ use_alpha = true; break; } i = image->numcomps; if (i > 4) i = 4; while (i) { i--; if (image->comps[i].prec > 8) use_float = true; if (image->comps[i].sgnd) signed_offsets[i] = 1 << (image->comps[i].prec - 1); /* only needed for float images but dosnt hurt to calc this */ float_divs[i] = (1 << image->comps[i].prec) - 1; } ibuf = IMB_allocImBuf(w, h, planes, use_float ? IB_rectfloat : IB_rect); if (ibuf == NULL) { if (dinfo) opj_destroy_decompress(dinfo); return NULL; } ibuf->ftype = JP2; if (is_jp2) ibuf->ftype |= JP2_JP2; else ibuf->ftype |= JP2_J2K; if (use_float) { float *rect_float = ibuf->rect_float; if (image->numcomps < 3) { r = image->comps[0].data; a = (use_alpha) ? image->comps[1].data : NULL; /* grayscale 12bits+ */ if (use_alpha) { a = image->comps[1].data; PIXEL_LOOPER_BEGIN(rect_float) { rect_float[0] = rect_float[1] = rect_float[2] = (float)(r[i] + signed_offsets[0]) / float_divs[0]; rect_float[3] = (a[i] + signed_offsets[1]) / float_divs[1]; } PIXEL_LOOPER_END; } else { PIXEL_LOOPER_BEGIN(rect_float) { rect_float[0] = rect_float[1] = rect_float[2] = (float)(r[i] + signed_offsets[0]) / float_divs[0]; rect_float[3] = 1.0f; } PIXEL_LOOPER_END; } }
static FIBITMAP * DLL_CALLCONV Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { if (handle) { opj_dparameters_t parameters; // decompression parameters opj_event_mgr_t event_mgr; // event manager opj_image_t *image = NULL; // decoded image BYTE *src = NULL; long file_length; opj_dinfo_t* dinfo = NULL; // handle to a decompressor opj_cio_t *cio = NULL; FIBITMAP *dib = NULL; // check the file format if(!Validate(io, handle)) { return NULL; } // configure the event callbacks memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); event_mgr.error_handler = jp2_error_callback; event_mgr.warning_handler = jp2_warning_callback; event_mgr.info_handler = NULL; // set decoding parameters to default values opj_set_default_decoder_parameters(¶meters); try { // read the input file and put it in memory long start_pos = io->tell_proc(handle); io->seek_proc(handle, 0, SEEK_END); file_length = io->tell_proc(handle) - start_pos; io->seek_proc(handle, start_pos, SEEK_SET); src = (BYTE*)malloc(file_length * sizeof(BYTE)); if(!src) { throw FI_MSG_ERROR_MEMORY; } if(io->read_proc(src, 1, file_length, handle) < 1) { throw "Error while reading input stream"; } // decode the JPEG-2000 file // get a decoder handle dinfo = opj_create_decompress(CODEC_JP2); // catch events using our callbacks opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL); // setup the decoder decoding parameters using user parameters opj_setup_decoder(dinfo, ¶meters); // open a byte stream cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); // decode the stream and fill the image structure image = opj_decode(dinfo, cio); if(!image) { throw "Failed to decode image!\n"; } // close the byte stream opj_cio_close(cio); cio = NULL; // free the memory containing the code-stream free(src); src = NULL; // free the codec context opj_destroy_decompress(dinfo); // create output image dib = J2KImageToFIBITMAP(s_format_id, image); if(!dib) throw "Failed to import JPEG2000 image"; // free image data structure opj_image_destroy(image); return dib; } catch (const char *text) { if(src) free(src); if(dib) FreeImage_Unload(dib); // free remaining structures opj_destroy_decompress(dinfo); opj_image_destroy(image); // close the byte stream if(cio) opj_cio_close(cio); FreeImage_OutputMessageProc(s_format_id, text); return NULL; } } return NULL; }
BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) { raw_image.decodedComment = LLImageMetaDataReader::ExtractKDUUploadComment(base.getData(), base.getDataSize()); LLTimer decode_timer; opj_dparameters_t parameters; /* decompression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_image_t *image = NULL; opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ opj_cio_t *cio = NULL; /* configure the event callbacks (not required) */ 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 decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); parameters.cp_reduce = base.getRawDiscardLevel(); /* decode the code-stream */ /* ---------------------- */ /* JPEG-2000 codestream */ /* 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, stderr); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize()); /* decode the stream and fill the image structure. Also fill in an additional structur to get the decoding result. This structure is a bit unusual in that it is not received through opj, but still has somt dynamically allocated fields that need to be cleared up at the end by calling a destroy function. */ opj_codestream_info_t cinfo; memset(&cinfo, 0, sizeof(opj_codestream_info_t)); image = opj_decode_with_info(dinfo, cio, &cinfo); /* close the byte stream */ opj_cio_close(cio); /* free remaining structures */ if(dinfo) { opj_destroy_decompress(dinfo); } // The image decode failed if the return was NULL or the component // count was zero. The latter is just a sanity check before we // dereference the array. if(!image) { LL_WARNS ("Openjpeg") << "Failed to decode image at discard: " << (S32)base.getRawDiscardLevel() << ". No image." << LL_ENDL; if (base.getRawDiscardLevel() == 0) { base.decodeFailed(); } return TRUE; // done } S32 img_components = image->numcomps; if( !img_components ) // < 1 ||img_components > 4 ) { LL_WARNS("Openjpeg") << "Failed to decode image at discard: " << (S32)base.getRawDiscardLevel() << ". Wrong number of components: " << img_components << LL_ENDL; if (image) { opj_destroy_cstr_info(&cinfo); opj_image_destroy(image); } if (base.getRawDiscardLevel() == 0) { base.decodeFailed(); } return TRUE; // done } // sometimes we get bad data out of the cache - check to see if the decode succeeded int decompdifference = 0; if (cinfo.numdecompos) // sanity { for (int comp = 0; comp < image->numcomps; comp++) { /* get maximum decomposition level difference, first field is from the COD header and the second is what is actually met in the codestream, NB: if everything was ok, this calculation will return what was set in the cp_reduce value! */ decompdifference = llmax(decompdifference, cinfo.numdecompos[comp] - image->comps[comp].resno_decoded); } if (decompdifference < 0) // sanity { decompdifference = 0; } } /* if OpenJPEG failed to decode all requested decomposition levels the difference will be greater than this level */ if (decompdifference > base.getRawDiscardLevel()) { LL_WARNS("Openjpeg") << "Not enough data for requested discard level " << (S32)base.getRawDiscardLevel() << ", difference: " << (decompdifference - base.getRawDiscardLevel()) << llendl; opj_destroy_cstr_info(&cinfo); opj_image_destroy(image); if (base.getRawDiscardLevel() == 0) { base.decodeFailed(); } return TRUE; } if(img_components <= first_channel) { LL_WARNS("Openjpeg") << "Trying to decode more channels than are present in image, numcomps: " << img_components << " first_channel: " << first_channel << LL_ENDL; if (image) { opj_destroy_cstr_info(&cinfo); opj_image_destroy(image); } if (base.getRawDiscardLevel() == 0) { base.decodeFailed(); } return TRUE; } // Copy image data into our raw image format (instead of the separate channel format S32 channels = img_components - first_channel; if( channels > max_channel_count ) channels = max_channel_count; // Component buffers are allocated in an image width by height buffer. // The image placed in that buffer is ceil(width/2^factor) by // ceil(height/2^factor) and if the factor isn't zero it will be at the // top left of the buffer with black filled in the rest of the pixels. // It is integer math so the formula is written in ceildivpo2. // (Assuming all the components have the same width, height and // factor.) S32 comp_width = image->comps[0].w; S32 f=image->comps[0].factor; S32 width = ceildivpow2(image->x1 - image->x0, f); S32 height = ceildivpow2(image->y1 - image->y0, f); raw_image.resize(width, height, channels); U8 *rawp = raw_image.getData(); // first_channel is what channel to start copying from // dest is what channel to copy to. first_channel comes from the // argument, dest always starts writing at channel zero. for (S32 comp = first_channel, dest=0; comp < first_channel + channels; comp++, dest++) { if (image->comps[comp].data) { S32 offset = dest; for (S32 y = (height - 1); y >= 0; y--) { for (S32 x = 0; x < width; x++) { rawp[offset] = image->comps[comp].data[y*comp_width + x]; offset += channels; } } } else // Some rare OpenJPEG versions have this bug. { LL_WARNS("Openjpeg") << "Failed to decode image! (NULL comp data - OpenJPEG bug)" << LL_ENDL; opj_destroy_cstr_info(&cinfo); opj_image_destroy(image); if (base.getRawDiscardLevel() == 0) { base.decodeFailed(); } return TRUE; // done } } /* free opj data structures */ if (image) { opj_destroy_cstr_info(&cinfo); opj_image_destroy(image); } return TRUE; // done }