From 024fd4eb79226d9f45b3581dfaf2f4faaa5e8ee6 Mon Sep 17 00:00:00 2001 From: tastytea Date: Wed, 26 Dec 2018 04:36:58 +0100 Subject: [PATCH] Refactored --- CMakeLists.txt | 12 ++----- example.cpp | 52 ++++++++++++++++++++-------- src/identiconpp.cpp | 82 ++++++++++++++++++++++++++++----------------- src/identiconpp.hpp | 47 ++++++++++++-------------- 4 files changed, 112 insertions(+), 81 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e802ec..ff9c652 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,17 +1,12 @@ cmake_minimum_required (VERSION 3.2) project(identiconpp - VERSION 0.0.0 + VERSION 0.1.0 LANGUAGES CXX ) include(GNUInstallDirs) find_package(PkgConfig REQUIRED) pkg_check_modules(MAGICPP REQUIRED Magick++) -pkg_check_modules(LIBCRYPTOPP libcryptopp) -if(NOT LIBCRYPTOPP_FOUND) - # Debian stretch package installs libcrypto++.pc - pkg_check_modules(LIBCRYPTOPP REQUIRED libcrypto++) -endif() set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -28,18 +23,15 @@ endif() include_directories(${PROJECT_SOURCE_DIR}/src) include_directories(${PROJECT_BINARY_DIR}) include_directories(${MAGICPP_INCLUDE_DIRS}) -include_directories(${LIBCRYPTOPP_INCLUDE_DIRS}) link_directories(${MAGICPP_LIBRARY_DIRS}) -link_directories(${LIBCRYPTOPP_LIBRARY_DIRS}) file(GLOB sources src/*.cpp) add_library(${CMAKE_PROJECT_NAME} SHARED "${sources}") set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${${CMAKE_PROJECT_NAME}_VERSION_MAJOR}) -target_link_libraries(${CMAKE_PROJECT_NAME} - "${MAGICPP_LDFLAGS} ${LIBCRYPTOPP_LDFLAGS}") +target_link_libraries(${CMAKE_PROJECT_NAME} "${MAGICPP_LDFLAGS}") add_executable(example "example.cpp") target_link_libraries(example ${CMAKE_PROJECT_NAME}) diff --git a/example.cpp b/example.cpp index 2b3c5df..1f935c8 100644 --- a/example.cpp +++ b/example.cpp @@ -21,25 +21,49 @@ int main(int argc, char *argv[]) if (algorithm == "simple") { cout << "You selected the \"simple\" algorithm.\n"; + Identiconpp identicon(13, 10, Identiconpp::identicon_type::simple, + "ffffff88", + { + "000000ff", + "ff0000ff", + "ffff00ff", + "00ff00ff", + "00ffffff", + "0000ffff" + }); + + Magick::Image img; + img = identicon.generate("55502f40dc8b7c769880b10874abc9d0"); + img.write("identicon_example_simple1.png"); + img = identicon.generate + ( + "973dfe463ec85785f5f95af5ba3906eedb2d931c24e69824a89ea65dba4e813b", + 500 + ); + img.write("identicon_example_simple2.png"); + } + else if (algorithm == "libravatar") + { + cout << "You selected the \"libravatar\" algorithm.\n"; + Identiconpp identicon(10, 10, Identiconpp::identicon_type::libravatar, + "ffffffff", + { + "000000ff", + "ff0000ff", + "ffff00ff", + "00ff00ff", + "00ffffff", + "0000ffff" + }); + + Magick::Image img; + img = identicon.generate("55502f40dc8b7c769880b10874abc9d0"); + img.write("identicon_example_libravatar.png"); } else { cout << "The algorithm \"" << algorithm << "\" is not known.\n"; return 1; } - - Identiconpp identicon(5, 5, 0xffffffff, - { - 0x000000ff, - 0xff0000ff, - 0xffff00ff, - 0x00ff00ff, - 0x00ffffff, - 0x0000ffff - }); - Identiconpp::Image image; - image = identicon.generate("2b7dd5def082abfca556d9e8feb1fc29", Identiconpp::identicon_type::simple); - cout.flush(); // We need to flush before we use /dev/stdout directly. - image.data.write("/dev/stdout"); return 0; } diff --git a/src/identiconpp.cpp b/src/identiconpp.cpp index a1d39a8..f8f2e2e 100644 --- a/src/identiconpp.cpp +++ b/src/identiconpp.cpp @@ -23,22 +23,41 @@ #include "debug.hpp" Identiconpp::Identiconpp(const uint8_t rows, const uint8_t columns, - const uint32_t background, - const vector &foreground) + identicon_type type, + const string background, + const vector &foreground) : _rows(rows) , _columns(columns) +, _type(type) , _background(background) , _foreground(foreground) { + if (background.length() != 8) + { + throw std::invalid_argument + ( + "The background color must consist of exactly 8 digits." + ); + } + + for (const string &color : foreground) + if (color.length() != 8) + { + throw std::invalid_argument + ( + "The foreground colors must consist of exactly 8 digits." + ); + } } -Identiconpp::Image Identiconpp::generate(const string &digest, - identicon_type type, - const uint16_t width, - const uint16_t height) +Magick::Image Identiconpp::generate(const string &digest, const uint16_t width) { - check_entropy(digest, type); - switch (type) + check_entropy(digest, _type); + const uint16_t height = width / _columns * _rows; + ttdebug << "width: " << std::to_string(width) + << ", height: " << std::to_string(height) << "\n"; + + switch (_type) { case identicon_type::simple: { @@ -52,15 +71,12 @@ Identiconpp::Image Identiconpp::generate(const string &digest, } } -Identiconpp::Image Identiconpp::generate_simple(const string &digest, - const uint16_t width, - const uint16_t height) +Magick::Image Identiconpp::generate_simple(const string &digest, + const uint16_t width, + const uint16_t height) { - std::stringstream ss; - ss << std::hex << _background; - const string bgcolor = "#" + ss.str(); Magick::Image img(Magick::Geometry(_columns, _rows), - Magick::Color(bgcolor)); + Magick::Color("#" + _background)); uint8_t used_columns = _columns / 2 + _columns % 2; Magick::Color dotcolor = get_color(used_columns * _rows + 1, digest); @@ -70,10 +86,10 @@ Identiconpp::Image Identiconpp::generate_simple(const string &digest, { if (get_bit(row * used_columns + column, digest)) { - ttdebug << "col=" << std::to_string(column) - << ", row=" << std::to_string(row) << '\n'; - ttdebug << "col=" << std::to_string(used_columns - 1 + column) - << ", row=" << std::to_string(_rows - 1 - row) << '\n'; + // ttdebug << "col=" << std::to_string(column) + // << ", row=" << std::to_string(row) << '\n'; + // ttdebug << "col=" << std::to_string(used_columns - 1 + column) + // << ", row=" << std::to_string(_rows - 1 - row) << '\n'; img.pixelColor(column, row, dotcolor); img.pixelColor(_columns - 1 - column, row, dotcolor); } @@ -82,20 +98,22 @@ Identiconpp::Image Identiconpp::generate_simple(const string &digest, img.scale(Magick::Geometry(width, height)); img.magick("png"); - return { 0, img }; + return img; } -Identiconpp::Image Identiconpp::generate_libravatar(const string &digest, - const uint16_t width, - const uint16_t height) +Magick::Image Identiconpp::generate_libravatar(const string &digest, + const uint16_t width, + const uint16_t height) { - return { 1, Magick::Image() }; + Magick::Image img(Magick::Geometry(_columns, _rows), + Magick::Color("#" + _background)); + return img; } void Identiconpp::check_entropy(const string &digest, identicon_type type) { - uint8_t entropy_provided; - uint8_t entropy_required; + uint16_t entropy_provided; + uint16_t entropy_required; switch (type) { case identicon_type::simple: @@ -167,10 +185,12 @@ Magick::Color Identiconpp::get_color(const uint16_t firstbit, // Get rid of excess bits bits = bits & (1 << colorbits) - 1; + if (bits > _foreground.size()) + { + bits -= _foreground.size(); + } + // Lookup und set color - ss.str(string()); - ss.clear(); - ss << std::hex << std::setw(8) << std::setfill('0') << _foreground[bits - 1]; - ttdebug << "Color: #" << ss.str() << '\n'; - return Magick::Color("#" + ss.str()); + ttdebug << "Color: #" << _foreground[bits - 1] << '\n'; + return Magick::Color("#" + _foreground[bits - 1]); } diff --git a/src/identiconpp.hpp b/src/identiconpp.hpp index 9079624..b67ed7e 100644 --- a/src/identiconpp.hpp +++ b/src/identiconpp.hpp @@ -29,20 +29,12 @@ using std::vector; /*! * @brief Base class for identiconpp. * - * Use this class for all your identicons. + * Use this class for all your identicons. Exceptions will be thrown on + * error. */ class Identiconpp { public: - /*! - * @brief Return type for images. - */ - struct Image - { - uint8_t error; - Magick::Image data; - }; - /*! * @brief List of identicon types * @@ -59,35 +51,36 @@ public: * @brief Initialises an instance of Identiconpp. * * The instance can be used for creating identicons with differing - * image formats and sizes. + * image formats and sizes. The colors must consist of exactly 8 + * digits. * * @param rows Number of rows * @param columns Number of columns + * @param type The type of identicon * @param background Background color, hexadecimal, rrggbbaa * @param foreground vector of foreground colors */ explicit Identiconpp(const uint8_t rows, const uint8_t columns, - const uint32_t background = 0xffffffff, - const vector &foreground = { 0x000000ff } ); + identicon_type type, + const string background = "ffffffff", + const vector &foreground = { "000000ff" } ); /*! * @brief Generates identicon from digest. * * @param digest The pre-computed digest - * @param type The type of identicon * @param width The width of the image - * @param height The height of the image * - * @return 0 and an image on success, 1 and an empty image on error. + * @return The image */ - Image generate(const string &digest, identicon_type type, - const uint16_t width = 100, const uint16_t height = 100); + Magick::Image generate(const string &digest, const uint16_t width = 100); private: const uint8_t _rows; const uint8_t _columns; - const uint32_t _background; - const vector _foreground; + const identicon_type _type; + const string _background; + const vector _foreground; /*! * @brief Generate simple identicon. @@ -96,10 +89,11 @@ private: * @param width The width of the image * @param height The height of the image * - * @return 0 and an image on success, 1 and an empty image on error. + * @return The image */ - Image generate_simple(const string &digest, - const uint16_t width, const uint16_t height); + Magick::Image generate_simple(const string &digest, + const uint16_t width, + const uint16_t height); /*! * @brief Generate libravatar-style / sigil identicon. @@ -108,10 +102,11 @@ private: * @param width The width of the image * @param height The height of the image * - * @return 0 and an image on success, 1 and an empty image on error. + * @return The image */ - Image generate_libravatar(const string &digest, - const uint16_t width, const uint16_t height); + Magick::Image generate_libravatar(const string &digest, + const uint16_t width, + const uint16_t height); /*! * @brief Check if the digest contains enough entropy.