1 /*M/////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4 // 5 // By downloading, copying, installing or using the software you agree to this license. 6 // If you do not agree to this license, do not download, install, 7 // copy or use the software. 8 // 9 // 10 // License Agreement 11 // For Open Source Computer Vision Library 12 // 13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. 14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved. 15 // Third party copyrights are property of their respective owners. 16 // 17 // Redistribution and use in source and binary forms, with or without modification, 18 // are permitted provided that the following conditions are met: 19 // 20 // * Redistribution's of source code must retain the above copyright notice, 21 // this list of conditions and the following disclaimer. 22 // 23 // * Redistribution's in binary form must reproduce the above copyright notice, 24 // this list of conditions and the following disclaimer in the documentation 25 // and/or other materials provided with the distribution. 26 // 27 // * The name of the copyright holders may not be used to endorse or promote products 28 // derived from this software without specific prior written permission. 29 // 30 // This software is provided by the copyright holders and contributors "as is" and 31 // any express or implied warranties, including, but not limited to, the implied 32 // warranties of merchantability and fitness for a particular purpose are disclaimed. 33 // In no event shall the Intel Corporation or contributors be liable for any direct, 34 // indirect, incidental, special, exemplary, or consequential damages 35 // (including, but not limited to, procurement of substitute goods or services; 36 // loss of use, data, or profits; or business interruption) however caused 37 // and on any theory of liability, whether in contract, strict liability, 38 // or tort (including negligence or otherwise) arising in any way out of 39 // the use of this software, even if advised of the possibility of such damage. 40 // 41 //M*/ 42 43 #include "precomp.hpp" 44 45 #ifdef HAVE_JASPER 46 47 #include "grfmt_jpeg2000.hpp" 48 #include "opencv2/imgproc.hpp" 49 50 #ifdef WIN32 51 #define JAS_WIN_MSVC_BUILD 1 52 #ifdef __GNUC__ 53 #define HAVE_STDINT_H 1 54 #endif 55 #endif 56 57 #undef VERSION 58 59 #include <jasper/jasper.h> 60 // FIXME bad hack 61 #undef uchar 62 #undef ulong 63 64 namespace cv 65 { 66 67 struct JasperInitializer 68 { 69 JasperInitializer() { jas_init(); } 70 ~JasperInitializer() { jas_cleanup(); } 71 }; 72 73 static JasperInitializer initialize_jasper; 74 75 76 /////////////////////// Jpeg2KDecoder /////////////////// 77 78 Jpeg2KDecoder::Jpeg2KDecoder() 79 { 80 m_signature = '\0' + String() + '\0' + String() + '\0' + String("\x0cjP \r\n\x87\n"); 81 m_stream = 0; 82 m_image = 0; 83 } 84 85 86 Jpeg2KDecoder::~Jpeg2KDecoder() 87 { 88 } 89 90 ImageDecoder Jpeg2KDecoder::newDecoder() const 91 { 92 return makePtr<Jpeg2KDecoder>(); 93 } 94 95 void Jpeg2KDecoder::close() 96 { 97 if( m_stream ) 98 { 99 jas_stream_close( (jas_stream_t*)m_stream ); 100 m_stream = 0; 101 } 102 103 if( m_image ) 104 { 105 jas_image_destroy( (jas_image_t*)m_image ); 106 m_image = 0; 107 } 108 } 109 110 111 bool Jpeg2KDecoder::readHeader() 112 { 113 bool result = false; 114 115 close(); 116 jas_stream_t* stream = jas_stream_fopen( m_filename.c_str(), "rb" ); 117 m_stream = stream; 118 119 if( stream ) 120 { 121 jas_image_t* image = jas_image_decode( stream, -1, 0 ); 122 m_image = image; 123 if( image ) { 124 m_width = jas_image_width( image ); 125 m_height = jas_image_height( image ); 126 127 int cntcmpts = 0; // count the known components 128 int numcmpts = jas_image_numcmpts( image ); 129 int depth = 0; 130 for( int i = 0; i < numcmpts; i++ ) 131 { 132 int depth_i = jas_image_cmptprec( image, i ); 133 depth = MAX(depth, depth_i); 134 if( jas_image_cmpttype( image, i ) > 2 ) 135 continue; 136 cntcmpts++; 137 } 138 139 if( cntcmpts ) 140 { 141 m_type = CV_MAKETYPE(depth <= 8 ? CV_8U : CV_16U, cntcmpts > 1 ? 3 : 1); 142 result = true; 143 } 144 } 145 } 146 147 if( !result ) 148 close(); 149 150 return result; 151 } 152 153 154 bool Jpeg2KDecoder::readData( Mat& img ) 155 { 156 bool result = false; 157 int color = img.channels() > 1; 158 uchar* data = img.ptr(); 159 int step = (int)img.step; 160 jas_stream_t* stream = (jas_stream_t*)m_stream; 161 jas_image_t* image = (jas_image_t*)m_image; 162 163 #ifndef WIN32 164 // At least on some Linux instances the 165 // system libjasper segfaults when 166 // converting color to grey. 167 // We do this conversion manually at the end. 168 Mat clr; 169 if (CV_MAT_CN(img.type()) < CV_MAT_CN(this->type())) 170 { 171 clr.create(img.size().height, img.size().width, this->type()); 172 color = true; 173 data = clr.ptr(); 174 step = (int)clr.step; 175 } 176 #endif 177 178 if( stream && image ) 179 { 180 bool convert; 181 int colorspace; 182 if( color ) 183 { 184 convert = (jas_image_clrspc( image ) != JAS_CLRSPC_SRGB); 185 colorspace = JAS_CLRSPC_SRGB; 186 } 187 else 188 { 189 convert = (jas_clrspc_fam( jas_image_clrspc( image ) ) != JAS_CLRSPC_FAM_GRAY); 190 colorspace = JAS_CLRSPC_SGRAY; // TODO GENGRAY or SGRAY? (GENGRAY fails on Win.) 191 } 192 193 // convert to the desired colorspace 194 if( convert ) 195 { 196 jas_cmprof_t *clrprof = jas_cmprof_createfromclrspc( colorspace ); 197 if( clrprof ) 198 { 199 jas_image_t *_img = jas_image_chclrspc( image, clrprof, JAS_CMXFORM_INTENT_RELCLR ); 200 if( _img ) 201 { 202 jas_image_destroy( image ); 203 m_image = image = _img; 204 result = true; 205 } 206 else 207 fprintf(stderr, "JPEG 2000 LOADER ERROR: cannot convert colorspace\n"); 208 jas_cmprof_destroy( clrprof ); 209 } 210 else 211 fprintf(stderr, "JPEG 2000 LOADER ERROR: unable to create colorspace\n"); 212 } 213 else 214 result = true; 215 216 if( result ) 217 { 218 int ncmpts; 219 int cmptlut[3]; 220 if( color ) 221 { 222 cmptlut[0] = jas_image_getcmptbytype( image, JAS_IMAGE_CT_RGB_B ); 223 cmptlut[1] = jas_image_getcmptbytype( image, JAS_IMAGE_CT_RGB_G ); 224 cmptlut[2] = jas_image_getcmptbytype( image, JAS_IMAGE_CT_RGB_R ); 225 if( cmptlut[0] < 0 || cmptlut[1] < 0 || cmptlut[2] < 0 ) 226 result = false; 227 ncmpts = 3; 228 } 229 else 230 { 231 cmptlut[0] = jas_image_getcmptbytype( image, JAS_IMAGE_CT_GRAY_Y ); 232 if( cmptlut[0] < 0 ) 233 result = false; 234 ncmpts = 1; 235 } 236 237 if( result ) 238 { 239 for( int i = 0; i < ncmpts; i++ ) 240 { 241 int maxval = 1 << jas_image_cmptprec( image, cmptlut[i] ); 242 int offset = jas_image_cmptsgnd( image, cmptlut[i] ) ? maxval / 2 : 0; 243 244 int yend = jas_image_cmptbry( image, cmptlut[i] ); 245 int ystep = jas_image_cmptvstep( image, cmptlut[i] ); 246 int xend = jas_image_cmptbrx( image, cmptlut[i] ); 247 int xstep = jas_image_cmpthstep( image, cmptlut[i] ); 248 249 jas_matrix_t *buffer = jas_matrix_create( yend / ystep, xend / xstep ); 250 if( buffer ) 251 { 252 if( !jas_image_readcmpt( image, cmptlut[i], 0, 0, xend / xstep, yend / ystep, buffer )) 253 { 254 if( img.depth() == CV_8U ) 255 result = readComponent8u( data + i, buffer, step, cmptlut[i], maxval, offset, ncmpts ); 256 else 257 result = readComponent16u( ((unsigned short *)data) + i, buffer, step / 2, cmptlut[i], maxval, offset, ncmpts ); 258 if( !result ) 259 { 260 i = ncmpts; 261 result = false; 262 } 263 } 264 jas_matrix_destroy( buffer ); 265 } 266 } 267 } 268 } 269 else 270 fprintf(stderr, "JPEG2000 LOADER ERROR: colorspace conversion failed\n" ); 271 } 272 273 close(); 274 275 #ifndef WIN32 276 if (!clr.empty()) 277 { 278 cv::cvtColor(clr, img, COLOR_BGR2GRAY); 279 } 280 #endif 281 282 return result; 283 } 284 285 286 bool Jpeg2KDecoder::readComponent8u( uchar *data, void *_buffer, 287 int step, int cmpt, 288 int maxval, int offset, int ncmpts ) 289 { 290 jas_matrix_t* buffer = (jas_matrix_t*)_buffer; 291 jas_image_t* image = (jas_image_t*)m_image; 292 int xstart = jas_image_cmpttlx( image, cmpt ); 293 int xend = jas_image_cmptbrx( image, cmpt ); 294 int xstep = jas_image_cmpthstep( image, cmpt ); 295 int xoffset = jas_image_tlx( image ); 296 int ystart = jas_image_cmpttly( image, cmpt ); 297 int yend = jas_image_cmptbry( image, cmpt ); 298 int ystep = jas_image_cmptvstep( image, cmpt ); 299 int yoffset = jas_image_tly( image ); 300 int x, y, x1, y1, j; 301 int rshift = cvRound(std::log(maxval/256.)/std::log(2.)); 302 int lshift = MAX(0, -rshift); 303 rshift = MAX(0, rshift); 304 int delta = (rshift > 0 ? 1 << (rshift - 1) : 0) + offset; 305 306 for( y = 0; y < yend - ystart; ) 307 { 308 jas_seqent_t* pix_row = &jas_matrix_get( buffer, y / ystep, 0 ); 309 uchar* dst = data + (y - yoffset) * step - xoffset; 310 311 if( xstep == 1 ) 312 { 313 if( maxval == 256 && offset == 0 ) 314 for( x = 0; x < xend - xstart; x++ ) 315 { 316 int pix = pix_row[x]; 317 dst[x*ncmpts] = cv::saturate_cast<uchar>(pix); 318 } 319 else 320 for( x = 0; x < xend - xstart; x++ ) 321 { 322 int pix = ((pix_row[x] + delta) >> rshift) << lshift; 323 dst[x*ncmpts] = cv::saturate_cast<uchar>(pix); 324 } 325 } 326 else if( xstep == 2 && offset == 0 ) 327 for( x = 0, j = 0; x < xend - xstart; x += 2, j++ ) 328 { 329 int pix = ((pix_row[j] + delta) >> rshift) << lshift; 330 dst[x*ncmpts] = dst[(x+1)*ncmpts] = cv::saturate_cast<uchar>(pix); 331 } 332 else 333 for( x = 0, j = 0; x < xend - xstart; j++ ) 334 { 335 int pix = ((pix_row[j] + delta) >> rshift) << lshift; 336 pix = cv::saturate_cast<uchar>(pix); 337 for( x1 = x + xstep; x < x1; x++ ) 338 dst[x*ncmpts] = (uchar)pix; 339 } 340 y1 = y + ystep; 341 for( ++y; y < y1; y++, dst += step ) 342 for( x = 0; x < xend - xstart; x++ ) 343 dst[x*ncmpts + step] = dst[x*ncmpts]; 344 } 345 346 return true; 347 } 348 349 350 bool Jpeg2KDecoder::readComponent16u( unsigned short *data, void *_buffer, 351 int step, int cmpt, 352 int maxval, int offset, int ncmpts ) 353 { 354 jas_matrix_t* buffer = (jas_matrix_t*)_buffer; 355 jas_image_t* image = (jas_image_t*)m_image; 356 int xstart = jas_image_cmpttlx( image, cmpt ); 357 int xend = jas_image_cmptbrx( image, cmpt ); 358 int xstep = jas_image_cmpthstep( image, cmpt ); 359 int xoffset = jas_image_tlx( image ); 360 int ystart = jas_image_cmpttly( image, cmpt ); 361 int yend = jas_image_cmptbry( image, cmpt ); 362 int ystep = jas_image_cmptvstep( image, cmpt ); 363 int yoffset = jas_image_tly( image ); 364 int x, y, x1, y1, j; 365 int rshift = cvRound(std::log(maxval/65536.)/std::log(2.)); 366 int lshift = MAX(0, -rshift); 367 rshift = MAX(0, rshift); 368 int delta = (rshift > 0 ? 1 << (rshift - 1) : 0) + offset; 369 370 for( y = 0; y < yend - ystart; ) 371 { 372 jas_seqent_t* pix_row = &jas_matrix_get( buffer, y / ystep, 0 ); 373 ushort* dst = data + (y - yoffset) * step - xoffset; 374 375 if( xstep == 1 ) 376 { 377 if( maxval == 65536 && offset == 0 ) 378 for( x = 0; x < xend - xstart; x++ ) 379 { 380 int pix = pix_row[x]; 381 dst[x*ncmpts] = cv::saturate_cast<ushort>(pix); 382 } 383 else 384 for( x = 0; x < xend - xstart; x++ ) 385 { 386 int pix = ((pix_row[x] + delta) >> rshift) << lshift; 387 dst[x*ncmpts] = cv::saturate_cast<ushort>(pix); 388 } 389 } 390 else if( xstep == 2 && offset == 0 ) 391 for( x = 0, j = 0; x < xend - xstart; x += 2, j++ ) 392 { 393 int pix = ((pix_row[j] + delta) >> rshift) << lshift; 394 dst[x*ncmpts] = dst[(x+1)*ncmpts] = cv::saturate_cast<ushort>(pix); 395 } 396 else 397 for( x = 0, j = 0; x < xend - xstart; j++ ) 398 { 399 int pix = ((pix_row[j] + delta) >> rshift) << lshift; 400 pix = cv::saturate_cast<ushort>(pix); 401 for( x1 = x + xstep; x < x1; x++ ) 402 dst[x*ncmpts] = (ushort)pix; 403 } 404 y1 = y + ystep; 405 for( ++y; y < y1; y++, dst += step ) 406 for( x = 0; x < xend - xstart; x++ ) 407 dst[x*ncmpts + step] = dst[x*ncmpts]; 408 } 409 410 return true; 411 } 412 413 414 /////////////////////// Jpeg2KEncoder /////////////////// 415 416 417 Jpeg2KEncoder::Jpeg2KEncoder() 418 { 419 m_description = "JPEG-2000 files (*.jp2)"; 420 } 421 422 423 Jpeg2KEncoder::~Jpeg2KEncoder() 424 { 425 } 426 427 ImageEncoder Jpeg2KEncoder::newEncoder() const 428 { 429 return makePtr<Jpeg2KEncoder>(); 430 } 431 432 bool Jpeg2KEncoder::isFormatSupported( int depth ) const 433 { 434 return depth == CV_8U || depth == CV_16U; 435 } 436 437 438 bool Jpeg2KEncoder::write( const Mat& _img, const std::vector<int>& ) 439 { 440 int width = _img.cols, height = _img.rows; 441 int depth = _img.depth(), channels = _img.channels(); 442 depth = depth == CV_8U ? 8 : 16; 443 444 if( channels > 3 || channels < 1 ) 445 return false; 446 447 jas_image_cmptparm_t component_info[3]; 448 for( int i = 0; i < channels; i++ ) 449 { 450 component_info[i].tlx = 0; 451 component_info[i].tly = 0; 452 component_info[i].hstep = 1; 453 component_info[i].vstep = 1; 454 component_info[i].width = width; 455 component_info[i].height = height; 456 component_info[i].prec = depth; 457 component_info[i].sgnd = 0; 458 } 459 jas_image_t *img = jas_image_create( channels, component_info, (channels == 1) ? JAS_CLRSPC_SGRAY : JAS_CLRSPC_SRGB ); 460 if( !img ) 461 return false; 462 463 if(channels == 1) 464 jas_image_setcmpttype( img, 0, JAS_IMAGE_CT_GRAY_Y ); 465 else 466 { 467 jas_image_setcmpttype( img, 0, JAS_IMAGE_CT_RGB_B ); 468 jas_image_setcmpttype( img, 1, JAS_IMAGE_CT_RGB_G ); 469 jas_image_setcmpttype( img, 2, JAS_IMAGE_CT_RGB_R ); 470 } 471 472 bool result; 473 if( depth == 8 ) 474 result = writeComponent8u( img, _img ); 475 else 476 result = writeComponent16u( img, _img ); 477 if( result ) 478 { 479 jas_stream_t *stream = jas_stream_fopen( m_filename.c_str(), "wb" ); 480 if( stream ) 481 { 482 result = !jas_image_encode( img, stream, jas_image_strtofmt( (char*)"jp2" ), (char*)"" ); 483 484 jas_stream_close( stream ); 485 } 486 487 } 488 jas_image_destroy( img ); 489 490 return result; 491 } 492 493 494 bool Jpeg2KEncoder::writeComponent8u( void *__img, const Mat& _img ) 495 { 496 jas_image_t* img = (jas_image_t*)__img; 497 int w = _img.cols, h = _img.rows, ncmpts = _img.channels(); 498 jas_matrix_t *row = jas_matrix_create( 1, w ); 499 if(!row) 500 return false; 501 502 for( int y = 0; y < h; y++ ) 503 { 504 const uchar* data = _img.ptr(y); 505 for( int i = 0; i < ncmpts; i++ ) 506 { 507 for( int x = 0; x < w; x++) 508 jas_matrix_setv( row, x, data[x * ncmpts + i] ); 509 jas_image_writecmpt( img, i, 0, y, w, 1, row ); 510 } 511 } 512 513 jas_matrix_destroy( row ); 514 return true; 515 } 516 517 518 bool Jpeg2KEncoder::writeComponent16u( void *__img, const Mat& _img ) 519 { 520 jas_image_t* img = (jas_image_t*)__img; 521 int w = _img.cols, h = _img.rows, ncmpts = _img.channels(); 522 jas_matrix_t *row = jas_matrix_create( 1, w ); 523 if(!row) 524 return false; 525 526 for( int y = 0; y < h; y++ ) 527 { 528 const uchar* data = _img.ptr(y); 529 for( int i = 0; i < ncmpts; i++ ) 530 { 531 for( int x = 0; x < w; x++) 532 jas_matrix_setv( row, x, data[x * ncmpts + i] ); 533 jas_image_writecmpt( img, i, 0, y, w, 1, row ); 534 } 535 } 536 537 jas_matrix_destroy( row ); 538 539 return true; 540 } 541 542 } 543 544 #endif 545 546 /* End of file. */ 547