grfmt_tiff.cpp 36.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

/****************************************************************************************\
    A part of the file implements TIFF reader on base of libtiff library
    (see otherlibs/_graphics/readme.txt for copyright notice)
\****************************************************************************************/

#include "precomp.hpp"
49 50

#ifdef HAVE_TIFF
51 52
#include <opencv2/core/utils/logger.hpp>

53
#include "grfmt_tiff.hpp"
54
#include <limits>
55

56 57 58 59 60 61 62
// TODO FIXIT Conflict declarations for common types like int64/uint64
namespace tiff_dummy_namespace {
#include "tiff.h"
#include "tiffio.h"
}
using namespace tiff_dummy_namespace;

63 64 65
namespace cv
{

66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
#define CV_TIFF_CHECK_CALL(call) \
    if (0 == (call)) { \
        CV_LOG_WARNING(NULL, "OpenCV TIFF(line " << __LINE__ << "): failed " #call); \
        CV_Error(Error::StsError, "OpenCV TIFF: failed " #call); \
    }

#define CV_TIFF_CHECK_CALL_INFO(call) \
    if (0 == (call)) { \
        CV_LOG_INFO(NULL, "OpenCV TIFF(line " << __LINE__ << "): failed optional call: " #call ", ignoring"); \
    }

#define CV_TIFF_CHECK_CALL_DEBUG(call) \
    if (0 == (call)) { \
        CV_LOG_DEBUG(NULL, "OpenCV TIFF(line " << __LINE__ << "): failed optional call: " #call ", ignoring"); \
    }

static void cv_tiffCloseHandle(void* handle)
{
    TIFFClose((TIFF*)handle);
}

static void cv_tiffErrorHandler(const char* module, const char* fmt, va_list ap)
{
    if (cv::utils::logging::getLogLevel() < cv::utils::logging::LOG_LEVEL_DEBUG)
        return;
    // TODO cv::vformat() with va_list parameter
    fprintf(stderr, "OpenCV TIFF: ");
    if (module != NULL)
        fprintf(stderr, "%s: ", module);
    fprintf(stderr, "Warning, ");
    vfprintf(stderr, fmt, ap);
    fprintf(stderr, ".\n");
}

static bool cv_tiffSetErrorHandler_()
{
    TIFFSetErrorHandler(cv_tiffErrorHandler);
    TIFFSetWarningHandler(cv_tiffErrorHandler);
    return true;
}

static bool cv_tiffSetErrorHandler()
{
    static bool v = cv_tiffSetErrorHandler_();
    return v;
}
112

113
static const char fmtSignTiffII[] = "II\x2a\x00";
114
static const char fmtSignTiffMM[] = "MM\x00\x2a";
S
Suleyman TURKMEN 已提交
115 116
static const char fmtSignBigTiffII[] = "II\x2b\x00";
static const char fmtSignBigTiffMM[] = "MM\x00\x2b";
117

118 119
TiffDecoder::TiffDecoder()
{
120
    m_hdr = false;
121 122
    m_buf_supported = true;
    m_buf_pos = 0;
123 124 125 126 127
}


void TiffDecoder::close()
{
128
    m_tif.release();
129 130 131 132 133 134 135 136 137 138 139 140
}

TiffDecoder::~TiffDecoder()
{
    close();
}

size_t TiffDecoder::signatureLength() const
{
    return 4;
}

141
bool TiffDecoder::checkSignature( const String& signature ) const
142 143 144
{
    return signature.size() >= 4 &&
        (memcmp(signature.c_str(), fmtSignTiffII, 4) == 0 ||
S
Suleyman TURKMEN 已提交
145 146 147
        memcmp(signature.c_str(), fmtSignTiffMM, 4) == 0 ||
        memcmp(signature.c_str(), fmtSignBigTiffII, 4) == 0 ||
        memcmp(signature.c_str(), fmtSignBigTiffMM, 4) == 0);
148 149
}

150 151
int TiffDecoder::normalizeChannelsNumber(int channels) const
{
152
    CV_Assert(channels <= 4);
153 154 155
    return channels > 4 ? 4 : channels;
}

156 157
ImageDecoder TiffDecoder::newDecoder() const
{
158
    cv_tiffSetErrorHandler();
R
Roman Donchenko 已提交
159
    return makePtr<TiffDecoder>();
160 161
}

162 163
class TiffDecoderBufHelper
{
164 165
    Mat& m_buf;
    size_t& m_buf_pos;
166
public:
167 168 169
    TiffDecoderBufHelper(Mat& buf, size_t& buf_pos) :
        m_buf(buf), m_buf_pos(buf_pos)
    {}
170 171
    static tmsize_t read( thandle_t handle, void* buffer, tmsize_t n )
    {
172 173
        TiffDecoderBufHelper *helper = reinterpret_cast<TiffDecoderBufHelper*>(handle);
        const Mat& buf = helper->m_buf;
174
        const tmsize_t size = buf.cols*buf.rows*buf.elemSize();
175
        tmsize_t pos = helper->m_buf_pos;
176 177 178 179 180
        if ( n > (size - pos) )
        {
            n = size - pos;
        }
        memcpy(buffer, buf.ptr() + pos, n);
181
        helper->m_buf_pos += n;
182 183 184 185 186 187 188 189 190 191 192
        return n;
    }

    static tmsize_t write( thandle_t /*handle*/, void* /*buffer*/, tmsize_t /*n*/ )
    {
        // Not used for decoding.
        return 0;
    }

    static toff_t seek( thandle_t handle, toff_t offset, int whence )
    {
193 194
        TiffDecoderBufHelper *helper = reinterpret_cast<TiffDecoderBufHelper*>(handle);
        const Mat& buf = helper->m_buf;
195
        const toff_t size = buf.cols*buf.rows*buf.elemSize();
196
        toff_t new_pos = helper->m_buf_pos;
197 198 199 200 201 202 203 204 205 206 207 208 209
        switch (whence)
        {
            case SEEK_SET:
                new_pos = offset;
                break;
            case SEEK_CUR:
                new_pos += offset;
                break;
            case SEEK_END:
                new_pos = size + offset;
                break;
        }
        new_pos = std::min(new_pos, size);
210
        helper->m_buf_pos = (size_t)new_pos;
211 212 213 214 215
        return new_pos;
    }

    static int map( thandle_t handle, void** base, toff_t* size )
    {
216 217
        TiffDecoderBufHelper *helper = reinterpret_cast<TiffDecoderBufHelper*>(handle);
        Mat& buf = helper->m_buf;
218 219 220 221 222 223 224
        *base = buf.ptr();
        *size = buf.cols*buf.rows*buf.elemSize();
        return 0;
    }

    static toff_t size( thandle_t handle )
    {
225 226
        TiffDecoderBufHelper *helper = reinterpret_cast<TiffDecoderBufHelper*>(handle);
        const Mat& buf = helper->m_buf;
227 228 229
        return buf.cols*buf.rows*buf.elemSize();
    }

230
    static int close( thandle_t handle )
231
    {
232 233
        TiffDecoderBufHelper *helper = reinterpret_cast<TiffDecoderBufHelper*>(handle);
        delete helper;
234 235 236 237
        return 0;
    }
};

238 239 240 241
bool TiffDecoder::readHeader()
{
    bool result = false;

242 243
    TIFF* tif = static_cast<TIFF*>(m_tif.get());
    if (!tif)
244 245 246
    {
        // TIFFOpen() mode flags are different to fopen().  A 'b' in mode "rb" has no effect when reading.
        // http://www.remotesensing.org/libtiff/man/TIFFOpen.3tiff.html
247 248 249
        if ( !m_buf.empty() )
        {
            m_buf_pos = 0;
250 251
            TiffDecoderBufHelper* buf_helper = new TiffDecoderBufHelper(this->m_buf, this->m_buf_pos);
            tif = TIFFClientOpen( "", "r", reinterpret_cast<thandle_t>(buf_helper), &TiffDecoderBufHelper::read,
252 253 254
                                  &TiffDecoderBufHelper::write, &TiffDecoderBufHelper::seek,
                                  &TiffDecoderBufHelper::close, &TiffDecoderBufHelper::size,
                                  &TiffDecoderBufHelper::map, /*unmap=*/0 );
255 256
            if (!tif)
                delete buf_helper;
257 258 259 260 261
        }
        else
        {
            tif = TIFFOpen(m_filename.c_str(), "r");
        }
262 263 264 265
        if (tif)
            m_tif.reset(tif, cv_tiffCloseHandle);
        else
            m_tif.release();
266
    }
267

268
    if (tif)
269
    {
270 271
        uint32 wdth = 0, hght = 0;
        uint16 photometric = 0;
272

273 274 275 276
        CV_TIFF_CHECK_CALL(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &wdth));
        CV_TIFF_CHECK_CALL(TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &hght));
        CV_TIFF_CHECK_CALL(TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric));

277
        {
278 279
            bool isGrayScale = photometric == PHOTOMETRIC_MINISWHITE || photometric == PHOTOMETRIC_MINISBLACK;
            uint16 bpp = 8, ncn = isGrayScale ? 1 : 3;
280 281 282 283 284
            if (0 == TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bpp))
            {
                // TIFF bi-level images don't require TIFFTAG_BITSPERSAMPLE tag
                bpp = 1;
            }
285
            CV_TIFF_CHECK_CALL_DEBUG(TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &ncn));
A
Andrey Kamaev 已提交
286 287 288

            m_width = wdth;
            m_height = hght;
289
            if (ncn == 3 && photometric == PHOTOMETRIC_LOGLUV)
290 291 292 293 294 295
            {
                m_type = CV_32FC3;
                m_hdr = true;
                return true;
            }
            m_hdr = false;
296

297
            if( bpp > 8 &&
298
               ((photometric > 2) ||
299 300
                (ncn != 1 && ncn != 3 && ncn != 4)))
                bpp = 8;
301

302 303
            uint16 sample_format = SAMPLEFORMAT_UINT;
            TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &sample_format);
304
            int wanted_channels = normalizeChannelsNumber(ncn);
305
            switch (bpp)
306
            {
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
            case 1:
            {
                CV_Check((int)sample_format, sample_format == SAMPLEFORMAT_UINT || sample_format == SAMPLEFORMAT_INT, "");
                int depth = sample_format == SAMPLEFORMAT_INT ? CV_8S : CV_8U;
                m_type = CV_MAKETYPE(depth, !isGrayScale ? wanted_channels : 1);
                result = true;
                break;
            }
            case 8:
            {
                //Palette color, the value of the component is used as an index into the red,
                //green and blue curves in the ColorMap field to retrieve an RGB triplet that defines the color.
                CV_Check((int)sample_format, sample_format == SAMPLEFORMAT_UINT || sample_format == SAMPLEFORMAT_INT, "");
                int depth = sample_format == SAMPLEFORMAT_INT ? CV_8S : CV_8U;
                if (photometric == PHOTOMETRIC_PALETTE)
                    m_type = CV_MAKETYPE(depth, 3);
                else
                    m_type = CV_MAKETYPE(depth, !isGrayScale ? wanted_channels : 1);
                result = true;
                break;
            }
            case 16:
            {
                CV_Check((int)sample_format, sample_format == SAMPLEFORMAT_UINT || sample_format == SAMPLEFORMAT_INT, "");
                int depth = sample_format == SAMPLEFORMAT_INT ? CV_16S : CV_16U;
                m_type = CV_MAKETYPE(depth, !isGrayScale ? wanted_channels : 1);
                result = true;
                break;
            }
            case 32:
            {
                CV_Check((int)sample_format, sample_format == SAMPLEFORMAT_IEEEFP || sample_format == SAMPLEFORMAT_INT, "");
                int depth = sample_format == SAMPLEFORMAT_IEEEFP ? CV_32F : CV_32S;
                m_type = CV_MAKETYPE(depth, wanted_channels);
                result = true;
                break;
            }
            case 64:
                CV_CheckEQ((int)sample_format, SAMPLEFORMAT_IEEEFP, "");
                m_type = CV_MAKETYPE(CV_64F, wanted_channels);
                result = true;
                break;
349 350
            default:
                CV_Error(cv::Error::StsError, "Invalid bitsperpixel value read from TIFF header! Must be 1, 8, 16, 32 or 64.");
351
            }
352 353 354 355 356 357 358 359 360
        }
    }

    if( !result )
        close();

    return result;
}

