forked from tastytea/libravatarserv
Added identicon support (closes #2)
This commit is contained in:
parent
3db99fbd03
commit
645554e226
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required (VERSION 3.2)
|
cmake_minimum_required (VERSION 3.2)
|
||||||
project(libravatarserv
|
project(libravatarserv
|
||||||
VERSION 0.4.3
|
VERSION 0.5.0
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ images tied to email or OpenID addresses.
|
||||||
* MD5 hashes
|
* MD5 hashes
|
||||||
* SHA256 hashes
|
* SHA256 hashes
|
||||||
* Variable image size (`s` or `size`)
|
* Variable image size (`s` or `size`)
|
||||||
* Default actions (`d` or `default`): 404, URL, mp/mm
|
* Default actions (`d` or `default`): 404, URL, mp/mm, identicon
|
||||||
|
|
||||||
The default behaviour for unknown users is to return a 404 error. If a default
|
The default behaviour for unknown users is to return a 404 error. If a default
|
||||||
image is put in the avatar directory, that is returned instead. The default
|
image is put in the avatar directory, that is returned instead. The default
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <array>
|
||||||
#include "libravatarserv.hpp"
|
#include "libravatarserv.hpp"
|
||||||
|
|
||||||
using std::cout;
|
using std::cout;
|
||||||
|
@ -69,3 +71,61 @@ void image::write(Image &image)
|
||||||
cout.flush(); // We need to flush before we use /dev/stdout directly.
|
cout.flush(); // We need to flush before we use /dev/stdout directly.
|
||||||
image.image.write("/dev/stdout");
|
image.image.write("/dev/stdout");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Image image::identicon(const string &digest)
|
||||||
|
{
|
||||||
|
const string sha256 = hash::sha256(digest);
|
||||||
|
Magick::Image img(Magick::Geometry(4, 4), Magick::Color("white"));
|
||||||
|
// The 16 named colors specified in HTML 14.01 minus white, silver and gray.
|
||||||
|
const std::array<Magick::Color, 13> colors =
|
||||||
|
{
|
||||||
|
Magick::Color("black"),
|
||||||
|
Magick::Color("red"),
|
||||||
|
Magick::Color("maroon"),
|
||||||
|
Magick::Color("yellow"),
|
||||||
|
Magick::Color("olive"),
|
||||||
|
Magick::Color("lime"),
|
||||||
|
Magick::Color("green"),
|
||||||
|
Magick::Color("aqua"),
|
||||||
|
Magick::Color("teal"),
|
||||||
|
Magick::Color("blue"),
|
||||||
|
Magick::Color("navy"),
|
||||||
|
Magick::Color("fuchsia"),
|
||||||
|
Magick::Color("purple")
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::uint64_t random = 0xffff;
|
||||||
|
for (uint64_t chunk = 0; chunk < 4; ++chunk)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << std::hex << sha256.substr(chunk * 16, 16);
|
||||||
|
random = (random / 2) + (static_cast<std::uint64_t>(ss.get()) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Magick::Color dotcolor = colors[random % 13];
|
||||||
|
for (uint8_t row = 0; row < 4; ++row)
|
||||||
|
{
|
||||||
|
for (uint8_t column = 0; column < 4; ++column)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
uint16_t px;
|
||||||
|
ss << std::hex << sha256.substr(row * 4 + column, 4);
|
||||||
|
ss >> px;
|
||||||
|
if (px > 0x8000)
|
||||||
|
{
|
||||||
|
img.pixelColor(column, row, dotcolor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
cerr << "Error: " << e.what() << endl;
|
||||||
|
return { 5, img };
|
||||||
|
}
|
||||||
|
|
||||||
|
img.magick("png");
|
||||||
|
return { 0, img };
|
||||||
|
}
|
||||||
|
|
|
@ -71,8 +71,8 @@ int main()
|
||||||
avatar.fallback.substr(0, 2) == "mm")
|
avatar.fallback.substr(0, 2) == "mm")
|
||||||
{
|
{
|
||||||
// MD5 hash of 'mp'
|
// MD5 hash of 'mp'
|
||||||
image = image::get("1f2dfa567dcf95833eddf7aec167fec7",
|
image = image::get("1f2dfa567dcf95833eddf7aec167fec7",
|
||||||
avatar.size);
|
avatar.size);
|
||||||
if (image.error == 0)
|
if (image.error == 0)
|
||||||
{
|
{
|
||||||
image::write(image);
|
image::write(image);
|
||||||
|
@ -80,7 +80,21 @@ int main()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cout << "Status: 404 Not Found\n\n";
|
cout << "Status: 404 Not Found\n\n";
|
||||||
cerr << "Mystery person not found.\n";
|
cerr << "Error: Mystery person not found.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (avatar.fallback.substr(0, 9) == "identicon")
|
||||||
|
{
|
||||||
|
image = image::identicon(avatar.digest);
|
||||||
|
if (image.error == 0)
|
||||||
|
{
|
||||||
|
image.image.scale(Magick::Geometry(avatar.size, avatar.size));
|
||||||
|
image::write(image);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cout << "Status: 404 Not Found\n\n";
|
||||||
|
cerr << "Error: Couldn't generate identicon.\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -75,6 +75,7 @@ namespace image // image.cpp
|
||||||
|
|
||||||
const Image get(const string &digest, const uint16_t size);
|
const Image get(const string &digest, const uint16_t size);
|
||||||
void write(Image &image);
|
void write(Image &image);
|
||||||
|
Image identicon(const string &digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // LIBRAVATARSERV_HPP
|
#endif // LIBRAVATARSERV_HPP
|
||||||
|
|
Loading…
Reference in New Issue