grfmt_tiff.cpp 36.3 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 115
static const char fmtSignTiffMM[] = "MM\x00\x2a";

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


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

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

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

139
bool TiffDecoder::checkSignature( const String& signature ) const
140 141 142 143 144 145
{
    return signature.size() >= 4 &&
        (memcmp(signature.c_str(), fmtSignTiffII, 4) == 0 ||
        memcmp(signature.c_str(), fmtSignTiffMM, 4) == 0);
}

146 147
int TiffDecoder::normalizeChannelsNumber(int channels) const
{
148 149
    CV_Check(channels, channels >= 1 && channels <= 4, "Unsupported number of channels");
    return channels;
150 151
}

152 153
ImageDecoder TiffDecoder::newDecoder() const
{
154
    cv_tiffSetErrorHandler();
R
Roman Donchenko 已提交
155
    return makePtr<TiffDecoder>();
156 157
}

158 159
class TiffDecoderBufHelper
{
160 161
    Mat& m_buf;
    size_t& m_buf_pos;
162
public:
163 164 165
    TiffDecoderBufHelper(Mat& buf, size_t& buf_pos) :
        m_buf(buf), m_buf_pos(buf_pos)
    {}
166 167
    static tmsize_t read( thandle_t handle, void* buffer, tmsize_t n )
    {
168 169
        TiffDecoderBufHelper *helper = reinterpret_cast<TiffDecoderBufHelper*>(handle);
        const Mat& buf = helper->m_buf;
170
        const tmsize_t size = buf.cols*buf.rows*buf.elemSize();
171
        tmsize_t pos = helper->m_buf_pos;
172 173 174 175 176
        if ( n > (size - pos) )
        {
            n = size - pos;
        }
        memcpy(buffer, buf.ptr() + pos, n);
177
        helper->m_buf_pos += n;
178 179 180 181 182 183 184 185 186 187 188
        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 )
    {
189 190
        TiffDecoderBufHelper *helper = reinterpret_cast<TiffDecoderBufHelper*>(handle);
        const Mat& buf = helper->m_buf;
191
        const toff_t size = buf.cols*buf.rows*buf.elemSize();
192
        toff_t new_pos = helper->m_buf_pos;
193 194 195 196 197 198 199 200 201 202 203 204 205
        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);
206
        helper->m_buf_pos = (size_t)new_pos;
207 208 209 210 211
        return new_pos;
    }

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

    static toff_t size( thandle_t handle )
    {
221 222
        TiffDecoderBufHelper *helper = reinterpret_cast<TiffDecoderBufHelper*>(handle);
        const Mat& buf = helper->m_buf;
223 224 225
        return buf.cols*buf.rows*buf.elemSize();
    }

226
    static int close( thandle_t handle )
227
    {
228 229
        TiffDecoderBufHelper *helper = reinterpret_cast<TiffDecoderBufHelper*>(handle);
        delete helper;
230 231 232 233
        return 0;
    }
};

234 235 236 237
bool TiffDecoder::readHeader()
{
    bool result = false;

238 239
    TIFF* tif = static_cast<TIFF*>(m_tif.get());
    if (!tif)
240 241 242
    {
        // 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
243 244 245
        if ( !m_buf.empty() )
        {
            m_buf_pos = 0;
246 247
            TiffDecoderBufHelper* buf_helper = new TiffDecoderBufHelper(this->m_buf, this->m_buf_pos);
            tif = TIFFClientOpen( "", "r", reinterpret_cast<thandle_t>(buf_helper), &TiffDecoderBufHelper::read,
248 249 250
                                  &TiffDecoderBufHelper::write, &TiffDecoderBufHelper::seek,
                                  &TiffDecoderBufHelper::close, &TiffDecoderBufHelper::size,
                                  &TiffDecoderBufHelper::map, /*unmap=*/0 );
251 252
            if (!tif)
                delete buf_helper;
253 254 255 256 257
        }
        else
        {
            tif = TIFFOpen(m_filename.c_str(), "r");
        }
258 259 260 261
        if (tif)
            m_tif.reset(tif, cv_tiffCloseHandle);
        else
            m_tif.release();
262
    }
263

264
    if (tif)
265
    {
266 267
        uint32 wdth = 0, hght = 0;
        uint16 photometric = 0;
268

269 270 271 272
        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));

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

            m_width = wdth;
            m_height = hght;
285
            if (ncn == 3 && photometric == PHOTOMETRIC_LOGLUV)
