Apply maemo2 patch
[opencv] / otherlibs / highgui / grfmt_jpeg2000.cpp
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
49 GrFmtJpeg2000::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
58 GrFmtJpeg2000::~GrFmtJpeg2000()
59 {
60     jas_cleanup();
61 }
62
63
64 GrFmtReader* GrFmtJpeg2000::NewReader( const char* filename )
65 {
66     return new GrFmtJpeg2000Reader( filename );
67 }
68
69
70 GrFmtWriter* GrFmtJpeg2000::NewWriter( const char* filename )
71 {
72     return new GrFmtJpeg2000Writer( filename );
73 }
74
75
76 /////////////////////// GrFmtJpeg2000Reader ///////////////////
77
78 GrFmtJpeg2000Reader::GrFmtJpeg2000Reader( const char* filename ) : GrFmtReader( filename )
79 {
80         m_stream = 0;
81         m_image = 0;
82 }
83
84
85 GrFmtJpeg2000Reader::~GrFmtJpeg2000Reader()
86 {
87 }
88
89
90 void  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
107 bool  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
152 bool  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
259 bool  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
321 bool  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
386 GrFmtJpeg2000Writer::GrFmtJpeg2000Writer( const char* filename ) : GrFmtWriter( filename )
387 {
388 }
389
390
391 GrFmtJpeg2000Writer::~GrFmtJpeg2000Writer()
392 {
393 }
394
395
396 bool  GrFmtJpeg2000Writer::IsFormatSupported( int depth )
397 {
398     return depth == IPL_DEPTH_8U || depth == IPL_DEPTH_16U;
399 }
400
401
402 bool  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
455 bool  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
478 bool  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. */