Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/imgcodecs/src/grfmt_jpeg2000.cpp
16337 views
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
static const unsigned char signature_[12] = { 0, 0, 0, 0x0c, 'j', 'P', ' ', ' ', 13, 10, 0x87, 10};
81
m_signature = String((const char*)signature_, (const char*)signature_ + sizeof(signature_));
82
m_stream = 0;
83
m_image = 0;
84
}
85
86
87
Jpeg2KDecoder::~Jpeg2KDecoder()
88
{
89
}
90
91
ImageDecoder Jpeg2KDecoder::newDecoder() const
92
{
93
return makePtr<Jpeg2KDecoder>();
94
}
95
96
void Jpeg2KDecoder::close()
97
{
98
if( m_stream )
99
{
100
jas_stream_close( (jas_stream_t*)m_stream );
101
m_stream = 0;
102
}
103
104
if( m_image )
105
{
106
jas_image_destroy( (jas_image_t*)m_image );
107
m_image = 0;
108
}
109
}
110
111
112
bool Jpeg2KDecoder::readHeader()
113
{
114
bool result = false;
115
116
close();
117
jas_stream_t* stream = jas_stream_fopen( m_filename.c_str(), "rb" );
118
m_stream = stream;
119
120
if( stream )
121
{
122
jas_image_t* image = jas_image_decode( stream, -1, 0 );
123
m_image = image;
124
if( image ) {
125
CV_Assert(0 == (jas_image_tlx(image)) && "not supported");
126
CV_Assert(0 == (jas_image_tly(image)) && "not supported");
127
m_width = jas_image_width( image );
128
m_height = jas_image_height( image );
129
130
int cntcmpts = 0; // count the known components
131
int numcmpts = jas_image_numcmpts( image );
132
int depth = 0;
133
for( int i = 0; i < numcmpts; i++ )
134
{
135
int depth_i = jas_image_cmptprec( image, i );
136
CV_Assert(depth == 0 || depth == depth_i); // component data type mismatch
137
depth = MAX(depth, depth_i);
138
if( jas_image_cmpttype( image, i ) > 2 )
139
continue;
140
int sgnd = jas_image_cmptsgnd(image, i);
141
int xstart = jas_image_cmpttlx(image, i);
142
int xend = jas_image_cmptbrx(image, i);
143
int xstep = jas_image_cmpthstep(image, i);
144
int ystart = jas_image_cmpttly(image, i);
145
int yend = jas_image_cmptbry(image, i);
146
int ystep = jas_image_cmptvstep(image, i);
147
CV_Assert(sgnd == 0 && "not supported");
148
CV_Assert(xstart == 0 && "not supported");
149
CV_Assert(ystart == 0 && "not supported");
150
CV_Assert(xstep == 1 && "not supported");
151
CV_Assert(ystep == 1 && "not supported");
152
CV_Assert(xend == m_width);
153
CV_Assert(yend == m_height);
154
cntcmpts++;
155
}
156
157
if( cntcmpts )
158
{
159
CV_Assert(depth == 8 || depth == 16);
160
CV_Assert(cntcmpts == 1 || cntcmpts == 3);
161
m_type = CV_MAKETYPE(depth <= 8 ? CV_8U : CV_16U, cntcmpts > 1 ? 3 : 1);
162
result = true;
163
}
164
}
165
}
166
167
if( !result )
168
close();
169
170
return result;
171
}
172
173
static void Jpeg2KDecoder_close(Jpeg2KDecoder* ptr)
174
{
175
ptr->close();
176
}
177
178
bool Jpeg2KDecoder::readData( Mat& img )
179
{
180
Ptr<Jpeg2KDecoder> close_this(this, Jpeg2KDecoder_close);
181
bool result = false;
182
bool color = img.channels() > 1;
183
uchar* data = img.ptr();
184
size_t step = img.step;
185
jas_stream_t* stream = (jas_stream_t*)m_stream;
186
jas_image_t* image = (jas_image_t*)m_image;
187
188
#ifndef _WIN32
189
// At least on some Linux instances the
190
// system libjasper segfaults when
191
// converting color to grey.
192
// We do this conversion manually at the end.
193
Mat clr;
194
if (CV_MAT_CN(img.type()) < CV_MAT_CN(this->type()))
195
{
196
clr.create(img.size().height, img.size().width, this->type());
197
color = true;
198
data = clr.ptr();
199
step = (int)clr.step;
200
}
201
#endif
202
203
if( stream && image )
204
{
205
bool convert;
206
int colorspace;
207
if( color )
208
{
209
convert = (jas_image_clrspc( image ) != JAS_CLRSPC_SRGB);
210
colorspace = JAS_CLRSPC_SRGB;
211
}
212
else
213
{
214
convert = (jas_clrspc_fam( jas_image_clrspc( image ) ) != JAS_CLRSPC_FAM_GRAY);
215
colorspace = JAS_CLRSPC_SGRAY; // TODO GENGRAY or SGRAY? (GENGRAY fails on Win.)
216
}
217
218
// convert to the desired colorspace
219
if( convert )
220
{
221
jas_cmprof_t *clrprof = jas_cmprof_createfromclrspc( colorspace );
222
if( clrprof )
223
{
224
jas_image_t *_img = jas_image_chclrspc( image, clrprof, JAS_CMXFORM_INTENT_RELCLR );
225
if( _img )
226
{
227
jas_image_destroy( image );
228
m_image = image = _img;
229
result = true;
230
}
231
else
232
{
233
jas_cmprof_destroy(clrprof);
234
CV_Error(Error::StsError, "JPEG 2000 LOADER ERROR: cannot convert colorspace");
235
}
236
jas_cmprof_destroy( clrprof );
237
}
238
else
239
{
240
CV_Error(Error::StsError, "JPEG 2000 LOADER ERROR: unable to create colorspace");
241
}
242
}
243
else
244
result = true;
245
246
if( result )
247
{
248
int ncmpts;
249
int cmptlut[3];
250
if( color )
251
{
252
cmptlut[0] = jas_image_getcmptbytype( image, JAS_IMAGE_CT_RGB_B );
253
cmptlut[1] = jas_image_getcmptbytype( image, JAS_IMAGE_CT_RGB_G );
254
cmptlut[2] = jas_image_getcmptbytype( image, JAS_IMAGE_CT_RGB_R );
255
if( cmptlut[0] < 0 || cmptlut[1] < 0 || cmptlut[2] < 0 )
256
result = false;
257
ncmpts = 3;
258
}
259
else
260
{
261
cmptlut[0] = jas_image_getcmptbytype( image, JAS_IMAGE_CT_GRAY_Y );
262
if( cmptlut[0] < 0 )
263
result = false;
264
ncmpts = 1;
265
}
266
267
if( result )
268
{
269
for( int i = 0; i < ncmpts; i++ )
270
{
271
int maxval = 1 << jas_image_cmptprec( image, cmptlut[i] );
272
int offset = jas_image_cmptsgnd( image, cmptlut[i] ) ? maxval / 2 : 0;
273
274
int yend = jas_image_cmptbry( image, cmptlut[i] );
275
int ystep = jas_image_cmptvstep( image, cmptlut[i] );
276
int xend = jas_image_cmptbrx( image, cmptlut[i] );
277
int xstep = jas_image_cmpthstep( image, cmptlut[i] );
278
279
jas_matrix_t *buffer = jas_matrix_create( yend / ystep, xend / xstep );
280
if( buffer )
281
{
282
if( !jas_image_readcmpt( image, cmptlut[i], 0, 0, xend / xstep, yend / ystep, buffer ))
283
{
284
if( img.depth() == CV_8U )
285
result = readComponent8u( data + i, buffer, validateToInt(step), cmptlut[i], maxval, offset, ncmpts );
286
else
287
result = readComponent16u( ((unsigned short *)data) + i, buffer, validateToInt(step / 2), cmptlut[i], maxval, offset, ncmpts );
288
if( !result )
289
{
290
jas_matrix_destroy( buffer );
291
CV_Error(Error::StsError, "JPEG2000 LOADER ERROR: failed to read component");
292
}
293
}
294
jas_matrix_destroy( buffer );
295
}
296
}
297
}
298
}
299
else
300
{
301
CV_Error(Error::StsError, "JPEG2000 LOADER ERROR: colorspace conversion failed");
302
}
303
}
304
305
CV_Assert(result == true);
306
307
#ifndef _WIN32
308
if (!clr.empty())
309
{
310
cv::cvtColor(clr, img, COLOR_BGR2GRAY);
311
}
312
#endif
313
314
return result;
315
}
316
317
318
bool Jpeg2KDecoder::readComponent8u( uchar *data, void *_buffer,
319
int step, int cmpt,
320
int maxval, int offset, int ncmpts )
321
{
322
jas_matrix_t* buffer = (jas_matrix_t*)_buffer;
323
jas_image_t* image = (jas_image_t*)m_image;
324
int xstart = jas_image_cmpttlx( image, cmpt );
325
int xend = jas_image_cmptbrx( image, cmpt );
326
int xstep = jas_image_cmpthstep( image, cmpt );
327
int xoffset = jas_image_tlx( image );
328
int ystart = jas_image_cmpttly( image, cmpt );
329
int yend = jas_image_cmptbry( image, cmpt );
330
int ystep = jas_image_cmptvstep( image, cmpt );
331
int yoffset = jas_image_tly( image );
332
int x, y, x1, y1, j;
333
int rshift = cvRound(std::log(maxval/256.)/std::log(2.));
334
int lshift = MAX(0, -rshift);
335
rshift = MAX(0, rshift);
336
int delta = (rshift > 0 ? 1 << (rshift - 1) : 0) + offset;
337
338
for( y = 0; y < yend - ystart; )
339
{
340
jas_seqent_t* pix_row = &jas_matrix_get( buffer, y / ystep, 0 );
341
uchar* dst = data + (y - yoffset) * step - xoffset;
342
343
if( xstep == 1 )
344
{
345
if( maxval == 256 && offset == 0 )
346
for( x = 0; x < xend - xstart; x++ )
347
{
348
int pix = pix_row[x];
349
dst[x*ncmpts] = cv::saturate_cast<uchar>(pix);
350
}
351
else
352
for( x = 0; x < xend - xstart; x++ )
353
{
354
int pix = ((pix_row[x] + delta) >> rshift) << lshift;
355
dst[x*ncmpts] = cv::saturate_cast<uchar>(pix);
356
}
357
}
358
else if( xstep == 2 && offset == 0 )
359
for( x = 0, j = 0; x < xend - xstart; x += 2, j++ )
360
{
361
int pix = ((pix_row[j] + delta) >> rshift) << lshift;
362
dst[x*ncmpts] = dst[(x+1)*ncmpts] = cv::saturate_cast<uchar>(pix);
363
}
364
else
365
for( x = 0, j = 0; x < xend - xstart; j++ )
366
{
367
int pix = ((pix_row[j] + delta) >> rshift) << lshift;
368
pix = cv::saturate_cast<uchar>(pix);
369
for( x1 = x + xstep; x < x1; x++ )
370
dst[x*ncmpts] = (uchar)pix;
371
}
372
y1 = y + ystep;
373
for( ++y; y < y1; y++, dst += step )
374
for( x = 0; x < xend - xstart; x++ )
375
dst[x*ncmpts + step] = dst[x*ncmpts];
376
}
377
378
return true;
379
}
380
381
382
bool Jpeg2KDecoder::readComponent16u( unsigned short *data, void *_buffer,
383
int step, int cmpt,
384
int maxval, int offset, int ncmpts )
385
{
386
jas_matrix_t* buffer = (jas_matrix_t*)_buffer;
387
jas_image_t* image = (jas_image_t*)m_image;
388
int xstart = jas_image_cmpttlx( image, cmpt );
389
int xend = jas_image_cmptbrx( image, cmpt );
390
int xstep = jas_image_cmpthstep( image, cmpt );
391
int xoffset = jas_image_tlx( image );
392
int ystart = jas_image_cmpttly( image, cmpt );
393
int yend = jas_image_cmptbry( image, cmpt );
394
int ystep = jas_image_cmptvstep( image, cmpt );
395
int yoffset = jas_image_tly( image );
396
int x, y, x1, y1, j;
397
int rshift = cvRound(std::log(maxval/65536.)/std::log(2.));
398
int lshift = MAX(0, -rshift);
399
rshift = MAX(0, rshift);
400
int delta = (rshift > 0 ? 1 << (rshift - 1) : 0) + offset;
401
402
for( y = 0; y < yend - ystart; )
403
{
404
jas_seqent_t* pix_row = &jas_matrix_get( buffer, y / ystep, 0 );
405
ushort* dst = data + (y - yoffset) * step - xoffset;
406
407
if( xstep == 1 )
408
{
409
if( maxval == 65536 && offset == 0 )
410
for( x = 0; x < xend - xstart; x++ )
411
{
412
int pix = pix_row[x];
413
dst[x*ncmpts] = cv::saturate_cast<ushort>(pix);
414
}
415
else
416
for( x = 0; x < xend - xstart; x++ )
417
{
418
int pix = ((pix_row[x] + delta) >> rshift) << lshift;
419
dst[x*ncmpts] = cv::saturate_cast<ushort>(pix);
420
}
421
}
422
else if( xstep == 2 && offset == 0 )
423
for( x = 0, j = 0; x < xend - xstart; x += 2, j++ )
424
{
425
int pix = ((pix_row[j] + delta) >> rshift) << lshift;
426
dst[x*ncmpts] = dst[(x+1)*ncmpts] = cv::saturate_cast<ushort>(pix);
427
}
428
else
429
for( x = 0, j = 0; x < xend - xstart; j++ )
430
{
431
int pix = ((pix_row[j] + delta) >> rshift) << lshift;
432
pix = cv::saturate_cast<ushort>(pix);
433
for( x1 = x + xstep; x < x1; x++ )
434
dst[x*ncmpts] = (ushort)pix;
435
}
436
y1 = y + ystep;
437
for( ++y; y < y1; y++, dst += step )
438
for( x = 0; x < xend - xstart; x++ )
439
dst[x*ncmpts + step] = dst[x*ncmpts];
440
}
441
442
return true;
443
}
444
445
446
/////////////////////// Jpeg2KEncoder ///////////////////
447
448
449
Jpeg2KEncoder::Jpeg2KEncoder()
450
{
451
m_description = "JPEG-2000 files (*.jp2)";
452
}
453
454
455
Jpeg2KEncoder::~Jpeg2KEncoder()
456
{
457
}
458
459
ImageEncoder Jpeg2KEncoder::newEncoder() const
460
{
461
return makePtr<Jpeg2KEncoder>();
462
}
463
464
bool Jpeg2KEncoder::isFormatSupported( int depth ) const
465
{
466
return depth == CV_8U || depth == CV_16U;
467
}
468
469
470
bool Jpeg2KEncoder::write( const Mat& _img, const std::vector<int>& )
471
{
472
int width = _img.cols, height = _img.rows;
473
int depth = _img.depth(), channels = _img.channels();
474
depth = depth == CV_8U ? 8 : 16;
475
476
if( channels > 3 || channels < 1 )
477
return false;
478
479
jas_image_cmptparm_t component_info[3];
480
for( int i = 0; i < channels; i++ )
481
{
482
component_info[i].tlx = 0;
483
component_info[i].tly = 0;
484
component_info[i].hstep = 1;
485
component_info[i].vstep = 1;
486
component_info[i].width = width;
487
component_info[i].height = height;
488
component_info[i].prec = depth;
489
component_info[i].sgnd = 0;
490
}
491
jas_image_t *img = jas_image_create( channels, component_info, (channels == 1) ? JAS_CLRSPC_SGRAY : JAS_CLRSPC_SRGB );
492
if( !img )
493
return false;
494
495
if(channels == 1)
496
jas_image_setcmpttype( img, 0, JAS_IMAGE_CT_GRAY_Y );
497
else
498
{
499
jas_image_setcmpttype( img, 0, JAS_IMAGE_CT_RGB_B );
500
jas_image_setcmpttype( img, 1, JAS_IMAGE_CT_RGB_G );
501
jas_image_setcmpttype( img, 2, JAS_IMAGE_CT_RGB_R );
502
}
503
504
bool result;
505
if( depth == 8 )
506
result = writeComponent8u( img, _img );
507
else
508
result = writeComponent16u( img, _img );
509
if( result )
510
{
511
jas_stream_t *stream = jas_stream_fopen( m_filename.c_str(), "wb" );
512
if( stream )
513
{
514
result = !jas_image_encode( img, stream, jas_image_strtofmt( (char*)"jp2" ), (char*)"" );
515
516
jas_stream_close( stream );
517
}
518
519
}
520
jas_image_destroy( img );
521
522
return result;
523
}
524
525
526
bool Jpeg2KEncoder::writeComponent8u( void *__img, const Mat& _img )
527
{
528
jas_image_t* img = (jas_image_t*)__img;
529
int w = _img.cols, h = _img.rows, ncmpts = _img.channels();
530
jas_matrix_t *row = jas_matrix_create( 1, w );
531
if(!row)
532
return false;
533
534
for( int y = 0; y < h; y++ )
535
{
536
const uchar* data = _img.ptr(y);
537
for( int i = 0; i < ncmpts; i++ )
538
{
539
for( int x = 0; x < w; x++)
540
jas_matrix_setv( row, x, data[x * ncmpts + i] );
541
jas_image_writecmpt( img, i, 0, y, w, 1, row );
542
}
543
}
544
545
jas_matrix_destroy( row );
546
return true;
547
}
548
549
550
bool Jpeg2KEncoder::writeComponent16u( void *__img, const Mat& _img )
551
{
552
jas_image_t* img = (jas_image_t*)__img;
553
int w = _img.cols, h = _img.rows, ncmpts = _img.channels();
554
jas_matrix_t *row = jas_matrix_create( 1, w );
555
if(!row)
556
return false;
557
558
for( int y = 0; y < h; y++ )
559
{
560
const ushort* data = _img.ptr<ushort>(y);
561
for( int i = 0; i < ncmpts; i++ )
562
{
563
for( int x = 0; x < w; x++)
564
jas_matrix_setv( row, x, data[x * ncmpts + i] );
565
jas_image_writecmpt( img, i, 0, y, w, 1, row );
566
}
567
}
568
569
jas_matrix_destroy( row );
570
571
return true;
572
}
573
574
}
575
576
#endif
577
578
/* End of file. */
579
580