/** @brief JPEG 2000グラフィックデータ定義 for C++ (with OpenJpeg-2.x) 現在は JPEG 2000の読み込みのみ.@n 何枚もの画像が含まれていたり,オフセットが指定されている場合には未対応. @file Jpeg2KTool2.cpp @version 0.9 @date 2014 09/24 @author Fumi.Iseki (C) @attention this software is based on OpenJPEG. http://www.openjpeg.org/ */ #include "Jpeg2KTool.h" #ifdef ENABLE_OPENJPEG #if OPENJPEG_VER >= JP2K_VER_20 using namespace jbxl; void JPEG2KImage::init(void) { xs = 0; ys = 0; ws = 0; hs = 0; col = 0; cmode = GRAPH_COLOR_RGBA; state = 0; image = NULL; } bool JPEG2KImage::isNull(void) { if (image!=NULL && image->comps!=NULL) return false; return true; } void JPEG2KImage::free(void) { if (image!=NULL) { opj_image_destroy(image); } init(); } void JPEG2KImage::fill(int v) { if (!isNull()) { for (int k=0; kcomps[k].data!=NULL) { for (int i=0; icomps[k].data[i] = (OPJ_INT32)v; } } } } } void JPEG2KImage::setup_image(void) { if (!isNull()) { // xs = image->x1 - image->x0; ys = image->y1 - image->y0; int fac = (int)image->comps->factor; ws = (xs + (1<>fac; hs = (ys + (1<>fac; col = (int)image->numcomps; if (image->color_space==OPJ_CLRSPC_SRGB) { col = 3; } else if (image->color_space==OPJ_CLRSPC_GRAY) { col = 1; } /* else if (image->color_space==OPJ_CLRSPC_UNSPECIFIED) { col = (int)image->numcomps; } */ // 設定されないものについては,未対応 cmode = GRAPH_COLOR_UNKNOWN; #if OPENJPEG_VER < JP2K_VER_25 int depth = (int)image->comps->bpp; #else int depth = (int)image->comps->prec; #endif if (depth==0) { if (col==3) cmode = GRAPH_COLOR_RGB; else if (col==4) cmode = GRAPH_COLOR_RGBA; else if (col==1) cmode = GRAPH_COLOR_MONO; } else if (depth==32) { if (col==3) cmode = GRAPH_COLOR_RGB; else if (col==4) cmode = GRAPH_COLOR_RGBA; } else if (depth==24) { if (col==3) cmode = GRAPH_COLOR_RGB; } else if (depth==16) { if (col==1) cmode = GRAPH_COLOR_MONO16; else if (col==3) cmode = GRAPH_COLOR_RGB16; else if (col==4) cmode = GRAPH_COLOR_RGBA16; } else if (depth==8) { if (col==1) cmode = GRAPH_COLOR_MONO; } /* DEBUG_MODE { PRINT_MESG("JPEG2KImage::setup_image: OFFSET %d %d %d %d\n", image->x0, image->y0, image->x1, image->y1); PRINT_MESG("JPEG2KImage::setup_image: NUMCOMP %d\n", image->numcomps); PRINT_MESG("JPEG2KImage::setup_image: COLORSP %d\n", image->color_space); PRINT_MESG("JPEG2KImage::setup_image: XS YS %d %d\n", xs, ys); PRINT_MESG("JPEG2KImage::setup_image: COLOR %d\n", col); PRINT_MESG("JPEG2KImage::setup_image: CMODE %d\n", cmode); PRINT_MESG("\n"); for (int i=0; i<(int)image->numcomps; i++) { PRINT_MESG("JPEG2KImage::setup_image: DX DY %d %d\n", image->comps[i].dx, image->comps[i].dy); PRINT_MESG("JPEG2KImage::setup_image: W H %d %d\n", image->comps[i].w, image->comps[i].h); PRINT_MESG("JPEG2KImage::setup_image: X0 Y0 %d %d\n", image->comps[i].x0, image->comps[i].y0); PRINT_MESG("JPEG2KImage::setup_image: PREC %d\n", image->comps[i].prec); PRINT_MESG("JPEG2KImage::setup_image: DEPTH %d\n", image->comps[i].bpp); PRINT_MESG("JPEG2KImage::setup_image: SGND %d\n", image->comps[i].sgnd); PRINT_MESG("JPEG2KImage::setup_image: RESNO %d\n", image->comps[i].resno_decoded); PRINT_MESG("JPEG2KImage::setup_image: FACT %d\n", image->comps[i].factor); PRINT_MESG("\n"); } } */ } } ////////////////////////////////////////////////////////////////////// JPEG2KImage jbxl::readJPEG2KFile(const char* fname) { JPEG2KImage jp; // if (fname==NULL) { jp.state = JBXL_GRAPH_IVDARG_ERROR; return jp; } FILE* fp = fopen(fname, "rb"); if (fp==NULL) { jp.state = JBXL_GRAPH_OPFILE_ERROR; return jp; } Buffer buf = read_Buffer_data(fp, 12); if (buf.vldsz<12) { free_Buffer(&buf); jp.state = JBXL_GRAPH_FILESZ_ERROR; fclose(fp); return jp; } fseek(fp, 0, 0); int format = isJPEG2KHeader(buf); if (format==JP2K_FMT_NONE) format = JP2K_FMT_JPT; free_Buffer(&buf); #if OPENJPEG_VER < JP2K_VER_21 jp = readJPEG2KData(fp, format); fclose(fp); #else fclose(fp); jp = readJPEG2KData(fname, format); #endif return jp; } #if OPENJPEG_VER < JP2K_VER_21 JPEG2KImage jbxl::readJPEG2KData(FILE* fp, int format) #else JPEG2KImage jbxl::readJPEG2KData(const char* fname, int format) #endif { JPEG2KImage jp; opj_stream_t* stream = NULL; opj_codec_t* codec = NULL; opj_dparameters_t parameters; opj_set_default_decoder_parameters(¶meters); #if OPENJPEG_VER < JP2K_VER_21 stream = opj_stream_create_default_file_stream(fp, 1); #else stream = opj_stream_create_default_file_stream(fname, 1); #endif if (stream==NULL){ jp.state = JBXL_GRAPH_RDFILE_ERROR; return jp; } if (format==JP2K_FMT_J2K) { // JPEG 2000 codestream codec = opj_create_decompress(OPJ_CODEC_J2K); } else if (format==JP2K_FMT_JP2) { // JPEG 2000 compressed image data codec = opj_create_decompress(OPJ_CODEC_JP2); } else if (format==JP2K_FMT_JPT) { // JPEG 2000 JPIP codec = opj_create_decompress(OPJ_CODEC_JPT); } else { PRINT_MESG("JBXL::readJPEG2KData: ERROR: unknown file format!\n"); opj_stream_destroy(stream); return jp; } if (!opj_setup_decoder(codec, ¶meters) ){ opj_stream_destroy(stream); opj_destroy_codec(codec); jp.state = JBXL_GRAPH_ERROR; return jp; } if (!opj_read_header(stream, codec, &jp.image)){ opj_stream_destroy(stream); opj_destroy_codec(codec); jp.state = JBXL_GRAPH_ERROR; return jp; } // if (!opj_set_decode_area(codec, jp.image, 0, 0, 0, 0)){ if (!opj_set_decode_area(codec, jp.image, (OPJ_INT32)parameters.DA_x0, (OPJ_INT32)parameters.DA_y0, (OPJ_INT32)parameters.DA_x1, (OPJ_INT32)parameters.DA_y1)){ opj_stream_destroy(stream); opj_destroy_codec(codec); jp.free(); jp.state = JBXL_GRAPH_ERROR; return jp; } if (!(opj_decode(codec, stream, jp.image) && opj_end_decompress(codec, stream))) { opj_destroy_codec(codec); opj_stream_destroy(stream); jp.free(); jp.state = JBXL_GRAPH_ERROR; return jp; } jp.setup_image(); opj_stream_destroy(stream); opj_destroy_codec(codec); return jp; } /** JPEG 2000のヘッダからファイルの種類を返す.@n ただし,ヘッダから JP2K_FMT_JPTであることは判別できないので,注意する. @param buf ヘッダ情報の入った Buffer変数.最低12Byte必要. @return ファイル種別 (JP2K_FMT_NONE, JP2K_FMT_JP2, JP2K_FMT_J2K) */ int jbxl::isJPEG2KHeader(Buffer buf) { int format = JP2K_FMT_NONE; if (!memcmp(buf.buf, JP2K_MAGIC_RFC3745_JP2, 12) || !memcmp(buf.buf, JP2K_MAGIC_JP2, 4)) { format = JP2K_FMT_JP2; } else if (!memcmp(buf.buf, JP2K_MAGIC_J2K, 4)) { format = JP2K_FMT_J2K; } return format; } #endif // OPENJPEG_VER >= JP2K_VER_20 #endif // ENABLE_OPENJPEG