static OPJ_CODEC_FORMAT format_from_header(const unsigned char mem[JP2_FILEHEADER_SIZE]) { if (check_jp2(mem)) { return OPJ_CODEC_JP2; } else if (check_j2k(mem)) { return OPJ_CODEC_J2K; } else { return OPJ_CODEC_UNKNOWN; } }
int imb_is_a_jp2(unsigned char *buf) { return check_jp2(buf); }
struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { struct ImBuf *ibuf = NULL; bool use_float = false; /* for precision higher then 8 use float */ bool use_alpha = false; long signed_offsets[4] = {0, 0, 0, 0}; int float_divs[4] = {1, 1, 1, 1}; unsigned int i, i_next, w, h, planes; unsigned int y; int *r, *g, *b, *a; /* matching 'opj_image_comp.data' type */ int is_jp2, is_j2k; opj_dparameters_t parameters; /* decompression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_image_t *image = NULL; opj_dinfo_t *dinfo = NULL; /* handle to a decompressor */ opj_cio_t *cio = NULL; is_jp2 = check_jp2(mem); is_j2k = check_j2k(mem); if (!is_jp2 && !is_j2k) return(NULL); /* both 8, 12 and 16 bit JP2Ks are default to standard byte colorspace */ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); /* configure the event callbacks (not required) */ memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); event_mgr.error_handler = error_callback; event_mgr.warning_handler = warning_callback; event_mgr.info_handler = info_callback; /* set decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); /* JPEG 2000 compressed image data */ /* get a decoder handle */ dinfo = opj_create_decompress(is_jp2 ? CODEC_JP2 : CODEC_J2K); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); /* setup the decoder decoding parameters using the current image and user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, mem, size); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); if (!image) { fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); opj_destroy_decompress(dinfo); opj_cio_close(cio); return NULL; } /* close the byte stream */ opj_cio_close(cio); if ((image->numcomps * image->x1 * image->y1) == 0) { fprintf(stderr, "\nError: invalid raw image parameters\n"); return NULL; } w = image->comps[0].w; h = image->comps[0].h; switch (image->numcomps) { case 1: /* Grayscale */ case 3: /* Color */ planes = 24; use_alpha = false; break; default: /* 2 or 4 - Grayscale or Color + alpha */ planes = 32; /* grayscale + alpha */ use_alpha = true; break; } i = image->numcomps; if (i > 4) i = 4; while (i) { i--; if (image->comps[i].prec > 8) use_float = true; if (image->comps[i].sgnd) signed_offsets[i] = 1 << (image->comps[i].prec - 1); /* only needed for float images but dosnt hurt to calc this */ float_divs[i] = (1 << image->comps[i].prec) - 1; } ibuf = IMB_allocImBuf(w, h, planes, use_float ? IB_rectfloat : IB_rect); if (ibuf == NULL) { if (dinfo) opj_destroy_decompress(dinfo); return NULL; } ibuf->ftype = JP2; if (is_jp2) ibuf->ftype |= JP2_JP2; else ibuf->ftype |= JP2_J2K; if (use_float) { float *rect_float = ibuf->rect_float; if (image->numcomps < 3) { r = image->comps[0].data; a = (use_alpha) ? image->comps[1].data : NULL; /* grayscale 12bits+ */ if (use_alpha) { a = image->comps[1].data; PIXEL_LOOPER_BEGIN(rect_float) { rect_float[0] = rect_float[1] = rect_float[2] = (float)(r[i] + signed_offsets[0]) / float_divs[0]; rect_float[3] = (a[i] + signed_offsets[1]) / float_divs[1]; } PIXEL_LOOPER_END; } else { PIXEL_LOOPER_BEGIN(rect_float) { rect_float[0] = rect_float[1] = rect_float[2] = (float)(r[i] + signed_offsets[0]) / float_divs[0]; rect_float[3] = 1.0f; } PIXEL_LOOPER_END; } }
struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags) { struct ImBuf *ibuf = 0; int use_float = 0; /* for precision higher then 8 use float */ long signed_offsets[4]= {0, 0, 0, 0}; int float_divs[4]= {1, 1, 1, 1}; int index; int w, h, depth; opj_dparameters_t parameters; /* decompression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_image_t *image = NULL; int i; opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ opj_cio_t *cio = NULL; if (check_jp2(mem) == 0) return(0); /* configure the event callbacks (not required) */ memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); event_mgr.error_handler = error_callback; event_mgr.warning_handler = warning_callback; event_mgr.info_handler = info_callback; /* set decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); /* JPEG 2000 compressed image data */ /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_JP2); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); /* setup the decoder decoding parameters using the current image and user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, mem, size); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); if(!image) { fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); opj_destroy_decompress(dinfo); opj_cio_close(cio); return NULL; } /* close the byte stream */ opj_cio_close(cio); if((image->numcomps * image->x1 * image->y1) == 0) { fprintf(stderr,"\nError: invalid raw image parameters\n"); return NULL; } w = image->comps[0].w; h = image->comps[0].h; switch (image->numcomps) { case 1: /* Greyscale */ case 3: /* Color */ depth= 24; break; default: /* 2 or 4 - Greyscale or Color + alpha */ depth= 32; /* greyscale + alpha */ break; } i = image->numcomps; if (i>4) i= 4; while (i) { i--; if (image->comps[i].prec > 8) use_float = 1; if (image->comps[i].sgnd) signed_offsets[i]= 1 << (image->comps[i].prec - 1); /* only needed for float images but dosnt hurt to calc this */ float_divs[i]= (1<<image->comps[i].prec)-1; } ibuf= IMB_allocImBuf(w, h, depth, use_float ? IB_rectfloat : IB_rect); if (ibuf==NULL) { if(dinfo) opj_destroy_decompress(dinfo); return NULL; } ibuf->ftype = JP2; if (use_float) { float *rect_float= ibuf->rect_float; if (image->numcomps < 3) { /* greyscale 12bits+ */ for (i = 0; i < w * h; i++, rect_float+=4) { index = w * h - ((i) / (w) + 1) * w + (i) % (w); rect_float[0]= rect_float[1]= rect_float[2]= (float)(image->comps[0].data[index] + signed_offsets[0]) / float_divs[0]; if (image->numcomps == 2) rect_float[3]= (image->comps[1].data[index] + signed_offsets[1]) / float_divs[1]; else rect_float[3]= 1.0f; } } else { /* rgb or rgba 12bits+ */ for (i = 0; i < w * h; i++, rect_float+=4) { index = w * h - ((i) / (w) + 1) * w + (i) % (w); rect_float[0]= (float)(image->comps[0].data[index] + signed_offsets[0]) / float_divs[0]; rect_float[1]= (float)(image->comps[1].data[index] + signed_offsets[1]) / float_divs[1]; rect_float[2]= (float)(image->comps[2].data[index] + signed_offsets[2]) / float_divs[2]; if (image->numcomps >= 4) rect_float[3]= (float)(image->comps[3].data[index] + signed_offsets[3]) / float_divs[3]; else rect_float[3]= 1.0f; } } } else { unsigned char *rect= (unsigned char *)ibuf->rect; if (image->numcomps < 3) { /* greyscale */ for (i = 0; i < w * h; i++, rect+=4) { index = w * h - ((i) / (w) + 1) * w + (i) % (w); rect[0]= rect[1]= rect[2]= (image->comps[0].data[index] + signed_offsets[0]); if (image->numcomps == 2) rect[3]= image->comps[1].data[index] + signed_offsets[1]; else rect[3]= 255; } } else { /* 8bit rgb or rgba */ for (i = 0; i < w * h; i++, rect+=4) { int index = w * h - ((i) / (w) + 1) * w + (i) % (w); rect[0]= image->comps[0].data[index] + signed_offsets[0]; rect[1]= image->comps[1].data[index] + signed_offsets[1]; rect[2]= image->comps[2].data[index] + signed_offsets[2]; if (image->numcomps >= 4) rect[3]= image->comps[3].data[index] + signed_offsets[3]; else rect[3]= 255; } } } /* free remaining structures */ if(dinfo) { opj_destroy_decompress(dinfo); } /* free image data structure */ opj_image_destroy(image); if (flags & IB_rect) { IMB_rect_from_float(ibuf); } return(ibuf); }