diff --git a/CMakeLists.txt b/CMakeLists.txt index e8298c2e..c90d137e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,6 @@ link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf) configure_file(bin/install_hyperion.sh ${LIBRARY_OUTPUT_PATH} @ONLY) configure_file(config/hyperion.config.json ${LIBRARY_OUTPUT_PATH} @ONLY) -configure_file(config/hyperion.schema.json ${LIBRARY_OUTPUT_PATH} @ONLY) # Add the source/lib directories add_subdirectory(dependencies) diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index 3539db3a..de7cdf88 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -23,6 +23,9 @@ class Hyperion : public QObject public: static LedString createLedString(const Json::Value& ledsConfig); + static Json::Value loadConfig(const std::string& configFile); + + Hyperion(const std::string& configFile); Hyperion(const Json::Value& jsonConfig); ~Hyperion(); diff --git a/libsrc/hyperion/BlackBorderDetector.cpp b/libsrc/hyperion/BlackBorderDetector.cpp new file mode 100644 index 00000000..5f7ea7fe --- /dev/null +++ b/libsrc/hyperion/BlackBorderDetector.cpp @@ -0,0 +1,110 @@ +#include "BlackBorderDetector.h" + +BlackBorderDetector::BlackBorderDetector() +{ +} + +BlackBorder BlackBorderDetector::process(const RgbImage& image) +{ + int firstNonBlackPixelTop = -1; + int firstNonBlackPixelLeft = -1; + + for (unsigned x=0; x (int)(image.height()/2) ) + { + // We don't know + // B-B-B-B ... B-B-B-B + // B +---- ... ----- ? + // B | + // B | + // : + // B | + // B | + // B | + // B ? + + detectedBorder.type = BlackBorder::unknown; + detectedBorder.size = -1; + } + else //(firstNonBlackPixelLeft > 0 && firstNonBlackPixelLeft < image.height()/2) + { + // Border at top of screen + // B-B-B-B ... B-B-B-B + // B +---- ... ----- ? + // C | + // ? | + // : + + detectedBorder.type = BlackBorder::horizontal; + detectedBorder.size = firstNonBlackPixelLeft; + } + } + else // (firstNonBlackPixelTop > 0) + { + if (firstNonBlackPixelTop < int(image.width()/2) && firstNonBlackPixelLeft < 0) + { + // Border at left of screen + // B-B-C-? ... + // B +---- ... ----- ? + // B | + // B | + // : + // B | + // B | + // B | + // B ? + + detectedBorder.type = BlackBorder::vertical; + detectedBorder.size = firstNonBlackPixelTop; + } + else //(firstNonBlackPixelTop > int(mage.width()/2) || firstNonBlackPixelLeft > 0) + { + // No black border + // B-B-C-? ... + // B +---- + // C | + // ? | + // : + + detectedBorder.type = BlackBorder::none; + detectedBorder.size = -1; + } + } + + return detectedBorder; +} diff --git a/libsrc/hyperion/BlackBorderDetector.h b/libsrc/hyperion/BlackBorderDetector.h new file mode 100644 index 00000000..1ca1ac09 --- /dev/null +++ b/libsrc/hyperion/BlackBorderDetector.h @@ -0,0 +1,38 @@ + +#pragma once + +// Utils includes +#include + +struct BlackBorder +{ + enum Type + { + none, + horizontal, + vertical, + unknown + }; + + Type type; + int size; + +}; + +class BlackBorderDetector +{ +public: + BlackBorderDetector(); + + BlackBorder process(const RgbImage& image); + + +private: + + inline bool isBlack(const RgbColor& color) + { + return RgbColor::BLACK == color; + } + + +}; diff --git a/libsrc/hyperion/CMakeLists.txt b/libsrc/hyperion/CMakeLists.txt index ed76ce33..f997fdeb 100644 --- a/libsrc/hyperion/CMakeLists.txt +++ b/libsrc/hyperion/CMakeLists.txt @@ -18,6 +18,7 @@ SET(Hyperion_HEADERS ${CURRENT_SOURCE_DIR}/LedDeviceWs2801.h ${CURRENT_SOURCE_DIR}/LedDeviceTest.h ${CURRENT_SOURCE_DIR}/ImageToLedsMap.h + ${CURRENT_SOURCE_DIR}/BlackBorderDetector.h ${CURRENT_SOURCE_DIR}/ColorTransform.h ) @@ -31,16 +32,24 @@ SET(Hyperion_SOURCES ${CURRENT_SOURCE_DIR}/LedDeviceWs2801.cpp ${CURRENT_SOURCE_DIR}/LedDeviceTest.cpp ${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp + ${CURRENT_SOURCE_DIR}/BlackBorderDetector.cpp ${CURRENT_SOURCE_DIR}/ColorTransform.cpp ) +set(Hyperion_RESOURCES + ${CURRENT_SOURCE_DIR}/resource.qrc +) + QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) +qt4_add_resources(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") + add_library(hyperion ${Hyperion_HEADERS} ${Hyperion_QT_HEADERS} ${Hyperion_HEADERS_MOC} ${Hyperion_SOURCES} + ${Hyperion_RESOURCES_RCC} ) target_link_libraries(hyperion diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index 5ad60f52..b9b7571e 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -1,8 +1,7 @@ -// Syslog include -#include - +// QT includes #include +#include // JsonSchema include #include @@ -75,6 +74,33 @@ LedString Hyperion::createLedString(const Json::Value& ledsConfig) return ledString; } +Json::Value Hyperion::loadConfig(const std::string& configFile) +{ + // read the json schema from the resource + QResource schemaData(":/hyperion.schema.json"); + assert(schemaData.isValid()); + + Json::Reader jsonReader; + Json::Value schemaJson; + if (!jsonReader.parse(reinterpret_cast(schemaData.data()), reinterpret_cast(schemaData.data()) + schemaData.size(), schemaJson, false)) + { + throw std::runtime_error("Schema error: " + jsonReader.getFormattedErrorMessages()) ; + } + JsonSchemaChecker schemaChecker; + schemaChecker.setSchema(schemaJson); + + const Json::Value jsonConfig = JsonFactory::readJson(configFile); + schemaChecker.validate(jsonConfig); + + return jsonConfig; +} + +Hyperion::Hyperion(const std::string& configFile) : + Hyperion(loadConfig(configFile)) +{ + // empty +} + Hyperion::Hyperion(const Json::Value &jsonConfig) : mLedString(createLedString(jsonConfig["leds"])), mRedTransform( createColorTransform(jsonConfig["color"]["red"])), diff --git a/config/hyperion.schema.json b/libsrc/hyperion/hyperion.schema.json similarity index 100% rename from config/hyperion.schema.json rename to libsrc/hyperion/hyperion.schema.json diff --git a/libsrc/hyperion/resource.qrc b/libsrc/hyperion/resource.qrc new file mode 100644 index 00000000..f11664c4 --- /dev/null +++ b/libsrc/hyperion/resource.qrc @@ -0,0 +1,5 @@ + + + hyperion.schema.json + + diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 9166f180..351f7fe4 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -20,21 +20,17 @@ int main(int argc, char** argv) QCoreApplication app(argc, argv); std::cout << "QCoreApplication initialised" << std::endl; - // Select config and schema file - //const std::string homeDir = getenv("RASPILIGHT_HOME"); - const std::string schemaFile = "hyperion.schema.json"; - const std::string configFile = "hyperion.config.json"; - - // Load configuration and check against the schema at the same time - Json::Value config; - if (JsonFactory::load(schemaFile, configFile, config) < 0) + if (argc < 2) { - std::cerr << "UNABLE TO LOAD CONFIGURATION" << std::endl; - return -1; + std::cout << "Missing required configuration file. Usage:" << std::endl; + std::cout << "hyperiond [config.file]" << std::endl; + return 0; } - std::cout << "Configuration loaded from: " << configFile << std::endl; - Hyperion hyperion(config); + const std::string configFile = argv[2]; + std::cout << "Selected configuration file: " << configFile.c_str() << std::endl; + + Hyperion hyperion(configFile); std::cout << "Hyperion created and initialised" << std::endl; DispmanxWrapper dispmanx(64, 64, 10, &hyperion); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 18b38b82..0ce25302 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -29,3 +29,8 @@ target_link_libraries(test_image2ledsmap hyperion) add_subdirectory(dispmanx2png) + +add_executable(test_blackborderdetector + TestBlackBorderDetector.cpp) +target_link_libraries(test_blackborderdetector + hyperion) diff --git a/test/TestBlackBorderDetector.cpp b/test/TestBlackBorderDetector.cpp new file mode 100644 index 00000000..4d576e5c --- /dev/null +++ b/test/TestBlackBorderDetector.cpp @@ -0,0 +1,120 @@ + +// STL includes +#include + +// Hyperion includes +#include "hyperion/BlackBorderDetector.h" + +RgbColor randomColor() +{ + const uint8_t randomRedValue = uint8_t(rand() % (std::numeric_limits::max() + 1)); + const uint8_t randomGreenValue = uint8_t(rand() % (std::numeric_limits::max() + 1)); + const uint8_t randomBlueValue = uint8_t(rand() % (std::numeric_limits::max() + 1)); + + return {randomRedValue, randomGreenValue, randomBlueValue}; +} + +RgbImage createImage(unsigned width, unsigned height, unsigned topBorder, unsigned leftBorder) +{ + RgbImage image(width, height); + for (unsigned x=0; x