361 362 363
bool TiffDecoder::nextPage()
{
    // Prepare the next page, if any.
364 365
    return !m_tif.empty() &&
           TIFFReadDirectory(static_cast<TIFF*>(m_tif.get())) &&
366 367
           readHeader();
}
368

369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
static void fixOrientationPartial(Mat &img, uint16 orientation)
{
    switch(orientation) {
        case ORIENTATION_RIGHTTOP:
        case ORIENTATION_LEFTBOT:
            flip(img, img, -1);
            /* fall through */

        case ORIENTATION_LEFTTOP:
        case ORIENTATION_RIGHTBOT:
            transpose(img, img);
            break;
    }
}

static void fixOrientationFull(Mat &img, int orientation)
{
    switch(orientation) {
        case ORIENTATION_TOPRIGHT:
            flip(img, img, 1);
            break;

        case ORIENTATION_BOTRIGHT:
            flip(img, img, -1);
            break;

        case ORIENTATION_BOTLEFT:
            flip(img, img, 0);
            break;

        case ORIENTATION_LEFTTOP:
            transpose(img, img);
            break;

        case ORIENTATION_RIGHTTOP:
            transpose(img, img);
            flip(img, img, 1);
            break;

        case ORIENTATION_RIGHTBOT:
            transpose(img, img);
            flip(img, img, -1);
            break;

        case ORIENTATION_LEFTBOT:
            transpose(img, img);
            flip(img, img, 0);
            break;
    }
}

