grfmt_tiff.cpp

The modified version of the same file - Aashish Kumar, 2012-10-03 09:57 am

Download (21.1 kB)

 
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
/****************************************************************************************\
44
    A part of the file implements TIFF reader on base of libtiff library
45
    (see otherlibs/_graphics/readme.txt for copyright notice)
46
\****************************************************************************************/
47
48
#include "precomp.hpp"
49
#include "grfmt_tiff.hpp"
50
51
namespace cv
52
{
53
static const char fmtSignTiffII[] = "II\x2a\x00";
54
static const char fmtSignTiffMM[] = "MM\x00\x2a";
55
56
#ifdef HAVE_TIFF
57
58
#include "tiff.h"
59
#include "tiffio.h"
60
61
static int grfmt_tiff_err_handler_init = 0;
62
static void GrFmtSilentTIFFErrorHandler( const char*, const char*, va_list ) {}
63
64
TiffDecoder::TiffDecoder()
65
{
66
    m_tif = 0;
67
    if( !grfmt_tiff_err_handler_init )
68
    {
69
        grfmt_tiff_err_handler_init = 1;
70
71
        TIFFSetErrorHandler( GrFmtSilentTIFFErrorHandler );
72
        TIFFSetWarningHandler( GrFmtSilentTIFFErrorHandler );
73
    }
74
}
75
76
77
void TiffDecoder::close()
78
{
79
    if( m_tif )
80
    {
81
        TIFF* tif = (TIFF*)m_tif;
82
        TIFFClose( tif );
83
        m_tif = 0;
84
    }
85
}
86
87
TiffDecoder::~TiffDecoder()
88
{
89
    close();
90
}
91
92
size_t TiffDecoder::signatureLength() const
93
{
94
    return 4;
95
}
96
97
bool TiffDecoder::checkSignature( const string& signature ) const
98
{
99
    return signature.size() >= 4 &&
100
        (memcmp(signature.c_str(), fmtSignTiffII, 4) == 0 ||
101
        memcmp(signature.c_str(), fmtSignTiffMM, 4) == 0);
102
}
103
104
ImageDecoder TiffDecoder::newDecoder() const
105
{
106
    return new TiffDecoder;
107
}
108
109
bool TiffDecoder::readHeader()
110
{
111
    char errmsg[1024];
112
    bool result = false;
113
114
    close();
115
    TIFF* tif = TIFFOpen( m_filename.c_str(), "rb" );
116
117
    if( tif )
118
    {
119
        int width = 0, height = 0, photometric = 0;
120
        m_tif = tif;
121
122
        if( TIFFRGBAImageOK( tif, errmsg ) &&
123
            TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &width ) &&
124
            TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &height ) &&
125
            TIFFGetField( tif, TIFFTAG_PHOTOMETRIC, &photometric ))
126
        {
127
            int bpp=8, ncn = photometric > 1 ? 3 : 1;
128
            TIFFGetField( tif, TIFFTAG_BITSPERSAMPLE, &bpp );
129
            TIFFGetField( tif, TIFFTAG_SAMPLESPERPIXEL, &ncn );
130
            
131
            m_width = width;
132
            m_height = height;
133
            if( bpp > 8 &&
134
               ((photometric != 2 && photometric != 1) ||
135
                (ncn != 1 && ncn != 3 && ncn != 4)))
136
                bpp = 8;
137
            m_type = CV_MAKETYPE(bpp > 8 ? CV_16U : CV_8U, photometric > 1 ? 3 : 1);
138
            result = true;
139
        }
140
    }
141
142
    if( !result )
143
        close();
144
145
    return result;
