2013-03-25 14:23:07 +00:00
|
|
|
/*
|
2019-04-15 13:44:45 +00:00
|
|
|
* Copyright 2005-2019 ECMWF.
|
2013-03-25 14:23:07 +00:00
|
|
|
*
|
|
|
|
* This software is licensed under the terms of the Apache Licence Version 2.0
|
|
|
|
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
|
|
|
|
*
|
|
|
|
* In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
|
|
|
|
* virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
|
|
|
|
*/
|
|
|
|
|
2013-03-25 12:04:10 +00:00
|
|
|
#include "grib_api_internal.h"
|
|
|
|
|
|
|
|
#if HAVE_LIBJASPER
|
2014-10-23 12:41:22 +00:00
|
|
|
/* Remove compiler warnings re macros being redefined */
|
|
|
|
#undef PACKAGE_BUGREPORT
|
|
|
|
#undef PACKAGE_NAME
|
|
|
|
#undef PACKAGE_STRING
|
|
|
|
#undef PACKAGE_TARNAME
|
|
|
|
#undef PACKAGE_VERSION
|
2013-03-25 12:04:10 +00:00
|
|
|
#include "jasper/jasper.h"
|
|
|
|
|
|
|
|
#define MAXOPTSSIZE 1024
|
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
int grib_jasper_decode(grib_context* c, unsigned char* buf, size_t* buflen, double* values, size_t* no_values)
|
2016-08-03 10:30:19 +00:00
|
|
|
{
|
2013-09-30 13:08:41 +00:00
|
|
|
/*jas_setdbglevel(99999);*/
|
2020-01-22 13:10:59 +00:00
|
|
|
jas_image_t* image = NULL;
|
|
|
|
jas_stream_t* jpeg = NULL;
|
|
|
|
int code = GRIB_SUCCESS;
|
|
|
|
jas_matrix_t* matrix = NULL;
|
|
|
|
jas_image_cmpt_t* p;
|
|
|
|
int i, j, k;
|
|
|
|
|
|
|
|
jpeg = jas_stream_memopen((char*)buf, *buflen);
|
|
|
|
if (!jpeg) {
|
2013-09-30 13:08:41 +00:00
|
|
|
code = GRIB_DECODING_ERROR;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-03-25 12:04:10 +00:00
|
|
|
|
2016-08-03 10:30:19 +00:00
|
|
|
grib_context_log(c, GRIB_LOG_DEBUG, "grib_jasper_decode: Jasper version %s", jas_getversion());
|
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
image = jpc_decode(jpeg, NULL);
|
|
|
|
if (!image) {
|
2013-09-30 13:08:41 +00:00
|
|
|
code = GRIB_DECODING_ERROR;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-03-25 12:04:10 +00:00
|
|
|
|
2013-09-30 13:08:41 +00:00
|
|
|
p = image->cmpts_[0];
|
2013-03-25 12:04:10 +00:00
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
if (image->numcmpts_ != 1) {
|
2013-09-30 13:08:41 +00:00
|
|
|
/* Image not gray scale */
|
|
|
|
code = GRIB_DECODING_ERROR;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-03-25 12:04:10 +00:00
|
|
|
|
2013-09-30 13:08:41 +00:00
|
|
|
matrix = jas_matrix_create(jas_image_height(image), jas_image_width(image));
|
2013-03-25 12:04:10 +00:00
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
if (!matrix) {
|
2013-09-30 13:08:41 +00:00
|
|
|
code = GRIB_DECODING_ERROR;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-03-25 12:04:10 +00:00
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
jas_image_readcmpt(image, 0, 0, 0, jas_image_width(image), jas_image_height(image), matrix);
|
2013-03-25 12:04:10 +00:00
|
|
|
|
2013-09-30 13:08:41 +00:00
|
|
|
Assert(p->height_ * p->width_ == *no_values);
|
2013-03-25 12:04:10 +00:00
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
k = 0;
|
|
|
|
for (i = 0; i < p->height_; i++)
|
|
|
|
for (j = 0; j < p->width_; j++) {
|
2013-09-30 13:08:41 +00:00
|
|
|
values[k++] = matrix->rows_[i][j];
|
|
|
|
}
|
2013-03-25 12:04:10 +00:00
|
|
|
|
|
|
|
cleanup:
|
2020-01-22 13:10:59 +00:00
|
|
|
if (matrix)
|
|
|
|
jas_matrix_destroy(matrix);
|
|
|
|
if (image)
|
|
|
|
jas_image_destroy(image);
|
|
|
|
if (jpeg)
|
|
|
|
jas_stream_close(jpeg);
|
2013-03-25 12:04:10 +00:00
|
|
|
|
2013-09-30 13:08:41 +00:00
|
|
|
return code;
|
2013-03-25 12:04:10 +00:00
|
|
|
}
|
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
int grib_jasper_encode(grib_context* c, j2k_encode_helper* helper)
|
2016-08-03 10:30:19 +00:00
|
|
|
{
|
2013-09-30 13:08:41 +00:00
|
|
|
int code = GRIB_SUCCESS;
|
|
|
|
int jaserr;
|
|
|
|
|
|
|
|
char opts[MAXOPTSSIZE];
|
|
|
|
double reference_value = helper->reference_value;
|
2020-01-22 13:10:59 +00:00
|
|
|
double decimal = helper->decimal;
|
|
|
|
double divisor = helper->divisor;
|
|
|
|
const double* values = helper->values;
|
|
|
|
long no_values = helper->no_values;
|
2013-09-30 13:08:41 +00:00
|
|
|
long bits8;
|
|
|
|
int i;
|
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
size_t buflen = 0;
|
|
|
|
unsigned char* encoded = NULL;
|
|
|
|
unsigned char* p = NULL;
|
2013-09-30 13:08:41 +00:00
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
jas_image_t image = { 0 };
|
|
|
|
jas_stream_t* jpcstream = 0;
|
|
|
|
jas_stream_t* istream = 0;
|
2020-01-22 14:48:06 +00:00
|
|
|
jas_image_cmpt_t cmpt = {0,};
|
2020-01-22 13:10:59 +00:00
|
|
|
jas_image_cmpt_t* pcmpt = 0;
|
2013-09-30 13:08:41 +00:00
|
|
|
|
|
|
|
image.tlx_ = 0;
|
|
|
|
image.tly_ = 0;
|
|
|
|
image.brx_ = helper->width;
|
|
|
|
image.bry_ = helper->height;
|
|
|
|
image.numcmpts_ = 1;
|
|
|
|
image.maxcmpts_ = 1;
|
|
|
|
image.clrspc_ = JAS_CLRSPC_SGRAY;
|
|
|
|
image.cmprof_ = 0;
|
2016-12-06 11:51:41 +00:00
|
|
|
|
|
|
|
#if JASPER_VERSION_MAJOR == 1
|
|
|
|
/* ECC-396: Support for Jasper 2.0
|
|
|
|
* Jasper version 1 had the 'inmem_' data member but
|
|
|
|
* version 2 removed it from the interface */
|
2020-01-22 13:10:59 +00:00
|
|
|
image.inmem_ = 1;
|
2016-12-06 11:51:41 +00:00
|
|
|
#endif
|
2013-09-30 13:08:41 +00:00
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
cmpt.tlx_ = 0;
|
|
|
|
cmpt.tly_ = 0;
|
|
|
|
cmpt.hstep_ = 1;
|
|
|
|
cmpt.vstep_ = 1;
|
|
|
|
cmpt.width_ = helper->width;
|
|
|
|
cmpt.height_ = helper->height;
|
|
|
|
cmpt.type_ = JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y);
|
|
|
|
cmpt.prec_ = helper->bits_per_value;
|
|
|
|
cmpt.sgnd_ = 0;
|
|
|
|
cmpt.cps_ = (helper->bits_per_value + 7) / 8;
|
2013-09-30 13:08:41 +00:00
|
|
|
|
|
|
|
/* Simple packing encoding */
|
2020-01-22 13:10:59 +00:00
|
|
|
bits8 = (helper->bits_per_value + 7) / 8 * 8;
|
2013-09-30 13:08:41 +00:00
|
|
|
Assert(bits8 > 0);
|
2020-01-22 13:10:59 +00:00
|
|
|
encoded = (unsigned char*)grib_context_malloc_clear(c, bits8 / 8 * no_values);
|
2013-09-30 13:08:41 +00:00
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
if (!encoded) {
|
2013-09-30 13:08:41 +00:00
|
|
|
code = GRIB_OUT_OF_MEMORY;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
buflen = 0;
|
2016-08-03 10:30:19 +00:00
|
|
|
p = encoded;
|
2013-09-30 13:08:41 +00:00
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
for (i = 0; i < no_values; i++) {
|
|
|
|
long blen = bits8;
|
|
|
|
unsigned long unsigned_val = (unsigned long)((((values[i] * decimal) - (reference_value)) * divisor) + 0.5);
|
|
|
|
while (blen >= 8) {
|
|
|
|
blen -= 8;
|
2013-09-30 13:08:41 +00:00
|
|
|
*p = (unsigned_val >> blen);
|
|
|
|
p++;
|
|
|
|
buflen++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*jas_init();*/
|
|
|
|
|
|
|
|
opts[0] = 0;
|
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
if (helper->compression != 0) {
|
2013-09-30 13:08:41 +00:00
|
|
|
/* Lossy */
|
2020-01-22 13:10:59 +00:00
|
|
|
ecc_snprintf(opts, MAXOPTSSIZE, "mode=real\nrate=%f", 1.0 / helper->compression);
|
2013-09-30 13:08:41 +00:00
|
|
|
}
|
2013-03-25 12:04:10 +00:00
|
|
|
|
2013-09-30 13:08:41 +00:00
|
|
|
Assert(cmpt.width_ * cmpt.height_ * cmpt.cps_ == buflen);
|
2016-08-03 10:30:19 +00:00
|
|
|
grib_context_log(c, GRIB_LOG_DEBUG, "grib_jasper_encode: Jasper version %s", jas_getversion());
|
2013-03-25 12:04:10 +00:00
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
pcmpt = &cmpt;
|
|
|
|
image.cmpts_ = &pcmpt;
|
2013-03-25 12:04:10 +00:00
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
istream = jas_stream_memopen((char*)encoded, buflen);
|
|
|
|
cmpt.stream_ = istream;
|
2013-03-25 12:04:10 +00:00
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
jpcstream = jas_stream_memopen((char*)helper->jpeg_buffer, helper->buffer_size);
|
|
|
|
jaserr = jpc_encode(&image, jpcstream, opts);
|
2013-03-25 12:04:10 +00:00
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
if (jaserr != 0) {
|
2013-09-30 13:08:41 +00:00
|
|
|
/* increase the number of guard bits */
|
2020-01-22 13:10:59 +00:00
|
|
|
strcat(opts, "\nnumgbits=4");
|
2013-09-30 13:08:41 +00:00
|
|
|
grib_context_log(c, GRIB_LOG_ERROR, "JASPER: error %d, increasing the number of guard bits", jaserr);
|
2020-01-22 13:10:59 +00:00
|
|
|
jas_stream_close(istream);
|
|
|
|
istream = 0;
|
|
|
|
jas_stream_close(jpcstream);
|
|
|
|
jpcstream = 0;
|
|
|
|
|
|
|
|
istream = jas_stream_memopen((char*)encoded, buflen);
|
|
|
|
cmpt.stream_ = istream;
|
|
|
|
jpcstream = jas_stream_memopen((char*)helper->jpeg_buffer, helper->buffer_size);
|
|
|
|
jaserr = jpc_encode(&image, jpcstream, opts);
|
2013-09-30 13:08:41 +00:00
|
|
|
}
|
2013-03-25 12:04:10 +00:00
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
if (jaserr != 0) {
|
2013-09-30 13:08:41 +00:00
|
|
|
grib_context_log(c, GRIB_LOG_ERROR, "JASPER: error %d", jaserr);
|
|
|
|
code = GRIB_ENCODING_ERROR;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-03-25 12:04:10 +00:00
|
|
|
|
2013-09-30 13:08:41 +00:00
|
|
|
helper->jpeg_length = jpcstream->rwcnt_;
|
2020-01-22 13:10:59 +00:00
|
|
|
jaserr = jas_stream_close(istream);
|
|
|
|
istream = 0;
|
|
|
|
jaserr = jas_stream_close(jpcstream);
|
|
|
|
jpcstream = 0;
|
2013-03-25 12:04:10 +00:00
|
|
|
|
|
|
|
cleanup:
|
2020-01-22 13:10:59 +00:00
|
|
|
grib_context_free(c, encoded);
|
|
|
|
if (istream)
|
|
|
|
jas_stream_close(istream);
|
|
|
|
if (jpcstream)
|
|
|
|
jas_stream_close(jpcstream);
|
2013-03-25 12:04:10 +00:00
|
|
|
|
2013-09-30 13:08:41 +00:00
|
|
|
return code;
|
2013-03-25 12:04:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
int grib_jasper_decode(grib_context* c, unsigned char* buf, size_t* buflen, double* val, size_t* n_vals)
|
2016-08-03 10:30:19 +00:00
|
|
|
{
|
2013-09-30 13:08:41 +00:00
|
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
2020-01-22 13:10:59 +00:00
|
|
|
"grib_accessor_data_jpeg2000_packing: Jasper JPEG support not enabled.");
|
2019-08-15 14:58:52 +00:00
|
|
|
return GRIB_FUNCTIONALITY_NOT_ENABLED;
|
2013-03-25 12:04:10 +00:00
|
|
|
}
|
|
|
|
|
2020-01-22 13:10:59 +00:00
|
|
|
int grib_jasper_encode(grib_context* c, j2k_encode_helper* helper)
|
2016-08-03 10:30:19 +00:00
|
|
|
{
|
2013-09-30 13:08:41 +00:00
|
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
2020-01-22 13:10:59 +00:00
|
|
|
"grib_accessor_data_jpeg2000_packing: Jasper JPEG support not enabled.");
|
2019-08-15 14:58:52 +00:00
|
|
|
return GRIB_FUNCTIONALITY_NOT_ENABLED;
|
2013-03-25 12:04:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|