286 287 288 289 290 291
            {
                m_type = CV_32FC3;
                m_hdr = true;
                return true;
            }
            m_hdr = false;
292

293
            if( bpp > 8 &&
294
               ((photometric > 2) ||
295 296
                (ncn != 1 && ncn != 3 && ncn != 4)))
                bpp = 8;
297

298 299
            uint16 sample_format = SAMPLEFORMAT_UINT;
            TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &sample_format);
300
            int wanted_channels = normalizeChannelsNumber(ncn);
301
            switch (bpp)
302
            {
303 304 305 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
            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;
345 346
            default:
                CV_Error(cv::Error::StsError, "Invalid bitsperpixel value read from TIFF header! Must be 1, 8, 16, 32 or 64.");
347
            }
348 349 350 351 352 353 354 355 356
        }
    }

    if( !result )
        close();

    return result;
}

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

365 366 367 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
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;
    }
}

436 437
bool  TiffDecoder::readData( Mat& img )
{
438 439
    int type = img.type();
    int depth = CV_MAT_DEPTH(type);
440 441 442 443 444 445 446 447

    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)
448
    {
449
        CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT));
450
    }
451

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

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

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

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

487 488 489 490 491 492 493 494
        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
495
        {
496 497 498
            // optional
            CV_TIFF_CHECK_CALL_DEBUG(TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &tile_height0));
        }
499

500 501
        {
            if (tile_width0 == 0)
502 503
                tile_width0 = m_width;

504 505
            if (tile_height0 == 0 ||
                    (!is_tiled && tile_height0 == std::numeric_limits<uint32>::max()) )
506 507
                tile_height0 = m_height;

508 509 510 511 512 513 514 515
            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");
516

517 518
            if (dst_bpp == 8)
            {
519 520 521 522
                // we will use TIFFReadRGBA* functions, so allocate temporary buffer for 32bit RGBA
                bpp = 8;
                ncn = 4;
            }
523 524 525 526 527 528 529
            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);
530
            uchar* buffer = _buffer.data();
531 532
            ushort* buffer16 = (ushort*)buffer;
            int tileidx = 0;
533

534
            for (int y = 0; y < m_height; y += (int)tile_height0)
535
            {
536
                int tile_height = std::min((int)tile_height0, m_height - y);
537

538
                const int img_y = vert_flip ? m_height - y - tile_height : y;
539

540
                for(int x = 0; x < m_width; x += (int)tile_width0, tileidx++)
541
                {
542
                    int tile_width = std::min((int)tile_width0, m_width - x);
543

544
                    switch (dst_bpp)
545
                    {
546
                        case 8:
547
                        {
548 549
                            uchar* bstart = buffer;
                            if (!is_tiled)
550
                            {
551
                                CV_TIFF_CHECK_CALL(TIFFReadRGBAStrip(tif, y, (uint32*)buffer));
552
                            }
553
                            else
554
                            {
555 556 557
                                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;
558 559
                            }

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

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

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

                        case 32:
                        case 64:
                        {
                            if( !is_tiled )
663
                            {
664
                                CV_TIFF_CHECK_CALL((int)TIFFReadEncodedStrip(tif, tileidx, buffer, buffer_size) >= 0);
665
                            }
666
                            else
667
                            {
668
                                CV_TIFF_CHECK_CALL((int)TIFFReadEncodedTile(tif, tileidx, buffer, buffer_size) >= 0);
669
                            }
670

671
                            Mat m_tile(Size(tile_width0, tile_height0), CV_MAKETYPE((dst_bpp == 32) ? (depth == CV_32S ? CV_32S : CV_32F) : CV_64F, ncn), buffer);
672 673 674 675 676 677 678 679
                            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));
680
                            break;
681
                        }
682 683
                        default:
                        {
684
                            CV_Assert(0 && "OpenCV TIFF: unsupported depth");
685
                        }
686 687 688
                    }  // switch (dst_bpp)
                }  // for x
            }  // for y
689
        }
690
        fixOrientation(img, img_orientation, dst_bpp);
691 692
    }

693
    if (m_hdr && depth >= CV_32F)
694
    {
695
        CV_Assert(photometric == PHOTOMETRIC_LOGLUV);
696 697 698
        cvtColor(img, img, COLOR_XYZ2BGR);
    }
    return true;
699 700
}

701 702 703 704 705 706 707 708 709 710 711 712 713 714
//////////////////////////////////////////////////////////////////////////////////////////

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

TiffEncoder::~TiffEncoder()
{
}

