NCEPLIBS-g2c  1.7.0
decenc_openjpeg.c
Go to the documentation of this file.
1 
19 #if !defined USE_JPEG2000 && defined USE_OPENJPEG
20 
21 #include "grib2_int.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  /* get a decoder handle */
267  codec = opj_create_decompress(OPJ_CODEC_J2K);
268 
269  /* catch events using our callbacks */
270  opj_set_info_handler(codec, openjpeg_info, NULL);
271  opj_set_warning_handler(codec, openjpeg_warning, NULL);
272  opj_set_error_handler(codec, openjpeg_error,NULL);
273 
274  /* initialize our memory stream */
275  opj_memory_stream mstream;
276  mstream.pData = (OPJ_UINT8 *)injpc;
277  mstream.dataSize = (OPJ_SIZE_T)bufsize;
278  mstream.offset = 0;
279  /* open a byte stream from memory stream */
280  stream = opj_stream_create_default_memory_stream( &mstream, OPJ_STREAM_READ);
281 
282  /* setup the decoder decoding parameters using user parameters */
283  if (!opj_setup_decoder(codec, &parameters)) {
284  fprintf(stderr,"openjpeg: failed to setup decoder");
285  iret = -3;
286  goto cleanup;
287  }
288  if (!opj_read_header(stream, codec, &image)) {
289  fprintf(stderr,"openjpeg: failed to read the header");
290  iret = -3;
291  goto cleanup;
292  }
293  if (!opj_decode(codec, stream, image)) {
294  fprintf(stderr,"openjpeg: failed to decode");
295  iret = -3;
296  goto cleanup;
297  }
298 
299  if ( (image->numcomps != 1) || (image->x1 * image->y1)==0 ) {
300  iret = -3;
301  goto cleanup;
302  }
303 
304  assert(image->comps[0].sgnd == 0);
305  assert(image->comps[0].prec < sizeof(mask)*8-1);
306 
307  mask = (1 << image->comps[0].prec) - 1;
308 
309  for(unsigned int i = 0; i < image->comps[0].w * image->comps[0].h ; i++)
310  outfld[i] = (g2int) (image->comps[0].data[i] & mask);
311 
312  if (!opj_end_decompress(codec, stream)) {
313  fprintf(stderr,"openjpeg: failed in opj_end_decompress");
314  iret = -3;
315  }
316 
317 cleanup:
318  /* close the byte stream */
319  if (codec) opj_destroy_codec(codec);
320  if (stream) opj_stream_destroy(stream);
321  if (image) opj_image_destroy(image);
322 
323  return iret;
324 }
325 
359 int enc_jpeg2000(unsigned char *cin, g2int width, g2int height, g2int nbits,
360  g2int ltype, g2int ratio, g2int retry, char *outjpc,
361  g2int jpclen)
362 {
363  (void) retry;
364  int iret = 0;
365  const int numcomps = 1;
366 
367  opj_codec_t *codec = NULL;
368  opj_image_t *image = NULL;
369  opj_stream_t *stream = NULL;
370 
371  /* set encoding parameters to default values */
372  opj_cparameters_t parameters = {0,}; /* compression parameters */
373  opj_set_default_encoder_parameters(&parameters);
374 
375  parameters.tcp_numlayers = 1;
376  parameters.cp_disto_alloc = 1;
377  if (ltype == 1) {
378  assert(ratio != 255);
379  parameters.tcp_rates[0] = 1.0f/(float)ratio;
380  }
381 
382  /* By default numresolution = 6 (must be between 1 and 32)
383  * This may be too large for some of our datasets, eg. 1xn, so adjust ...
384  */
385  parameters.numresolution = 6;
386  while ((width < (1 << (parameters.numresolution - 1))) ||
387  (height < (1 << (parameters.numresolution - 1))))
388  {
389  parameters.numresolution--;
390  }
391 
392  /* initialize image component */
393  opj_image_cmptparm_t cmptparm = {0,};
394  cmptparm.prec = (OPJ_UINT32)nbits;
395  cmptparm.bpp = (OPJ_UINT32)nbits;
396  cmptparm.sgnd = 0;
397  cmptparm.dx = 1;
398  cmptparm.dy = 1;
399  cmptparm.w = (OPJ_UINT32)width;
400  cmptparm.h = (OPJ_UINT32)height;
401 
402  /* create the image */
403  image = opj_image_create(numcomps, &cmptparm, OPJ_CLRSPC_GRAY);
404  if (!image)
405  {
406  iret = -3;
407  goto cleanup;
408  }
409  image->x0 = 0;
410  image->y0 = 0;
411  image->x1 = (OPJ_UINT32)width;
412  image->y1 = (OPJ_UINT32)height;
413 
414  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 */
415 
416  /* Simple packing */
417  for (int i = 0; i < width * height; i++)
418  image->comps[0].data[i] = cin[i];
419 
420  /* get a J2K compressor handle */
421  codec = opj_create_compress(OPJ_CODEC_J2K);
422 
423  opj_set_info_handler(codec, openjpeg_info, NULL);
424  opj_set_warning_handler(codec, openjpeg_warning, NULL);
425  opj_set_error_handler(codec, openjpeg_error,NULL);
426 
427  /* setup the encoder parameters using the current image and user parameters */
428  if (!opj_setup_encoder(codec, &parameters, image))
429  {
430  fprintf(stderr,"openjpeg: failed to setup encoder");
431  iret = -3;
432  goto cleanup;
433  }
434 
435  /* open a byte stream for writing */
436  opj_memory_stream mstream;
437  mstream.pData = (OPJ_UINT8 *)outjpc;
438  mstream.offset = 0;
439  mstream.dataSize = (OPJ_SIZE_T)jpclen;
440  stream = opj_stream_create_default_memory_stream(&mstream, OPJ_STREAM_WRITE);
441  if (!stream)
442  {
443  fprintf(stderr,"openjpeg: failed create default memory stream");
444  iret = -3;
445  goto cleanup;
446  }
447 
448  if (!opj_start_compress(codec, image, stream))
449  {
450  fprintf(stderr,"openjpeg: failed to setup encoder");
451  iret = -3;
452  goto cleanup;
453  }
454 
455  /* encode image */
456  if (!opj_encode(codec, stream))
457  {
458  fprintf(stderr,"openjpeg: opj_encode failed");
459  iret = -3;
460  goto cleanup;
461  }
462 
463  if (!opj_end_compress(codec, stream))
464  {
465  fprintf(stderr,"openjpeg: opj_end_compress failed");
466  iret = -3;
467  goto cleanup;
468  }
469  iret = (int)mstream.offset;
470 
471 cleanup:
472  if (codec)
473  opj_destroy_codec(codec);
474  if (stream)
475  opj_stream_destroy(stream);
476  if (image)
477  opj_image_destroy(image);
478 
479  return iret;
480 }
481 
482 #endif
grib2_int.h
Header file with internal function prototypes NCEPLIBS-g2c library.
dec_jpeg2000
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:38
g2int
int64_t g2int
Long integer type.
Definition: grib2.h:28
enc_jpeg2000
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:51