/**
 * Fix orientation defined in tag 274.
 * For 8 bit some corrections are done by TIFFReadRGBAStrip/Tile already.
 * Not so for 16/32/64 bit.
 */
static void fixOrientation(Mat &img, uint16 orientation, int dst_bpp)
{
    switch(dst_bpp) {
        case 8:
            fixOrientationPartial(img, orientation);
            break;

        case 16:
        case 32:
        case 64:
            fixOrientationFull(img, orientation);
            break;
    }
}

440 441
bool  TiffDecoder::readData( Mat& img )
{
442 443
    int type = img.type();
    int depth = CV_MAT_DEPTH(type);
444 445 446 447 448 449 450 451

    CV_Assert(!m_tif.empty());
    TIFF* tif = (TIFF*)m_tif.get();

    uint16 photometric = (uint16)-1;
    CV_TIFF_CHECK_CALL(TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric));

    if (m_hdr && depth >= CV_32F)
452
    {
453
        CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT));
454
    }
455

456
    bool color = img.channels() > 1;
A
Andrey Kamaev 已提交
457

458
    CV_CheckType(type, depth == CV_8U || depth == CV_8S || depth == CV_16U || depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F, "");
459

460
    if (m_width && m_height)
461
    {
462 463 464
        int is_tiled = TIFFIsTiled(tif) != 0;
        bool isGrayScale = photometric == PHOTOMETRIC_MINISWHITE || photometric == PHOTOMETRIC_MINISBLACK;
        uint16 bpp = 8, ncn = isGrayScale ? 1 : 3;
465 466 467 468 469
        if (0 == TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bpp))
        {
            // TIFF bi-level images don't require TIFFTAG_BITSPERSAMPLE tag
            bpp = 1;
        }