ImageEncoder TiffEncoder::newEncoder() const
{
R
Roman Donchenko 已提交
715
    return makePtr<TiffEncoder>();
716 717
}

718 719
bool TiffEncoder::isFormatSupported( int depth ) const
{
720
    return depth == CV_8U || depth == CV_16U || depth == CV_32F || depth == CV_64F;
721 722
}

723 724 725 726 727 728 729 730 731 732
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 );
}

733 734 735 736 737 738 739 740 741 742
class TiffEncoderBufHelper
{
public:

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

    TIFF* open ()
    {
743 744
        // 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
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759
        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);
760
        size_t begin = (size_t)helper->m_buf_pos;
761 762 763 764 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
        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;
};

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

823
bool TiffEncoder::writeLibTiff( const std::vector<Mat>& img_vec, const std::vector<int>& params)
824 825 826
{
    // 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
827
    TIFF* tif = NULL;
828 829 830 831

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

844 845 846
    //Settings that matter to all images
    int compression = COMPRESSION_LZW;
    int predictor = PREDICTOR_HORIZONTAL;
847
    int resUnit = -1, dpiX = -1, dpiY = -1;
848

849
    readParam(params, IMWRITE_TIFF_COMPRESSION, compression);
850
    readParam(params, TIFFTAG_PREDICTOR, predictor);
851 852 853
    readParam(params, IMWRITE_TIFF_RESUNIT, resUnit);
    readParam(params, IMWRITE_TIFF_XDPI, dpiX);
    readParam(params, IMWRITE_TIFF_YDPI, dpiY);
854

855 856
    //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 已提交
857
    {
858
        const Mat& img = img_vec[page];
859
        CV_Assert(!img.empty());
860 861
        int channels = img.channels();
        int width = img.cols, height = img.rows;
862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884
        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;
885

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

917 918
        const int bitsPerByte = 8;
        size_t fileStep = (width * channels * bitsPerChannel) / bitsPerByte;
919
        CV_Assert(fileStep > 0);
920 921 922

        int rowsPerStrip = (int)((1 << 13) / fileStep);
        readParam(params, TIFFTAG_ROWSPERSTRIP, rowsPerStrip);
923 924 925
        rowsPerStrip = std::max(1, std::min(height, rowsPerStrip));

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

927 928 929 930 931 932
        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));
933

934 935 936
        CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, depth >= CV_32F ? SAMPLEFORMAT_IEEEFP : SAMPLEFORMAT_UINT));

        if (page_compression != COMPRESSION_NONE)
937
        {
938
            CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor));
939 940
        }

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

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

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

                case 3:
                {
972
                    cvtColor(img(Rect(0, y, width, 1)), (const Mat&)m_buffer, COLOR_BGR2RGB);
973 974 975 976 977
                    break;
                }

                case 4:
                {
978
                    cvtColor(img(Rect(0, y, width, 1)), (const Mat&)m_buffer, COLOR_BGRA2RGBA);
979 980 981 982 983
                    break;
                }

                default:
                {
984
                    CV_Assert(0);
985 986 987
                }
            }

988
            CV_TIFF_CHECK_CALL(TIFFWriteScanline(tif, buffer, y, 0) == 1);
989 990
        }

991
        CV_TIFF_CHECK_CALL(TIFFWriteDirectory(tif));
992
    }
A
Andrey Kamaev 已提交
993

994 995 996
    return true;
}

997
bool TiffEncoder::write_32FC3_SGILOG(const Mat& _img, void* tif_)
998
{
999 1000 1001
    TIFF* tif = (TIFF*)tif_;
    CV_Assert(tif);

1002 1003
    Mat img;
    cvtColor(_img, img, COLOR_BGR2XYZ);
1004

1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019
    //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));
1020 1021 1022
    return true;
}

1023 1024 1025 1026 1027
bool TiffEncoder::writemulti(const std::vector<Mat>& img_vec, const std::vector<int>& params)
{
    return writeLibTiff(img_vec, params);
}

1028
bool  TiffEncoder::write( const Mat& img, const std::vector<int>& params)
1029
{
1030 1031
    int type = img.type();
    int depth = CV_MAT_DEPTH(type);
1032

1033
    CV_CheckType(type, depth == CV_8U || depth == CV_16U || depth == CV_32F || depth == CV_64F, "");
1034

1035 1036 1037
    std::vector<Mat> img_vec;
    img_vec.push_back(img);
    return writeLibTiff(img_vec, params);
1038
}
1039

1040
} // namespace
1041

1042
#endif