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