Add logo shape 01/289501/1
authorKwanghoon Son <k.son@samsung.com>
Fri, 24 Feb 2023 04:23:10 +0000 (13:23 +0900)
committerKwanghoon Son <k.son@samsung.com>
Thu, 9 Mar 2023 02:00:10 +0000 (11:00 +0900)
The shape of the logo image is changed according to the shape
of the qrcode finder.

Change-Id: Id8020ee208babd9409b099e53912e453245e5810
Signed-off-by: Kwanghoon Son <k.son@samsung.com>
mv_barcode/barcode_generator/src/BarcodeGenerator.cpp
test/testsuites/barcode/test_designqr.cpp

index 28fd094..64cca89 100644 (file)
@@ -149,8 +149,86 @@ int createBarcode(const std::string &message, BarcodeType type, BarcodeQREncodin
        return error;
 }
 
+static void __round_rect(cv::Mat &inOutImg, cv::Rect &rect, cv::Scalar &color)
+{
+       auto gapW = rect.width / 4;
+       auto gapH = rect.height / 4;
+       cv::rectangle(inOutImg, cv::Rect(rect.x + gapW, rect.y, rect.width / 2, rect.height), color, -1);
+       cv::rectangle(inOutImg, cv::Rect(rect.x, rect.y + gapH, rect.width, rect.height / 2), color, -1);
+       cv::circle(inOutImg, cv::Point(rect.x + gapW, rect.y + gapH), gapW, color, -1);
+       cv::circle(inOutImg, cv::Point(rect.x + 3 * gapW, rect.y + gapH), gapW, color, -1);
+       cv::circle(inOutImg, cv::Point(rect.x + gapW, rect.y + 3 * gapH), gapW, color, -1);
+       cv::circle(inOutImg, cv::Point(rect.x + 3 * gapW, rect.y + 3 * gapH), gapW, color, -1);
+}
+
+static int __draw_logo(cv::Mat &image, Common::EngineConfig *engineCfg)
+{
+       std::string logoPath;
+       int error = engineCfg->getStringAttribute(std::string(MV_BARCODE_GENERATE_ATTR_EMBED_IMG_PATH), &logoPath);
+       if (error != BARCODE_ERROR_NONE) {
+               LOGE("getStringAttribute failed error : %d", error);
+               return error;
+       }
+       std::string backgroundColor;
+       error = engineCfg->getStringAttribute(std::string(MV_BARCODE_GENERATE_ATTR_COLOR_BACK), &backgroundColor);
+       if (error != BARCODE_ERROR_NONE) {
+               LOGE("getStringAttribute failed error : %d", error);
+               return error;
+       }
+       int finderShape;
+       error = engineCfg->getIntegerAttribute(std::string(MV_BARCODE_GENERATE_ATTR_FINDER_SHAPE), &finderShape);
+       if (error != BARCODE_ERROR_NONE) {
+               LOGE("getIntegerAttribute failed error : %d", error);
+               return error;
+       }
+
+       if (!logoPath.empty()) {
+               auto logo = cv::imread(logoPath.c_str(), cv::IMREAD_COLOR);
+
+               int color_decimal = strtol(backgroundColor.c_str(), nullptr, 16);
+               int B = color_decimal % 256;
+               color_decimal /= 256;
+               int G = color_decimal % 256;
+               color_decimal /= 256;
+               int R = color_decimal;
+
+               auto color_frame = cv::Scalar(B, G, R);
+               auto color_black = cv::Scalar(255, 255, 255);
+
+               auto logoSize = image.size() / 5;
+               auto logoFrameSize = logoSize + logoSize / 10;
+
+               cv::resize(logo, logo, logoSize);
+               cv::Mat maskMat = cv::Mat::zeros(image.size(), image.type());
+               cv::Mat logoMat = cv::Mat::zeros(image.size(), image.type());
+               auto logoRect = cv::Rect((image.size() - logoSize) / 2, logoSize);
+               auto logoFrameRect = cv::Rect((image.size() - logoFrameSize) / 2, logoFrameSize);
+               logo.copyTo(logoMat(logoRect));
+
+               switch (finderShape) {
+               case MV_BARCODE_GENERATE_ATTR_SHAPE_ROUND_RECT:
+                       __round_rect(maskMat, logoRect, color_black);
+                       __round_rect(image, logoFrameRect, color_frame);
+                       break;
+               case MV_BARCODE_GENERATE_ATTR_SHAPE_CIRCLE:
+                       cv::circle(maskMat, image.size() / 2, logoSize.width / 2, color_black, -1);
+                       cv::circle(image, image.size() / 2, logoFrameSize.width / 2, color_frame, -1);
+                       break;
+
+               default:
+                       cv::rectangle(maskMat, logoRect, color_black, -1);
+                       cv::rectangle(image, logoFrameRect, color_frame, -1);
+                       break;
+               }
+               cv::multiply(cv::Scalar::all(1.0) - maskMat, image, image);
+               cv::multiply(maskMat / 255, logoMat, logoMat);
+               cv::add(logoMat, image, image);
+       }
+       return error;
+}
+
 static int __write_buffer_to_img(zint_symbol *symbol, const std::string &imageFileName, BarcodeImageFormat imageFormat,
-                                                                const int imageWidth, const int imageHeight, const std::string &logoPath)
+                                                                const int imageWidth, const int imageHeight, Common::EngineConfig *engineCfg)
 {
        if (imageWidth <= 0 || imageHeight <= 0) {
                LOGE("Barcode image size is invalid: %i x %i. Terminate write to "
@@ -204,10 +282,12 @@ static int __write_buffer_to_img(zint_symbol *symbol, const std::string &imageFi
        cv::Mat image(symbol->bitmap_height, symbol->bitmap_width, CV_8UC3, symbol->bitmap);
        cv::resize(image, image, cv::Size(imageWidth, imageHeight), 0, 0, cv::INTER_AREA);
 
-       if (!logoPath.empty()) {
-               cv::Mat logo = cv::imread(logoPath.c_str(), cv::IMREAD_COLOR);
-               cv::resize(logo, logo, cv::Size(imageWidth / 5, imageHeight / 5), 0, 0, cv::INTER_AREA);
-               logo.copyTo(image(cv::Rect(2 * logo.cols, 2 * logo.rows, logo.cols, logo.rows)));
+       if (engineCfg) {
+               error = __draw_logo(image, engineCfg);
+               if (error != MEDIA_VISION_ERROR_NONE) {
+                       LOGE("__draw_logo error code : %d", error);
+                       return error;
+               }
        }
 
        error = cv::imwrite(resultFilePath, image, compressionParams) ? BARCODE_ERROR_NONE : BARCODE_ERROR_INVALID_DATA;
@@ -245,15 +325,7 @@ int BarcodeGenerator::generateBarcodeToImage(const std::string &imageFileName, B
                goto zbarcode_delete;
        }
 
-       if (engineCfg) {
-               error = engineCfg->getStringAttribute(std::string(MV_BARCODE_GENERATE_ATTR_EMBED_IMG_PATH), &logoPath);
-               if (error != BARCODE_ERROR_NONE) {
-                       LOGE("getStringAttribute failed error : %d", error);
-                       goto zbarcode_delete;
-               }
-       }
-
-       error = __write_buffer_to_img(symbol, imageFileName, imageFormat, imageWidth, imageHeight, logoPath);
+       error = __write_buffer_to_img(symbol, imageFileName, imageFormat, imageWidth, imageHeight, engineCfg);
        if (error != BARCODE_ERROR_NONE)
                LOGE("Barcode [%s] file write fail, clean memory", imageFileName.c_str());
        else
index fa27b50..f263f10 100644 (file)
@@ -2,7 +2,6 @@
 #include <algorithm>
 #include <mv_barcode_generate.h>
 
-#define LARGE_COMB_SET 0
 #define IMAGE1_PATH MV_CONFIG_PATH "/res/inference/images/banana.jpg"
 
 using namespace std;
@@ -23,6 +22,11 @@ protected:
        void TearDown() override
        {
                ASSERT_EQ(mv_destroy_engine_config(engine_cfg), MEDIA_VISION_ERROR_NONE);
+#ifndef SAVE_QR_IMG
+               if (access(test_file.c_str(), F_OK) != -1) {
+                       std::remove(test_file.c_str());
+               }
+#endif
        }
 
        mv_engine_config_h engine_cfg = NULL;
@@ -63,10 +67,9 @@ INSTANTIATE_TEST_CASE_P(
                                                                 "smalletextHttps://",
                                                 }),
                                                 testing::ValuesIn(vector<mv_barcode_qr_mode_e> { MV_BARCODE_QR_MODE_UTF8 }),
-                                                testing::ValuesIn(vector<mv_barcode_qr_ecc_e> {
-                                                        MV_BARCODE_QR_ECC_HIGH,
-#if LARGE_COMB_SET
-                                                                        MV_BARCODE_QR_ECC_LOW
+                                                testing::ValuesIn(vector<mv_barcode_qr_ecc_e> { MV_BARCODE_QR_ECC_HIGH,
+#ifdef LARGE_COMB_SET
+                                                                                                                                                MV_BARCODE_QR_ECC_LOW
 #endif
                                                 }),
                                                 testing::ValuesIn(vector<int> { 5 }),