470
        CV_TIFF_CHECK_CALL_DEBUG(TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &ncn));
471
        uint16 img_orientation = ORIENTATION_TOPLEFT;
472
        CV_TIFF_CHECK_CALL_DEBUG(TIFFGetField(tif, TIFFTAG_ORIENTATION, &img_orientation));
473
        const int bitsPerByte = 8;
474
        int dst_bpp = (int)(img.elemSize1() * bitsPerByte);
475 476 477
        bool vert_flip = dst_bpp == 8 &&
                        (img_orientation == ORIENTATION_BOTRIGHT || img_orientation == ORIENTATION_RIGHTBOT ||
                         img_orientation == ORIENTATION_BOTLEFT || img_orientation == ORIENTATION_LEFTBOT);
478
        int wanted_channels = normalizeChannelsNumber(img.channels());
479

480
        if (dst_bpp == 8)
481 482
        {
            char errmsg[1024];
483
            if (!TIFFRGBAImageOK(tif, errmsg))
484
            {
485
                CV_LOG_WARNING(NULL, "OpenCV TIFF: TIFFRGBAImageOK: " << errmsg);
486 487 488 489
                close();
                return false;
            }
        }
490

491 492 493 494 495 496 497 498
        uint32 tile_width0 = m_width, tile_height0 = 0;

        if (is_tiled)
        {
            CV_TIFF_CHECK_CALL(TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width0));
            CV_TIFF_CHECK_CALL(TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height0));
        }
        else
499
        {
500 501 502
            // optional
            CV_TIFF_CHECK_CALL_DEBUG(TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &tile_height0));
        }
503

504 505
        {
            if (tile_width0 == 0)
506 507
                tile_width0 = m_width;

508 509
            if (tile_height0 == 0 ||
                    (!is_tiled && tile_height0 == std::numeric_limits<uint32>::max()) )
510 511
                tile_height0 = m_height;

512 513 514 515 516 517 518 519
            const int TILE_MAX_WIDTH = (1 << 24);
            const int TILE_MAX_HEIGHT = (1 << 24);
            CV_Assert((int)tile_width0 > 0 && (int)tile_width0 <= TILE_MAX_WIDTH);
            CV_Assert((int)tile_height0 > 0 && (int)tile_height0 <= TILE_MAX_HEIGHT);
            const uint64_t MAX_TILE_SIZE = (CV_BIG_UINT(1) << 30);
            CV_CheckLE((int)ncn, 4, "");
            CV_CheckLE((int)bpp, 64, "");
            CV_Assert(((uint64_t)tile_width0 * tile_height0 * ncn * std::max(1, (int)(bpp / bitsPerByte)) < MAX_TILE_SIZE) && "TIFF tile size is too large: >= 1Gb");
520

521 522
            if (dst_bpp == 8)
            {
523 524 525 526
                // we will use TIFFReadRGBA* functions, so allocate temporary buffer for 32bit RGBA
                bpp = 8;
                ncn = 4;
            }
527 528 529 530 531 532 533
            else if (dst_bpp == 32 || dst_bpp == 64)
            {
                CV_Assert(ncn == img.channels());
                CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP));
            }
            const size_t buffer_size = (bpp / bitsPerByte) * ncn * tile_height0 * tile_width0;
            AutoBuffer<uchar> _buffer(buffer_size);
534
            uchar* buffer = _buffer.data();
535 536
            ushort* buffer16 = (ushort*)buffer;
            int tileidx = 0;
