mirror of
https://github.com/opencv/opencv.git
synced 2025-08-05 22:19:14 +08:00
Merge pull request #26788 from Kumataro:fix26767
jpegxl: support cv::IMREAD_UNCHANGED and other ImreadFlags #26788 Close https://github.com/opencv/opencv/issues/26767 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
parent
db962ea069
commit
ea023b72ce
@ -12,6 +12,19 @@
|
||||
|
||||
namespace cv
|
||||
{
|
||||
// Callback functions for JpegXLDecoder
|
||||
static void cbRGBtoBGR_8U(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels);
|
||||
static void cbRGBAtoBGRA_8U(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels);
|
||||
static void cbRGBtoBGR_16U(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels);
|
||||
static void cbRGBAtoBGRA_16U(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels);
|
||||
static void cbRGBtoBGR_32F(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels);
|
||||
static void cbRGBAtoBGRA_32F(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels);
|
||||
static void cbRGBtoGRAY_8U(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels);
|
||||
static void cbRGBAtoGRAY_8U(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels);
|
||||
static void cbRGBtoGRAY_16U(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels);
|
||||
static void cbRGBAtoGRAY_16U(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels);
|
||||
static void cbRGBtoGRAY_32F(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels);
|
||||
static void cbRGBAtoGRAY_32F(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels);
|
||||
|
||||
/////////////////////// JpegXLDecoder ///////////////////
|
||||
|
||||
@ -20,7 +33,7 @@ JpegXLDecoder::JpegXLDecoder() : m_f(nullptr, &fclose)
|
||||
m_signature = "\xFF\x0A";
|
||||
m_decoder = nullptr;
|
||||
m_buf_supported = false;
|
||||
m_type = m_convert = -1;
|
||||
m_type = -1;
|
||||
m_status = JXL_DEC_NEED_MORE_INPUT;
|
||||
}
|
||||
|
||||
@ -37,7 +50,7 @@ void JpegXLDecoder::close()
|
||||
m_f.reset();
|
||||
m_read_buffer = {};
|
||||
m_width = m_height = 0;
|
||||
m_type = m_convert = -1;
|
||||
m_type = -1;
|
||||
m_status = JXL_DEC_NEED_MORE_INPUT;
|
||||
}
|
||||
|
||||
@ -76,7 +89,7 @@ ImageDecoder JpegXLDecoder::newDecoder() const
|
||||
return makePtr<JpegXLDecoder>();
|
||||
}
|
||||
|
||||
bool JpegXLDecoder::read(Mat* pimg)
|
||||
bool JpegXLDecoder::readHeader()
|
||||
{
|
||||
// Open file
|
||||
if (!m_f) {
|
||||
@ -106,24 +119,87 @@ bool JpegXLDecoder::read(Mat* pimg)
|
||||
}
|
||||
}
|
||||
|
||||
return read();
|
||||
}
|
||||
|
||||
bool JpegXLDecoder::readData(Mat& img)
|
||||
{
|
||||
if (!m_decoder || m_width == 0 || m_height == 0 || m_type == -1)
|
||||
return false;
|
||||
|
||||
// Prepare to decode image
|
||||
const uint32_t scn = CV_MAT_CN(m_type); // from image
|
||||
const uint32_t dcn = (uint32_t)img.channels(); // to OpenCV
|
||||
const int depth = CV_MAT_DEPTH(img.type());
|
||||
JxlImageOutCallback cbFunc = nullptr;
|
||||
|
||||
CV_CheckChannels(scn, (scn == 1 || scn == 3 || scn == 4), "Unsupported src channels");
|
||||
CV_CheckChannels(dcn, (dcn == 1 || dcn == 3 || dcn == 4), "Unsupported dst channels");
|
||||
CV_CheckDepth(depth, (depth == CV_8U || depth == CV_16U || depth == CV_32F), "Unsupported depth");
|
||||
|
||||
m_format = {
|
||||
dcn,
|
||||
JXL_TYPE_UINT8, // (temporary)
|
||||
JXL_NATIVE_ENDIAN, // endianness
|
||||
0 // align stride to bytes
|
||||
};
|
||||
switch (depth) {
|
||||
case CV_8U: m_format.data_type = JXL_TYPE_UINT8; break;
|
||||
case CV_16U: m_format.data_type = JXL_TYPE_UINT16; break;
|
||||
case CV_32F: m_format.data_type = JXL_TYPE_FLOAT; break;
|
||||
default: break;
|
||||
}
|
||||
// libjxl cannot read to BGR pixel order directly.
|
||||
// So we have to use callback function to convert from RGB(A) to BGR(A).
|
||||
if (!m_use_rgb) {
|
||||
switch (dcn) {
|
||||
case 1: break;
|
||||
case 3: cbFunc = (depth == CV_32F)? cbRGBtoBGR_32F: (depth == CV_16U)? cbRGBtoBGR_16U: cbRGBtoBGR_8U; break;
|
||||
case 4: cbFunc = (depth == CV_32F)? cbRGBAtoBGRA_32F: (depth == CV_16U)? cbRGBAtoBGRA_16U: cbRGBAtoBGRA_8U; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
// libjxl cannot convert from color image to gray image directly.
|
||||
// So we have to use callback function to convert from RGB(A) to GRAY.
|
||||
if( (scn >= 3) && (dcn == 1) )
|
||||
{
|
||||
m_format.num_channels = scn;
|
||||
switch (scn) {
|
||||
case 3: cbFunc = (depth == CV_32F)? cbRGBtoGRAY_32F: (depth == CV_16U)? cbRGBtoGRAY_16U: cbRGBtoGRAY_8U; break;
|
||||
case 4: cbFunc = (depth == CV_32F)? cbRGBAtoGRAY_32F: (depth == CV_16U)? cbRGBAtoGRAY_16U: cbRGBAtoGRAY_8U; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if(cbFunc != nullptr)
|
||||
{
|
||||
if (JXL_DEC_SUCCESS != JxlDecoderSetImageOutCallback(m_decoder.get(),
|
||||
&m_format,
|
||||
cbFunc,
|
||||
static_cast<void*>(&img)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if (JXL_DEC_SUCCESS != JxlDecoderSetImageOutBuffer(m_decoder.get(),
|
||||
&m_format,
|
||||
img.ptr<uint8_t>(),
|
||||
img.total() * img.elemSize()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return read();
|
||||
}
|
||||
|
||||
// Common reading routine for readHeader() and readBody()
|
||||
bool JpegXLDecoder::read()
|
||||
{
|
||||
// Create buffer for reading
|
||||
const size_t read_buffer_size = 16384; // 16KB chunks
|
||||
if (m_read_buffer.capacity() < read_buffer_size)
|
||||
m_read_buffer.resize(read_buffer_size);
|
||||
|
||||
// Create image if needed
|
||||
if (m_type != -1 && pimg) {
|
||||
pimg->create(m_height, m_width, m_type);
|
||||
if (!pimg->isContinuous())
|
||||
return false;
|
||||
if (JXL_DEC_SUCCESS != JxlDecoderSetImageOutBuffer(m_decoder.get(),
|
||||
&m_format,
|
||||
pimg->ptr<uint8_t>(),
|
||||
pimg->total() * pimg->elemSize())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Start decoding loop
|
||||
do {
|
||||
// Check if we need more input
|
||||
@ -163,6 +239,7 @@ bool JpegXLDecoder::read(Mat* pimg)
|
||||
case JXL_DEC_BASIC_INFO: {
|
||||
if (m_type != -1)
|
||||
return false;
|
||||
|
||||
JxlBasicInfo info;
|
||||
if (JXL_DEC_SUCCESS != JxlDecoderGetBasicInfo(m_decoder.get(), &info))
|
||||
return false;
|
||||
@ -172,49 +249,18 @@ bool JpegXLDecoder::read(Mat* pimg)
|
||||
|
||||
m_width = info.xsize;
|
||||
m_height = info.ysize;
|
||||
m_format = {
|
||||
ncn,
|
||||
JXL_TYPE_UINT8, // (temporary)
|
||||
JXL_LITTLE_ENDIAN, // endianness
|
||||
0 // align stride to bytes
|
||||
};
|
||||
if (!m_use_rgb) {
|
||||
switch (ncn) {
|
||||
case 3:
|
||||
m_convert = cv::COLOR_RGB2BGR;
|
||||
break;
|
||||
case 4:
|
||||
m_convert = cv::COLOR_RGBA2BGRA;
|
||||
break;
|
||||
default:
|
||||
m_convert = -1;
|
||||
}
|
||||
int depth = (info.exponent_bits_per_sample > 0)?CV_32F:
|
||||
(info.bits_per_sample == 16)?CV_16U:
|
||||
(info.bits_per_sample == 8)?CV_8U: -1;
|
||||
if(depth == -1)
|
||||
{
|
||||
return false; // Return to readHeader()
|
||||
}
|
||||
if (info.exponent_bits_per_sample > 0) {
|
||||
m_format.data_type = JXL_TYPE_FLOAT;
|
||||
m_type = CV_MAKETYPE( CV_32F, ncn );
|
||||
} else {
|
||||
switch (info.bits_per_sample) {
|
||||
case 8:
|
||||
m_format.data_type = JXL_TYPE_UINT8;
|
||||
m_type = CV_MAKETYPE( CV_8U, ncn );
|
||||
break;
|
||||
case 16:
|
||||
m_format.data_type = JXL_TYPE_UINT16;
|
||||
m_type = CV_MAKETYPE( CV_16U, ncn );
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!pimg)
|
||||
return true;
|
||||
break;
|
||||
m_type = CV_MAKETYPE( depth, ncn );
|
||||
return true;
|
||||
}
|
||||
case JXL_DEC_FULL_IMAGE: {
|
||||
// Image is ready
|
||||
if (m_convert != -1)
|
||||
cv::cvtColor(*pimg, *pimg, m_convert);
|
||||
break;
|
||||
}
|
||||
case JXL_DEC_ERROR: {
|
||||
@ -229,17 +275,172 @@ bool JpegXLDecoder::read(Mat* pimg)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JpegXLDecoder::readHeader()
|
||||
// Callback functopms
|
||||
static void cbRGBtoBGR_8U(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels)
|
||||
{
|
||||
close();
|
||||
return read(nullptr);
|
||||
const uint8_t* src = static_cast<const uint8_t*>(pixels);
|
||||
|
||||
constexpr int dstStep = 3;
|
||||
const cv::Mat *pDst = static_cast<cv::Mat*>(opaque);
|
||||
uint8_t* dstBase = const_cast<uint8_t*>(pDst->ptr(y));
|
||||
uint8_t* dst = dstBase + x * dstStep;
|
||||
|
||||
icvCvt_RGB2BGR_8u_C3R( src, 0, dst, 0, Size(num_pixels , 1) );
|
||||
}
|
||||
static void cbRGBAtoBGRA_8U(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels)
|
||||
{
|
||||
const uint8_t* src = static_cast<const uint8_t*>(pixels);
|
||||
|
||||
constexpr int dstStep = 4;
|
||||
const cv::Mat *pDst = static_cast<cv::Mat*>(opaque);
|
||||
uint8_t* dstBase = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(pDst->ptr(y)));
|
||||
uint8_t* dst = dstBase + x * dstStep;
|
||||
|
||||
icvCvt_RGBA2BGRA_8u_C4R( src, 0, dst, 0, Size(num_pixels, 1) );
|
||||
}
|
||||
static void cbRGBtoBGR_16U(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels)
|
||||
{
|
||||
const uint16_t* src = static_cast<const uint16_t*>(pixels);
|
||||
|
||||
constexpr int dstStep = 3;
|
||||
const cv::Mat *pDst = static_cast<cv::Mat*>(opaque);
|
||||
uint16_t* dstBase = const_cast<uint16_t*>(reinterpret_cast<const uint16_t*>(pDst->ptr(y)));
|
||||
uint16_t* dst = dstBase + x * dstStep;
|
||||
|
||||
icvCvt_BGR2RGB_16u_C3R( src, 0, dst, 0, Size(num_pixels, 1));
|
||||
}
|
||||
static void cbRGBAtoBGRA_16U(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels)
|
||||
{
|
||||
const uint16_t* src = static_cast<const uint16_t*>(pixels);
|
||||
|
||||
constexpr int dstStep = 4;
|
||||
const cv::Mat *pDst = static_cast<cv::Mat*>(opaque);
|
||||
uint16_t* dstBase = const_cast<uint16_t*>(reinterpret_cast<const uint16_t*>(pDst->ptr(y)));
|
||||
uint16_t* dst = dstBase + x * dstStep;
|
||||
|
||||
icvCvt_BGRA2RGBA_16u_C4R( src, 0, dst, 0, Size(num_pixels, 1));
|
||||
}
|
||||
static void cbRGBtoBGR_32F(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels)
|
||||
{
|
||||
constexpr int srcStep = 3;
|
||||
const uint32_t* src = static_cast<const uint32_t*>(pixels);
|
||||
|
||||
constexpr int dstStep = 3;
|
||||
const cv::Mat *pDst = static_cast<cv::Mat*>(opaque);
|
||||
uint32_t* dstBase = const_cast<uint32_t*>(reinterpret_cast<const uint32_t*>(pDst->ptr(y)));
|
||||
uint32_t* dst = dstBase + x * dstStep;
|
||||
|
||||
for(size_t i = 0 ; i < num_pixels; i++)
|
||||
{
|
||||
dst[ i * dstStep + 0 ] = src[ i * srcStep + 2];
|
||||
dst[ i * dstStep + 1 ] = src[ i * srcStep + 1];
|
||||
dst[ i * dstStep + 2 ] = src[ i * srcStep + 0];
|
||||
}
|
||||
}
|
||||
static void cbRGBAtoBGRA_32F(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels)
|
||||
{
|
||||
constexpr int srcStep = 4;
|
||||
const uint32_t* src = static_cast<const uint32_t*>(pixels);
|
||||
|
||||
constexpr int dstStep = 4;
|
||||
const cv::Mat *pDst = static_cast<cv::Mat*>(opaque);
|
||||
uint32_t* dstBase = const_cast<uint32_t*>(reinterpret_cast<const uint32_t*>(pDst->ptr(y)));
|
||||
uint32_t* dst = dstBase + x * dstStep;
|
||||
|
||||
for(size_t i = 0 ; i < num_pixels; i++)
|
||||
{
|
||||
dst[ i * dstStep + 0 ] = src[ i * srcStep + 2];
|
||||
dst[ i * dstStep + 1 ] = src[ i * srcStep + 1];
|
||||
dst[ i * dstStep + 2 ] = src[ i * srcStep + 0];
|
||||
dst[ i * dstStep + 3 ] = src[ i * srcStep + 3];
|
||||
}
|
||||
}
|
||||
|
||||
bool JpegXLDecoder::readData(Mat& img)
|
||||
static void cbRGBtoGRAY_8U(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels)
|
||||
{
|
||||
if (!m_decoder || m_width == 0 || m_height == 0)
|
||||
return false;
|
||||
return read(&img);
|
||||
const uint8_t* src = static_cast<const uint8_t*>(pixels);
|
||||
|
||||
constexpr int dstStep = 1;
|
||||
const cv::Mat *pDst = static_cast<cv::Mat*>(opaque);
|
||||
uint8_t* dstBase = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(pDst->ptr(y)));
|
||||
uint8_t* dst = dstBase + x * dstStep;
|
||||
|
||||
icvCvt_BGR2Gray_8u_C3C1R(src, 0, dst, 0, Size(num_pixels, 1) );
|
||||
}
|
||||
static void cbRGBAtoGRAY_8U(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels)
|
||||
{
|
||||
const uint8_t* src = static_cast<const uint8_t*>(pixels);
|
||||
|
||||
constexpr int dstStep = 1;
|
||||
const cv::Mat *pDst = static_cast<cv::Mat*>(opaque);
|
||||
uint8_t* dstBase = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(pDst->ptr(y)));
|
||||
uint8_t* dst = dstBase + x * dstStep;
|
||||
|
||||
icvCvt_BGRA2Gray_8u_C4C1R(src, 0, dst, 0, Size(num_pixels, 1) );
|
||||
}
|
||||
static void cbRGBtoGRAY_16U(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels)
|
||||
{
|
||||
const uint16_t* src = static_cast<const uint16_t*>(pixels);
|
||||
|
||||
constexpr int dstStep = 1;
|
||||
const cv::Mat *pDst = static_cast<cv::Mat*>(opaque);
|
||||
uint16_t* dstBase = const_cast<uint16_t*>(reinterpret_cast<const uint16_t*>(pDst->ptr(y)));
|
||||
uint16_t* dst = dstBase + x * dstStep;
|
||||
|
||||
icvCvt_BGRA2Gray_16u_CnC1R(src, 0, dst, 0, Size(num_pixels, 1), /* ncn= */ 3 );
|
||||
}
|
||||
static void cbRGBAtoGRAY_16U(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels)
|
||||
{
|
||||
const uint16_t* src = static_cast<const uint16_t*>(pixels);
|
||||
|
||||
constexpr int dstStep = 1;
|
||||
const cv::Mat *pDst = static_cast<cv::Mat*>(opaque);
|
||||
uint16_t* dstBase = const_cast<uint16_t*>(reinterpret_cast<const uint16_t*>(pDst->ptr(y)));
|
||||
uint16_t* dst = dstBase + x * dstStep;
|
||||
|
||||
icvCvt_BGRA2Gray_16u_CnC1R(src, 0, dst, 0, Size(num_pixels, 1), /* ncn= */ 4 );
|
||||
}
|
||||
static void cbRGBtoGRAY_32F(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels)
|
||||
{
|
||||
constexpr float cR = 0.299f;
|
||||
constexpr float cG = 0.587f;
|
||||
constexpr float cB = 1.000f - cR - cG;
|
||||
|
||||
constexpr int srcStep = 3;
|
||||
const float* src = static_cast<const float*>(pixels);
|
||||
|
||||
constexpr int dstStep = 1;
|
||||
const cv::Mat *pDst = static_cast<cv::Mat*>(opaque);
|
||||
float* dstBase = const_cast<float*>(reinterpret_cast<const float*>(pDst->ptr(y)));
|
||||
float* dst = dstBase + x * dstStep;
|
||||
|
||||
for(size_t i = 0 ; i < num_pixels; i++)
|
||||
{
|
||||
dst[ i * dstStep ] = src[ i * srcStep + 0] * cR +
|
||||
src[ i * srcStep + 1] * cG +
|
||||
src[ i * srcStep + 2] * cB;
|
||||
}
|
||||
}
|
||||
static void cbRGBAtoGRAY_32F(void *opaque, size_t x, size_t y, size_t num_pixels, const void *pixels)
|
||||
{
|
||||
constexpr float cR = 0.299f;
|
||||
constexpr float cG = 0.587f;
|
||||
constexpr float cB = 1.000f - cR - cG;
|
||||
|
||||
constexpr int srcStep = 4;
|
||||
const float* src = static_cast<const float*>(pixels);
|
||||
|
||||
constexpr int dstStep = 1;
|
||||
const cv::Mat *pDst = static_cast<cv::Mat*>(opaque);
|
||||
float* dstBase = const_cast<float*>(reinterpret_cast<const float*>(pDst->ptr(y)));
|
||||
float* dst = dstBase + x * dstStep;
|
||||
|
||||
for(size_t i = 0 ; i < num_pixels; i++)
|
||||
{
|
||||
dst[ i * dstStep ] = src[ i * srcStep + 0] * cR +
|
||||
src[ i * srcStep + 1] * cG +
|
||||
src[ i * srcStep + 2] * cB;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////// JpegXLEncoder ///////////////////
|
||||
|
@ -41,12 +41,11 @@ protected:
|
||||
JxlDecoderPtr m_decoder;
|
||||
JxlThreadParallelRunnerPtr m_parallel_runner;
|
||||
JxlPixelFormat m_format;
|
||||
int m_convert;
|
||||
std::vector<uint8_t> m_read_buffer;
|
||||
JxlDecoderStatus m_status;
|
||||
|
||||
private:
|
||||
bool read(Mat* pimg);
|
||||
bool read();
|
||||
};
|
||||
|
||||
|
||||
|
@ -180,6 +180,75 @@ TEST(Imgcodecs_JpegXL, encode_from_uncontinued_image)
|
||||
EXPECT_TRUE(ret);
|
||||
}
|
||||
|
||||
// See https://github.com/opencv/opencv/issues/26767
|
||||
|
||||
typedef tuple<perf::MatType, ImreadModes> MatType_and_ImreadFlag;
|
||||
typedef testing::TestWithParam<MatType_and_ImreadFlag> Imgcodecs_JpegXL_MatType_ImreadFlag;
|
||||
|
||||
TEST_P(Imgcodecs_JpegXL_MatType_ImreadFlag, all_imreadFlags)
|
||||
{
|
||||
string tmp_fname = cv::tempfile(".jxl");
|
||||
const int matType = get<0>(GetParam());
|
||||
const int imreadFlag = get<1>(GetParam());
|
||||
|
||||
Mat img(240, 320, matType);
|
||||
randu(img, Scalar(0, 0, 0, 255), Scalar(255, 255, 255, 255));
|
||||
|
||||
vector<int> param;
|
||||
param.push_back(IMWRITE_JPEGXL_DISTANCE);
|
||||
param.push_back(0 /* Lossless */);
|
||||
EXPECT_NO_THROW(imwrite(tmp_fname, img, param));
|
||||
|
||||
Mat img_decoded;
|
||||
EXPECT_NO_THROW(img_decoded = imread(tmp_fname, imreadFlag));
|
||||
EXPECT_FALSE(img_decoded.empty());
|
||||
|
||||
switch( imreadFlag )
|
||||
{
|
||||
case IMREAD_UNCHANGED:
|
||||
EXPECT_EQ( img.type(), img_decoded.type() );
|
||||
break;
|
||||
case IMREAD_GRAYSCALE:
|
||||
EXPECT_EQ( img_decoded.depth(), CV_8U );
|
||||
EXPECT_EQ( img_decoded.channels(), 1 );
|
||||
break;
|
||||
case IMREAD_COLOR:
|
||||
case IMREAD_COLOR_RGB:
|
||||
EXPECT_EQ( img_decoded.depth(), CV_8U );
|
||||
EXPECT_EQ( img_decoded.channels(), 3 );
|
||||
break;
|
||||
case IMREAD_ANYDEPTH:
|
||||
EXPECT_EQ( img_decoded.depth(), img.depth() );
|
||||
EXPECT_EQ( img_decoded.channels(), 1 );
|
||||
break;
|
||||
case IMREAD_ANYCOLOR:
|
||||
EXPECT_EQ( img_decoded.depth(), CV_8U ) ;
|
||||
EXPECT_EQ( img_decoded.channels(), img.channels() == 1 ? 1 : 3 ); // Alpha channel will be dropped.
|
||||
break;
|
||||
}
|
||||
remove(tmp_fname.c_str());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
/**/,
|
||||
Imgcodecs_JpegXL_MatType_ImreadFlag,
|
||||
testing::Combine(
|
||||
testing::Values(
|
||||
CV_8UC1, CV_8UC3, CV_8UC4,
|
||||
CV_16UC1, CV_16UC3, CV_16UC4,
|
||||
CV_32FC1, CV_32FC3, CV_32FC4
|
||||
),
|
||||
testing::Values(
|
||||
IMREAD_UNCHANGED,
|
||||
IMREAD_GRAYSCALE,
|
||||
IMREAD_COLOR,
|
||||
IMREAD_COLOR_RGB,
|
||||
IMREAD_ANYDEPTH,
|
||||
IMREAD_ANYCOLOR
|
||||
)
|
||||
) );
|
||||
|
||||
|
||||
#endif // HAVE_JPEGXL
|
||||
|
||||
} // namespace
|
||||
|
@ -25,6 +25,16 @@ void PrintTo(const ImreadModes& val, std::ostream* os)
|
||||
v &= ~IMREAD_COLOR;
|
||||
*os << "IMREAD_COLOR" << (v == 0 ? "" : " | ");
|
||||
}
|
||||
else if ((v & IMREAD_COLOR_RGB) != 0)
|
||||
{
|
||||
CV_Assert(IMREAD_COLOR_RGB == 256);
|
||||
v &= ~IMREAD_COLOR_RGB;
|
||||
*os << "IMREAD_COLOR_RGB" << (v == 0 ? "" : " | ");
|
||||
}
|
||||
else if ((v & IMREAD_ANYCOLOR) != 0)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert(IMREAD_GRAYSCALE == 0);
|
||||
@ -50,11 +60,6 @@ void PrintTo(const ImreadModes& val, std::ostream* os)
|
||||
v &= ~IMREAD_IGNORE_ORIENTATION;
|
||||
*os << "IMREAD_IGNORE_ORIENTATION" << (v == 0 ? "" : " | ");
|
||||
}
|
||||
if ((v & IMREAD_COLOR_RGB) != 0)
|
||||
{
|
||||
v &= ~IMREAD_COLOR_RGB;
|
||||
*os << "IMREAD_COLOR_RGB" << (v == 0 ? "" : " | ");
|
||||
}
|
||||
switch (v)
|
||||
{
|
||||
case IMREAD_UNCHANGED: return;
|
||||
|
Loading…
Reference in New Issue
Block a user