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

Generated on Thu Jul 1 06:08:44 2010 for Second Life Viewer by  doxygen 1.4.7