537

538
            for (int y = 0; y < m_height; y += (int)tile_height0)
539
            {
540
                int tile_height = std::min((int)tile_height0, m_height - y);
541

542
                const int img_y = vert_flip ? m_height - y - tile_height : y;
543

544
                for(int x = 0; x < m_width; x += (int)tile_width0, tileidx++)
545
                {
546
                    int tile_width = std::min((int)tile_width0, m_width - x);
547

548
                    switch (dst_bpp)
549
                    {
550
                        case 8:
551
                        {
552 553
                            uchar* bstart = buffer;
                            if (!is_tiled)
554
                            {
555
                                CV_TIFF_CHECK_CALL(TIFFReadRGBAStrip(tif, y, (uint32*)buffer));
556
                            }
557
                            else
558
                            {
559 560 561
                                CV_TIFF_CHECK_CALL(TIFFReadRGBATile(tif, x, y, (uint32*)buffer));
                                // Tiles fill the buffer from the bottom up
                                bstart += (tile_height0 - tile_height) * tile_width0 * 4;
562 563
                            }

564 565 566
                            for (int i = 0; i < tile_height; i++)
                            {
                                if (color)
567 568 569
                                {
                                    if (wanted_channels == 4)
                                    {
570 571 572
                                        icvCvt_BGRA2RGBA_8u_C4R(bstart + i*tile_width0*4, 0,
                                                img.ptr(img_y + tile_height - i - 1, x), 0,
                                                Size(tile_width, 1) );
573 574 575
                                    }
                                    else
                                    {
576
                                        CV_CheckEQ(wanted_channels, 3, "TIFF-8bpp: BGR/BGRA images are supported only");
577 578 579
                                        icvCvt_BGRA2BGR_8u_C4C3R(bstart + i*tile_width0*4, 0,
                                                img.ptr(img_y + tile_height - i - 1, x), 0,
                                                Size(tile_width, 1), 2);
580 581
                                    }
                                }
582
                                else
583
                                {
584
                                    CV_CheckEQ(wanted_channels, 1, "");
585
                                    icvCvt_BGRA2Gray_8u_C4C1R( bstart + i*tile_width0*4, 0,
586 587 588 589
                                            img.ptr(img_y + tile_height - i - 1, x), 0,
                                            Size(tile_width, 1), 2);
                                }
                            }
590
                            break;
591
                        }
592 593

                        case 16:
594
                        {
595 596 597 598
                            if (!is_tiled)
                            {
                                CV_TIFF_CHECK_CALL((int)TIFFReadEncodedStrip(tif, tileidx, (uint32*)buffer, buffer_size) >= 0);
                            }
599
                            else
600
                            {
601
                                CV_TIFF_CHECK_CALL((int)TIFFReadEncodedTile(tif, tileidx, (uint32*)buffer, buffer_size) >= 0);
602 603
                            }

604
                            for (int i = 0; i < tile_height; i++)
605
                            {
606
                                if (color)
607
                                {
608
                                    if (ncn == 1)
609
                                    {
610
                                        CV_CheckEQ(wanted_channels, 3, "");
611
                                        icvCvt_Gray2BGR_16u_C1C3R(buffer16 + i*tile_width0*ncn, 0,
612 613
                                                img.ptr<ushort>(img_y + i, x), 0,
                                                Size(tile_width, 1));
614
                                    }
615
                                    else if (ncn == 3)
616
                                    {
617
                                        CV_CheckEQ(wanted_channels, 3, "");
618
                                        icvCvt_RGB2BGR_16u_C3R(buffer16 + i*tile_width0*ncn, 0,
619 620
                                                img.ptr<ushort>(img_y + i, x), 0,
                                                Size(tile_width, 1));
621
                                    }
622 623 624 625 626
                                    else if (ncn == 4)
                                    {
                                        if (wanted_channels == 4)
                                        {
                                            icvCvt_BGRA2RGBA_16u_C4R(buffer16 + i*tile_width0*ncn, 0,
627
                                                img.ptr<ushort>(img_y + i, x), 0,
628
                                                Size(tile_width, 1));
629 630 631
                                        }
                                        else
                                        {
632
                                            CV_CheckEQ(wanted_channels, 3, "TIFF-16bpp: BGR/BGRA images are supported only");
633
                                            icvCvt_BGRA2BGR_16u_C4C3R(buffer16 + i*tile_width0*ncn, 0,
634
                                                img.ptr<ushort>(img_y + i, x), 0,
635
                                                Size(tile_width, 1), 2);
636 637
                                        }
                                    }
638 639
                                    else
                                    {
640
                                        CV_Error(Error::StsError, "Not supported");
641
                                    }
642 643 644
                                }
                                else
                                {
645
                                    CV_CheckEQ(wanted_channels, 1, "");
646 647
                                    if( ncn == 1 )
                                    {
648
                                        memcpy(img.ptr<ushort>(img_y + i, x),
649
                                               buffer16 + i*tile_width0*ncn,
650
                                               tile_width*sizeof(ushort));
651 652 653
                                    }
                                    else
                                    {
654
                                        icvCvt_BGRA2Gray_16u_CnC1R(buffer16 + i*tile_width0*ncn, 0,
655 656
                                                img.ptr<ushort>(img_y + i, x), 0,
                                                Size(tile_width, 1), ncn, 2);
657
                                    }
658 659
                                }
                            }
660 661 662 663 664 665 666
                            break;
                        }

                        case 32:
                        case 64:
                        {
                            if( !is_tiled )
667
                            {
668
                                CV_TIFF_CHECK_CALL((int)TIFFReadEncodedStrip(tif, tileidx, buffer, buffer_size) >= 0);
669
                            }
670
                            else
671
                            {
672
                                CV_TIFF_CHECK_CALL((int)TIFFReadEncodedTile(tif, tileidx, buffer, buffer_size) >= 0);
673
                            }
674

675
                            Mat m_tile(Size(tile_width0, tile_height0), CV_MAKETYPE((dst_bpp == 32) ? (depth == CV_32S ? CV_32S : CV_32F) : CV_64F, ncn), buffer);
676 677 678 679 680 681 682 683
                            Rect roi_tile(0, 0, tile_width, tile_height);
                            Rect roi_img(x, img_y, tile_width, tile_height);
                            if (!m_hdr && ncn == 3)
                                cvtColor(m_tile(roi_tile), img(roi_img), COLOR_RGB2BGR);
                            else if (!m_hdr && ncn == 4)
                                cvtColor(m_tile(roi_tile), img(roi_img), COLOR_RGBA2BGRA);
                            else
                                m_tile(roi_tile).copyTo(img(roi_img));
684
                            break;
685
                        }
686 687
                        default:
                        {
688
                            CV_Assert(0 && "OpenCV TIFF: unsupported depth");
689
                        }
690 691 692
                    }  // switch (dst_bpp)
                }  // for x
            }  // for y
