1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 23:33:05 +04:00

Merge pull request #26211 from Kumataro:fix26207

imgcodecs: implement imencodemulti() #26211

Close #26207
### 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:
Kumataro
2024-10-18 20:44:55 +09:00
committed by GitHub
parent 3919f33e21
commit 35dbf32227
6 changed files with 199 additions and 46 deletions
+22 -16
View File
@@ -171,7 +171,7 @@ public:
{
n = size - pos;
}
memcpy(buffer, buf.ptr() + pos, n);
std::memcpy(buffer, buf.ptr() + pos, n);
helper->m_buf_pos += n;
return n;
}
@@ -848,9 +848,9 @@ bool TiffDecoder::readData( Mat& img )
switch ( convert_flag )
{
case MAKE_FLAG( 1, 1 ): // GRAY to GRAY
memcpy( (void*) img_line_buffer,
(void*) bstart,
tile_width * sizeof(uchar) );
std::memcpy( (void*) img_line_buffer,
(void*) bstart,
tile_width * sizeof(uchar) );
break;
case MAKE_FLAG( 1, 3 ): // GRAY to BGR
@@ -867,9 +867,9 @@ bool TiffDecoder::readData( Mat& img )
case MAKE_FLAG( 3, 3 ): // RGB to BGR
if (m_use_rgb)
memcpy( (void*) img_line_buffer,
(void*) bstart,
tile_width * sizeof(uchar) );
std::memcpy( (void*) img_line_buffer,
(void*) bstart,
tile_width * sizeof(uchar) );
else
icvCvt_BGR2RGB_8u_C3R( bstart, 0,
img_line_buffer, 0,
@@ -979,7 +979,7 @@ bool TiffDecoder::readData( Mat& img )
{
CV_CheckEQ(wanted_channels, 3, "");
if (m_use_rgb)
memcpy(buffer16, img.ptr<ushort>(img_y + i, x), tile_width * sizeof(ushort));
std::memcpy(buffer16, img.ptr<ushort>(img_y + i, x), tile_width * sizeof(ushort));
else
icvCvt_RGB2BGR_16u_C3R(buffer16, 0,
img.ptr<ushort>(img_y + i, x), 0,
@@ -1011,9 +1011,9 @@ bool TiffDecoder::readData( Mat& img )
CV_CheckEQ(wanted_channels, 1, "");
if( ncn == 1 )
{
memcpy(img.ptr<ushort>(img_y + i, x),
buffer16,
tile_width*sizeof(ushort));
std::memcpy(img.ptr<ushort>(img_y + i, x),
buffer16,
tile_width*sizeof(ushort));
}
else
{
@@ -1118,10 +1118,16 @@ public:
/*map=*/0, /*unmap=*/0 );
}
static tmsize_t read( thandle_t /*handle*/, void* /*buffer*/, tmsize_t /*n*/ )
static tmsize_t read( thandle_t handle, void* buffer, tmsize_t n )
{
// Not used for encoding.
return 0;
// Used for imencodemulti() to stores multi-images.
TiffEncoderBufHelper *helper = reinterpret_cast<TiffEncoderBufHelper*>(handle);
size_t begin = (size_t)helper->m_buf_pos;
size_t end = begin + n;
CV_CheckGT( helper->m_buf->size(), end , "do not be over-run buffer");
std::memcpy(buffer, &(*helper->m_buf)[begin], n);
helper->m_buf_pos = end;
return n;
}
static tmsize_t write( thandle_t handle, void* buffer, tmsize_t n )
@@ -1133,7 +1139,7 @@ public:
{
helper->m_buf->resize(end);
}
memcpy(&(*helper->m_buf)[begin], buffer, n);
std::memcpy(&(*helper->m_buf)[begin], buffer, n);
helper->m_buf_pos = end;
return n;
}
@@ -1350,7 +1356,7 @@ bool TiffEncoder::writeLibTiff( const std::vector<Mat>& img_vec, const std::vect
{
case 1:
{
memcpy(buffer, img.ptr(y), scanlineSize);
std::memcpy(buffer, img.ptr(y), scanlineSize);
break;
}
+64 -24
View File
@@ -723,6 +723,7 @@ static bool imwrite_( const String& filename, const std::vector<Mat>& img_vec,
Mat temp;
if( !encoder->isFormatSupported(image.depth()) )
{
CV_LOG_ONCE_WARNING(NULL, "Unsupported depth image for selected encoder is fallbacked to CV_8U.");
CV_Assert( encoder->isFormatSupported(CV_8U) );
image.convertTo( temp, CV_8U );
image = temp;
@@ -787,10 +788,12 @@ static bool imwrite_( const String& filename, const std::vector<Mat>& img_vec,
catch (const cv::Exception& e)
{
CV_LOG_ERROR(NULL, "imwrite_('" << filename << "'): can't write data: " << e.what());
code = false;
}
catch (...)
{
CV_LOG_ERROR(NULL, "imwrite_('" << filename << "'): can't write data: unknown exception");
code = false;
}
return code;
@@ -978,7 +981,7 @@ imdecodemulti_(const Mat& buf, int flags, std::vector<Mat>& mats, int start, int
ImageDecoder decoder = findDecoder(buf_row);
if (!decoder)
return 0;
return false;
// Try to decode image by RGB instead of BGR.
if (flags & IMREAD_COLOR_RGB && flags != IMREAD_UNCHANGED)
@@ -995,7 +998,7 @@ imdecodemulti_(const Mat& buf, int flags, std::vector<Mat>& mats, int start, int
filename = tempfile();
FILE* f = fopen(filename.c_str(), "wb");
if (!f)
return 0;
return false;
size_t bufSize = buf_row.total() * buf.elemSize();
if (fwrite(buf_row.ptr(), 1, bufSize, f) != bufSize)
{
@@ -1121,27 +1124,44 @@ bool imdecodemulti(InputArray _buf, int flags, CV_OUT std::vector<Mat>& mats, co
}
}
bool imencode( const String& ext, InputArray _image,
bool imencode( const String& ext, InputArray _img,
std::vector<uchar>& buf, const std::vector<int>& params_ )
{
CV_TRACE_FUNCTION();
Mat image = _image.getMat();
CV_Assert(!image.empty());
int channels = image.channels();
CV_Assert( channels == 1 || channels == 3 || channels == 4 );
ImageEncoder encoder = findEncoder( ext );
if( !encoder )
CV_Error( Error::StsError, "could not find encoder for the specified extension" );
if( !encoder->isFormatSupported(image.depth()) )
std::vector<Mat> img_vec;
CV_Assert(!_img.empty());
if (_img.isMatVector() || _img.isUMatVector())
_img.getMatVector(img_vec);
else
img_vec.push_back(_img.getMat());
CV_Assert(!img_vec.empty());
const bool isMultiImg = img_vec.size() > 1;
std::vector<Mat> write_vec;
for (size_t page = 0; page < img_vec.size(); page++)
{
CV_Assert( encoder->isFormatSupported(CV_8U) );
Mat image = img_vec[page];
CV_Assert(!image.empty());
const int channels = image.channels();
CV_Assert( channels == 1 || channels == 3 || channels == 4 );
Mat temp;
image.convertTo(temp, CV_8U);
image = temp;
if( !encoder->isFormatSupported(image.depth()) )
{
CV_LOG_ONCE_WARNING(NULL, "Unsupported depth image for selected encoder is fallbacked to CV_8U.");
CV_Assert( encoder->isFormatSupported(CV_8U) );
image.convertTo( temp, CV_8U );
image = temp;
}
write_vec.push_back(image);
}
#if CV_VERSION_MAJOR < 5 && defined(HAVE_IMGCODEC_HDR)
@@ -1166,23 +1186,37 @@ bool imencode( const String& ext, InputArray _image,
CV_Check(params.size(), (params.size() & 1) == 0, "Encoding 'params' must be key-value pairs");
CV_CheckLE(params.size(), (size_t)(CV_IO_MAX_IMAGE_PARAMS*2), "");
bool code;
if( encoder->setDestination(buf) )
bool code = false;
String filename;
if( !encoder->setDestination(buf) )
{
code = encoder->write(image, params);
filename = tempfile();
code = encoder->setDestination(filename);
CV_Assert( code );
}
try {
if (!isMultiImg)
code = encoder->write(write_vec[0], params);
else
code = encoder->writemulti(write_vec, params);
encoder->throwOnEror();
CV_Assert( code );
}
else
catch (const cv::Exception& e)
{
String filename = tempfile();
code = encoder->setDestination(filename);
CV_Assert( code );
code = encoder->write(image, params);
encoder->throwOnEror();
CV_Assert( code );
CV_LOG_ERROR(NULL, "imencode(): can't encode data: " << e.what());
code = false;
}
catch (...)
{
CV_LOG_ERROR(NULL, "imencode(): can't encode data: unknown exception");
code = false;
}
if( !filename.empty() && code )
{
FILE* f = fopen( filename.c_str(), "rb" );
CV_Assert(f != 0);
fseek( f, 0, SEEK_END );
@@ -1196,6 +1230,12 @@ bool imencode( const String& ext, InputArray _image,
return code;
}
bool imencodemulti( const String& ext, InputArrayOfArrays imgs,
std::vector<uchar>& buf, const std::vector<int>& params)
{
return imencode(ext, imgs, buf, params);
}
bool haveImageReader( const String& filename )
{
ImageDecoder decoder = cv::findDecoder(filename);