diff options
| author | Antonin Descampe <antonin@gmail.com> | 2010-10-05 10:33:15 +0000 |
|---|---|---|
| committer | Antonin Descampe <antonin@gmail.com> | 2010-10-05 10:33:15 +0000 |
| commit | eeefefd56cb3edddefb73141733fd1e757c4b798 (patch) | |
| tree | 4727958764c4c348762c043c2efbb7470a9ffcca /libopenjpeg/jp2.c | |
| parent | 531c0cf26f0c327b42a5caa79725e4afeb98768d (diff) | |
Added files to let people build openjpeg with configure tools ; Added makefiles to let people manually build openjpeg on *nix platforms ; Removed obsolete Makefiles ; Renamed dirent.h to windirent.h ; Made optional the PNG, TIFF, and LCMS support in CMake files ; Added opj_config* files to configure openjpeg before building it (opj_config.h generated by configure, cmake, or manually by the user) ; Renamed this file from ChangeLog to CHANGES ; Renamed License.txt to LICENSE ; Updated README files ; Added INSTALL and LICENSE files ; Added man pages
Diffstat (limited to 'libopenjpeg/jp2.c')
| -rw-r--r-- | libopenjpeg/jp2.c | 768 |
1 files changed, 663 insertions, 105 deletions
diff --git a/libopenjpeg/jp2.c b/libopenjpeg/jp2.c index b2831cfb..449466b4 100644 --- a/libopenjpeg/jp2.c +++ b/libopenjpeg/jp2.c @@ -28,8 +28,17 @@ * 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 */ /*@{*/ @@ -57,7 +66,6 @@ static void jp2_write_ihdr(opj_jp2_t *jp2, opj_cio_t *cio); static void jp2_write_bpcc(opj_jp2_t *jp2, opj_cio_t *cio); static bool jp2_read_bpcc(opj_jp2_t *jp2, opj_cio_t *cio); static void jp2_write_colr(opj_jp2_t *jp2, opj_cio_t *cio); -static bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio); /** Write the FTYP box - File type box @param jp2 JP2 handle @@ -87,7 +95,8 @@ Decode the structure of a JP2 file @param cio Input buffer stream @return Returns true if successful, returns false otherwise */ -static bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio); +static bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio, + struct extension *ext); /*@}*/ @@ -258,42 +267,664 @@ static void jp2_write_colr(opj_jp2_t *jp2, opj_cio_t *cio) { cio_seek(cio, box.init_pos + box.length); } -static bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio) { - opj_jp2_box_t box; +static void jp2_free_pclr(struct extension *ext) +{ + opj_free(ext->jp2_pclr->channel_sign); + opj_free(ext->jp2_pclr->channel_size); + opj_free(ext->jp2_pclr->entries); + + if(ext->jp2_pclr->cmap) opj_free(ext->jp2_pclr->cmap); + + opj_free(ext->jp2_pclr); ext->jp2_pclr = NULL; +} + +static void free_ext_data(struct extension *ext) +{ + if(ext->jp2_pclr) + { + jp2_free_pclr(ext); + } + if(ext->jp2_cdef) + { + if(ext->jp2_cdef->info) opj_free(ext->jp2_cdef->info); + opj_free(ext->jp2_cdef); + } + if(ext->jp2_profile_buf) opj_free(ext->jp2_profile_buf); +} + +static void jp2_apply_pclr(struct extension *ext, opj_image_t *image) +{ + opj_image_comp_t *old_comps, *new_comps; + unsigned char *channel_size, *channel_sign; + unsigned int *entries; + opj_jp2_cmap_comp_t *cmap; + int *src, *dst; + unsigned int j, max; + 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; + + old_comps = image->comps; + new_comps = (opj_image_comp_t*) + opj_malloc(nr_channels * sizeof(opj_image_comp_t)); + + for(i = 0; i < nr_channels; ++i) + { + pcol = cmap[i].pcol; cmp = cmap[i].cmp; + + new_comps[pcol] = old_comps[cmp]; + + if(cmap[i].mtyp == 0) /* Direct use */ + { + old_comps[cmp].data = NULL; continue; + } +/* Palette mapping: */ + new_comps[pcol].data = (int*) + opj_malloc(old_comps[cmp].w * old_comps[cmp].h * sizeof(int)); + new_comps[pcol].prec = channel_size[i]; + new_comps[pcol].sgnd = channel_sign[i]; + } + top_k = ext->jp2_pclr->nr_entries - 1; + + for(i = 0; i < nr_channels; ++i) + { +/* Direct use: */ + if(cmap[i].mtyp == 0) continue; + +/* Palette mapping: */ + cmp = cmap[i].cmp; pcol = cmap[i].pcol; + src = old_comps[cmp].data; + dst = new_comps[pcol].data; + max = new_comps[pcol].w * new_comps[pcol].h; + + for(j = 0; j < max; ++j) + { +/* The index */ + if((k = src[j]) < 0) k = 0; else if(k > top_k) k = top_k; +/* The colour */ + dst[j] = entries[k * nr_channels + pcol]; + } + } + max = image->numcomps; + for(i = 0; i < max; ++i) + { + if(old_comps[i].data) opj_free(old_comps[i].data); + } + opj_free(old_comps); + image->comps = new_comps; + image->numcomps = nr_channels; + + jp2_free_pclr(ext); + +}/* 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_pclr_t *jp2_pclr; + unsigned char *channel_size, *channel_sign; + unsigned int *entries; + unsigned short nr_entries, nr_channels; + unsigned short i, j; + unsigned char uc; + +/* 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; + + nr_entries = cio_read(cio, 2); /* NE */ + nr_channels = cio_read(cio, 1);/* NPC */ + + entries = (unsigned int*) + opj_malloc(nr_channels * nr_entries * sizeof(unsigned int)); + channel_size = (unsigned char*)opj_malloc(nr_channels); + channel_sign = (unsigned char*)opj_malloc(nr_channels); + + jp2_pclr = (opj_jp2_pclr_t*)opj_malloc(sizeof(opj_jp2_pclr_t)); + jp2_pclr->channel_sign = channel_sign; + jp2_pclr->channel_size = channel_size; + jp2_pclr->entries = entries; + jp2_pclr->nr_entries = nr_entries; + jp2_pclr->nr_channels = nr_channels; + jp2_pclr->cmap = NULL; + + ext->jp2_pclr = jp2_pclr; + + for(i = 0; i < nr_channels; ++i) + { + uc = cio_read(cio, 1); /* Bi */ + channel_size[i] = (uc & 0x7f) + 1; + channel_sign[i] = (uc & 0x80)?1:0; + } + + for(j = 0; j < nr_entries; ++j) + { + for(i = 0; i < nr_channels; ++i) + { +/* Cji */ + *entries++ = cio_read(cio, channel_size[i]>>3); + } + } + + return true; +}/* 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_cmap_comp_t *cmap; + unsigned short i, nr_channels; + +/* Need nr_channels: */ + if(ext->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; + + nr_channels = ext->jp2_pclr->nr_channels; + cmap = (opj_jp2_cmap_comp_t*) + opj_malloc(nr_channels * sizeof(opj_jp2_cmap_comp_t)); + + for(i = 0; i < nr_channels; ++i) + { + cmap[i].cmp = cio_read(cio, 2); + cmap[i].mtyp = cio_read(cio, 1); + cmap[i].pcol = cio_read(cio, 1); + + } + ext->jp2_pclr->cmap = cmap; + + return true; +}/* jp2_read_cmap() */ + +static void jp2_apply_cdef(opj_image_t *image, struct extension *ext) +{ + 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; + + for(i = 0; i < n; ++i) + { +/* WATCH: acn = asoc - 1 ! */ + if((asoc = info[i].asoc) == 0) continue; + + cn = info[i].cn; typ = info[i].typ; acn = asoc - 1; + + if(cn != acn) + { + opj_image_comp_t saved; + + memcpy(&saved, &image->comps[cn], sizeof(opj_image_comp_t)); + memcpy(&image->comps[cn], &image->comps[acn], sizeof(opj_image_comp_t)); + memcpy(&image->comps[acn], &saved, sizeof(opj_image_comp_t)); + + info[i].asoc = cn + 1; + info[acn].asoc = info[acn].cn + 1; + } + } + if(ext->jp2_cdef->info) opj_free(ext->jp2_cdef->info); + + opj_free(ext->jp2_cdef); ext->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_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((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; + + for(i = 0; i < n; ++i) + { + info[i].cn = cio_read(cio, 2); + info[i].typ = cio_read(cio, 2); + info[i].asoc = cio_read(cio, 2); + + } + return true; +}/* jp2_read_cdef() */ + +static bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_box_t *box, struct extension *ext) +{ int skip_len; - opj_common_ptr cinfo = jp2->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; - jp2_read_boxhdr(cinfo, cio, &box); - do { - if (JP2_COLR != box.type) { - cio_skip(cio, box.length - 8); - jp2_read_boxhdr(cinfo, cio, &box); - } - } while(JP2_COLR != box.type); + opj_common_ptr cinfo = jp2->cinfo; jp2->meth = cio_read(cio, 1); /* METH */ jp2->precedence = cio_read(cio, 1); /* PRECEDENCE */ jp2->approx = cio_read(cio, 1); /* APPROX */ - if (jp2->meth == 1) { - jp2->enumcs = cio_read(cio, 4); /* EnumCS */ - } else { - /* skip PROFILE */ - skip_len = box.init_pos + box.length - cio_tell(cio); - if (skip_len < 0) { - opj_event_msg(cinfo, EVT_ERROR, "Error with JP2H box size\n"); - return false; - } - cio_skip(cio, box.init_pos + box.length - cio_tell(cio)); - } + if (jp2->meth == 1) + { + jp2->enumcs = cio_read(cio, 4); /* EnumCS */ + } + else + { +/* skip PROFILE */ + skip_len = box->init_pos + box->length - cio_tell(cio); + if (skip_len < 0) + { + opj_event_msg(cinfo, EVT_ERROR, "Error with COLR box size\n"); + return false; + } + if(skip_len > 0) + { + unsigned char *start; + + start = cio_getbp(cio); + ext->jp2_profile_buf = (unsigned char*)opj_malloc(skip_len); + ext->jp2_profile_len = skip_len; + + cio_skip(cio, box->init_pos + box->length - cio_tell(cio)); + + memcpy(ext->jp2_profile_buf, start, skip_len); + } + } + + if (cio_tell(cio) - box->init_pos != box->length) + { + opj_event_msg(cinfo, EVT_ERROR, "Error with COLR Box\n"); + return false; + } + ext->jp2_has_colr = 1; - if (cio_tell(cio) - box.init_pos != box.length) { - opj_event_msg(cinfo, EVT_ERROR, "Error with BPCC Box\n"); - return false; - } 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) +{ + opj_jp2_box_t box; + unsigned int jp2h_end; + + opj_common_ptr cinfo = jp2->cinfo; + + jp2_read_boxhdr(cinfo, cio, &box); + do + { + if (JP2_JP2H != box.type) + { + if (box.type == JP2_JP2C) + { + opj_event_msg(cinfo, EVT_ERROR, "Expected JP2H Marker\n"); + return false; + } + cio_skip(cio, box.length - 8); + + if(cio->bp >= cio->end) return false; + + jp2_read_boxhdr(cinfo, cio, &box); + } + } while(JP2_JP2H != box.type); + + if (!jp2_read_ihdr(jp2, cio)) + return false; + jp2h_end = box.init_pos + box.length; + + if (jp2->bpc == 255) + { + if (!jp2_read_bpcc(jp2, cio)) + return false; + } + jp2_read_boxhdr(cinfo, cio, &box); + + while(cio_tell(cio) < jp2h_end) + { + if(box.type == JP2_COLR) + { + if( !jp2_read_colr(jp2, cio, &box, ext)) + { + cio_seek(cio, box.init_pos + 8); + cio_skip(cio, box.length - 8); + } + jp2_read_boxhdr(cinfo, cio, &box); + continue; + } + if(box.type == JP2_CDEF) + { + if( !jp2_read_cdef(jp2, cio, &box, ext)) + { + cio_seek(cio, box.init_pos + 8); + cio_skip(cio, box.length - 8); + } + jp2_read_boxhdr(cinfo, cio, &box); + continue; + } + if(box.type == JP2_PCLR) + { + if( !jp2_read_pclr(jp2, cio, &box, ext)) + { + cio_seek(cio, box.init_pos + 8); + cio_skip(cio, box.length - 8); + } + jp2_read_boxhdr(cinfo, cio, &box); + continue; + } + if(box.type == JP2_CMAP) + { + if( !jp2_read_cmap(jp2, cio, &box, ext)) + { + cio_seek(cio, box.init_pos + 8); + cio_skip(cio, box.length - 8); + } + jp2_read_boxhdr(cinfo, cio, &box); + continue; + } + cio_seek(cio, box.init_pos + 8); + cio_skip(cio, box.length - 8); + jp2_read_boxhdr(cinfo, cio, &box); + + }/* while(cio_tell(cio) < box_end) */ + + cio_seek(cio, jp2h_end); + +/* Part 1, I.5.3.3 : 'must contain at least one' */ + return (ext->jp2_has_colr == 1); + +}/* jp2_read_jp2h() */ + +opj_image_t* 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; + + if(!jp2 || !cio) + { + return NULL; + } + memset(&ext, 0, sizeof(struct extension)); + cinfo = jp2->cinfo; + +/* JP2 decoding */ + if(!jp2_read_struct(jp2, cio, &ext)) + { + free_ext_data(&ext); + opj_event_msg(cinfo, EVT_ERROR, "Failed to decode jp2 structure\n"); + return NULL; + } + +/* J2K decoding */ + image = j2k_decode(jp2->j2k, cio, cstr_info); + + if(!image) + { + free_ext_data(&ext); + opj_event_msg(cinfo, EVT_ERROR, "Failed to decode J2K image\n"); + return NULL; + } + +/* Set Image Color Space */ + if (jp2->enumcs == 16) + image->color_space = CLRSPC_SRGB; + else if (jp2->enumcs == 17) + image->color_space = CLRSPC_GRAY; + else if (jp2->enumcs == 18) + image->color_space = CLRSPC_SYCC; + else + image->color_space = CLRSPC_UNKNOWN; + + if(ext.jp2_cdef) + { + jp2_apply_cdef(image, &ext); + } + if(ext.jp2_pclr) + { +/* Part 1, I.5.3.4: Either both or none : */ + if( !ext.jp2_pclr->cmap) + jp2_free_pclr(&ext); + else + jp2_apply_pclr(&ext, 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) + { + opj_convert_sycc_to_rgb(image); + } + return image; + +}/* jp2_decode() */ + void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) { opj_jp2_box_t box; @@ -315,44 +946,6 @@ void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) { cio_seek(cio, box.init_pos + box.length); } -bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) { - opj_jp2_box_t box; - int skip_len; - - opj_common_ptr cinfo = jp2->cinfo; - - jp2_read_boxhdr(cinfo, cio, &box); - do { - if (JP2_JP2H != box.type) { - if (box.type == JP2_JP2C) { - opj_event_msg(cinfo, EVT_ERROR, "Expected JP2H Marker\n"); - return false; - } - cio_skip(cio, box.length - 8); - jp2_read_boxhdr(cinfo, cio, &box); - } - } while(JP2_JP2H != box.type); - - if (!jp2_read_ihdr(jp2, cio)) - return false; - - if (jp2->bpc == 255) { - if (!jp2_read_bpcc(jp2, cio)) - return false; - } - if (!jp2_read_colr(jp2, cio)) - return false; - - skip_len = box.init_pos + box.length - cio_tell(cio); - if (skip_len < 0) { - opj_event_msg(cinfo, EVT_ERROR, "Error with JP2H Box\n"); - return false; - } - cio_skip(cio, box.init_pos + box.length - cio_tell(cio)); - - return true; -} - static void jp2_write_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) { unsigned int i; opj_jp2_box_t box; @@ -489,12 +1082,13 @@ static bool jp2_read_jp(opj_jp2_t *jp2, opj_cio_t *cio) { } -static bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio) { +static bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio, + struct extension *ext) { if (!jp2_read_jp(jp2, cio)) return false; if (!jp2_read_ftyp(jp2, cio)) return false; - if (!jp2_read_jp2h(jp2, cio)) + if (!jp2_read_jp2h(jp2, cio, ext)) return false; if (!jp2_read_jp2c(jp2, cio, &jp2->j2k_codestream_length, &jp2->j2k_codestream_offset)) return false; @@ -541,42 +1135,6 @@ void jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) { /* further JP2 initializations go here */ } -opj_image_t* 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; - - if(!jp2 || !cio) { - return NULL; - } - - cinfo = jp2->cinfo; - - /* JP2 decoding */ - if(!jp2_read_struct(jp2, cio)) { - opj_event_msg(cinfo, EVT_ERROR, "Failed to decode jp2 structure\n"); - return NULL; - } - - /* J2K decoding */ - image = j2k_decode(jp2->j2k, cio, cstr_info); - if(!image) { - opj_event_msg(cinfo, EVT_ERROR, "Failed to decode J2K image\n"); - return NULL; - } - - /* Set Image Color Space */ - if (jp2->enumcs == 16) - image->color_space = CLRSPC_SRGB; - else if (jp2->enumcs == 17) - image->color_space = CLRSPC_GRAY; - else if (jp2->enumcs == 18) - image->color_space = CLRSPC_SYCC; - else - image->color_space = CLRSPC_UNKNOWN; - - return image; -} - /* ----------------------------------------------------------------------- */ /* JP2 encoder interface */ /* ----------------------------------------------------------------------- */ |