693
        }
694
        fixOrientation(img, img_orientation, dst_bpp);
695 696
    }

697
    if (m_hdr && depth >= CV_32F)
698
    {
699
        CV_Assert(photometric == PHOTOMETRIC_LOGLUV);
700 701 702
        cvtColor(img, img, COLOR_XYZ2BGR);
    }
    return true;
703 704
}

705 706 707 708 709 710 711 712 713 714 715 716 717 718
//////////////////////////////////////////////////////////////////////////////////////////

TiffEncoder::TiffEncoder()
{
    m_description = "TIFF Files (*.tiff;*.tif)";
    m_buf_supported = true;
}

TiffEncoder::~TiffEncoder()
{
}

ImageEncoder TiffEncoder::newEncoder() const
{
R
Roman Donchenko 已提交
719
    return makePtr<TiffEncoder>();
720 721
}

722 723
bool TiffEncoder::isFormatSupported( int depth ) const
{
724
    return depth == CV_8U || depth == CV_16U || depth == CV_32F || depth == CV_64F;
725 726
}

727 728 729 730 731 732 733 734 735 736
void  TiffEncoder::writeTag( WLByteStream& strm, TiffTag tag,
                             TiffFieldType fieldType,
                             int count, int value )
{
    strm.putWord( tag );
    strm.putWord( fieldType );
    strm.putDWord( count );
    strm.putDWord( value );
}

737 738 739 740 741 742 743 744 745 746
class TiffEncoderBufHelper
{
public:

    TiffEncoderBufHelper(std::vector<uchar> *buf)
            : m_buf(buf), m_buf_pos(0)
    {}

    TIFF* open ()
    {
747 748
        // do NOT put "wb" as the mode, because the b means "big endian" mode, not "binary" mode.
        // http://www.remotesensing.org/libtiff/man/TIFFOpen.3tiff.html
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763
        return TIFFClientOpen( "", "w", reinterpret_cast<thandle_t>(this), &TiffEncoderBufHelper::read,
                               &TiffEncoderBufHelper::write, &TiffEncoderBufHelper::seek,
                               &TiffEncoderBufHelper::close, &TiffEncoderBufHelper::size,
                               /*map=*/0, /*unmap=*/0 );
    }

    static tmsize_t read( thandle_t /*handle*/, void* /*buffer*/, tmsize_t /*n*/ )
    {
        // Not used for encoding.
        return 0;
    }

    static tmsize_t write( thandle_t handle, void* buffer, tmsize_t n )
    {
        TiffEncoderBufHelper *helper = reinterpret_cast<TiffEncoderBufHelper*>(handle);
764
        size_t begin = (size_t)helper->m_buf_pos;
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813
        size_t end = begin + n;
        if ( helper->m_buf->size() < end )
        {
            helper->m_buf->resize(end);
        }
        memcpy(&(*helper->m_buf)[begin], buffer, n);
        helper->m_buf_pos = end;
        return n;
    }

