// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
# include "test_precomp.hpp"
namespace opencv_test { namespace {
# if !defined CV_CXX11
// Wrapper for generating seeded random number via std::rand.
template < unsigned Seed >
class SeededRandFunctor {
public :
SeededRandFunctor ( ) { std : : srand ( Seed ) ; }
int operator ( ) ( int i ) { return std : : rand ( ) % ( i + 1 ) ; }
} ;
# endif
std : : string encode_qrcode_images_name [ ] = {
" version1_mode1.png " , " version1_mode2.png " , " version1_mode4.png " ,
" version2_mode1.png " , " version2_mode2.png " , " version2_mode4.png " ,
" version3_mode2.png " , " version3_mode4.png " ,
" version4_mode4.png "
} ;
std : : string encode_qrcode_eci_images_name [ ] = {
" version1_mode7.png " ,
" version2_mode7.png " ,
" version3_mode7.png " ,
" version4_mode7.png " ,
" version5_mode7.png "
} ;
const Size fixed_size = Size ( 200 , 200 ) ;
const float border_width = 2.0 ;
int establishCapacity ( QRCodeEncoder : : EncodeMode mode , int version , int capacity )
{
int result = 0 ;
capacity * = 8 ;
capacity - = 4 ;
switch ( mode )
{
case QRCodeEncoder : : MODE_NUMERIC :
{
if ( version > = 10 )
capacity - = 12 ;
else
capacity - = 10 ;
int tmp = capacity / 10 ;
result = tmp * 3 ;
if ( tmp * 10 + 7 < = capacity )
result + = 2 ;
else if ( tmp * 10 + 4 < = capacity )
result + = 1 ;
break ;
}
case QRCodeEncoder : : MODE_ALPHANUMERIC :
{
if ( version < 10 )
capacity - = 9 ;
else
capacity - = 13 ;
int tmp = capacity / 11 ;
result = tmp * 2 ;
if ( tmp * 11 + 6 < = capacity )
result + + ;
break ;
}
case QRCodeEncoder : : MODE_BYTE :
{
if ( version > 9 )
capacity - = 16 ;
else
capacity - = 8 ;
result = capacity / 8 ;
break ;
}
default :
break ;
}
return result ;
}
// #define UPDATE_TEST_DATA
# ifdef UPDATE_TEST_DATA
TEST ( Objdetect_QRCode_Encode , generate_test_data )
{
const std : : string root = " qrcode/encode " ;
const std : : string dataset_config = findDataFile ( root + " / " + " dataset_config.json " ) ;
FileStorage file_config ( dataset_config , FileStorage : : WRITE ) ;
file_config < < " test_images " < < " [ " ;
size_t images_count = sizeof ( encode_qrcode_images_name ) / sizeof ( encode_qrcode_images_name [ 0 ] ) ;
for ( size_t i = 0 ; i < images_count ; i + + )
{
file_config < < " {: " < < " image_name " < < encode_qrcode_images_name [ i ] ;
std : : string image_path = findDataFile ( root + " / " + encode_qrcode_images_name [ i ] ) ;
Mat src = imread ( image_path , IMREAD_GRAYSCALE ) ;
Mat straight_barcode ;
EXPECT_TRUE ( ! src . empty ( ) ) < < " Can't read image: " < < image_path ;
std : : vector < Point2f > corners ( 4 ) ;
corners [ 0 ] = Point2f ( border_width , border_width ) ;
corners [ 1 ] = Point2f ( qrcode . cols * 1.0f - border_width , border_width ) ;
corners [ 2 ] = Point2f ( qrcode . cols * 1.0f - border_width , qrcode . rows * 1.0f - border_width ) ;
corners [ 3 ] = Point2f ( border_width , qrcode . rows * 1.0f - border_width ) ;
Mat resized_src ;
resize ( qrcode , resized_src , fixed_size , 0 , 0 , INTER_AREA ) ;
float width_ratio = resized_src . cols * 1.0f / qrcode . cols ;
float height_ratio = resized_src . rows * 1.0f / qrcode . rows ;
for ( size_t j = 0 ; j < corners . size ( ) ; j + + )
{
corners [ j ] . x = corners [ j ] . x * width_ratio ;
corners [ j ] . y = corners [ j ] . y * height_ratio ;
}
std : : string decoded_info = " " ;
# ifdef HAVE_QUIRC
EXPECT_TRUE ( decodeQRCode ( resized_src , corners , decoded_info , straight_barcode ) ) < < " The QR code cannot be decoded: " < < image_path ;
# endif
file_config < < " info " < < decoded_info ;
file_config < < " } " ;
}
file_config < < " ] " ;
file_config . release ( ) ;
}
# else
typedef testing : : TestWithParam < std : : string > Objdetect_QRCode_Encode ;
TEST_P ( Objdetect_QRCode_Encode , regression ) {
const int pixels_error = 3 ;
const std : : string name_current_image = GetParam ( ) ;
const std : : string root = " qrcode/encode " ;
std : : string image_path = findDataFile ( root + " / " + name_current_image ) ;
const std : : string dataset_config = findDataFile ( root + " / " + " dataset_config.json " ) ;
FileStorage file_config ( dataset_config , FileStorage : : READ ) ;
ASSERT_TRUE ( file_config . isOpened ( ) ) < < " Can't read validation data: " < < dataset_config ;
{
FileNode images_list = file_config [ " test_images " ] ;
size_t images_count = static_cast < size_t > ( images_list . size ( ) ) ;
ASSERT_GT ( images_count , 0u ) < < " Can't find validation data entries in 'test_images': " < < dataset_config ;
for ( size_t index = 0 ; index < images_count ; index + + )
{
FileNode config = images_list [ ( int ) index ] ;
std : : string name_test_image = config [ " image_name " ] ;
if ( name_test_image = = name_current_image )
{
std : : string original_info = config [ " info " ] ;
Ptr < QRCodeEncoder > encoder = QRCodeEncoder : : create ( ) ;
Mat result ;
encoder - > encode ( original_info , result ) ;
EXPECT_FALSE ( result . empty ( ) ) < < " Can't generate QR code image " ;
Mat src = imread ( image_path , IMREAD_GRAYSCALE ) ;
Mat straight_barcode ;
EXPECT_TRUE ( ! src . empty ( ) ) < < " Can't read image: " < < image_path ;
double diff_norm = cvtest : : norm ( result - src , NORM_L1 ) ;
EXPECT_NEAR ( diff_norm , 0.0 , pixels_error ) < < " The generated QRcode is not same as test data. The difference: " < < diff_norm ;
return ; // done
}
}
FAIL ( ) < < " Not found results in config file: " < < dataset_config
< < " \n Re-run tests with enabled UPDATE_ENCODE_TEST_DATA macro to update test data. " ;
}
}
typedef testing : : TestWithParam < std : : string > Objdetect_QRCode_Encode_ECI ;
TEST_P ( Objdetect_QRCode_Encode_ECI , regression ) {
const int pixels_error = 3 ;
const std : : string name_current_image = GetParam ( ) ;
const std : : string root = " qrcode/encode " ;
std : : string image_path = findDataFile ( root + " / " + name_current_image ) ;
const std : : string dataset_config = findDataFile ( root + " / " + " dataset_config.json " ) ;
FileStorage file_config ( dataset_config , FileStorage : : READ ) ;
ASSERT_TRUE ( file_config . isOpened ( ) ) < < " Can't read validation data: " < < dataset_config ;
{
FileNode images_list = file_config [ " test_images " ] ;
size_t images_count = static_cast < size_t > ( images_list . size ( ) ) ;
ASSERT_GT ( images_count , 0u ) < < " Can't find validation data entries in 'test_images': " < < dataset_config ;
QRCodeEncoder : : Params params ;
params . mode = QRCodeEncoder : : MODE_ECI ;
for ( size_t index = 0 ; index < images_count ; index + + )
{
FileNode config = images_list [ ( int ) index ] ;
std : : string name_test_image = config [ " image_name " ] ;
if ( name_test_image = = name_current_image )
{
std : : string original_info = config [ " info " ] ;
Mat result ;
Ptr < QRCodeEncoder > encoder = QRCodeEncoder : : create ( params ) ;
encoder - > encode ( original_info , result ) ;
EXPECT_FALSE ( result . empty ( ) ) < < " Can't generate QR code image " ;
Mat src = imread ( image_path , IMREAD_GRAYSCALE ) ;
Mat straight_barcode ;
EXPECT_TRUE ( ! src . empty ( ) ) < < " Can't read image: " < < image_path ;
double diff_norm = cvtest : : norm ( result - src , NORM_L1 ) ;
EXPECT_NEAR ( diff_norm , 0.0 , pixels_error ) < < " The generated QRcode is not same as test data. The difference: " < < diff_norm ;
return ; // done
}
}
FAIL ( ) < < " Not found results in config file: " < < dataset_config
< < " \n Re-run tests with enabled UPDATE_ENCODE_TEST_DATA macro to update test data. " ;
}
}
INSTANTIATE_TEST_CASE_P ( /**/ , Objdetect_QRCode_Encode , testing : : ValuesIn ( encode_qrcode_images_name ) ) ;
INSTANTIATE_TEST_CASE_P ( /**/ , Objdetect_QRCode_Encode_ECI , testing : : ValuesIn ( encode_qrcode_eci_images_name ) ) ;
TEST ( Objdetect_QRCode_Encode_Decode , regression )
{
const std : : string root = " qrcode/decode_encode " ;
const int min_version = 1 ;
const int test_max_version = 5 ;
const int max_ec_level = 3 ;
const std : : string dataset_config = findDataFile ( root + " / " + " symbol_sets.json " ) ;
const std : : string version_config = findDataFile ( root + " / " + " capacity.json " ) ;
FileStorage file_config ( dataset_config , FileStorage : : READ ) ;
FileStorage capacity_config ( version_config , FileStorage : : READ ) ;
ASSERT_TRUE ( file_config . isOpened ( ) ) < < " Can't read validation data: " < < dataset_config ;
ASSERT_TRUE ( capacity_config . isOpened ( ) ) < < " Can't read validation data: " < < version_config ;
FileNode mode_list = file_config [ " symbols_sets " ] ;
FileNode capacity_list = capacity_config [ " version_ecc_capacity " ] ;
size_t mode_count = static_cast < size_t > ( mode_list . size ( ) ) ;
ASSERT_GT ( mode_count , 0u ) < < " Can't find validation data entries in 'test_images': " < < dataset_config ;
const int testing_modes = 3 ;
QRCodeEncoder : : EncodeMode modes [ testing_modes ] = {
QRCodeEncoder : : MODE_NUMERIC ,
QRCodeEncoder : : MODE_ALPHANUMERIC ,
QRCodeEncoder : : MODE_BYTE
} ;
for ( int i = 0 ; i < testing_modes ; i + + )
{
QRCodeEncoder : : EncodeMode mode = modes [ i ] ;
FileNode config = mode_list [ i ] ;
std : : string symbol_set = config [ " symbols_set " ] ;
for ( int version = min_version ; version < = test_max_version ; version + + )
{
FileNode capa_config = capacity_list [ version - 1 ] ;
for ( int level = 0 ; level < = max_ec_level ; level + + )
{
const int cur_capacity = capa_config [ " ecc_level " ] [ level ] ;
int true_capacity = establishCapacity ( mode , version , cur_capacity ) ;
std : : string input_info = symbol_set ;
std : : random_shuffle ( input_info . begin ( ) , input_info . end ( ) ) ;
int count = 0 ;
if ( ( int ) input_info . length ( ) > true_capacity )
{
input_info = input_info . substr ( 0 , true_capacity ) ;
}
else
{
while ( ( int ) input_info . length ( ) ! = true_capacity )
{
input_info + = input_info . substr ( count % ( int ) input_info . length ( ) , 1 ) ;
count + + ;
}
}
QRCodeEncoder : : Params params ;
params . version = version ;
params . correction_level = static_cast < QRCodeEncoder : : CorrectionLevel > ( level ) ;
params . mode = mode ;
Ptr < QRCodeEncoder > encoder = QRCodeEncoder : : create ( params ) ;
Mat qrcode ;
encoder - > encode ( input_info , qrcode ) ;
EXPECT_TRUE ( ! qrcode . empty ( ) ) < < " Can't generate this QR image ( " < < " mode: " < < ( int ) mode < <
" version: " < < version < < " error correction level: " < < ( int ) level < < " ) " ;
std : : vector < Point2f > corners ( 4 ) ;
corners [ 0 ] = Point2f ( border_width , border_width ) ;
corners [ 1 ] = Point2f ( qrcode . cols * 1.0f - border_width , border_width ) ;
corners [ 2 ] = Point2f ( qrcode . cols * 1.0f - border_width , qrcode . rows * 1.0f - border_width ) ;
corners [ 3 ] = Point2f ( border_width , qrcode . rows * 1.0f - border_width ) ;
Mat resized_src ;
resize ( qrcode , resized_src , fixed_size , 0 , 0 , INTER_AREA ) ;
float width_ratio = resized_src . cols * 1.0f / qrcode . cols ;
float height_ratio = resized_src . rows * 1.0f / qrcode . rows ;
for ( size_t k = 0 ; k < corners . size ( ) ; k + + )
{
corners [ k ] . x = corners [ k ] . x * width_ratio ;
corners [ k ] . y = corners [ k ] . y * height_ratio ;
}
# ifdef HAVE_QUIRC
Mat straight_barcode ;
std : : string output_info = QRCodeDetector ( ) . decode ( resized_src , corners , straight_barcode ) ;
EXPECT_FALSE ( output_info . empty ( ) )
< < " The generated QRcode cannot be decoded. " < < " Mode: " < < ( int ) mode
< < " version: " < < version < < " error correction level: " < < ( int ) level ;
EXPECT_EQ ( input_info , output_info ) < < " The generated QRcode is not same as test data. " < < " Mode: " < < ( int ) mode < <
" version: " < < version < < " error correction level: " < < ( int ) level ;
# endif
}
}
}
}
TEST ( Objdetect_QRCode_Encode_Kanji , regression )
{
QRCodeEncoder : : Params params ;
params . mode = QRCodeEncoder : : MODE_KANJI ;
Mat qrcode ;
const int testing_versions = 3 ;
std : : string input_infos [ testing_versions ] = { " \x82 \xb1 \x82 \xf1 \x82 \xc9 \x82 \xbf \x82 \xcd \x90 \xa2 \x8a \x45 " , // "Hello World" in Japanese
" \x82 \xa8 \x95 \xa0 \x82 \xaa \x8b \xf3 \x82 \xa2 \x82 \xc4 \x82 \xa2 \x82 \xdc \x82 \xb7 " , // "I am hungry" in Japanese
" \x82 \xb1 \x82 \xf1 \x82 \xc9 \x82 \xbf \x82 \xcd \x81 \x41 \x8e \x84 \x82 \xcd \x8f \xad \x82 \xb5 \x93 \xfa \x96 \x7b \x8c \xea \x82 \xf0 \x98 \x62 \x82 \xb5 \x82 \xdc \x82 \xb7 " // "Hello, I speak a little Japanese" in Japanese
} ;
for ( int i = 0 ; i < testing_versions ; i + + )
{
std : : string input_info = input_infos [ i ] ;
Ptr < QRCodeEncoder > encoder = QRCodeEncoder : : create ( params ) ;
encoder - > encode ( input_info , qrcode ) ;
std : : vector < Point2f > corners ( 4 ) ;
corners [ 0 ] = Point2f ( border_width , border_width ) ;
corners [ 1 ] = Point2f ( qrcode . cols * 1.0f - border_width , border_width ) ;
corners [ 2 ] = Point2f ( qrcode . cols * 1.0f - border_width , qrcode . rows * 1.0f - border_width ) ;
corners [ 3 ] = Point2f ( border_width , qrcode . rows * 1.0f - border_width ) ;
Mat resized_src ;
resize ( qrcode , resized_src , fixed_size , 0 , 0 , INTER_AREA ) ;
float width_ratio = resized_src . cols * 1.0f / qrcode . cols ;
float height_ratio = resized_src . rows * 1.0f / qrcode . rows ;
for ( size_t j = 0 ; j < corners . size ( ) ; j + + )
{
corners [ j ] . x = corners [ j ] . x * width_ratio ;
corners [ j ] . y = corners [ j ] . y * height_ratio ;
}
# ifdef HAVE_QUIRC
Mat straight_barcode ;
std : : string decoded_info = QRCodeDetector ( ) . decode ( resized_src , corners , straight_barcode ) ;
EXPECT_FALSE ( decoded_info . empty ( ) ) < < " The generated QRcode cannot be decoded. " ;
EXPECT_EQ ( input_info , decoded_info ) ;
# endif
}
}
TEST ( Objdetect_QRCode_Encode_Decode_Structured_Append , DISABLED_regression )
{
// disabled since QR decoder probably doesn't support structured append mode qr codes
const std : : string root = " qrcode/decode_encode " ;
const std : : string dataset_config = findDataFile ( root + " / " + " symbol_sets.json " ) ;
const std : : string version_config = findDataFile ( root + " / " + " capacity.json " ) ;
FileStorage file_config ( dataset_config , FileStorage : : READ ) ;
ASSERT_TRUE ( file_config . isOpened ( ) ) < < " Can't read validation data: " < < dataset_config ;
FileNode mode_list = file_config [ " symbols_sets " ] ;
size_t mode_count = static_cast < size_t > ( mode_list . size ( ) ) ;
ASSERT_GT ( mode_count , 0u ) < < " Can't find validation data entries in 'test_images': " < < dataset_config ;
int modes [ ] = { 1 , 2 , 4 } ;
const int min_stuctures_num = 2 ;
const int max_stuctures_num = 5 ;
for ( int i = 0 ; i < 3 ; i + + )
{
int mode = modes [ i ] ;
FileNode config = mode_list [ i ] ;
std : : string symbol_set = config [ " symbols_set " ] ;
std : : string input_info = symbol_set ;
# if defined CV_CXX11
// std::random_shuffle is deprecated since C++11 and removed in C++17.
// Use manually constructed RNG with a fixed seed and std::shuffle instead.
std : : mt19937 rand_gen { 1 } ;
std : : shuffle ( input_info . begin ( ) , input_info . end ( ) , rand_gen ) ;
# else
SeededRandFunctor < 1 > rand_gen ;
std : : random_shuffle ( input_info . begin ( ) , input_info . end ( ) , rand_gen ) ;
# endif
for ( int j = min_stuctures_num ; j < max_stuctures_num ; j + + )
{
QRCodeEncoder : : Params params ;
params . structure_number = j ;
Ptr < QRCodeEncoder > encoder = QRCodeEncoder : : create ( params ) ;
vector < Mat > qrcodes ;
encoder - > encodeStructuredAppend ( input_info , qrcodes ) ;
EXPECT_TRUE ( ! qrcodes . empty ( ) ) < < " Can't generate this QR images " ;
std : : string output_info = " " ;
for ( size_t k = 0 ; k < qrcodes . size ( ) ; k + + )
{
Mat qrcode = qrcodes [ k ] ;
std : : vector < Point2f > corners ( 4 ) ;
corners [ 0 ] = Point2f ( border_width , border_width ) ;
corners [ 1 ] = Point2f ( qrcode . cols * 1.0f - border_width , border_width ) ;
corners [ 2 ] = Point2f ( qrcode . cols * 1.0f - border_width , qrcode . rows * 1.0f - border_width ) ;
corners [ 3 ] = Point2f ( border_width , qrcode . rows * 1.0f - border_width ) ;
Mat resized_src ;
resize ( qrcode , resized_src , fixed_size , 0 , 0 , INTER_AREA ) ;
float width_ratio = resized_src . cols * 1.0f / qrcode . cols ;
float height_ratio = resized_src . rows * 1.0f / qrcode . rows ;
for ( size_t m = 0 ; m < corners . size ( ) ; m + + )
{
corners [ m ] . x = corners [ m ] . x * width_ratio ;
corners [ m ] . y = corners [ m ] . y * height_ratio ;
}
# ifdef HAVE_QUIRC
Mat straight_barcode ;
std : : string decoded_info = QRCodeDetector ( ) . decode ( resized_src , corners , straight_barcode ) ;
EXPECT_FALSE ( decoded_info . empty ( ) )
< < " The generated QRcode cannot be decoded. " < < " Mode: " < < modes [ i ]
< < " structures number: " < < k < < " / " < < j ;
output_info + = decoded_info ;
# endif
}
# ifdef HAVE_QUIRC
EXPECT_EQ ( input_info , output_info ) < < " The generated QRcode is not same as test data. " < < " Mode: " < < mode < <
" structures number: " < < j ;
# else
std : : cout < < " Mode= " < < mode < < " : Unable to verify generated QR codes - QUIRC is disabled " < < std : : endl ;
# endif
}
}
}
# endif // UPDATE_QRCODE_TEST_DATA
CV_ENUM ( EncodeModes , QRCodeEncoder : : EncodeMode : : MODE_NUMERIC ,
QRCodeEncoder : : EncodeMode : : MODE_ALPHANUMERIC ,
QRCodeEncoder : : EncodeMode : : MODE_BYTE )
typedef : : testing : : TestWithParam < EncodeModes > 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 < cv : : Mat > result_qrcodes ;
cv : : QRCodeEncoder : : Params params ;
int encode_mode = GetParam ( ) ;
params . mode = static_cast < cv : : QRCodeEncoder : : EncodeMode > ( encode_mode ) ;
for ( size_t struct_num = 2 ; struct_num < 5 ; + + struct_num )
{
params . structure_number = static_cast < int > ( struct_num ) ;
cv : : Ptr < cv : : QRCodeEncoder > 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 " ;
const int min_version = 1 ;
const int max_version = 40 ;
for ( int v = min_version ; v < = max_version ; v + + )
{
SCOPED_TRACE ( cv : : format ( " version=%d " , v ) ) ;
Mat qrimg ;
QRCodeEncoder : : Params params ;
params . version = v ;
Ptr < QRCodeEncoder > qrcode_enc = cv : : QRCodeEncoder : : create ( params ) ;
qrcode_enc - > encode ( msg , qrimg ) ;
const int white_margin = 2 ;
const int finder_width = 7 ;
const int timing_pos = white_margin + 6 ;
int i ;
// Horizontal Check
// (1) White margin(Left)
for ( i = 0 ; i < white_margin ; i + + )
{
ASSERT_EQ ( ( uint8_t ) 255 , qrimg . at < uint8_t > ( i , timing_pos ) ) < < " i= " < < i ;
}
// (2) Finder pattern(Left)
for ( ; i < white_margin + finder_width ; i + + )
{
ASSERT_EQ ( ( uint8_t ) 0 , qrimg . at < uint8_t > ( i , timing_pos ) ) < < " i= " < < i ;
}
// (3) Timing pattern
for ( ; i < qrimg . rows - finder_width - white_margin ; i + + )
{
ASSERT_EQ ( ( uint8_t ) ( i % 2 = = 0 ) ? 0 : 255 , qrimg . at < uint8_t > ( i , timing_pos ) ) < < " i= " < < i ;
}
// (4) Finder pattern(Right)
for ( ; i < qrimg . rows - white_margin ; i + + )
{
ASSERT_EQ ( ( uint8_t ) 0 , qrimg . at < uint8_t > ( i , timing_pos ) ) < < " i= " < < i ;
}
// (5) White margin(Right)
for ( ; i < qrimg . rows ; i + + )
{
ASSERT_EQ ( ( uint8_t ) 255 , qrimg . at < uint8_t > ( i , timing_pos ) ) < < " i= " < < i ;
}
// Vertical Check
// (1) White margin(Top)
for ( i = 0 ; i < white_margin ; i + + )
{
ASSERT_EQ ( ( uint8_t ) 255 , qrimg . at < uint8_t > ( timing_pos , i ) ) < < " i= " < < i ;
}
// (2) Finder pattern(Top)
for ( ; i < white_margin + finder_width ; i + + )
{
ASSERT_EQ ( ( uint8_t ) 0 , qrimg . at < uint8_t > ( timing_pos , i ) ) < < " i= " < < i ;
}
// (3) Timing pattern
for ( ; i < qrimg . rows - finder_width - white_margin ; i + + )
{
ASSERT_EQ ( ( uint8_t ) ( i % 2 = = 0 ) ? 0 : 255 , qrimg . at < uint8_t > ( timing_pos , i ) ) < < " i= " < < i ;
}
// (4) Finder pattern(Bottom)
for ( ; i < qrimg . rows - white_margin ; i + + )
{
ASSERT_EQ ( ( uint8_t ) 0 , qrimg . at < uint8_t > ( timing_pos , i ) ) < < " i= " < < i ;
}
// (5) White margin(Bottom)
for ( ; i < qrimg . rows ; i + + )
{
ASSERT_EQ ( ( uint8_t ) 255 , qrimg . at < uint8_t > ( timing_pos , i ) ) < < " i= " < < i ;
}
}
}
} } // namespace