llimagej2coj.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 #include "llimagej2coj.h"
00034 
00035 // this is defined so that we get static linking.
00036 #include "openjpeg/openjpeg.h"
00037 
00038 #include "lltimer.h"
00039 #include "llmemory.h"
00040 
00041 const char* fallbackEngineInfoLLImageJ2CImpl()
00042 {
00043         static std::string version_string =
00044                 std::string("OpenJPEG: " OPENJPEG_VERSION ", Runtime: ")
00045                 + opj_version();
00046         return version_string.c_str();
00047 }
00048 
00049 LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl()
00050 {
00051         return new LLImageJ2COJ();
00052 }
00053 
00054 void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl)
00055 {
00056         delete impl;
00057         impl = NULL;
00058 }
00059 
00063 void error_callback(const char* msg, void*)
00064 {
00065         lldebugs << "LLImageJ2CImpl error_callback: " << msg << llendl;
00066 }
00070 void warning_callback(const char* msg, void*)
00071 {
00072         lldebugs << "LLImageJ2CImpl warning_callback: " << msg << llendl;
00073 }
00077 void info_callback(const char* msg, void*)
00078 {
00079         lldebugs << "LLImageJ2CImpl info_callback: " << msg << llendl;
00080 }
00081 
00082 
00083 LLImageJ2COJ::LLImageJ2COJ() : LLImageJ2CImpl()
00084 {
00085 }
00086 
00087 
00088 LLImageJ2COJ::~LLImageJ2COJ()
00089 {
00090 }
00091 
00092 
00093 BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
00094 {
00095         //
00096         // FIXME: Get the comment field out of the texture
00097         //
00098 
00099         LLTimer decode_timer;
00100 
00101         opj_dparameters_t parameters;   /* decompression parameters */
00102         opj_event_mgr_t event_mgr;              /* event manager */
00103         opj_image_t *image = NULL;
00104 
00105         opj_dinfo_t* dinfo = NULL;      /* handle to a decompressor */
00106         opj_cio_t *cio = NULL;
00107 
00108 
00109         /* configure the event callbacks (not required) */
00110         memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
00111         event_mgr.error_handler = error_callback;
00112         event_mgr.warning_handler = warning_callback;
00113         event_mgr.info_handler = info_callback;
00114 
00115         /* set decoding parameters to default values */
00116         opj_set_default_decoder_parameters(&parameters);
00117 
00118         parameters.cp_reduce = base.getRawDiscardLevel();
00119 
00120         /* decode the code-stream */
00121         /* ---------------------- */
00122 
00123         /* JPEG-2000 codestream */
00124 
00125         /* get a decoder handle */
00126         dinfo = opj_create_decompress(CODEC_J2K);
00127 
00128         /* catch events using our callbacks and give a local context */
00129         opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);                   
00130 
00131         /* setup the decoder decoding parameters using user parameters */
00132         opj_setup_decoder(dinfo, &parameters);
00133 
00134         /* open a byte stream */
00135         cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize());
00136 
00137         /* decode the stream and fill the image structure */
00138         image = opj_decode(dinfo, cio);
00139 
00140         /* close the byte stream */
00141         opj_cio_close(cio);
00142 
00143         /* free remaining structures */
00144         if(dinfo)
00145         {
00146                 opj_destroy_decompress(dinfo);
00147         }
00148 
00149         // The image decode failed if the return was NULL or the component
00150         // count was zero.  The latter is just a sanity check before we
00151         // dereference the array.
00152         if(!image || !image->numcomps)
00153         {
00154                 fprintf(stderr, "ERROR -> decodeImpl: failed to decode image!\n");
00155                 if (image)
00156                         opj_image_destroy(image);
00157 
00158                 return TRUE; // done
00159         }
00160 
00161         // sometimes we get bad data out of the cache - check to see if the decode succeeded
00162         for (S32 i = 0; i < image->numcomps; i++)
00163         {
00164                 if (image->comps[i].factor != base.getRawDiscardLevel())
00165                 {
00166                         // if we didn't get the discard level we're expecting, fail
00167                         opj_image_destroy(image);
00168                         base.mDecoding = FALSE;
00169                         return TRUE;
00170                 }
00171         }
00172         
00173         // Copy image data into our raw image format (instead of the separate channel format
00174 
00175         S32 img_components = image->numcomps;
00176         S32 channels = img_components - first_channel;
00177         if( channels > max_channel_count )
00178                 channels = max_channel_count;
00179 
00180         // Component buffers are allocated in an image width by height buffer.
00181         // The image placed in that buffer is ceil(width/2^factor) by
00182         // ceil(height/2^factor) and if the factor isn't zero it will be at the
00183         // top left of the buffer with black filled in the rest of the pixels.
00184         // It is integer math so the formula is written in ceildivpo2.
00185         // (Assuming all the components have the same width, height and
00186         // factor.)
00187         S32 comp_width = image->comps[0].w;
00188         S32 f=image->comps[0].factor;
00189         S32 width = ceildivpow2(image->x1 - image->x0, f);
00190         S32 height = ceildivpow2(image->y1 - image->y0, f);
00191         raw_image.resize(width, height, channels);
00192         U8 *rawp = raw_image.getData();
00193 
00194         // first_channel is what channel to start copying from
00195         // dest is what channel to copy to.  first_channel comes from the
00196         // argument, dest always starts writing at channel zero.
00197         for (S32 comp = first_channel, dest=0; comp < first_channel + channels;
00198                 comp++, dest++)
00199         {
00200                 if (image->comps[comp].data)
00201                 {
00202                         S32 offset = dest;
00203                         for (S32 y = (height - 1); y >= 0; y--)
00204                         {
00205                                 for (S32 x = 0; x < width; x++)
00206                                 {
00207                                         rawp[offset] = image->comps[comp].data[y*comp_width + x];
00208                                         offset += channels;
00209                                 }
00210                         }
00211                 }
00212                 else // Some rare OpenJPEG versions have this bug.
00213                 {
00214                         fprintf(stderr, "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)\n");
00215                         opj_image_destroy(image);
00216 
00217                         return TRUE; // done
00218                 }
00219         }
00220 
00221         /* free image data structure */
00222         opj_image_destroy(image);
00223 
00224         return TRUE; // done
00225 }
00226 
00227 
00228 BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, BOOL reversible)
00229 {
00230         const S32 MAX_COMPS = 5;
00231         opj_cparameters_t parameters;   /* compression parameters */
00232         opj_event_mgr_t event_mgr;              /* event manager */
00233 
00234 
00235         /* 
00236         configure the event callbacks (not required)
00237         setting of each callback is optional 
00238         */
00239         memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
00240         event_mgr.error_handler = error_callback;
00241         event_mgr.warning_handler = warning_callback;
00242         event_mgr.info_handler = info_callback;
00243 
00244         /* set encoding parameters to default values */
00245         opj_set_default_encoder_parameters(&parameters);
00246         parameters.cod_format = 0;
00247         parameters.cp_disto_alloc = 1;
00248 
00249         if (reversible)
00250         {
00251                 parameters.tcp_numlayers = 1;
00252                 parameters.tcp_rates[0] = 0.0f;
00253         }
00254         else
00255         {
00256                 parameters.tcp_numlayers = 5;
00257                 parameters.tcp_rates[0] = 1920.0f;
00258                 parameters.tcp_rates[1] = 480.0f;
00259                 parameters.tcp_rates[2] = 120.0f;
00260                 parameters.tcp_rates[3] = 30.0f;
00261                 parameters.tcp_rates[4] = 10.0f;
00262                 parameters.irreversible = 1;
00263                 if (raw_image.getComponents() >= 3)
00264                 {
00265                         parameters.tcp_mct = 1;
00266                 }
00267         }
00268 
00269         if (!comment_text)
00270         {
00271                 parameters.cp_comment = "";
00272         }
00273         else
00274         {
00275                 // Awful hacky cast, too lazy to copy right now.
00276                 parameters.cp_comment = (char *)comment_text;
00277         }
00278 
00279         //
00280         // Fill in the source image from our raw image
00281         //
00282         OPJ_COLOR_SPACE color_space = CLRSPC_SRGB;
00283         opj_image_cmptparm_t cmptparm[MAX_COMPS];
00284         opj_image_t * image = NULL;
00285         S32 numcomps = raw_image.getComponents();
00286         S32 width = raw_image.getWidth();
00287         S32 height = raw_image.getHeight();
00288 
00289         memset(&cmptparm[0], 0, MAX_COMPS * sizeof(opj_image_cmptparm_t));
00290         for(S32 c = 0; c < numcomps; c++) {
00291                 cmptparm[c].prec = 8;
00292                 cmptparm[c].bpp = 8;
00293                 cmptparm[c].sgnd = 0;
00294                 cmptparm[c].dx = parameters.subsampling_dx;
00295                 cmptparm[c].dy = parameters.subsampling_dy;
00296                 cmptparm[c].w = width;
00297                 cmptparm[c].h = height;
00298         }
00299 
00300         /* create the image */
00301         image = opj_image_create(numcomps, &cmptparm[0], color_space);
00302 
00303         image->x1 = width;
00304         image->y1 = height;
00305 
00306         S32 i = 0;
00307         const U8 *src_datap = raw_image.getData();
00308         for (S32 y = height - 1; y >= 0; y--)
00309         {
00310                 for (S32 x = 0; x < width; x++)
00311                 {
00312                         const U8 *pixel = src_datap + (y*width + x) * numcomps;
00313                         for (S32 c = 0; c < numcomps; c++)
00314                         {
00315                                 image->comps[c].data[i] = *pixel;
00316                                 pixel++;
00317                         }
00318                         i++;
00319                 }
00320         }
00321 
00322 
00323 
00324         /* encode the destination image */
00325         /* ---------------------------- */
00326 
00327         int codestream_length;
00328         opj_cio_t *cio = NULL;
00329 
00330         /* get a J2K compressor handle */
00331         opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K);
00332 
00333         /* catch events using our callbacks and give a local context */
00334         opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);                   
00335 
00336         /* setup the encoder parameters using the current image and using user parameters */
00337         opj_setup_encoder(cinfo, &parameters, image);
00338 
00339         /* open a byte stream for writing */
00340         /* allocate memory for all tiles */
00341         cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
00342 
00343         /* encode the image */
00344         bool bSuccess = opj_encode(cinfo, cio, image, NULL);
00345         if (!bSuccess)
00346         {
00347                 opj_cio_close(cio);
00348                 llinfos << "Failed to encode image." << llendl;
00349                 return FALSE;
00350         }
00351         codestream_length = cio_tell(cio);
00352 
00353         base.copyData(cio->buffer, codestream_length);
00354         base.updateData(); // set width, height
00355 
00356         /* close and free the byte stream */
00357         opj_cio_close(cio);
00358 
00359         /* free remaining compression structures */
00360         opj_destroy_compress(cinfo);
00361 
00362 
00363         /* free user parameters structure */
00364         if(parameters.cp_matrice) free(parameters.cp_matrice);
00365 
00366         /* free image data */
00367         opj_image_destroy(image);
00368         return TRUE;
00369 }
00370 
00371 BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base)
00372 {
00373         //
00374         // FIXME: We get metadata by decoding the ENTIRE image.
00375         //
00376 
00377         // Update the raw discard level
00378         base.updateRawDiscardLevel();
00379 
00380         opj_dparameters_t parameters;   /* decompression parameters */
00381         opj_event_mgr_t event_mgr;              /* event manager */
00382         opj_image_t *image = NULL;
00383 
00384         opj_dinfo_t* dinfo = NULL;      /* handle to a decompressor */
00385         opj_cio_t *cio = NULL;
00386 
00387 
00388         /* configure the event callbacks (not required) */
00389         memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
00390         event_mgr.error_handler = error_callback;
00391         event_mgr.warning_handler = warning_callback;
00392         event_mgr.info_handler = info_callback;
00393 
00394         /* set decoding parameters to default values */
00395         opj_set_default_decoder_parameters(&parameters);
00396 
00397         // Only decode what's required to get the size data.
00398         parameters.cp_limit_decoding=LIMIT_TO_MAIN_HEADER;
00399 
00400         //parameters.cp_reduce = mRawDiscardLevel;
00401 
00402         /* decode the code-stream */
00403         /* ---------------------- */
00404 
00405         /* JPEG-2000 codestream */
00406 
00407         /* get a decoder handle */
00408         dinfo = opj_create_decompress(CODEC_J2K);
00409 
00410         /* catch events using our callbacks and give a local context */
00411         opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);                   
00412 
00413         /* setup the decoder decoding parameters using user parameters */
00414         opj_setup_decoder(dinfo, &parameters);
00415 
00416         /* open a byte stream */
00417         cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize());
00418 
00419         /* decode the stream and fill the image structure */
00420         image = opj_decode(dinfo, cio);
00421 
00422         /* close the byte stream */
00423         opj_cio_close(cio);
00424 
00425         /* free remaining structures */
00426         if(dinfo)
00427         {
00428                 opj_destroy_decompress(dinfo);
00429         }
00430 
00431         if(!image)
00432         {
00433                 fprintf(stderr, "ERROR -> getMetadata: failed to decode image!\n");
00434                 return FALSE;
00435         }
00436 
00437         // Copy image data into our raw image format (instead of the separate channel format
00438         S32 width = 0;
00439         S32 height = 0;
00440 
00441         S32 img_components = image->numcomps;
00442         width = image->x1 - image->x0;
00443         height = image->y1 - image->y0;
00444         base.setSize(width, height, img_components);
00445 
00446         /* free image data structure */
00447         opj_image_destroy(image);
00448         return TRUE;
00449 }

Generated on Fri May 16 08:32:11 2008 for SecondLife by  doxygen 1.5.5