    static toff_t seek( thandle_t handle, toff_t offset, int whence )
    {
        TiffEncoderBufHelper *helper = reinterpret_cast<TiffEncoderBufHelper*>(handle);
        const toff_t size = helper->m_buf->size();
        toff_t new_pos = helper->m_buf_pos;
        switch (whence)
        {
            case SEEK_SET:
                new_pos = offset;
                break;
            case SEEK_CUR:
                new_pos += offset;
                break;
            case SEEK_END:
                new_pos = size + offset;
                break;
        }
        helper->m_buf_pos = new_pos;
        return new_pos;
    }

    static toff_t size( thandle_t handle )
    {
        TiffEncoderBufHelper *helper = reinterpret_cast<TiffEncoderBufHelper*>(handle);
        return helper->m_buf->size();
    }

    static int close( thandle_t /*handle*/ )
    {
        // Do nothing.
        return 0;
    }

private:

    std::vector<uchar>* m_buf;
    toff_t m_buf_pos;
};

814
static bool readParam(const std::vector<int>& params, int key, int& value)
815
{
816 817 818
    for (size_t i = 0; i + 1 < params.size(); i += 2)
    {
        if (params[i] == key)
819
        {
820 821
            value = params[i + 1];
            return true;
822
        }
823 824
    }
    return false;
825 826
}

827
bool TiffEncoder::writeLibTiff( const std::vector<Mat>& img_vec, const std::vector<int>& params)
828 829 830
{
    // do NOT put "wb" as the mode, because the b means "big endian" mode, not "binary" mode.
    // http://www.remotesensing.org/libtiff/man/TIFFOpen.3tiff.html
831
    TIFF* tif = NULL;
832 833 834 835

    TiffEncoderBufHelper buf_helper(m_buf);
    if ( m_buf )
    {
836
        tif = buf_helper.open();
837 838 839
    }
    else
    {
840
        tif = TIFFOpen(m_filename.c_str(), "w");
841
    }
842
    if (!tif)
843 844 845
    {
        return false;
    }
846
    cv::Ptr<void> tif_cleanup(tif, cv_tiffCloseHandle);
A
Andrey Kamaev 已提交
847

848 849 850
    //Settings that matter to all images
    int compression = COMPRESSION_LZW;
    int predictor = PREDICTOR_HORIZONTAL;
851
    int resUnit = -1, dpiX = -1, dpiY = -1;
852

853
    readParam(params, IMWRITE_TIFF_COMPRESSION, compression);
854
    readParam(params, TIFFTAG_PREDICTOR, predictor);
855 856 857
    readParam(params, IMWRITE_TIFF_RESUNIT, resUnit);
    readParam(params, IMWRITE_TIFF_XDPI, dpiX);
    readParam(params, IMWRITE_TIFF_YDPI, dpiY);
858

859 860
    //Iterate through each image in the vector and write them out as Tiff directories
    for (size_t page = 0; page < img_vec.size(); page++)
E
Eric Sommerlade 已提交
861
    {
862
        const Mat& img = img_vec[page];
863
        CV_Assert(!img.empty());
864 865
        int channels = img.channels();
        int width = img.cols, height = img.rows;
866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888
        int type = img.type();
        int depth = CV_MAT_DEPTH(type);
        CV_CheckType(type, depth == CV_8U || depth == CV_16U || depth == CV_32F || depth == CV_64F, "");
        CV_CheckType(type, channels >= 1 && channels <= 4, "");

        CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width));
        CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height));

        if (img_vec.size() > 1)
        {
            CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE));
            CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_PAGENUMBER, page, img_vec.size()));
        }

        int compression_param = -1;  // OPENCV_FUTURE
        if (type == CV_32FC3 && (!readParam(params, IMWRITE_TIFF_COMPRESSION, compression_param) || compression_param == COMPRESSION_SGILOG))
        {
            if (!write_32FC3_SGILOG(img, tif))
                return false;
            continue;
        }

        int page_compression = compression;
889

890 891
        int bitsPerChannel = -1;
        switch (depth)
892
        {
893
            case CV_8U:
894
            {
895
                bitsPerChannel = 8;
896 897
                break;
            }
898
            case CV_16U:
899
            {
900
                bitsPerChannel = 16;
901
                break;
902
            }
903 904 905 906 907 908 909 910 911 912 913 914
            case CV_32F:
            {
                bitsPerChannel = 32;
                page_compression = COMPRESSION_NONE;
                break;
            }
            case CV_64F:
            {
                bitsPerChannel = 64;
                page_compression = COMPRESSION_NONE;
                break;
            }
915 916 917 918 919 920
            default:
            {
                return false;
            }
        }

