diff --git a/modules/objdetect/src/qrcode_encoder.cpp b/modules/objdetect/src/qrcode_encoder.cpp index 1016a17936..24a9548899 100644 --- a/modules/objdetect/src/qrcode_encoder.cpp +++ b/modules/objdetect/src/qrcode_encoder.cpp @@ -332,14 +332,16 @@ void QRCodeEncoderImpl::generateQR(const std::string &input) } total_num = (uint8_t) struct_num - 1; } - int segment_len = (int) ceil((int) input.length() / struct_num); - for (int i = 0; i < struct_num; i++) + auto string_itr = input.begin(); + for (int i = struct_num; i > 0; --i) { sequence_num = (uint8_t) i; - int segment_begin = i * segment_len; - int segemnt_end = min((i + 1) * segment_len, (int) input.length()) - 1; - std::string input_info = input.substr(segment_begin, segemnt_end - segment_begin + 1); + size_t segment_begin = string_itr - input.begin(); + size_t segment_end = (input.end() - string_itr) / i; + + std::string input_info = input.substr(segment_begin, segment_end); + string_itr += segment_end; int detected_version = versionAuto(input_info); CV_Assert(detected_version != -1); if (version_level == 0) @@ -349,7 +351,6 @@ void QRCodeEncoderImpl::generateQR(const std::string &input) payload.clear(); payload.reserve(MAX_PAYLOAD_LEN); - final_qrcodes.clear(); format = vector (15, 255); version_reserved = vector (18, 255); version_size = (21 + (version_level - 1) * 4); @@ -1234,6 +1235,7 @@ void QRCodeEncoderImpl::encode(const String& input, OutputArray output) generateQR(input); CV_Assert(!final_qrcodes.empty()); output.assign(final_qrcodes[0]); + final_qrcodes.clear(); } void QRCodeEncoderImpl::encodeStructuredAppend(const String& input, OutputArrayOfArrays output) @@ -1250,6 +1252,7 @@ void QRCodeEncoderImpl::encodeStructuredAppend(const String& input, OutputArrayO { output.getMatRef(i) = final_qrcodes[i]; } + final_qrcodes.clear(); } Ptr QRCodeEncoder::create(const QRCodeEncoder::Params& parameters) diff --git a/modules/objdetect/test/test_qrcode_encode.cpp b/modules/objdetect/test/test_qrcode_encode.cpp index fe2d51480b..14900c3078 100644 --- a/modules/objdetect/test/test_qrcode_encode.cpp +++ b/modules/objdetect/test/test_qrcode_encode.cpp @@ -450,6 +450,32 @@ TEST(Objdetect_QRCode_Encode_Decode_Structured_Append, DISABLED_regression) #endif // UPDATE_QRCODE_TEST_DATA +CV_ENUM(EncodeModes, QRCodeEncoder::EncodeMode::MODE_NUMERIC, + QRCodeEncoder::EncodeMode::MODE_ALPHANUMERIC, + QRCodeEncoder::EncodeMode::MODE_BYTE) + +typedef ::testing::TestWithParam Objdetect_QRCode_Encode_Decode_Structured_Append_Parameterized; +TEST_P(Objdetect_QRCode_Encode_Decode_Structured_Append_Parameterized, regression_22205) +{ + const std::string input_data = "the quick brown fox jumps over the lazy dog"; + + std::vector result_qrcodes; + + cv::QRCodeEncoder::Params params; + int encode_mode = GetParam(); + params.mode = static_cast(encode_mode); + + for(size_t struct_num = 2; struct_num < 5; ++struct_num) + { + params.structure_number = static_cast(struct_num); + cv::Ptr encoder = cv::QRCodeEncoder::create(params); + encoder->encodeStructuredAppend(input_data, result_qrcodes); + EXPECT_EQ(result_qrcodes.size(), struct_num) << "The number of QR Codes requested is not equal"<< + "to the one returned"; + } +} +INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode_Encode_Decode_Structured_Append_Parameterized, EncodeModes::all()); + TEST(Objdetect_QRCode_Encode_Decode, regression_issue22029) { const cv::String msg = "OpenCV";