Refactored
All checks were successful
the build was successful

This commit is contained in:
tastytea 2018-12-26 04:36:58 +01:00
parent 80b2a59c9f
commit 024fd4eb79
Signed by: tastytea
GPG Key ID: CFC39497F1B26E07
4 changed files with 112 additions and 81 deletions

View File

@ -1,17 +1,12 @@
cmake_minimum_required (VERSION 3.2) cmake_minimum_required (VERSION 3.2)
project(identiconpp project(identiconpp
VERSION 0.0.0 VERSION 0.1.0
LANGUAGES CXX LANGUAGES CXX
) )
include(GNUInstallDirs) include(GNUInstallDirs)
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
pkg_check_modules(MAGICPP REQUIRED Magick++) 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 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
@ -28,18 +23,15 @@ endif()
include_directories(${PROJECT_SOURCE_DIR}/src) include_directories(${PROJECT_SOURCE_DIR}/src)
include_directories(${PROJECT_BINARY_DIR}) include_directories(${PROJECT_BINARY_DIR})
include_directories(${MAGICPP_INCLUDE_DIRS}) include_directories(${MAGICPP_INCLUDE_DIRS})
include_directories(${LIBCRYPTOPP_INCLUDE_DIRS})
link_directories(${MAGICPP_LIBRARY_DIRS}) link_directories(${MAGICPP_LIBRARY_DIRS})
link_directories(${LIBCRYPTOPP_LIBRARY_DIRS})
file(GLOB sources src/*.cpp) file(GLOB sources src/*.cpp)
add_library(${CMAKE_PROJECT_NAME} SHARED "${sources}") add_library(${CMAKE_PROJECT_NAME} SHARED "${sources}")
set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES
VERSION ${PROJECT_VERSION} VERSION ${PROJECT_VERSION}
SOVERSION ${${CMAKE_PROJECT_NAME}_VERSION_MAJOR}) SOVERSION ${${CMAKE_PROJECT_NAME}_VERSION_MAJOR})
target_link_libraries(${CMAKE_PROJECT_NAME} target_link_libraries(${CMAKE_PROJECT_NAME} "${MAGICPP_LDFLAGS}")
"${MAGICPP_LDFLAGS} ${LIBCRYPTOPP_LDFLAGS}")
add_executable(example "example.cpp") add_executable(example "example.cpp")
target_link_libraries(example ${CMAKE_PROJECT_NAME}) target_link_libraries(example ${CMAKE_PROJECT_NAME})

View File

@ -21,25 +21,49 @@ int main(int argc, char *argv[])
if (algorithm == "simple") if (algorithm == "simple")
{ {
cout << "You selected the \"simple\" algorithm.\n"; 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 else
{ {
cout << "The algorithm \"" << algorithm << "\" is not known.\n"; cout << "The algorithm \"" << algorithm << "\" is not known.\n";
return 1; 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; return 0;
} }

View File

@ -23,22 +23,41 @@
#include "debug.hpp" #include "debug.hpp"
Identiconpp::Identiconpp(const uint8_t rows, const uint8_t columns, Identiconpp::Identiconpp(const uint8_t rows, const uint8_t columns,
const uint32_t background, identicon_type type,
const vector<uint32_t> &foreground) const string background,
const vector<string> &foreground)
: _rows(rows) : _rows(rows)
, _columns(columns) , _columns(columns)
, _type(type)
, _background(background) , _background(background)
, _foreground(foreground) , _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, Magick::Image Identiconpp::generate(const string &digest, const uint16_t width)
identicon_type type,
const uint16_t width,
const uint16_t height)
{ {
check_entropy(digest, type); check_entropy(digest, _type);
switch (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: case identicon_type::simple:
{ {
@ -52,15 +71,12 @@ Identiconpp::Image Identiconpp::generate(const string &digest,
} }
} }
Identiconpp::Image Identiconpp::generate_simple(const string &digest, Magick::Image Identiconpp::generate_simple(const string &digest,
const uint16_t width, const uint16_t width,
const uint16_t height) const uint16_t height)
{ {
std::stringstream ss;
ss << std::hex << _background;
const string bgcolor = "#" + ss.str();
Magick::Image img(Magick::Geometry(_columns, _rows), Magick::Image img(Magick::Geometry(_columns, _rows),
Magick::Color(bgcolor)); Magick::Color("#" + _background));
uint8_t used_columns = _columns / 2 + _columns % 2; uint8_t used_columns = _columns / 2 + _columns % 2;
Magick::Color dotcolor = get_color(used_columns * _rows + 1, digest); 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)) if (get_bit(row * used_columns + column, digest))
{ {
ttdebug << "col=" << std::to_string(column) // ttdebug << "col=" << std::to_string(column)
<< ", row=" << std::to_string(row) << '\n'; // << ", row=" << std::to_string(row) << '\n';
ttdebug << "col=" << std::to_string(used_columns - 1 + column) // ttdebug << "col=" << std::to_string(used_columns - 1 + column)
<< ", row=" << std::to_string(_rows - 1 - row) << '\n'; // << ", row=" << std::to_string(_rows - 1 - row) << '\n';
img.pixelColor(column, row, dotcolor); img.pixelColor(column, row, dotcolor);
img.pixelColor(_columns - 1 - 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.scale(Magick::Geometry(width, height));
img.magick("png"); img.magick("png");
return { 0, img }; return img;
} }
Identiconpp::Image Identiconpp::generate_libravatar(const string &digest, Magick::Image Identiconpp::generate_libravatar(const string &digest,
const uint16_t width, const uint16_t width,
const uint16_t height) 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) void Identiconpp::check_entropy(const string &digest, identicon_type type)
{ {
uint8_t entropy_provided; uint16_t entropy_provided;
uint8_t entropy_required; uint16_t entropy_required;
switch (type) switch (type)
{ {
case identicon_type::simple: case identicon_type::simple:
@ -167,10 +185,12 @@ Magick::Color Identiconpp::get_color(const uint16_t firstbit,
// Get rid of excess bits // Get rid of excess bits
bits = bits & (1 << colorbits) - 1; bits = bits & (1 << colorbits) - 1;
if (bits > _foreground.size())
{
bits -= _foreground.size();
}
// Lookup und set color // Lookup und set color
ss.str(string()); ttdebug << "Color: #" << _foreground[bits - 1] << '\n';
ss.clear(); return Magick::Color("#" + _foreground[bits - 1]);
ss << std::hex << std::setw(8) << std::setfill('0') << _foreground[bits - 1];
ttdebug << "Color: #" << ss.str() << '\n';
return Magick::Color("#" + ss.str());
} }

View File

@ -29,20 +29,12 @@ using std::vector;
/*! /*!
* @brief Base class for identiconpp. * @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 class Identiconpp
{ {
public: public:
/*!
* @brief Return type for images.
*/
struct Image
{
uint8_t error;
Magick::Image data;
};
/*! /*!
* @brief List of identicon types * @brief List of identicon types
* *
@ -59,35 +51,36 @@ public:
* @brief Initialises an instance of Identiconpp. * @brief Initialises an instance of Identiconpp.
* *
* The instance can be used for creating identicons with differing * 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 rows Number of rows
* @param columns Number of columns * @param columns Number of columns
* @param type The type of identicon
* @param background Background color, hexadecimal, rrggbbaa * @param background Background color, hexadecimal, rrggbbaa
* @param foreground vector of foreground colors * @param foreground vector of foreground colors
*/ */
explicit Identiconpp(const uint8_t rows, const uint8_t columns, explicit Identiconpp(const uint8_t rows, const uint8_t columns,
const uint32_t background = 0xffffffff, identicon_type type,
const vector<uint32_t> &foreground = { 0x000000ff } ); const string background = "ffffffff",
const vector<string> &foreground = { "000000ff" } );
/*! /*!
* @brief Generates identicon from digest. * @brief Generates identicon from digest.
* *
* @param digest The pre-computed digest * @param digest The pre-computed digest
* @param type The type of identicon
* @param width The width of the image * @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, Magick::Image generate(const string &digest, const uint16_t width = 100);
const uint16_t width = 100, const uint16_t height = 100);
private: private:
const uint8_t _rows; const uint8_t _rows;
const uint8_t _columns; const uint8_t _columns;
const uint32_t _background; const identicon_type _type;
const vector<uint32_t> _foreground; const string _background;
const vector<string> _foreground;
/*! /*!
* @brief Generate simple identicon. * @brief Generate simple identicon.
@ -96,10 +89,11 @@ private:
* @param width The width of the image * @param width The width of the image
* @param height The height 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, Magick::Image generate_simple(const string &digest,
const uint16_t width, const uint16_t height); const uint16_t width,
const uint16_t height);
/*! /*!
* @brief Generate libravatar-style / sigil identicon. * @brief Generate libravatar-style / sigil identicon.
@ -108,10 +102,11 @@ private:
* @param width The width of the image * @param width The width of the image
* @param height The height 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, Magick::Image generate_libravatar(const string &digest,
const uint16_t width, const uint16_t height); const uint16_t width,
const uint16_t height);
/*! /*!
* @brief Check if the digest contains enough entropy. * @brief Check if the digest contains enough entropy.