921 922
        const int bitsPerByte = 8;
        size_t fileStep = (width * channels * bitsPerChannel) / bitsPerByte;
923
        CV_Assert(fileStep > 0);
924 925 926

        int rowsPerStrip = (int)((1 << 13) / fileStep);
        readParam(params, TIFFTAG_ROWSPERSTRIP, rowsPerStrip);
927 928 929
        rowsPerStrip = std::max(1, std::min(height, rowsPerStrip));

        int colorspace = channels > 1 ? PHOTOMETRIC_RGB : PHOTOMETRIC_MINISBLACK;
930

931 932 933 934 935 936
        CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bitsPerChannel));
        CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_COMPRESSION, page_compression));
        CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, colorspace));
        CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, channels));
        CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG));
        CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsPerStrip));
937

938 939 940
        CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, depth >= CV_32F ? SAMPLEFORMAT_IEEEFP : SAMPLEFORMAT_UINT));

        if (page_compression != COMPRESSION_NONE)
941
        {
942
            CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor));
943 944
        }

945
        if (resUnit >= RESUNIT_NONE && resUnit <= RESUNIT_CENTIMETER)
946
        {
947
            CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, resUnit));
948
        }
949
        if (dpiX >= 0)
950
        {
951 952 953 954 955
            CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_XRESOLUTION, (float)dpiX));
        }
        if (dpiY >= 0)
        {
            CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_YRESOLUTION, (float)dpiY));
956 957
        }

958
        // row buffer, because TIFFWriteScanline modifies the original data!
959
        size_t scanlineSize = TIFFScanlineSize(tif);
960
        AutoBuffer<uchar> _buffer(scanlineSize + 32);
961 962
        uchar* buffer = _buffer.data(); CV_DbgAssert(buffer);
        Mat m_buffer(Size(width, 1), CV_MAKETYPE(depth, channels), buffer, (size_t)scanlineSize);
963 964 965 966 967 968 969 970 971 972 973 974 975

        for (int y = 0; y < height; ++y)
        {
            switch (channels)
            {
                case 1:
                {
                    memcpy(buffer, img.ptr(y), scanlineSize);
                    break;
                }

                case 3:
                {
976
                    cvtColor(img(Rect(0, y, width, 1)), (const Mat&)m_buffer, COLOR_BGR2RGB);
977 978 979 980 981
                    break;
                }

                case 4:
                {
982
                    cvtColor(img(Rect(0, y, width, 1)), (const Mat&)m_buffer, COLOR_BGRA2RGBA);
983 984 985 986 987
                    break;
                }

                default:
                {
988
                    CV_Assert(0);
989 990 991
                }
            }

992
            CV_TIFF_CHECK_CALL(TIFFWriteScanline(tif, buffer, y, 0) == 1);
993 994
        }

995
        CV_TIFF_CHECK_CALL(TIFFWriteDirectory(tif));
996
    }
A
Andrey Kamaev 已提交
997

998 999 1000
    return true;
}

1001
bool TiffEncoder::write_32FC3_SGILOG(const Mat& _img, void* tif_)
1002
{
1003 1004 1005
    TIFF* tif = (TIFF*)tif_;
    CV_Assert(tif);

1006 1007
    Mat img;
    cvtColor(_img, img, COLOR_BGR2XYZ);
1008

1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
    //done by caller: CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, img.cols));
    //done by caller: CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_IMAGELENGTH, img.rows));
    CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3));
    CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32));
    CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_SGILOG));
    CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_LOGLUV));
    CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG));
    CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT));
    CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1));
    const int strip_size = 3 * img.cols;
    for (int i = 0; i < img.rows; i++)
    {
        CV_TIFF_CHECK_CALL(TIFFWriteEncodedStrip(tif, i, (tdata_t)img.ptr<float>(i), strip_size * sizeof(float)) != (tsize_t)-1);
    }
    CV_TIFF_CHECK_CALL(TIFFWriteDirectory(tif));
1024 1025 1026
    return true;
}

1027 1028 1029 1030 1031
bool TiffEncoder::writemulti(const std::vector<Mat>& img_vec, const std::vector<int>& params)
{
    return writeLibTiff(img_vec, params);
}

1032
bool  TiffEncoder::write( const Mat& img, const std::vector<int>& params)
1033
{
1034 1035
    int type = img.type();
    int depth = CV_MAT_DEPTH(type);
1036

1037
    CV_CheckType(type, depth == CV_8U || depth == CV_16U || depth == CV_32F || depth == CV_64F, "");
1038

1039 1040 1041
    std::vector<Mat> img_vec;
    img_vec.push_back(img);
    return writeLibTiff(img_vec, params);
1042
}
1043

1044
} // namespace
1045

1046
#endif