2021年6月15日火曜日

OpenCV imagecodes が color palette をモノクロ扱いしてしまう備忘録

前にも、pullreq を出そうとしたのだが、テストケースも含めて提案しないと取り込んでもらえなさそうだったので、ここに記す。

バージョンは opencv 4.5.2

imagecodes の grfmt_tiff.cpp
    if (tif)
    {
        uint32 wdth = 0, hght = 0;
        uint16 photometric = 0;

        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));

        {
            bool isGrayScale = photometric == PHOTOMETRIC_MINISWHITE || photometric == PHOTOMETRIC_MINISBLACK;
            uint16 bpp = 8, ncn = isGrayScale ? 1 : 3;
            if (0 == TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bpp))
            {
                // TIFF bi-level images don't require TIFFTAG_BITSPERSAMPLE tag
                bpp = 1;
            }
//char buf[256];
//sprintf(buf, "%d, %d, %d\n", ncn, isGrayScale, bpp);
//OutputDebugStringA(buf);
// カラーパレットの場合 ncn = 3, isGrayScale = false, bpp = 8
            CV_TIFF_CHECK_CALL_DEBUG(TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &ncn));

//sprintf(buf, "%d, %d\n", ncn, photometric);
//OutputDebugStringA(buf);
// カラーパレットの場合 ncn = 1, photometric = PHOTOMETRIC_PALETTE
            m_width = wdth;
            m_height = hght;
            if (ncn == 3 && photometric == PHOTOMETRIC_LOGLUV)
            {
                m_type = CV_32FC3;
                m_hdr = true;
                return true;
            }
            m_hdr = false;

            if( bpp > 8 &&
               ((photometric > 2) ||
                (ncn != 1 && ncn != 3 && ncn != 4)))
                bpp = 8;

            int wanted_channels = normalizeChannelsNumber(ncn);

            // カラーパレットの画像がモノクロ扱いされないよう修正
            // ここから --->
            if( !isGrayScale && ncn == 1 && bpp == 8) {
              wanted_channels = 3;
            }
            // <--- ここまで
            switch(bpp)
            {
                case 1:
                    m_type = CV_MAKETYPE(CV_8U, !isGrayScale ? wanted_channels : 1);
                    result = true;
                    break;
                case 8:
                    m_type = CV_MAKETYPE(CV_8U, !isGrayScale ? wanted_channels : 1);
                    result = true;
                    break;
                case 16:
                    m_type = CV_MAKETYPE(CV_16U, !isGrayScale ? wanted_channels : 1);
                    result = true;
                    break;
                case 32:
                    m_type = CV_MAKETYPE(CV_32F, wanted_channels);
                    result = true;
                    break;
                case 64:
                    m_type = CV_MAKETYPE(CV_64F, wanted_channels);
                    result = true;
                    break;
            default:
                CV_Error(cv::Error::StsError, "Invalid bitsperpixel value read from TIFF header! Must be 1, 8, 16, 32 or 64.");
            }
        }
    }
とすることで、ちゃんとカラーで読み込まれる。

0 件のコメント: