NCEPLIBS-g2c  1.6.4
decenc_openjpeg.c
Go to the documentation of this file.
1 
19 #if !defined USE_JPEG2000 && defined USE_OPENJPEG
20 
21 #include "grib2.h"
22 #include "openjpeg.h"
23 
24 #include <assert.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
37 static void openjpeg_warning(const char *msg, void *client_data)
38 {
39  (void)client_data;
40  fprintf(stderr,"openjpeg: %s",msg);
41 }
42 
51 static void openjpeg_error(const char *msg, void *client_data)
52 {
53  (void)client_data;
54  fprintf(stderr,"openjpeg: %s",msg);
55 }
56 
65 static void openjpeg_info(const char *msg, void *client_data)
66 {
67  (void)msg;
68  (void)client_data;
69  /* fprintf(stderr,"openjpeg: %s",msg); */
70 }
71 
72 /* opj_* Helper code from
73  * https://groups.google.com/forum/#!topic/openjpeg/8cebr0u7JgY
74  */
75 /* These routines are added to use memory instead of a file for input and output */
76 /* struct need to treat memory as a stream */
77 typedef struct
78 {
79  OPJ_UINT8* pData; /* our data */
80  OPJ_SIZE_T dataSize; /* how big is our data */
81  OPJ_SIZE_T offset; /* where we are currently in our data */
82 } opj_memory_stream;
83 
95 static OPJ_SIZE_T opj_memory_stream_read(void *buffer, OPJ_SIZE_T nb_bytes, void * p_user_data)
96 {
97  opj_memory_stream* mstream = (opj_memory_stream*) p_user_data; /* Our data */
98  OPJ_SIZE_T nb_bytes_read = nb_bytes; /* Amount to move to buffer */
99 
100  /* Check if the current offset is outside our data buffer */
101  if (mstream->offset >= mstream->dataSize)
102  return (OPJ_SIZE_T) -1;
103 
104  /* Check if we are reading more than we have */
105  if (nb_bytes > (mstream->dataSize - mstream->offset))
106  nb_bytes_read = mstream->dataSize - mstream->offset;
107 
108  memcpy(buffer, &(mstream->pData[mstream->offset]), nb_bytes_read);
109  mstream->offset += nb_bytes_read; /* Update the pointer to the new location */
110  return nb_bytes_read;
111 }
112 
124 static OPJ_SIZE_T opj_memory_stream_write(void *buffer, OPJ_SIZE_T nb_bytes, void *user_data)
125 {
126  opj_memory_stream* mstream = (opj_memory_stream*) user_data; /* our data */
127  OPJ_SIZE_T nb_bytes_write = nb_bytes; /* Amount to move to buffer */
128 
129  /* Check if the current offset is outside our data buffer */
130  if (mstream->offset >= mstream->dataSize)
131  return (OPJ_SIZE_T)-1;
132 
133  /* Check if we are writing more than we have space for */
134  if (nb_bytes > (mstream->dataSize - mstream->offset))
135  nb_bytes_write = mstream->dataSize - mstream->offset;
136 
137  /* Copy the data from the internal buffer */
138  memcpy(&(mstream->pData[mstream->offset]), buffer, nb_bytes_write);
139  mstream->offset += nb_bytes_write; /* Update the pointer to the new location */
140  return nb_bytes_write;
141 }
142 
153 static OPJ_OFF_T opj_memory_stream_skip(OPJ_OFF_T nb_bytes, void *user_data)
154 {
155  opj_memory_stream* mstream = (opj_memory_stream*) user_data;
156  OPJ_SIZE_T l_nb_bytes;
157 
158  if (nb_bytes < 0)
159  return -1; /* No skipping backwards */
160  l_nb_bytes = (OPJ_SIZE_T) nb_bytes; /* Allowed because it is positive */
161  /* Do not allow jumping past the end */
162  if (l_nb_bytes > mstream->dataSize - mstream->offset)
163  l_nb_bytes = mstream->dataSize - mstream->offset;
164  mstream->offset += l_nb_bytes;
165  return (OPJ_OFF_T)l_nb_bytes; /* Return how far we jumped */
166 }
167 
178 static OPJ_BOOL opj_memory_stream_seek(OPJ_OFF_T nb_bytes, void * user_data)
179 {
180  opj_memory_stream* mstream = (opj_memory_stream*) user_data;
181 
182  if (nb_bytes < 0)
183  return OPJ_FALSE; /* Not before the buffer */
184  if (nb_bytes >(OPJ_OFF_T) mstream->dataSize)
185  return OPJ_FALSE; /* Not after the buffer */
186  mstream->offset = (OPJ_SIZE_T) nb_bytes; /* Move to new position */
187  return OPJ_TRUE;
188 }
189 
197 static void opj_memory_stream_do_nothing(void * p_user_data)
198 {
199  OPJ_ARG_NOT_USED(p_user_data);
200 }
201 
212 static opj_stream_t* opj_stream_create_default_memory_stream(opj_memory_stream* memoryStream, OPJ_BOOL is_read_stream)
213 {
214  opj_stream_t* stream;
215 
216  if (!(stream = opj_stream_default_create(is_read_stream)))
217  return (NULL);
218  /* Set how to work with the frame buffer */
219  if (is_read_stream)
220  opj_stream_set_read_function(stream, opj_memory_stream_read);
221  else
222  opj_stream_set_write_function(stream, opj_memory_stream_write);
223 
224  opj_stream_set_seek_function(stream, opj_memory_stream_seek);
225  opj_stream_set_skip_function(stream, opj_memory_stream_skip);
226  opj_stream_set_user_data(stream, memoryStream, opj_memory_stream_do_nothing);
227  opj_stream_set_user_data_length(stream, memoryStream->dataSize);
228  return stream;
229 }
230 
252 int dec_jpeg2000(char *injpc,g2int bufsize,g2int *outfld)
253 {
254  int iret = 0;
255  OPJ_INT32 mask;
256 
257  opj_stream_t *stream = NULL;
258  opj_image_t *image = NULL;
259  opj_codec_t *codec = NULL;
260 
261  /* set decoding parameters to default values */
262  opj_dparameters_t parameters = {0,}; /* decompression parameters */
263  opj_set_default_decoder_parameters(&parameters);
264  parameters.decod_format = 1; /* JP2_FMT */
265 
266  /* JPEG-2000 codestream */
267 #define DUMP_JPEG_STREAM
268 #ifdef DUMP_JPEG_STREAM
269  FILE *fp=fopen("dump_openjpeg.j2k", "wb");
270  fwrite(injpc, 1, (size_t)bufsize, fp);
271  fclose(fp);
272 #endif
273 
274  /* get a decoder handle */
275  codec = opj_create_decompress(OPJ_CODEC_J2K);
276 
277  /* catch events using our callbacks */
278  opj_set_info_handler(codec, openjpeg_info, NULL);
279  opj_set_warning_handler(codec, openjpeg_warning, NULL);
280  opj_set_error_handler(codec, openjpeg_error,NULL);
281 
282  /* initialize our memory stream */
283  opj_memory_stream mstream;
284  mstream.pData = (OPJ_UINT8 *)injpc;
285  mstream.dataSize = (OPJ_SIZE_T)bufsize;
286  mstream.offset = 0;
287  /* open a byte stream from memory stream */
288  stream = opj_stream_create_default_memory_stream( &mstream, OPJ_STREAM_READ);
289 
290  /* setup the decoder decoding parameters using user parameters */
291  if (!opj_setup_decoder(codec, &parameters)) {
292  fprintf(stderr,"openjpeg: failed to setup decoder");
293  iret = -3;
294  goto cleanup;
295  }
296  if (!opj_read_header(stream, codec, &image)) {
297  fprintf(stderr,"openjpeg: failed to read the header");
298  iret = -3;
299  goto cleanup;
300  }
301  if (!opj_decode(codec, stream, image)) {
302  fprintf(stderr,"openjpeg: failed to decode");
303  iret = -3;
304  goto cleanup;
305  }
306 
307  if ( (image->numcomps != 1) || (image->x1 * image->y1)==0 ) {
308  iret = -3;
309  goto cleanup;
310  }
311 
312  assert(image->comps[0].sgnd == 0);
313  assert(image->comps[0].prec < sizeof(mask)*8-1);
314 
315  mask = (1 << image->comps[0].prec) - 1;
316 
317  for(unsigned int i = 0; i < image->comps[0].w * image->comps[0].h ; i++)
318  outfld[i] = (g2int) (image->comps[0].data[i] & mask);
319 
320  if (!opj_end_decompress(codec, stream)) {
321  fprintf(stderr,"openjpeg: failed in opj_end_decompress");
322  iret = -3;
323  }
324 
325 cleanup:
326  /* close the byte stream */
327  if (codec) opj_destroy_codec(codec);
328  if (stream) opj_stream_destroy(stream);
329  if (image) opj_image_destroy(image);
330 
331  return iret;
332 }
333 
367 int enc_jpeg2000(unsigned char *cin, g2int width, g2int height, g2int nbits,
368  g2int ltype, g2int ratio, g2int retry, char *outjpc,
369  g2int jpclen)
370 {
371  (void) retry;
372  int iret = 0;
373  const int numcomps = 1;
374 
375  opj_codec_t *codec = NULL;
376  opj_image_t *image = NULL;
377  opj_stream_t *stream = NULL;
378 
379  /* set encoding parameters to default values */
380  opj_cparameters_t parameters = {0,}; /* compression parameters */
381  opj_set_default_encoder_parameters(&parameters);
382 
383  parameters.tcp_numlayers = 1;
384  parameters.cp_disto_alloc = 1;
385  if (ltype == 1) {
386  assert(ratio != 255);
387  parameters.tcp_rates[0] = 1.0f/(float)ratio;
388  }
389 
390  /* By default numresolution = 6 (must be between 1 and 32)
391  * This may be too large for some of our datasets, eg. 1xn, so adjust ...
392  */
393  parameters.numresolution = 6;
394  while ( (width < (1 << (parameters.numresolution - 1)) ) ||
395  (height < (1 << (parameters.numresolution - 1)) ))
396  {
397  parameters.numresolution--;
398  }
399 
400  /* initialize image component */
401  opj_image_cmptparm_t cmptparm = {0,};
402  cmptparm.prec = (OPJ_UINT32)nbits;
403  cmptparm.bpp = (OPJ_UINT32)nbits;
404  cmptparm.sgnd = 0;
405  cmptparm.dx = 1;
406  cmptparm.dy = 1;
407  cmptparm.w = (OPJ_UINT32)width;
408  cmptparm.h = (OPJ_UINT32)height;
409 
410  /* create the image */
411  image = opj_image_create(numcomps, &cmptparm, OPJ_CLRSPC_GRAY);
412  if(!image) {
413  iret = -3;
414  goto cleanup;
415  }
416  image->x0 = 0;
417  image->y0 = 0;
418  image->x1 = (OPJ_UINT32)width;
419  image->y1 = (OPJ_UINT32)height;
420 
421  assert(cmptparm.prec <= sizeof(image->comps[0].data[0])*8 - 1); /* BR: -1 because I don't know what happens if the sign bit is set */
422 
423  /* Simple packing */
424  for(int i=0; i< width*height; i++){
425  image->comps[0].data[i] = cin[i];
426  }
427 
428  /* get a J2K compressor handle */
429  codec = opj_create_compress(OPJ_CODEC_J2K);
430 
431  opj_set_info_handler(codec, openjpeg_info, NULL);
432  opj_set_warning_handler(codec, openjpeg_warning, NULL);
433  opj_set_error_handler(codec, openjpeg_error,NULL);
434 
435  /* setup the encoder parameters using the current image and user parameters */
436  if (!opj_setup_encoder(codec, &parameters, image)) {
437  fprintf(stderr,"openjpeg: failed to setup encoder");
438  iret = -3;
439  goto cleanup;
440  }
441 
442  /* open a byte stream for writing */
443  opj_memory_stream mstream;
444  mstream.pData = (OPJ_UINT8*) outjpc;
445  mstream.offset = 0;
446  mstream.dataSize = (OPJ_SIZE_T)jpclen;
447  stream = opj_stream_create_default_memory_stream(&mstream, OPJ_STREAM_WRITE);
448  if (stream == NULL) {
449  fprintf(stderr,"openjpeg: failed create default memory stream");
450  iret = -3;
451  goto cleanup;
452  }
453 
454  if (!opj_start_compress(codec, image, stream)) {
455  fprintf(stderr,"openjpeg: failed to setup encoder");
456  iret = -3;
457  goto cleanup;
458  }
459 
460  /* encode image */
461  if (!opj_encode(codec, stream)) {
462  fprintf(stderr,"openjpeg: opj_encode failed");
463  iret = -3;
464  goto cleanup;
465  }
466 
467  if (!opj_end_compress(codec, stream)) {
468  fprintf(stderr,"openjpeg: opj_end_compress failed");
469  iret = -3;
470  goto cleanup;
471  }
472  iret = (int)mstream.offset;
473 
474 cleanup:
475  if (codec) opj_destroy_codec(codec);
476  if (stream) opj_stream_destroy(stream);
477  if (image) opj_image_destroy(image);
478 
479  return iret;
480 }
481 
482 #endif
int dec_jpeg2000(char *injpc, g2int bufsize, g2int *outfld)
This Function decodes a JPEG2000 code stream specified in the JPEG2000 Part-1 standard (i....
Definition: dec_jpeg2000.c:42
int enc_jpeg2000(unsigned char *cin, g2int width, g2int height, g2int nbits, g2int ltype, g2int ratio, g2int retry, char *outjpc, g2int jpclen)
This Function encodes a grayscale image into a JPEG2000 code stream specified in the JPEG2000 Part-1 ...
Definition: enc_jpeg2000.c:57
Header file for NCEPLIBS-g2c library.
int64_t g2int
Long integer type.
Definition: grib2.h:20