mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 17:44:04 +08:00
Merge pull request #21966 from Harvey-Huang:Unicode_Path
Support use memory buffer to read multi-page image
This commit is contained in:
parent
ec26541771
commit
8b0aa6a64d
@ -306,6 +306,20 @@ reallocations when the function is called repeatedly for images of the same size
|
|||||||
*/
|
*/
|
||||||
CV_EXPORTS Mat imdecode( InputArray buf, int flags, Mat* dst);
|
CV_EXPORTS Mat imdecode( InputArray buf, int flags, Mat* dst);
|
||||||
|
|
||||||
|
/** @brief Reads a multi-page image from a buffer in memory.
|
||||||
|
|
||||||
|
The function imdecodemulti reads a multi-page image from the specified buffer in the memory. If the buffer is too short or
|
||||||
|
contains invalid data, the function returns false.
|
||||||
|
|
||||||
|
See cv::imreadmulti for the list of supported formats and flags description.
|
||||||
|
|
||||||
|
@note In the case of color images, the decoded images will have the channels stored in **B G R** order.
|
||||||
|
@param buf Input array or vector of bytes.
|
||||||
|
@param flags The same flags as in cv::imread, see cv::ImreadModes.
|
||||||
|
@param mats A vector of Mat objects holding each page, if more than one.
|
||||||
|
*/
|
||||||
|
CV_EXPORTS_W bool imdecodemulti(InputArray buf, int flags, CV_OUT std::vector<Mat>& mats);
|
||||||
|
|
||||||
/** @brief Encodes an image into a memory buffer.
|
/** @brief Encodes an image into a memory buffer.
|
||||||
|
|
||||||
The function imencode compresses the image and stores it in the memory buffer that is resized to fit the
|
The function imencode compresses the image and stores it in the memory buffer that is resized to fit the
|
||||||
|
@ -929,6 +929,157 @@ Mat imdecode( InputArray _buf, int flags, Mat* dst )
|
|||||||
return *dst;
|
return *dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
imdecodemulti_(const Mat& buf, int flags, std::vector<Mat>& mats, int start, int count)
|
||||||
|
{
|
||||||
|
CV_Assert(!buf.empty());
|
||||||
|
CV_Assert(buf.isContinuous());
|
||||||
|
CV_Assert(buf.checkVector(1, CV_8U) > 0);
|
||||||
|
Mat buf_row = buf.reshape(1, 1); // decoders expects single row, avoid issues with vector columns
|
||||||
|
|
||||||
|
String filename;
|
||||||
|
|
||||||
|
ImageDecoder decoder = findDecoder(buf_row);
|
||||||
|
if (!decoder)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (count < 0) {
|
||||||
|
count = std::numeric_limits<int>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!decoder->setSource(buf_row))
|
||||||
|
{
|
||||||
|
filename = tempfile();
|
||||||
|
FILE* f = fopen(filename.c_str(), "wb");
|
||||||
|
if (!f)
|
||||||
|
return 0;
|
||||||
|
size_t bufSize = buf_row.total() * buf.elemSize();
|
||||||
|
if (fwrite(buf_row.ptr(), 1, bufSize, f) != bufSize)
|
||||||
|
{
|
||||||
|
fclose(f);
|
||||||
|
CV_Error(Error::StsError, "failed to write image data to temporary file");
|
||||||
|
}
|
||||||
|
if (fclose(f) != 0)
|
||||||
|
{
|
||||||
|
CV_Error(Error::StsError, "failed to write image data to temporary file");
|
||||||
|
}
|
||||||
|
decoder->setSource(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read the header to make sure it succeeds
|
||||||
|
bool success = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// read the header to make sure it succeeds
|
||||||
|
if (decoder->readHeader())
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
catch (const cv::Exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << "imreadmulti_('" << filename << "'): can't read header: " << e.what() << std::endl << std::flush;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
std::cerr << "imreadmulti_('" << filename << "'): can't read header: unknown exception" << std::endl << std::flush;
|
||||||
|
}
|
||||||
|
|
||||||
|
int current = start;
|
||||||
|
while (success && current > 0)
|
||||||
|
{
|
||||||
|
if (!decoder->nextPage())
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
--current;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
decoder.release();
|
||||||
|
if (!filename.empty())
|
||||||
|
{
|
||||||
|
if (0 != remove(filename.c_str()))
|
||||||
|
{
|
||||||
|
std::cerr << "unable to remove temporary file:" << filename << std::endl << std::flush;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (current < count)
|
||||||
|
{
|
||||||
|
// grab the decoded type
|
||||||
|
int type = decoder->type();
|
||||||
|
if ((flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED)
|
||||||
|
{
|
||||||
|
if ((flags & IMREAD_ANYDEPTH) == 0)
|
||||||
|
type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
|
||||||
|
|
||||||
|
if ((flags & IMREAD_COLOR) != 0 ||
|
||||||
|
((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1))
|
||||||
|
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
|
||||||
|
else
|
||||||
|
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// established the required input image size
|
||||||
|
Size size = validateInputImageSize(Size(decoder->width(), decoder->height()));
|
||||||
|
|
||||||
|
// read the image data
|
||||||
|
Mat mat(size.height, size.width, type);
|
||||||
|
success = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (decoder->readData(mat))
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
catch (const cv::Exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << "imreadmulti_('" << filename << "'): can't read data: " << e.what() << std::endl << std::flush;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
std::cerr << "imreadmulti_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush;
|
||||||
|
}
|
||||||
|
if (!success)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// optionally rotate the data if EXIF' orientation flag says so
|
||||||
|
if ((flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED)
|
||||||
|
{
|
||||||
|
ApplyExifOrientation(decoder->getExifTag(ORIENTATION), mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
mats.push_back(mat);
|
||||||
|
if (!decoder->nextPage())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++current;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!filename.empty())
|
||||||
|
{
|
||||||
|
if (0 != remove(filename.c_str()))
|
||||||
|
{
|
||||||
|
std::cerr << "unable to remove temporary file:" << filename << std::endl << std::flush;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
mats.clear();
|
||||||
|
return !mats.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool imdecodemulti(InputArray _buf, int flags, CV_OUT std::vector<Mat>& mats)
|
||||||
|
{
|
||||||
|
CV_TRACE_FUNCTION();
|
||||||
|
|
||||||
|
Mat buf = _buf.getMat();
|
||||||
|
return imdecodemulti_(buf, flags, mats, 0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
bool imencode( const String& ext, InputArray _image,
|
bool imencode( const String& ext, InputArray _image,
|
||||||
std::vector<uchar>& buf, const std::vector<int>& params )
|
std::vector<uchar>& buf, const std::vector<int>& params )
|
||||||
{
|
{
|
||||||
|
@ -442,6 +442,43 @@ TEST_P(Imgcodecs_Tiff_Modes, decode_multipage)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(Imgcodecs_Tiff_Modes, decode_multipage_use_memory_buffer)
|
||||||
|
{
|
||||||
|
const int mode = GetParam();
|
||||||
|
const string root = cvtest::TS::ptr()->get_data_path();
|
||||||
|
const string filename = root + "readwrite/multipage.tif";
|
||||||
|
const string page_files[] = {
|
||||||
|
"readwrite/multipage_p1.tif",
|
||||||
|
"readwrite/multipage_p2.tif",
|
||||||
|
"readwrite/multipage_p3.tif",
|
||||||
|
"readwrite/multipage_p4.tif",
|
||||||
|
"readwrite/multipage_p5.tif",
|
||||||
|
"readwrite/multipage_p6.tif"
|
||||||
|
};
|
||||||
|
const size_t page_count = sizeof(page_files) / sizeof(page_files[0]);
|
||||||
|
vector<Mat> pages;
|
||||||
|
|
||||||
|
FILE* fp = fopen(filename.c_str(), "rb");
|
||||||
|
ASSERT_TRUE(fp != NULL);
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
long pos = ftell(fp);
|
||||||
|
|
||||||
|
std::vector<uchar> buf;
|
||||||
|
buf.resize((size_t)pos);
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
buf.resize(fread(&buf[0], 1, buf.size(), fp));
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
bool res = imdecodemulti(buf, mode, pages);
|
||||||
|
ASSERT_TRUE(res == true);
|
||||||
|
ASSERT_EQ(page_count, pages.size());
|
||||||
|
for (size_t i = 0; i < page_count; i++)
|
||||||
|
{
|
||||||
|
const Mat page = imread(root + page_files[i], mode);
|
||||||
|
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), page, pages[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const int all_modes[] =
|
const int all_modes[] =
|
||||||
{
|
{
|
||||||
IMREAD_UNCHANGED,
|
IMREAD_UNCHANGED,
|
||||||
|
Loading…
Reference in New Issue
Block a user