parent
80b2a59c9f
commit
024fd4eb79
|
@ -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})
|
||||||
|
|
52
example.cpp
52
example.cpp
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user