146
}
147
148
149
bool  TiffDecoder::readData( Mat& img )
150
{
151
    bool result = false;
152
    bool color = img.channels() > 1;
153
    uchar* data = img.data;
154
    int step = (int)img.step;
155
    
156
    if( img.depth() != CV_8U && img.depth() != CV_16U )
157
        return false;
158
159
    if( m_tif && m_width && m_height )
160
    {
161
        TIFF* tif = (TIFF*)m_tif;
162
        int tile_width0 = m_width, tile_height0 = 0;
163
        int x, y, i;
164
        int is_tiled = TIFFIsTiled(tif);
165
        int photometric;
166
        TIFFGetField( tif, TIFFTAG_PHOTOMETRIC, &photometric );
167
        int bpp = 8, ncn = photometric > 1 ? 3 : 1;
168
        TIFFGetField( tif, TIFFTAG_BITSPERSAMPLE, &bpp );
169
        TIFFGetField( tif, TIFFTAG_SAMPLESPERPIXEL, &ncn );
170
        int dst_bpp = img.depth() == CV_8U ? 8 : 16;
171
172
        if( (!is_tiled &&
173
            TIFFGetField( tif, TIFFTAG_ROWSPERSTRIP, &tile_height0 )) ||
174
            (is_tiled &&
175
            TIFFGetField( tif, TIFFTAG_TILEWIDTH, &tile_width0 ) &&
176
            TIFFGetField( tif, TIFFTAG_TILELENGTH, &tile_height0 )))
177
        {
178
            if( tile_width0 <= 0 )
179
                tile_width0 = m_width;
180
181
            if( tile_height0 <= 0 )
182
                tile_height0 = m_height;
183
184
            AutoBuffer<uchar> _buffer(tile_height0*tile_width0*8);
185
            uchar* buffer = _buffer;
186
            ushort* buffer16 = (ushort*)buffer;
187
            int tileidx = 0;
188
189
            for( y = 0; y < m_height; y += tile_height0, data += step*tile_height0 )
190
            {
191
                int tile_height = tile_height0;
192
193
                if( y + tile_height > m_height )
194
                    tile_height = m_height - y;
195
196
                for( x = 0; x < m_width; x += tile_width0, tileidx++ )
197
                {
198
                    int tile_width = tile_width0, ok;
199
200
                    if( x + tile_width > m_width )
201
                        tile_width = m_width - x;
202
203
                    if( dst_bpp == 8 )
204
                    {
205
                        if( !is_tiled )
206
                            ok = TIFFReadRGBAStrip( tif, y, (uint32*)buffer );
207
                        else
208
                            ok = TIFFReadRGBATile( tif, x, y, (uint32*)buffer );
209
                        
210
                        if( !ok )
211
                        {
212
                            close();
213
                            return false;
214
                        }
215
                        
216
                        for( i = 0; i < tile_height; i++ )
217
                            if( color )
218
                                icvCvt_BGRA2BGR_8u_C4C3R( buffer + i*tile_width*4, 0,
219
                                                         data + x*3 + step*(tile_height - i - 1), 0,
220
                                                         cvSize(tile_width,1), 2 );
221
                            else
222
                                icvCvt_BGRA2Gray_8u_C4C1R( buffer + i*tile_width*4, 0,
223
                                                          data + x + step*(tile_height - i - 1), 0,
224
                                                          cvSize(tile_width,1), 2 );
225
                    }
226
                    else
227
                    {
228
                        if( !is_tiled )
229
                            ok = (int)TIFFReadEncodedStrip( tif, tileidx, (uint32*)buffer, (tsize_t)-1 ) >= 0;
230
                        else
231
                            ok = (int)TIFFReadEncodedTile( tif, tileidx, (uint32*)buffer, (tsize_t)-1 ) >= 0;
232
                        
233
                        if( !ok )
234
                        {
235
                            close();
236
                            return false;
237
                        }
238
                        
239
                        for( i = 0; i < tile_height; i++ )
240
                        {
241
                            if( color )
242
                            {
243
                                if( ncn == 1 )
244
                                {
245
                                    icvCvt_Gray2BGR_16u_C1C3R(buffer16 + i*tile_width*ncn, 0,
246
                                                              (ushort*)(data + step*i) + x*3, 0,
247
                                                              cvSize(tile_width,1) );
248
                                }
249
                                else if( ncn == 3 )
250
                                {
251
                                    icvCvt_RGB2BGR_16u_C3R(buffer16 + i*tile_width*ncn, 0,
252
                                                           (ushort*)(data + step*i) + x*3, 0,
253
                                                           cvSize(tile_width,1) );
254
                                }
255
                                else
256
                                {
257
                                    icvCvt_BGRA2BGR_16u_C4C3R(buffer16 + i*tile_width*ncn, 0,
258
                                                           (ushort*)(data + step*i) + x*3, 0,
259
                                                           cvSize(tile_width,1), 2 );
260
                                }
261
                            }
262
                            else
263
                            {
264
                                if( ncn == 1 )
265
                                {
266
                                    memcpy((ushort*)(data + step*i)+x,
267
                                           buffer16 + i*tile_width*ncn,
268
                                           tile_width*sizeof(buffer16[0]));
269
                                }
270
                                else
271
                                {
272
                                    icvCvt_BGRA2Gray_16u_CnC1R(buffer16 + i*tile_width*ncn, 0,
273
                                                           (ushort*)(data + step*i) + x, 0,
274
                                                           cvSize(tile_width,1), ncn, 2 );
275
                                }
276
                            }
277
                        }
278
                    } 
279
                }
280
            }
281
282
            result = true;
283
        }
284
        else if( (!is_tiled &&
285
            !(TIFFGetField( tif, TIFFTAG_ROWSPERSTRIP, &tile_height0 ))))
286
        {
287
            if( tile_width0 <= 0 )
288
                tile_width0 = m_width;
289
290
            if( tile_height0 <= 0 )
291
                tile_height0 = m_height;
292
293
            AutoBuffer<uchar> _buffer(tile_height0*tile_width0*8);
294
            uchar* buffer = _buffer;
295
            ushort* buffer16 = (ushort*)buffer;
296
            int tileidx = 0;
297
298
            for( y = 0; y < m_height; y += tile_height0, data += step*tile_height0 )
299
            {
300
                int tile_height = tile_height0;
301
302
                if( y + tile_height > m_height )
303
                    tile_height = m_height - y;
304
305
                for( x = 0; x < m_width; x += tile_width0, tileidx++ )
306
                {
307
                    int tile_width = tile_width0, ok;
308
309
                    if( x + tile_width > m_width )
310
                        tile_width = m_width - x;
311
312
                    if( dst_bpp == 8 )
313
                    {
314
                        if( !is_tiled )
315
                            ok = TIFFReadRGBAStrip( tif, y, (uint32*)buffer );
316
                        else
317
                            ok = TIFFReadRGBATile( tif, x, y, (uint32*)buffer );
318
                        
319
                        if( !ok )
320
                        {
321
                            close();
322
                            return false;
323
                        }
324
                        
325
                        for( i = 0; i < tile_height; i++ )
326
                            if( color )
327
                                icvCvt_BGRA2BGR_8u_C4C3R( buffer + i*tile_width*4, 0,
328
                                                         data + x*3 + step*(tile_height - i - 1), 0,
329
                                                         cvSize(tile_width,1), 2 );
330
                            else
331
                                icvCvt_BGRA2Gray_8u_C4C1R( buffer + i*tile_width*4, 0,
332
                                                          data + x + step*(tile_height - i - 1), 0,
333
                                                          cvSize(tile_width,1), 2 );
334
                    }
335
                    else
336
                    {
337
                        if( !is_tiled )
338
                            ok = (int)TIFFReadEncodedStrip( tif, tileidx, (uint32*)buffer, (tsize_t)-1 ) >= 0;
339
                        else
340
                            ok = (int)TIFFReadEncodedTile( tif, tileidx, (uint32*)buffer, (tsize_t)-1 ) >= 0;
341
                        
342
                        if( !ok )
343
                        {
344
                            close();
345
                            return false;
346
                        }
347
                        
348
                        for( i = 0; i < tile_height; i++ )
349
                        {
350
                            if( color )
351
                            {
352
                                if( ncn == 1 )
353
                                {
354
                                    icvCvt_Gray2BGR_16u_C1C3R(buffer16 + i*tile_width*ncn, 0,
355
                                                              (ushort*)(data + step*i) + x*3, 0,
356
                                                              cvSize(tile_width,1) );
357
                                }
358
                                else if( ncn == 3 )
359
                                {
360
                                    icvCvt_RGB2BGR_16u_C3R(buffer16 + i*tile_width*ncn, 0,
361
                                                           (ushort*)(data + step*i) + x*3, 0,
362
                                                           cvSize(tile_width,1) );
363
                                }
364
                                else
365
                                {
366
                                    icvCvt_BGRA2BGR_16u_C4C3R(buffer16 + i*tile_width*ncn, 0,
367
                                                           (ushort*)(data + step*i) + x*3, 0,
368
                                                           cvSize(tile_width,1), 2 );
369
                                }
370
                            }
371
                            else
372
                            {
373
                                if( ncn == 1 )
374
                                {
375
                                    memcpy((ushort*)(data + step*i)+x,
376
                                           buffer16 + i*tile_width*ncn,
377
                                           tile_width*sizeof(buffer16[0]));
378
                                }
379
                                else
380
                                {
381
                                    icvCvt_BGRA2Gray_16u_CnC1R(buffer16 + i*tile_width*ncn, 0,
382
                                                           (ushort*)(data + step*i) + x, 0,
383
                                                           cvSize(tile_width,1), ncn, 2 );
384
                                }
385
                            }
386
                        }
387
                    } 
388
                }
389
            }
390
391
            result = true;
392
        }
393
    }
394
395
    close();
396
    return result;
397
}
398
399
#endif
400
401
//////////////////////////////////////////////////////////////////////////////////////////
402
403
TiffEncoder::TiffEncoder()
404
{
405
    m_description = "TIFF Files (*.tiff;*.tif)";
406
    m_buf_supported = true;
407
}
408
409
TiffEncoder::~TiffEncoder()
410
{
411
}
412
413
ImageEncoder TiffEncoder::newEncoder() const
414
{
415
    return new TiffEncoder;
416
}
417
418
void  TiffEncoder::writeTag( WLByteStream& strm, TiffTag tag,
419
                             TiffFieldType fieldType,
420
                             int count, int value )
