* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <opj_config.h>
-#ifdef HAVE_LIBLCMS2
-#include <math.h>
-#include <lcms2.h>
-#endif
-#ifdef HAVE_LIBLCMS1
-#include <math.h>
-#include <lcms.h>
-#endif
#include "opj_includes.h"
-#include "opj_convert.h"
/** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */
/*@{*/
Decode the structure of a JP2 file
@param jp2 JP2 handle
@param cio Input buffer stream
+@param color Collector for profile, cdef and pclr data
@return Returns true if successful, returns false otherwise
*/
static bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio,
- struct extension *ext);
-
+ opj_jp2_color_t *color);
+/**
+Apply collected palette data
+@param color Collector for profile, cdef and pclr data
+@param image
+*/
+static void jp2_apply_pclr(opj_jp2_color_t *color, opj_image_t *image);
+/**
+Collect palette data
+@param jp2 JP2 handle
+@param cio Input buffer stream
+@param box
+@param color Collector for profile, cdef and pclr data
+@return Returns true if successful, returns false otherwise
+*/
+static bool jp2_read_pclr(opj_jp2_t *jp2, opj_cio_t *cio,
+ opj_jp2_box_t *box, opj_jp2_color_t *color);
+/**
+Collect component mapping data
+@param jp2 JP2 handle
+@param cio Input buffer stream
+@param box
+@param color Collector for profile, cdef and pclr data
+@return Returns true if successful, returns false otherwise
+*/
+static bool jp2_read_cmap(opj_jp2_t *jp2, opj_cio_t *cio,
+ opj_jp2_box_t *box, opj_jp2_color_t *color);
+/**
+Collect colour specification data
+@param jp2 JP2 handle
+@param cio Input buffer stream
+@param box
+@param color Collector for profile, cdef and pclr data
+@return Returns true if successful, returns false otherwise
+*/
+static bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio,
+ opj_jp2_box_t *box, opj_jp2_color_t *color);
/*@}*/
/*@}*/
cio_seek(cio, box.init_pos + box.length);
}
-static void jp2_free_pclr(struct extension *ext)
+static void jp2_free_pclr(opj_jp2_color_t *color)
{
- opj_free(ext->jp2_pclr->channel_sign);
- opj_free(ext->jp2_pclr->channel_size);
- opj_free(ext->jp2_pclr->entries);
+ opj_free(color->jp2_pclr->channel_sign);
+ opj_free(color->jp2_pclr->channel_size);
+ opj_free(color->jp2_pclr->entries);
- if(ext->jp2_pclr->cmap) opj_free(ext->jp2_pclr->cmap);
+ if(color->jp2_pclr->cmap) opj_free(color->jp2_pclr->cmap);
- opj_free(ext->jp2_pclr); ext->jp2_pclr = NULL;
+ opj_free(color->jp2_pclr); color->jp2_pclr = NULL;
}
-static void free_ext_data(struct extension *ext)
+static void free_color_data(opj_jp2_color_t *color)
{
- if(ext->jp2_pclr)
+ if(color->jp2_pclr)
{
- jp2_free_pclr(ext);
+ jp2_free_pclr(color);
}
- if(ext->jp2_cdef)
+ if(color->jp2_cdef)
{
- if(ext->jp2_cdef->info) opj_free(ext->jp2_cdef->info);
- opj_free(ext->jp2_cdef);
+ if(color->jp2_cdef->info) opj_free(color->jp2_cdef->info);
+ opj_free(color->jp2_cdef);
}
- if(ext->jp2_profile_buf) opj_free(ext->jp2_profile_buf);
+ if(color->icc_profile_buf) opj_free(color->icc_profile_buf);
}
-static void jp2_apply_pclr(struct extension *ext, opj_image_t *image)
+static void jp2_apply_pclr(opj_jp2_color_t *color, opj_image_t *image)
{
opj_image_comp_t *old_comps, *new_comps;
unsigned char *channel_size, *channel_sign;
unsigned short i, nr_channels, cmp, pcol;
int k, top_k;
- channel_size = ext->jp2_pclr->channel_size;
- channel_sign = ext->jp2_pclr->channel_sign;
- entries = ext->jp2_pclr->entries;
- cmap = ext->jp2_pclr->cmap;
- nr_channels = ext->jp2_pclr->nr_channels;
+ channel_size = color->jp2_pclr->channel_size;
+ channel_sign = color->jp2_pclr->channel_sign;
+ entries = color->jp2_pclr->entries;
+ cmap = color->jp2_pclr->cmap;
+ nr_channels = color->jp2_pclr->nr_channels;
old_comps = image->comps;
new_comps = (opj_image_comp_t*)
new_comps[pcol].prec = channel_size[i];
new_comps[pcol].sgnd = channel_sign[i];
}
- top_k = ext->jp2_pclr->nr_entries - 1;
+ top_k = color->jp2_pclr->nr_entries - 1;
for(i = 0; i < nr_channels; ++i)
{
image->comps = new_comps;
image->numcomps = nr_channels;
- jp2_free_pclr(ext);
+ jp2_free_pclr(color);
}/* apply_pclr() */
static bool jp2_read_pclr(opj_jp2_t *jp2, opj_cio_t *cio,
- opj_jp2_box_t *box, struct extension *ext)
+ opj_jp2_box_t *box, opj_jp2_color_t *color)
{
opj_jp2_pclr_t *jp2_pclr;
unsigned char *channel_size, *channel_sign;
/* Part 1, I.5.3.4: 'There shall be at most one Palette box inside
* a JP2 Header box' :
*/
- if(ext->jp2_pclr) return false;
+ if(color->jp2_pclr) return false;
nr_entries = cio_read(cio, 2); /* NE */
nr_channels = cio_read(cio, 1);/* NPC */
jp2_pclr->nr_channels = nr_channels;
jp2_pclr->cmap = NULL;
- ext->jp2_pclr = jp2_pclr;
+ color->jp2_pclr = jp2_pclr;
for(i = 0; i < nr_channels; ++i)
{
}/* jp2_read_pclr() */
static bool jp2_read_cmap(opj_jp2_t *jp2, opj_cio_t *cio,
- opj_jp2_box_t *box, struct extension *ext)
+ opj_jp2_box_t *box, opj_jp2_color_t *color)
{
opj_jp2_cmap_comp_t *cmap;
unsigned short i, nr_channels;
/* Need nr_channels: */
- if(ext->jp2_pclr == NULL) return false;
+ if(color->jp2_pclr == NULL) return false;
/* Part 1, I.5.3.5: 'There shall be at most one Component Mapping box
* inside a JP2 Header box' :
*/
- if(ext->jp2_pclr->cmap) return false;
+ if(color->jp2_pclr->cmap) return false;
- nr_channels = ext->jp2_pclr->nr_channels;
+ nr_channels = color->jp2_pclr->nr_channels;
cmap = (opj_jp2_cmap_comp_t*)
opj_malloc(nr_channels * sizeof(opj_jp2_cmap_comp_t));
cmap[i].pcol = cio_read(cio, 1);
}
- ext->jp2_pclr->cmap = cmap;
+ color->jp2_pclr->cmap = cmap;
return true;
}/* jp2_read_cmap() */
-static void jp2_apply_cdef(opj_image_t *image, struct extension *ext)
+static void jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color)
{
opj_jp2_cdef_info_t *info;
int color_space;
unsigned short i, n, cn, typ, asoc, acn;
color_space = image->color_space;
- info = ext->jp2_cdef->info;
- n = ext->jp2_cdef->n;
+ info = color->jp2_cdef->info;
+ n = color->jp2_cdef->n;
for(i = 0; i < n; ++i)
{
info[acn].asoc = info[acn].cn + 1;
}
}
- if(ext->jp2_cdef->info) opj_free(ext->jp2_cdef->info);
+ if(color->jp2_cdef->info) opj_free(color->jp2_cdef->info);
- opj_free(ext->jp2_cdef); ext->jp2_cdef = NULL;
+ opj_free(color->jp2_cdef); color->jp2_cdef = NULL;
}/* jp2_apply_cdef() */
static bool jp2_read_cdef(opj_jp2_t *jp2, opj_cio_t *cio,
- opj_jp2_box_t *box, struct extension *ext)
+ opj_jp2_box_t *box, opj_jp2_color_t *color)
{
opj_jp2_cdef_info_t *info;
unsigned short i, n;
/* Part 1, I.5.3.6: 'The shall be at most one Channel Definition box
* inside a JP2 Header box.'
*/
- if(ext->jp2_cdef) return false;
+ if(color->jp2_cdef) return false;
if((n = cio_read(cio, 2)) == 0) return false; /* szukw000: FIXME */
info = (opj_jp2_cdef_info_t*)
opj_malloc(n * sizeof(opj_jp2_cdef_info_t));
- ext->jp2_cdef = (opj_jp2_cdef_t*)opj_malloc(sizeof(opj_jp2_cdef_t));
- ext->jp2_cdef->info = info;
- ext->jp2_cdef->n = n;
+ color->jp2_cdef = (opj_jp2_cdef_t*)opj_malloc(sizeof(opj_jp2_cdef_t));
+ color->jp2_cdef->info = info;
+ color->jp2_cdef->n = n;
for(i = 0; i < n; ++i)
{
}/* jp2_read_cdef() */
static bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio,
- opj_jp2_box_t *box, struct extension *ext)
+ opj_jp2_box_t *box, opj_jp2_color_t *color)
{
int skip_len;
opj_common_ptr cinfo;
/* Part 1, I.5.3.3 : 'A conforming JP2 reader shall ignore all Colour
* Specification boxes after the first.'
*/
- if(ext->jp2_has_colr) return false;
+ if(color->jp2_has_colr) return false;
cinfo = jp2->cinfo;
unsigned char *start;
start = cio_getbp(cio);
- ext->jp2_profile_buf = (unsigned char*)opj_malloc(skip_len);
- ext->jp2_profile_len = skip_len;
+ color->icc_profile_buf = (unsigned char*)opj_malloc(skip_len);
+ color->icc_profile_len = skip_len;
cio_skip(cio, box->init_pos + box->length - cio_tell(cio));
- memcpy(ext->jp2_profile_buf, start, skip_len);
+ memcpy(color->icc_profile_buf, start, skip_len);
}
}
opj_event_msg(cinfo, EVT_ERROR, "Error with COLR Box\n");
return false;
}
- ext->jp2_has_colr = 1;
+ color->jp2_has_colr = 1;
return true;
}/* jp2_read_colr() */
-#if defined(HAVE_LIBLCMS2) || defined(HAVE_LIBLCMS1)
-#ifdef HAVE_LIBLCMS1
-/* Bob Friesenhahn proposed:*/
-#define cmsSigXYZData icSigXYZData
-#define cmsSigLabData icSigLabData
-#define cmsSigCmykData icSigCmykData
-#define cmsSigYCbCrData icSigYCbCrData
-#define cmsSigLuvData icSigLuvData
-#define cmsSigGrayData icSigGrayData
-#define cmsSigRgbData icSigRgbData
-#define cmsUInt32Number DWORD
-
-#define cmsColorSpaceSignature icColorSpaceSignature
-#define cmsGetHeaderRenderingIntent cmsTakeRenderingIntent
-
-#endif /* HAVE_LIBLCMS1 */
-
-static void jp2_apply_profile(struct extension *ext, opj_image_t *image)
-{
- cmsHPROFILE in_prof, out_prof;
- cmsHTRANSFORM transform;
- cmsColorSpaceSignature in_space, out_space;
- cmsUInt32Number intent, in_type, out_type, nr_samples;
- int *r, *g, *b;
- int prec, i, max, max_w, max_h;
- OPJ_COLOR_SPACE oldspace;
-
- in_prof =
- cmsOpenProfileFromMem(ext->jp2_profile_buf, ext->jp2_profile_len);
- in_space = cmsGetPCS(in_prof);
- out_space = cmsGetColorSpace(in_prof);
- intent = cmsGetHeaderRenderingIntent(in_prof);
-
-
- max_w = image->comps[0].w; max_h = image->comps[0].h;
- prec = image->comps[0].prec;
- oldspace = image->color_space;
-
- if(out_space == cmsSigRgbData) /* enumCS 16 */
- {
- in_type = TYPE_RGB_16;
- out_type = TYPE_RGB_16;
- out_prof = cmsCreate_sRGBProfile();
- image->color_space = CLRSPC_SRGB;
- }
- else
- if(out_space == cmsSigGrayData) /* enumCS 17 */
- {
- in_type = TYPE_GRAY_8;
- out_type = TYPE_RGB_8;
- out_prof = cmsCreate_sRGBProfile();
- image->color_space = CLRSPC_SRGB;
- }
- else
- if(out_space == cmsSigYCbCrData) /* enumCS 18 */
- {
- in_type = TYPE_YCbCr_16;
- out_type = TYPE_RGB_16;
- out_prof = cmsCreate_sRGBProfile();
- image->color_space = CLRSPC_SRGB;
- }
- else
- {
-#ifdef DEBUG_PROFILE
-fprintf(stderr,"%s:%d: jp2_apply_profile\n\tICC Profile has unknown "
-"output colorspace(%#x)(%c%c%c%c)\n\tICC Profile ignored.\n",
-__FILE__,__LINE__,out_space,
-(out_space>>24) & 0xff,(out_space>>16) & 0xff,
-(out_space>>8) & 0xff, out_space & 0xff);
-#endif
- return;
- }
-
-#ifdef DEBUG_PROFILE
-fprintf(stderr,"%s:%d:jp2_apply_profile\n\tchannels(%d) prec(%d) w(%d) h(%d)"
-"\n\tprofile: in(%p) out(%p)\n",__FILE__,__LINE__,image->numcomps,prec,
-max_w,max_h, (void*)in_prof,(void*)out_prof);
-
-fprintf(stderr,"\trender_intent (%u)\n\t"
-"color_space: in(%#x)(%c%c%c%c) out:(%#x)(%c%c%c%c)\n\t"
-" type: in(%u) out:(%u)\n",
-intent,
-in_space,
-(in_space>>24) & 0xff,(in_space>>16) & 0xff,
-(in_space>>8) & 0xff, in_space & 0xff,
-
-out_space,
-(out_space>>24) & 0xff,(out_space>>16) & 0xff,
-(out_space>>8) & 0xff, out_space & 0xff,
-
-in_type,out_type
- );
-#endif /* DEBUG_PROFILE */
-
- transform = cmsCreateTransform(in_prof, in_type,
- out_prof, out_type, intent, 0);
-
-#ifdef HAVE_LIBLCMS2
-/* Possible for: LCMS_VERSION >= 2000 :*/
- cmsCloseProfile(in_prof);
- cmsCloseProfile(out_prof);
-#endif
-
- if(transform == NULL)
- {
-#ifdef DEBUG_PROFILE
-fprintf(stderr,"%s:%d:jp2_apply_profile\n\tcmsCreateTransform failed. "
-"ICC Profile ignored.\n",__FILE__,__LINE__);
-#endif
- image->color_space = oldspace;
-#ifdef HAVE_LIBLCMS1
- cmsCloseProfile(in_prof);
- cmsCloseProfile(out_prof);
-#endif
- return;
- }
-
- if(image->numcomps > 2)/* RGB, RGBA */
- {
- unsigned short *inbuf, *outbuf, *in, *out;
- max = max_w * max_h; nr_samples = max * 3 * sizeof(unsigned short);
- in = inbuf = (unsigned short*)opj_malloc(nr_samples);
- out = outbuf = (unsigned short*)opj_malloc(nr_samples);
-
- r = image->comps[0].data;
- g = image->comps[1].data;
- b = image->comps[2].data;
-
- for(i = 0; i < max; ++i)
- {
- *in++ = (unsigned short)*r++;
- *in++ = (unsigned short)*g++;
- *in++ = (unsigned short)*b++;
- }
-
- cmsDoTransform(transform, inbuf, outbuf, max);
-
- r = image->comps[0].data;
- g = image->comps[1].data;
- b = image->comps[2].data;
-
- for(i = 0; i < max; ++i)
- {
- *r++ = (int)*out++;
- *g++ = (int)*out++;
- *b++ = (int)*out++;
- }
- opj_free(inbuf); opj_free(outbuf);
- }
- else /* GRAY, GRAYA */
- {
- unsigned char *in, *inbuf, *out, *outbuf;
-
- max = max_w * max_h; nr_samples = max * 3 * sizeof(unsigned char);
- in = inbuf = (unsigned char*)opj_malloc(nr_samples);
- out = outbuf = (unsigned char*)opj_malloc(nr_samples);
-
- image->comps = (opj_image_comp_t*)
- opj_realloc(image->comps, (image->numcomps+2)*sizeof(opj_image_comp_t));
-
- if(image->numcomps == 2)
- image->comps[3] = image->comps[1];
-
- image->comps[1] = image->comps[0];
- image->comps[2] = image->comps[0];
-
- image->comps[1].data = (int*)opj_calloc(max, sizeof(int));
- image->comps[2].data = (int*)opj_calloc(max, sizeof(int));
-
- image->numcomps += 2;
-
- r = image->comps[0].data;
-
- for(i = 0; i < max; ++i)
- {
- *in++ = (unsigned char)*r++;
- }
- cmsDoTransform(transform, inbuf, outbuf, max);
-
- r = image->comps[0].data;
- g = image->comps[1].data;
- b = image->comps[2].data;
-
- for(i = 0; i < max; ++i)
- {
- *r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++;
- }
- opj_free(inbuf); opj_free(outbuf);
-
- }/* if(image->numcomps */
-
- cmsDeleteTransform(transform);
-
-#ifdef HAVE_LIBLCMS1
- cmsCloseProfile(in_prof);
- cmsCloseProfile(out_prof);
-#endif
-}/* jp2_apply_profile() */
-
-#endif /* HAVE_LIBLCMS2 || HAVE_LIBLCMS1 */
-
-bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio, struct extension *ext)
+bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio, opj_jp2_color_t *color)
{
opj_jp2_box_t box;
- unsigned int jp2h_end;
+ int jp2h_end;
opj_common_ptr cinfo = jp2->cinfo;
{
if(box.type == JP2_COLR)
{
- if( !jp2_read_colr(jp2, cio, &box, ext))
+ if( !jp2_read_colr(jp2, cio, &box, color))
{
cio_seek(cio, box.init_pos + 8);
cio_skip(cio, box.length - 8);
}
if(box.type == JP2_CDEF)
{
- if( !jp2_read_cdef(jp2, cio, &box, ext))
+ if( !jp2_read_cdef(jp2, cio, &box, color))
{
cio_seek(cio, box.init_pos + 8);
cio_skip(cio, box.length - 8);
}
if(box.type == JP2_PCLR)
{
- if( !jp2_read_pclr(jp2, cio, &box, ext))
+ if( !jp2_read_pclr(jp2, cio, &box, color))
{
cio_seek(cio, box.init_pos + 8);
cio_skip(cio, box.length - 8);
}
if(box.type == JP2_CMAP)
{
- if( !jp2_read_cmap(jp2, cio, &box, ext))
+ if( !jp2_read_cmap(jp2, cio, &box, color))
{
cio_seek(cio, box.init_pos + 8);
cio_skip(cio, box.length - 8);
cio_seek(cio, jp2h_end);
/* Part 1, I.5.3.3 : 'must contain at least one' */
- return (ext->jp2_has_colr == 1);
+ return (color->jp2_has_colr == 1);
}/* jp2_read_jp2h() */
-opj_image_t* jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio,
+opj_image_t* opj_jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio,
opj_codestream_info_t *cstr_info)
{
opj_common_ptr cinfo;
opj_image_t *image = NULL;
- struct extension ext;
+ opj_jp2_color_t color;
if(!jp2 || !cio)
{
return NULL;
}
- memset(&ext, 0, sizeof(struct extension));
+ memset(&color, 0, sizeof(opj_jp2_color_t));
cinfo = jp2->cinfo;
/* JP2 decoding */
- if(!jp2_read_struct(jp2, cio, &ext))
+ if(!jp2_read_struct(jp2, cio, &color))
{
- free_ext_data(&ext);
+ free_color_data(&color);
opj_event_msg(cinfo, EVT_ERROR, "Failed to decode jp2 structure\n");
return NULL;
}
if(!image)
{
- free_ext_data(&ext);
+ free_color_data(&color);
opj_event_msg(cinfo, EVT_ERROR, "Failed to decode J2K image\n");
return NULL;
}
else
image->color_space = CLRSPC_UNKNOWN;
- if(ext.jp2_cdef)
+ if(color.jp2_cdef)
{
- jp2_apply_cdef(image, &ext);
+ jp2_apply_cdef(image, &color);
}
- if(ext.jp2_pclr)
+ if(color.jp2_pclr)
{
/* Part 1, I.5.3.4: Either both or none : */
- if( !ext.jp2_pclr->cmap)
- jp2_free_pclr(&ext);
+ if( !color.jp2_pclr->cmap)
+ jp2_free_pclr(&color);
else
- jp2_apply_pclr(&ext, image);
+ jp2_apply_pclr(&color, image);
}
- if(ext.jp2_profile_buf)
- {
-#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
- jp2_apply_profile(&ext, image);
-#endif
- opj_free(ext.jp2_profile_buf);
- }
- else
- if(image->color_space == CLRSPC_SYCC)
+ if(color.icc_profile_buf)
{
- opj_convert_sycc_to_rgb(image);
+ image->icc_profile_buf = color.icc_profile_buf;
+ color.icc_profile_buf = NULL;
+ image->icc_profile_len = color.icc_profile_len;
}
return image;
-}/* jp2_decode() */
+}/* opj_jp2_decode() */
void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) {
static bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio,
- struct extension *ext) {
+ opj_jp2_color_t *color) {
if (!jp2_read_jp(jp2, cio))
return false;
if (!jp2_read_ftyp(jp2, cio))
return false;
- if (!jp2_read_jp2h(jp2, cio, ext))
+ if (!jp2_read_jp2h(jp2, cio, color))
return false;
if (!jp2_read_jp2c(jp2, cio, &jp2->j2k_codestream_length, &jp2->j2k_codestream_offset))
return false;
}
if (jp2->meth == 1) {
if (image->color_space == 1)
- jp2->enumcs = 16; /* sRGB as defined by IEC 61966�2�1 */
+ jp2->enumcs = 16; /* sRGB as defined by IEC 61966-2.1 */
else if (image->color_space == 2)
jp2->enumcs = 17; /* greyscale */
else if (image->color_space == 3)
}
-bool jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) {
+bool opj_jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) {
/* JP2 encoding */