• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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