421
{
422
    strm.putWord( tag );
423
    strm.putWord( fieldType );
424
    strm.putDWord( count );
425
    strm.putDWord( value );
426
}
427
428
429
bool  TiffEncoder::write( const Mat& img, const vector<int>& )
430
{
431
    int channels = img.channels();
432
    int width = img.cols, height = img.rows;
433
    int fileStep = width*channels;
434
    WLByteStream strm;
435
436
    if( m_buf )
437
    {
438
        if( !strm.open(*m_buf) )
439
            return false;
440
    }
441
    else if( !strm.open(m_filename) )
442
        return false;
443
444
    int rowsPerStrip = (1 << 13)/fileStep;
445
446
    if( rowsPerStrip < 1 )
447
        rowsPerStrip = 1;
448
449
    if( rowsPerStrip > height )
450
        rowsPerStrip = height;
451
452
    int i, stripCount = (height + rowsPerStrip - 1) / rowsPerStrip;
453
454
    if( m_buf )
455
        m_buf->reserve( alignSize(stripCount*8 + fileStep*height + 256, 256) );
456
457
/*#if defined _DEBUG || !defined WIN32
458
    int uncompressedRowSize = rowsPerStrip * fileStep;
459
#endif*/
460
    int directoryOffset = 0;
461
462
    AutoBuffer<int,1024> stripOffsets(stripCount);
463
    AutoBuffer<short,1024> stripCounts(stripCount);
464
    AutoBuffer<uchar,1024> _buffer(fileStep+32);
465
    uchar* buffer = _buffer;
466
    int  stripOffsetsOffset = 0;
467
    int  stripCountsOffset = 0;
468
    int  bitsPerSample = 8; // TODO support 16 bit
469
    int  y = 0;
470
471
    strm.putBytes( fmtSignTiffII, 4 );
472
    strm.putDWord( directoryOffset );
473
474
    // write an image data first (the most reasonable way
475
    // for compressed images)
476
    for( i = 0; i < stripCount; i++ )
477
    {
478
        int limit = y + rowsPerStrip;
479
480
        if( limit > height )
481
            limit = height;
482
483
        stripOffsets[i] = strm.getPos();
484
485
        for( ; y < limit; y++ )
486
        {
487
            if( channels == 3 )
488
                icvCvt_BGR2RGB_8u_C3R( img.data + img.step*y, 0, buffer, 0, cvSize(width,1) );
489
            else if( channels == 4 )
490
                icvCvt_BGRA2RGBA_8u_C4R( img.data + img.step*y, 0, buffer, 0, cvSize(width,1) );
491
492
            strm.putBytes( channels > 1 ? buffer : img.data + img.step*y, fileStep );
493
        }
494
495
        stripCounts[i] = (short)(strm.getPos() - stripOffsets[i]);
496
        /*assert( stripCounts[i] == uncompressedRowSize ||
497
                stripCounts[i] < uncompressedRowSize &&
498
                i == stripCount - 1);*/
499
    }
500
501
    if( stripCount > 2 )
502
    {
503
        stripOffsetsOffset = strm.getPos();
504
        for( i = 0; i < stripCount; i++ )
505
            strm.putDWord( stripOffsets[i] );
506
507
        stripCountsOffset = strm.getPos();
508
        for( i = 0; i < stripCount; i++ )
509
            strm.putWord( stripCounts[i] );
510
    }
511
    else if(stripCount == 2)
512
    {
513
        stripOffsetsOffset = strm.getPos();
514
        for (i = 0; i < stripCount; i++)
515
        {
516
            strm.putDWord (stripOffsets [i]);
517
        }
518
        stripCountsOffset = stripCounts [0] + (stripCounts [1] << 16);
519
    }
520
    else
521
    {
522
        stripOffsetsOffset = stripOffsets[0];
523
        stripCountsOffset = stripCounts[0];
524
    }
525
526
    if( channels > 1 )
527
    {
528
        bitsPerSample = strm.getPos();
529
        strm.putWord(8);
530
        strm.putWord(8);
531
        strm.putWord(8);
532
        if( channels == 4 )
533
            strm.putWord(8);
534
    }
535
536
    directoryOffset = strm.getPos();
537
538
    // write header
539
    strm.putWord( 9 );
540
541
    /* warning: specification 5.0 of Tiff want to have tags in
542
       ascending order. This is a non-fatal error, but this cause
543
       warning with some tools. So, keep this in ascending order */
544
545
    writeTag( strm, TIFF_TAG_WIDTH, TIFF_TYPE_LONG, 1, width );
546
    writeTag( strm, TIFF_TAG_HEIGHT, TIFF_TYPE_LONG, 1, height );
547
    writeTag( strm, TIFF_TAG_BITS_PER_SAMPLE,
548
              TIFF_TYPE_SHORT, channels, bitsPerSample );
549
    writeTag( strm, TIFF_TAG_COMPRESSION, TIFF_TYPE_LONG, 1, TIFF_UNCOMP );
550
    writeTag( strm, TIFF_TAG_PHOTOMETRIC, TIFF_TYPE_SHORT, 1, channels > 1 ? 2 : 1 );
551
552
    writeTag( strm, TIFF_TAG_STRIP_OFFSETS, TIFF_TYPE_LONG,
553
              stripCount, stripOffsetsOffset );
554
555
    writeTag( strm, TIFF_TAG_SAMPLES_PER_PIXEL, TIFF_TYPE_SHORT, 1, channels );
556
    writeTag( strm, TIFF_TAG_ROWS_PER_STRIP, TIFF_TYPE_LONG, 1, rowsPerStrip );
557
558
    writeTag( strm, TIFF_TAG_STRIP_COUNTS,
559
              stripCount > 1 ? TIFF_TYPE_SHORT : TIFF_TYPE_LONG,
560
              stripCount, stripCountsOffset );
561
562
    strm.putDWord(0);
563
    strm.close();
564
565
    if( m_buf )
566
    {
567
        (*m_buf)[4] = (uchar)directoryOffset;
568
        (*m_buf)[5] = (uchar)(directoryOffset >> 8);
569
        (*m_buf)[6] = (uchar)(directoryOffset >> 16);
570
        (*m_buf)[7] = (uchar)(directoryOffset >> 24);
571
    }
572
    else
573
    {
574
        // write directory offset
575
        FILE* f = fopen( m_filename.c_str(), "r+b" );
576
        buffer[0] = (uchar)directoryOffset;
577
        buffer[1] = (uchar)(directoryOffset >> 8);
578
        buffer[2] = (uchar)(directoryOffset >> 16);
579
        buffer[3] = (uchar)(directoryOffset >> 24);
580
581
        fseek( f, 4, SEEK_SET );
582
        fwrite( buffer, 1, 4, f );
583
        fclose(f);
584
    }
585
586
    return true;
587
}
588
589
}