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 {
JasperInitializercv::JasperInitializer69 JasperInitializer() { jas_init(); }
~JasperInitializercv::JasperInitializer70 ~JasperInitializer() { jas_cleanup(); }
71 };
72
73 static JasperInitializer initialize_jasper;
74
75
76 /////////////////////// Jpeg2KDecoder ///////////////////
77
Jpeg2KDecoder()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
~Jpeg2KDecoder()86 Jpeg2KDecoder::~Jpeg2KDecoder()
87 {
88 }
89
newDecoder() const90 ImageDecoder Jpeg2KDecoder::newDecoder() const
91 {
92 return makePtr<Jpeg2KDecoder>();
93 }
94
close()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
readHeader()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
readData(Mat & img)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
readComponent8u(uchar * data,void * _buffer,int step,int cmpt,int maxval,int offset,int ncmpts)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
readComponent16u(unsigned short * data,void * _buffer,int step,int cmpt,int maxval,int offset,int ncmpts)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
Jpeg2KEncoder()417 Jpeg2KEncoder::Jpeg2KEncoder()
418 {
419 m_description = "JPEG-2000 files (*.jp2)";
420 }
421
422
~Jpeg2KEncoder()423 Jpeg2KEncoder::~Jpeg2KEncoder()
424 {
425 }
426
newEncoder() const427 ImageEncoder Jpeg2KEncoder::newEncoder() const
428 {
429 return makePtr<Jpeg2KEncoder>();
430 }
431
isFormatSupported(int depth) const432 bool Jpeg2KEncoder::isFormatSupported( int depth ) const
433 {
434 return depth == CV_8U || depth == CV_16U;
435 }
436
437
write(const Mat & _img,const std::vector<int> &)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
writeComponent8u(void * __img,const Mat & _img)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
writeComponent16u(void * __img,const Mat & _img)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