NCEPLIBS-g2c 2.2.0
Loading...
Searching...
No Matches
decenc_openjpeg.c
Go to the documentation of this file.
1
6/* Copyright 2005-2019 ECMWF.
7 *
8 * This software is licensed under the terms of the Apache Licence
9 * Version 2.0 which can be obtained at
10 * http://www.apache.org/licenses/LICENSE-2.0.
11 *
12 * In applying this licence, ECMWF does not waive the privileges and
13 * immunities granted to it by virtue of its status as an
14 * intergovernmental organisation nor does it submit to any
15 * jurisdiction.
16 */
17
18#if !defined USE_JPEG2000 && defined USE_OPENJPEG
19
20#include "grib2_int.h"
21#include "openjpeg.h"
22
23#include <assert.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27
36static void
37openjpeg_warning(const char *msg, void *client_data)
38{
39 (void)client_data;
40 fprintf(stderr, "openjpeg: %s", msg);
41}
42
51static void
52openjpeg_error(const char *msg, void *client_data)
53{
54 (void)client_data;
55 fprintf(stderr, "openjpeg: %s", msg);
56}
57
66static void
67openjpeg_info(const char *msg, void *client_data)
68{
69 (void)msg;
70 (void)client_data;
71 /* fprintf(stderr,"openjpeg: %s",msg); */
72}
73
74/* opj_* Helper code from
75 * https://groups.google.com/forum/#!topic/openjpeg/8cebr0u7JgY
76 */
77/* These routines are added to use memory instead of a file for input and output */
78/* struct need to treat memory as a stream */
79typedef struct
80{
81 OPJ_UINT8 *pData; /* our data */
82 OPJ_SIZE_T dataSize; /* how big is our data */
83 OPJ_SIZE_T offset; /* where we are currently in our data */
84} opj_memory_stream;
85
97static OPJ_SIZE_T
98opj_memory_stream_read(void *buffer, OPJ_SIZE_T nb_bytes, void *p_user_data)
99{
100 opj_memory_stream *mstream = (opj_memory_stream *)p_user_data; /* Our data */
101 OPJ_SIZE_T nb_bytes_read = nb_bytes; /* Amount to move to buffer */
102
103 /* Check if the current offset is outside our data buffer */
104 if (mstream->offset >= mstream->dataSize)
105 return (OPJ_SIZE_T)-1;
106
107 /* Check if we are reading more than we have */
108 if (nb_bytes > (mstream->dataSize - mstream->offset))
109 nb_bytes_read = mstream->dataSize - mstream->offset;
110
111 memcpy(buffer, &(mstream->pData[mstream->offset]), nb_bytes_read);
112 mstream->offset += nb_bytes_read; /* Update the pointer to the new location */
113 return nb_bytes_read;
114}
115
127static OPJ_SIZE_T
128opj_memory_stream_write(void *buffer, OPJ_SIZE_T nb_bytes, void *user_data)
129{
130 opj_memory_stream *mstream = (opj_memory_stream *)user_data; /* our data */
131 OPJ_SIZE_T nb_bytes_write = nb_bytes; /* Amount to move to buffer */
132
133 /* Check if the current offset is outside our data buffer */
134 if (mstream->offset >= mstream->dataSize)
135 return (OPJ_SIZE_T)-1;
136
137 /* Check if we are writing more than we have space for */
138 if (nb_bytes > (mstream->dataSize - mstream->offset))
139 nb_bytes_write = mstream->dataSize - mstream->offset;
140
141 /* Copy the data from the internal buffer */
142 memcpy(&(mstream->pData[mstream->offset]), buffer, nb_bytes_write);
143 mstream->offset += nb_bytes_write; /* Update the pointer to the new location */
144 return nb_bytes_write;
145}
146
157static OPJ_OFF_T
158opj_memory_stream_skip(OPJ_OFF_T nb_bytes, void *user_data)
159{
160 opj_memory_stream *mstream = (opj_memory_stream *)user_data;
161 OPJ_SIZE_T l_nb_bytes;
162
163 if (nb_bytes < 0)
164 return -1; /* No skipping backwards */
165 l_nb_bytes = (OPJ_SIZE_T)nb_bytes; /* Allowed because it is positive */
166 /* Do not allow jumping past the end */
167 if (l_nb_bytes > mstream->dataSize - mstream->offset)
168 l_nb_bytes = mstream->dataSize - mstream->offset;
169 mstream->offset += l_nb_bytes;
170 return (OPJ_OFF_T)l_nb_bytes; /* Return how far we jumped */
171}
172
183static OPJ_BOOL
184opj_memory_stream_seek(OPJ_OFF_T nb_bytes, void *user_data)
185{
186 opj_memory_stream *mstream = (opj_memory_stream *)user_data;
187
188 if (nb_bytes < 0)
189 return OPJ_FALSE; /* Not before the buffer */
190 if (nb_bytes > (OPJ_OFF_T)mstream->dataSize)
191 return OPJ_FALSE; /* Not after the buffer */
192 mstream->offset = (OPJ_SIZE_T)nb_bytes; /* Move to new position */
193 return OPJ_TRUE;
194}
195
203static void
204opj_memory_stream_do_nothing(void *p_user_data)
205{
206 OPJ_ARG_NOT_USED(p_user_data);
207}
208
219static opj_stream_t *
220opj_stream_create_default_memory_stream(opj_memory_stream *memoryStream, OPJ_BOOL is_read_stream)
221{
222 opj_stream_t *stream;
223
224 if (!(stream = opj_stream_default_create(is_read_stream)))
225 return (NULL);
226 /* Set how to work with the frame buffer */
227 if (is_read_stream)
228 opj_stream_set_read_function(stream, opj_memory_stream_read);
229 else
230 opj_stream_set_write_function(stream, opj_memory_stream_write);
231
232 opj_stream_set_seek_function(stream, opj_memory_stream_seek);
233 opj_stream_set_skip_function(stream, opj_memory_stream_skip);
234 opj_stream_set_user_data(stream, memoryStream, opj_memory_stream_do_nothing);
235 opj_stream_set_user_data_length(stream, memoryStream->dataSize);
236 return stream;
237}
238
264static int
265int_dec_jpeg2000(char *injpc, g2int bufsize, void *outfld, int out_is_g2int)
266{
267 int iret = 0;
268 OPJ_INT32 mask;
269
270 opj_stream_t *stream = NULL;
271 opj_image_t *image = NULL;
272 opj_codec_t *codec = NULL;
273
274 /* set decoding parameters to default values */
275 opj_dparameters_t parameters = {
276 0,
277 }; /* decompression parameters */
278 opj_set_default_decoder_parameters(&parameters);
279 parameters.decod_format = 1; /* JP2_FMT */
280
281 /* get a decoder handle */
282 codec = opj_create_decompress(OPJ_CODEC_J2K);
283
284 /* catch events using our callbacks */
285 opj_set_info_handler(codec, openjpeg_info, NULL);
286 opj_set_warning_handler(codec, openjpeg_warning, NULL);
287 opj_set_error_handler(codec, openjpeg_error, NULL);
288
289 /* initialize our memory stream */
290 opj_memory_stream mstream;
291 mstream.pData = (OPJ_UINT8 *)injpc;
292 mstream.dataSize = (OPJ_SIZE_T)bufsize;
293 mstream.offset = 0;
294 /* open a byte stream from memory stream */
295 stream = opj_stream_create_default_memory_stream(&mstream, OPJ_STREAM_READ);
296
297 /* setup the decoder decoding parameters using user parameters */
298 if (!opj_setup_decoder(codec, &parameters))
299 {
300 fprintf(stderr, "openjpeg: failed to setup decoder");
301 iret = -3;
302 goto cleanup;
303 }
304 if (!opj_read_header(stream, codec, &image))
305 {
306 fprintf(stderr, "openjpeg: failed to read the header");
307 iret = -3;
308 goto cleanup;
309 }
310 if (!opj_decode(codec, stream, image))
311 {
312 fprintf(stderr, "openjpeg: failed to decode");
313 iret = -3;
314 goto cleanup;
315 }
316
317 if ((image->numcomps != 1) || (image->x1 * image->y1) == 0)
318 {
319 iret = -3;
320 goto cleanup;
321 }
322
323 assert(image->comps[0].sgnd == 0);
324 assert(image->comps[0].prec < sizeof(mask) * 8 - 1);
325
326 mask = (1 << image->comps[0].prec) - 1;
327
328 if (out_is_g2int)
329 {
330 for (unsigned int i = 0; i < image->comps[0].w * image->comps[0].h; i++)
331 ((g2int *)outfld)[i] = (g2int)(image->comps[0].data[i] & mask);
332 }
333 else
334 {
335 for (unsigned int i = 0; i < image->comps[0].w * image->comps[0].h; i++)
336 ((int *)outfld)[i] = (int)(image->comps[0].data[i] & mask);
337 }
338
339 if (!opj_end_decompress(codec, stream))
340 {
341 fprintf(stderr, "openjpeg: failed in opj_end_decompress");
342 iret = -3;
343 }
344
345cleanup:
346 /* close the byte stream */
347 if (codec)
348 opj_destroy_codec(codec);
349 if (stream)
350 opj_stream_destroy(stream);
351 if (image)
352 opj_image_destroy(image);
353
354 return iret;
355}
356
378int
379g2c_dec_jpeg2000(char *injpc, size_t bufsize, int *outfld)
380{
381 return int_dec_jpeg2000(injpc, bufsize, outfld, 0);
382}
383
406int
407dec_jpeg2000(char *injpc, g2int bufsize, g2int *outfld)
408{
409 return int_dec_jpeg2000(injpc, bufsize, outfld, 1);
410}
411
445int
446g2c_enc_jpeg2000(unsigned char *cin, int width, int height, int nbits,
447 int ltype, int ratio, int retry, char *outjpc,
448 size_t jpclen)
449{
450 g2int width8 = width, height8 = height, nbits8 = nbits, ltype8 = ltype;
451 g2int ratio8 = ratio, retry8 = retry, jpclen8 = jpclen;
452
453 return enc_jpeg2000(cin, width8, height8, nbits8, ltype8, ratio8, retry8,
454 outjpc, jpclen8);
455}
456
490int
491enc_jpeg2000(unsigned char *cin, g2int width, g2int height, g2int nbits,
492 g2int ltype, g2int ratio, g2int retry, char *outjpc,
493 g2int jpclen)
494{
495 (void)retry;
496 int iret = 0;
497 int nbytes = 0;
498 const int numcomps = 1;
499 g2int *ifld = NULL;
500
501 opj_codec_t *codec = NULL;
502 opj_image_t *image = NULL;
503 opj_stream_t *stream = NULL;
504
505 /* set encoding parameters to default values */
506 opj_cparameters_t parameters = {
507 0,
508 }; /* compression parameters */
509 opj_set_default_encoder_parameters(&parameters);
510
511 parameters.tcp_numlayers = 1;
512 parameters.cp_disto_alloc = 1;
513 if (ltype == 1)
514 {
515 assert(ratio != 255);
516 parameters.tcp_rates[0] = 1.0f / (float)ratio;
517 }
518
519 /* By default numresolution = 6 (must be between 1 and 32)
520 * This may be too large for some of our datasets, eg. 1xn, so adjust ...
521 */
522 parameters.numresolution = 6;
523 while ((width < (1 << (parameters.numresolution - 1))) ||
524 (height < (1 << (parameters.numresolution - 1))))
525 {
526 parameters.numresolution--;
527 }
528
529 /* initialize image component */
530 opj_image_cmptparm_t cmptparm = {
531 0,
532 };
533 cmptparm.prec = (OPJ_UINT32)nbits;
534 cmptparm.sgnd = 0;
535 cmptparm.dx = 1;
536 cmptparm.dy = 1;
537 cmptparm.w = (OPJ_UINT32)width;
538 cmptparm.h = (OPJ_UINT32)height;
539
540 /* create the image */
541 image = opj_image_create(numcomps, &cmptparm, OPJ_CLRSPC_GRAY);
542 if (!image)
543 {
544 iret = -3;
545 goto cleanup;
546 }
547 image->x0 = 0;
548 image->y0 = 0;
549 image->x1 = (OPJ_UINT32)width;
550 image->y1 = (OPJ_UINT32)height;
551
552 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 */
553
554 ifld = malloc(width * height * sizeof(g2int));
555 nbytes = (nbits + 7) / 8;
556 gbits(cin, ifld, 0, nbytes * 8, 0, width * height);
557 /* Simple packing */
558 for (int i = 0; i < width * height; i++)
559 {
560 image->comps[0].data[i] = ifld[i];
561 }
562 free(ifld);
563
564 /* get a J2K compressor handle */
565 codec = opj_create_compress(OPJ_CODEC_J2K);
566
567 opj_set_info_handler(codec, openjpeg_info, NULL);
568 opj_set_warning_handler(codec, openjpeg_warning, NULL);
569 opj_set_error_handler(codec, openjpeg_error, NULL);
570
571 /* setup the encoder parameters using the current image and user parameters */
572 if (!opj_setup_encoder(codec, &parameters, image))
573 {
574 fprintf(stderr, "openjpeg: failed to setup encoder");
575 iret = -3;
576 goto cleanup;
577 }
578
579 /* open a byte stream for writing */
580 opj_memory_stream mstream;
581 mstream.pData = (OPJ_UINT8 *)outjpc;
582 mstream.offset = 0;
583 mstream.dataSize = (OPJ_SIZE_T)jpclen;
584 stream = opj_stream_create_default_memory_stream(&mstream, OPJ_STREAM_WRITE);
585 if (!stream)
586 {
587 fprintf(stderr, "openjpeg: failed create default memory stream");
588 iret = -3;
589 goto cleanup;
590 }
591
592 if (!opj_start_compress(codec, image, stream))
593 {
594 fprintf(stderr, "openjpeg: failed to setup encoder");
595 iret = -3;
596 goto cleanup;
597 }
598
599 /* encode image */
600 if (!opj_encode(codec, stream))
601 {
602 fprintf(stderr, "openjpeg: opj_encode failed");
603 iret = -3;
604 goto cleanup;
605 }
606
607 if (!opj_end_compress(codec, stream))
608 {
609 fprintf(stderr, "openjpeg: opj_end_compress failed");
610 iret = -3;
611 goto cleanup;
612 }
613 iret = (int)mstream.offset;
614
615cleanup:
616 if (codec)
617 opj_destroy_codec(codec);
618 if (stream)
619 opj_stream_destroy(stream);
620 if (image)
621 opj_image_destroy(image);
622
623 return iret;
624}
625
626#endif
int g2c_dec_jpeg2000(char *injpc, size_t bufsize, int *outfld)
Decode a JPEG2000 code stream specified in the JPEG2000 Part-1 standard (i.e., ISO/IEC 15444-1) using...
int g2c_enc_jpeg2000(unsigned char *cin, int width, int height, int nbits, int ltype, int ratio, int retry, char *outjpc, size_t jpclen)
Encode a grayscale image into a JPEG2000 code stream specified in the JPEG2000 Part-1 standard (i....
static int int_dec_jpeg2000(char *injpc, g2int bufsize, void *outfld, int out_is_g2int)
Decode a JPEG2000 code stream specified in the JPEG2000 Part-1 standard (i.e., ISO/IEC 15444-1) using...
int dec_jpeg2000(char *injpc, g2int bufsize, g2int *outfld)
Decode a JPEG2000 code stream specified in the JPEG2000 Part-1 standard (i.e., ISO/IEC 15444-1) using...
int enc_jpeg2000(unsigned char *cin, g2int width, g2int height, g2int nbits, g2int ltype, g2int ratio, g2int retry, char *outjpc, g2int jpclen)
Encode a grayscale image into a JPEG2000 code stream specified in the JPEG2000 Part-1 standard (i....
void gbits(unsigned char *in, g2int *iout, g2int iskip, g2int nbits, g2int nskip, g2int n)
Unpack arbitrary size values from a packed bit string, right justifying each value in the unpacked io...
Definition gbits.c:57
int64_t g2int
Long integer type.
Definition grib2.h:32
Header file with internal function prototypes NCEPLIBS-g2c library.