initial commit
5
CHANGELOG.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
## Changelog
|
||||
|
||||
### 0.1.0
|
||||
|
||||
initial release
|
23
Controller.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace Piwik\Plugins\ProfileAvatar;
|
||||
|
||||
use Piwik\Common;
|
||||
use Piwik\Piwik;
|
||||
|
||||
class Controller extends \Piwik\Plugin\Controller
|
||||
{
|
||||
/**
|
||||
* Get profile Avatar
|
||||
*/
|
||||
public function getProfileAvatar(): void
|
||||
{
|
||||
Piwik::checkUserHasSomeViewAccess();
|
||||
$hash = Common::getRequestVar('hash', "", 'string');
|
||||
$settings = new UserSettings();
|
||||
$chosenGenerator = $settings->avatarType->getValue();
|
||||
$generator = GeneratorCollection::getGeneratorClasses($chosenGenerator, $hash);
|
||||
$generator->print();
|
||||
exit();
|
||||
}
|
||||
}
|
45
GeneratorCollection.php
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace Piwik\Plugins\ProfileAvatar;
|
||||
|
||||
use Piwik\Plugins\ProfileAvatar\Generators\AvatarBase;
|
||||
use Piwik\Plugins\ProfileAvatar\Generators\BirdAvatar;
|
||||
use Piwik\Plugins\ProfileAvatar\Generators\Blockies;
|
||||
use Piwik\Plugins\ProfileAvatar\Generators\CatAvatar;
|
||||
use Piwik\Plugins\ProfileAvatar\Generators\Identicon;
|
||||
use Piwik\Plugins\ProfileAvatar\Generators\MonsterID;
|
||||
|
||||
class GeneratorCollection
|
||||
{
|
||||
static public $generatorNames = [
|
||||
"CatAvatar" => "Cat Avatar",
|
||||
"BirdAvatar" => "Bird Avatar",
|
||||
"MonsterID" => "MonsterID",
|
||||
"Identicon" => "Identicon.js",
|
||||
"Blockies" => "Blockies"
|
||||
];
|
||||
|
||||
static public function getGeneratorClasses(string $name, string $hash): AvatarBase
|
||||
{
|
||||
switch ($name) {
|
||||
case "CatAvatar":
|
||||
return new CatAvatar($hash);
|
||||
break;
|
||||
case "BirdAvatar";
|
||||
return new BirdAvatar($hash);
|
||||
break;
|
||||
case "MonsterID":
|
||||
return new MonsterID($hash);
|
||||
break;
|
||||
case "Identicon":
|
||||
return new Identicon($hash);
|
||||
break;
|
||||
case "Blockies":
|
||||
return new Blockies($hash);
|
||||
break;
|
||||
default:
|
||||
throw new \Exception("invalid Generator");
|
||||
}
|
||||
}
|
||||
}
|
13
Generators/AvatarBase.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Piwik\Plugins\ProfileAvatar\Generators;
|
||||
|
||||
|
||||
abstract class AvatarBase
|
||||
{
|
||||
abstract function build();
|
||||
|
||||
abstract function print();
|
||||
|
||||
abstract function asDataURL();
|
||||
}
|
23
Generators/BirdAvatar.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace Piwik\Plugins\ProfileAvatar\Generators;
|
||||
|
||||
/**
|
||||
* based on cat-avatar-generator by David Revoy
|
||||
* Artwork license: https://creativecommons.org/licenses/by/4.0/
|
||||
*/
|
||||
class BirdAvatar extends MonsterIDBase
|
||||
{
|
||||
public $size = 240;
|
||||
protected $path = "CatAvatar/Bird";
|
||||
protected $partTemplate = [
|
||||
'tail' => [1, 9],
|
||||
'hoop' => [1, 9],
|
||||
'body' => [1, 9],
|
||||
'wing' => [1, 9],
|
||||
'eyes' => [1, 9],
|
||||
'bec' => [1, 9],
|
||||
'accessorie' => [1, 20]
|
||||
];
|
||||
|
||||
}
|
66
Generators/Blockies.php
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace Piwik\Plugins\ProfileAvatar\Generators;
|
||||
|
||||
/**
|
||||
* PHP port of Blockies
|
||||
* https://github.com/download13/blockies
|
||||
* by Erin Dachtler, Alex Van de Sande
|
||||
* MIT license / WTFPL license
|
||||
*/
|
||||
class Blockies extends PixelBased
|
||||
{
|
||||
protected $size = 100;
|
||||
protected $singleColor = FALSE;
|
||||
private $rowscols = 10;
|
||||
|
||||
protected function createPatterns(): void
|
||||
{
|
||||
srand(hexdec(substr($this->seed, -10)));
|
||||
$colors = [$this->createColor(), $this->createColor(), $this->createColor()];
|
||||
$cell = $this->size / $this->rowscols;
|
||||
for ($j = 0; $j < $this->rowscols; $j++) {
|
||||
|
||||
$values = $this->createRow();
|
||||
$values = array_merge($values, array_reverse($values));
|
||||
$i = 0;
|
||||
foreach ($values as $value) {
|
||||
$this->rectangles[] = [
|
||||
"x" => $i * $cell,
|
||||
"y" => $j * $cell,
|
||||
"w" => $cell,
|
||||
"h" => $cell,
|
||||
"color" => $colors[$value]
|
||||
];
|
||||
$i += 1;
|
||||
}
|
||||
}
|
||||
srand();
|
||||
}
|
||||
|
||||
private function createColor(): array
|
||||
{
|
||||
$h = rand(0, 360) / 360;
|
||||
$s = rand(40, 100) / 100;
|
||||
$l = ($this->rand() + $this->rand() + $this->rand() + $this->rand()) * 25 / 100;
|
||||
return [$h, $s, $l];
|
||||
}
|
||||
|
||||
private function rand(): float
|
||||
{
|
||||
return mt_rand() / mt_getrandmax();
|
||||
}
|
||||
|
||||
private function createRow(): array
|
||||
{
|
||||
for ($i = 0; $i < $this->rowscols / 2; $i++) {
|
||||
$row[] = floor($this->rand() * 2.3);
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
||||
protected function getForegroundColor(): void
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
18
Generators/CatAvatar.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace Piwik\Plugins\ProfileAvatar\Generators;
|
||||
|
||||
|
||||
class CatAvatar extends MonsterIDBase
|
||||
{
|
||||
public $size = 240;
|
||||
protected $path = "CatAvatar/Cat";
|
||||
protected $partTemplate = [
|
||||
'body' => [1, 15],
|
||||
'fur' => [1, 10],
|
||||
'eyes' => [1, 15],
|
||||
'mouth' => [1, 10],
|
||||
'accessorie' => [1, 20]
|
||||
];
|
||||
|
||||
}
|
75
Generators/Identicon.php
Normal file
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace Piwik\Plugins\ProfileAvatar\Generators;
|
||||
|
||||
/**
|
||||
* PHP port of https://github.com/stewartlord/identicon.js
|
||||
* Copyright (c) 2018, Stewart Lord
|
||||
* BSD 2-Clause
|
||||
*/
|
||||
class Identicon extends PixelBased
|
||||
{
|
||||
private $margin = 0.08;
|
||||
private $saturation = 0.7;
|
||||
private $lightness = 0.5;
|
||||
|
||||
|
||||
protected function createPatterns(): void
|
||||
{
|
||||
$baseMargin = floor($this->size * $this->margin);
|
||||
$cell = floor(($this->size - ($baseMargin * 2)) / 5);
|
||||
$margin = floor(($this->size - $cell * 5) / 2);
|
||||
|
||||
for ($i = 0; $i < 15; $i++) {
|
||||
$color = hexdec($this->seed[$i]) % 2 ? $this->backgroundColor : $this->getForegroundColor();
|
||||
if ($i < 5) {
|
||||
$this->rectangles[] = [
|
||||
"x" => 2 * $cell + $margin,
|
||||
"y" => $i * $cell + $margin,
|
||||
"w" => $cell,
|
||||
"h" => $cell,
|
||||
"color" => $color
|
||||
];
|
||||
} elseif ($i < 10) {
|
||||
$this->rectangles[] = [
|
||||
"x" => 1 * $cell + $margin,
|
||||
"y" => ($i - 5) * $cell + $margin,
|
||||
"w" => $cell,
|
||||
"h" => $cell,
|
||||
"color" => $color
|
||||
];
|
||||
$this->rectangles[] = [
|
||||
"x" => 3 * $cell + $margin,
|
||||
"y" => ($i - 5) * $cell + $margin,
|
||||
"w" => $cell,
|
||||
"h" => $cell,
|
||||
"color" => $color
|
||||
];
|
||||
} elseif ($i < 15) {
|
||||
$this->rectangles[] = [
|
||||
"x" => 0 * $cell + $margin,
|
||||
"y" => ($i - 10) * $cell + $margin,
|
||||
"w" => $cell,
|
||||
"h" => $cell,
|
||||
"color" => $color
|
||||
];
|
||||
$this->rectangles[] = [
|
||||
"x" => 4 * $cell + $margin,
|
||||
"y" => ($i - 10) * $cell + $margin,
|
||||
"w" => $cell,
|
||||
"h" => $cell,
|
||||
"color" => $color
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected function getForegroundColor(): array
|
||||
{
|
||||
$hue = hexdec(substr($this->seed, -7)) / 0xfffffff;
|
||||
return [$hue * 360, $this->saturation, $this->lightness];
|
||||
}
|
||||
|
||||
|
||||
}
|
30
Generators/MonsterID.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Piwik\Plugins\ProfileAvatar\Generators;
|
||||
|
||||
/**
|
||||
* Artwork by Andreas Gohr, code based on work by Andreas Gohr
|
||||
* https://github.com/splitbrain/monsterID
|
||||
* licenced under MIT license
|
||||
*/
|
||||
class MonsterID extends MonsterIDBase
|
||||
{
|
||||
protected $path = "monsterID";
|
||||
protected $partTemplate = [
|
||||
'legs' => [1, 5],
|
||||
'hair' => [1, 5],
|
||||
'arms' => [1, 5],
|
||||
'body' => [1, 15],
|
||||
'eyes' => [1, 15],
|
||||
'mouth' => [1, 10],
|
||||
];
|
||||
|
||||
protected function applyPartToImage($part, $number): void
|
||||
{
|
||||
parent::applyPartToImage($part, $number);
|
||||
if ($part == 'body') {
|
||||
$color = imagecolorallocate($this->monster, rand(20, 235), rand(20, 235), rand(20, 235));
|
||||
imagefill($this->monster, 60, 60, $color);
|
||||
}
|
||||
}
|
||||
}
|
116
Generators/MonsterIDBase.php
Normal file
|
@ -0,0 +1,116 @@
|
|||
<?php
|
||||
|
||||
namespace Piwik\Plugins\ProfileAvatar\Generators;
|
||||
|
||||
/**
|
||||
* based on code by Andreas Gohr and Anton Smirnov
|
||||
* both under MIT license
|
||||
* https://github.com/splitbrain/monsterID
|
||||
* https://github.com/arokettu/monsterid
|
||||
*/
|
||||
class MonsterIDBase extends AvatarBase
|
||||
{
|
||||
public $size = 120;
|
||||
protected $seed;
|
||||
protected $monster;
|
||||
protected $path;
|
||||
protected $partTemplate;
|
||||
|
||||
public function __construct($seed = null)
|
||||
{
|
||||
$this->seed = hexdec(substr($seed, -10));
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->monster) {
|
||||
imagedestroy($this->monster);
|
||||
}
|
||||
}
|
||||
|
||||
public function asDataUrl(): string
|
||||
{
|
||||
$this->build();
|
||||
$output = $this->toBuffer();
|
||||
|
||||
return $this->dataURL($output);
|
||||
}
|
||||
|
||||
public function build(): void
|
||||
{
|
||||
$this->createImage();
|
||||
|
||||
srand($this->seed);
|
||||
|
||||
$parts = $this->generateRandomParts();
|
||||
|
||||
foreach ($parts as $part => $number) {
|
||||
$this->applyPartToImage($part, $number);
|
||||
}
|
||||
|
||||
srand();
|
||||
}
|
||||
|
||||
private function createImage(): void
|
||||
{
|
||||
// create background
|
||||
$this->monster = imagecreatetruecolor($this->size, $this->size);
|
||||
if (!$this->monster) {
|
||||
throw new \Exception('GD image create failed');
|
||||
}
|
||||
$white = imagecolorallocate($this->monster, 255, 255, 255);
|
||||
imagefill($this->monster, 0, 0, $white);
|
||||
}
|
||||
|
||||
private function generateRandomParts(): array
|
||||
{
|
||||
// throw the dice for body parts
|
||||
foreach ($this->partTemplate as $name => $template) {
|
||||
list($min, $max) = $template;
|
||||
$parts[$name] = rand($min, $max);
|
||||
}
|
||||
return $parts;
|
||||
}
|
||||
|
||||
protected function applyPartToImage($part, $number): void
|
||||
{
|
||||
$file = implode(DIRECTORY_SEPARATOR, array(self::getPartsPath(), "{$part}_{$number}.png"));
|
||||
|
||||
$partImage = imagecreatefrompng($file);
|
||||
if (!$partImage) {
|
||||
throw new \Exception('Failed to load ' . $file);
|
||||
}
|
||||
imagesavealpha($partImage, true);
|
||||
imagecopy($this->monster, $partImage, 0, 0, 0, 0, $this->size, $this->size);
|
||||
imagedestroy($partImage);
|
||||
|
||||
}
|
||||
|
||||
private function getPartsPath(): string
|
||||
{
|
||||
return realpath(__DIR__ . '/../images/' . $this->path);
|
||||
}
|
||||
|
||||
public function toBuffer(): string
|
||||
{
|
||||
ob_start();
|
||||
imagepng($this->monster, null, 9);
|
||||
$buffer = ob_get_clean();
|
||||
imagedestroy($this->monster);
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
private function dataURL(string $output): string
|
||||
{
|
||||
$base64 = base64_encode($output);
|
||||
return "data:image/png;base64," . $base64;
|
||||
}
|
||||
|
||||
public function print(): void
|
||||
{
|
||||
$this->build();
|
||||
header('Content-type: image/png');
|
||||
imagepng($this->monster, null, 9);
|
||||
imagedestroy($this->monster);
|
||||
}
|
||||
}
|
92
Generators/PixelBased.php
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
namespace Piwik\Plugins\ProfileAvatar\Generators;
|
||||
|
||||
/**
|
||||
* Based on ported code by Erin Dachtler and Stewart Lord
|
||||
* Copyright (c) 2018, Stewart Lord
|
||||
* BSD 2-Clause
|
||||
* MIT license / WTFPL
|
||||
* https://github.com/stewartlord/identicon.js
|
||||
* https://github.com/download13/blockies
|
||||
*/
|
||||
abstract class PixelBased extends AvatarBase
|
||||
{
|
||||
protected $seed;
|
||||
protected $rectangles = [];
|
||||
protected $backgroundColor = [0, 0, 0.94];
|
||||
protected $size = 64;
|
||||
protected $singleColor = TRUE;
|
||||
|
||||
public function __construct($seed = null)
|
||||
{
|
||||
$this->seed = $seed;
|
||||
}
|
||||
|
||||
public function asDataURL()
|
||||
{
|
||||
$svg = $this->build();
|
||||
|
||||
return "data:image/svg+xml," . rawurlencode($svg);
|
||||
}
|
||||
|
||||
public function build()
|
||||
{
|
||||
$this->createPatterns();
|
||||
return $this->createSVG();
|
||||
}
|
||||
|
||||
abstract protected function createPatterns();
|
||||
|
||||
protected function createSVG()
|
||||
{
|
||||
$bg = $this->toSVGColor($this->backgroundColor);
|
||||
$stroke = $this->size * 0.005;
|
||||
$svg = "<svg xmlns='http://www.w3.org/2000/svg' width='$this->size' height='$this->size' style='background: $bg'>";
|
||||
if ($this->singleColor) {
|
||||
$fg = $this->toSVGColor($this->getForegroundColor());
|
||||
$svg .= "<g style='fill: $fg; stroke: $fg' stroke-width='$stroke'>";
|
||||
} else {
|
||||
$svg .= "<g stroke-width='$stroke'>";
|
||||
}
|
||||
|
||||
foreach ($this->rectangles as $rectangle) {
|
||||
$x = $rectangle["x"];
|
||||
$y = $rectangle["y"];
|
||||
$w = $rectangle["w"];
|
||||
$h = $rectangle["h"];
|
||||
if ($rectangle["color"] == $this->backgroundColor) {
|
||||
continue;
|
||||
}
|
||||
if ($this->singleColor) {
|
||||
$svg .= "<rect x='$x' y='$y' width='$w' height='$h' />\n";
|
||||
} else {
|
||||
$color = $this->toSVGColor($rectangle["color"]);
|
||||
$svg .= "<rect x='$x' y='$y' width='$w' height='$h' style='fill: $color; stroke: $color' />\n";
|
||||
}
|
||||
}
|
||||
$svg .= "</g></svg>";
|
||||
return $svg;
|
||||
}
|
||||
|
||||
protected static function toSVGColor(array $color)
|
||||
{
|
||||
list($h, $s, $l) = $color;
|
||||
$h *= 360;
|
||||
$s *= 100;
|
||||
$l *= 100;
|
||||
$h=round($h);
|
||||
$s=round($s);
|
||||
$l=round($l);
|
||||
return "hsl($h, $s%, $l%)";
|
||||
}
|
||||
|
||||
abstract protected function getForegroundColor();
|
||||
|
||||
public function print()
|
||||
{
|
||||
header('Content-type:image/svg+xml;charset=utf-8');
|
||||
echo $this->build();
|
||||
}
|
||||
|
||||
}
|
31
ProfileAvatar.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Piwik\Plugins\ProfileAvatar;
|
||||
|
||||
use Piwik\Plugin;
|
||||
|
||||
class ProfileAvatar extends Plugin
|
||||
{
|
||||
|
||||
public function registerEvents()
|
||||
{
|
||||
return [
|
||||
'Live.getExtraVisitorDetails' => 'getExtraVisitorDetails'
|
||||
];
|
||||
}
|
||||
|
||||
public function getExtraVisitorDetails(&$result): void
|
||||
{
|
||||
$settings = new UserSettings();
|
||||
$visitorID = $result["visitorId"];
|
||||
$hash = hash("sha256", $visitorID);
|
||||
|
||||
if ($settings->dataURLs->getValue()) {
|
||||
$chosenGenerator = $settings->avatarType->getValue();
|
||||
$generator = GeneratorCollection::getGeneratorClasses($chosenGenerator,$hash);
|
||||
$result['visitorAvatar'] = $generator->asDataUrl();
|
||||
} else {
|
||||
$result['visitorAvatar'] = "?module=ProfileAvatar&action=getProfileAvatar&hash=$hash";
|
||||
}
|
||||
}
|
||||
}
|
15
README.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Matomo ProfileAvatar Plugin
|
||||
|
||||
## Description
|
||||
|
||||
Are you tired of always seeing the same placeholder profile picture in the Vistitor Profile?
|
||||
|
||||
This plugin creates randomly generated user avatars based on the visitorID inspired by classical identicons:
|
||||
|
||||
- Cat Avatar (based on [cat-avatar-generator](https://framagit.org/Deevad/cat-avatar-generator/) by [David Revoy](https://www.davidrevoy.com/))
|
||||
- Bird Avatar (the same with birds)
|
||||
- MonsterID (based on [MonsterID](https://www.splitbrain.org/projects/monsterid) by Andreas Gohr)
|
||||
- Identicon (based on [indenticon.js](https://github.com/stewartlord/identicon.js) by Stewart Lord)
|
||||
- Blockies (based on [blockies](https://github.com/download13/blockies) by Erin Dachtler)
|
||||
|
||||
In the Personal Settings every use can choose which avatar type they want to see.
|
50
UserSettings.php
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
/**
|
||||
* Matomo - free/libre analytics platform
|
||||
*
|
||||
* @link https://matomo.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace Piwik\Plugins\ProfileAvatar;
|
||||
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Settings\FieldConfig;
|
||||
use Piwik\Settings\Setting;
|
||||
|
||||
class UserSettings extends \Piwik\Settings\Plugin\UserSettings
|
||||
{
|
||||
/** @var Setting */
|
||||
public $avatarType;
|
||||
|
||||
/** @var Setting */
|
||||
public $dataURLs;
|
||||
|
||||
protected $title = "Visitor Profile Avatar";
|
||||
|
||||
protected function init()
|
||||
{
|
||||
$this->avatarType = $this->createAvatarTypeSetting();
|
||||
|
||||
$this->dataURLs = $this->createDataURLsSetting();
|
||||
}
|
||||
|
||||
private function createAvatarTypeSetting():Setting
|
||||
{
|
||||
return $this->makeSetting("avatarType", "CatAvatar", FieldConfig::TYPE_STRING, function (FieldConfig $field) {
|
||||
$field->title = Piwik::translate('ProfileAvatar_AvatarTypeTitle');;
|
||||
$field->uiControl = FieldConfig::UI_CONTROL_RADIO;
|
||||
$field->description = Piwik::translate('ProfileAvatar_AvatarTypeDescription');
|
||||
$field->availableValues = GeneratorCollection::$generatorNames;
|
||||
});
|
||||
}
|
||||
|
||||
private function createDataURLsSetting():Setting
|
||||
{
|
||||
return $this->makeSetting("dataURLs", FALSE, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
|
||||
$field->title = Piwik::translate('ProfileAvatar_DataURLsTitle');
|
||||
$field->uiControl = FieldConfig::UI_CONTROL_CHECKBOX;
|
||||
$field->description = Piwik::translate('ProfileAvatar_DataURLsDescription');
|
||||
});
|
||||
}
|
||||
}
|
2
config/config.php
Normal file
|
@ -0,0 +1,2 @@
|
|||
<?php
|
||||
return array();
|
2
config/tracker.php
Normal file
|
@ -0,0 +1,2 @@
|
|||
<?php
|
||||
return array();
|
10
images/CatAvatar/Bird/README.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Cat-Avatar-Generator by David Revoy
|
||||
|
||||
https://framagit.org/Deevad/cat-avatar-generator/
|
||||
|
||||
### License
|
||||
|
||||
Artwork by David Revoy
|
||||
https://creativecommons.org/licenses/by/4.0/
|
||||
|
||||
https://www.davidrevoy.com/article720/bird-avatar-generator
|
BIN
images/CatAvatar/Bird/accessorie_1.png
Normal file
After Width: | Height: | Size: 8.5 KiB |
BIN
images/CatAvatar/Bird/accessorie_10.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
images/CatAvatar/Bird/accessorie_11.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
images/CatAvatar/Bird/accessorie_12.png
Normal file
After Width: | Height: | Size: 6.5 KiB |
BIN
images/CatAvatar/Bird/accessorie_13.png
Normal file
After Width: | Height: | Size: 114 B |
BIN
images/CatAvatar/Bird/accessorie_14.png
Normal file
After Width: | Height: | Size: 8.5 KiB |
BIN
images/CatAvatar/Bird/accessorie_15.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
images/CatAvatar/Bird/accessorie_16.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
images/CatAvatar/Bird/accessorie_17.png
Normal file
After Width: | Height: | Size: 114 B |
BIN
images/CatAvatar/Bird/accessorie_18.png
Normal file
After Width: | Height: | Size: 114 B |
BIN
images/CatAvatar/Bird/accessorie_19.png
Normal file
After Width: | Height: | Size: 114 B |
BIN
images/CatAvatar/Bird/accessorie_2.png
Normal file
After Width: | Height: | Size: 114 B |
BIN
images/CatAvatar/Bird/accessorie_20.png
Normal file
After Width: | Height: | Size: 114 B |
BIN
images/CatAvatar/Bird/accessorie_3.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
images/CatAvatar/Bird/accessorie_4.png
Normal file
After Width: | Height: | Size: 114 B |
BIN
images/CatAvatar/Bird/accessorie_5.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
images/CatAvatar/Bird/accessorie_6.png
Normal file
After Width: | Height: | Size: 8.3 KiB |
BIN
images/CatAvatar/Bird/accessorie_7.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
images/CatAvatar/Bird/accessorie_8.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
images/CatAvatar/Bird/accessorie_9.png
Normal file
After Width: | Height: | Size: 9.3 KiB |
BIN
images/CatAvatar/Bird/bec_1.png
Normal file
After Width: | Height: | Size: 7.3 KiB |
BIN
images/CatAvatar/Bird/bec_2.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
images/CatAvatar/Bird/bec_3.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
images/CatAvatar/Bird/bec_4.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
images/CatAvatar/Bird/bec_5.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
images/CatAvatar/Bird/bec_6.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
images/CatAvatar/Bird/bec_7.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
images/CatAvatar/Bird/bec_8.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
images/CatAvatar/Bird/bec_9.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
images/CatAvatar/Bird/body_1.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
images/CatAvatar/Bird/body_2.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
images/CatAvatar/Bird/body_3.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
images/CatAvatar/Bird/body_4.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
images/CatAvatar/Bird/body_5.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
images/CatAvatar/Bird/body_6.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
images/CatAvatar/Bird/body_7.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
images/CatAvatar/Bird/body_8.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
images/CatAvatar/Bird/body_9.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
images/CatAvatar/Bird/eyes_1.png
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
images/CatAvatar/Bird/eyes_2.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
images/CatAvatar/Bird/eyes_3.png
Normal file
After Width: | Height: | Size: 9.4 KiB |
BIN
images/CatAvatar/Bird/eyes_4.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
images/CatAvatar/Bird/eyes_5.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
images/CatAvatar/Bird/eyes_6.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
images/CatAvatar/Bird/eyes_7.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
images/CatAvatar/Bird/eyes_8.png
Normal file
After Width: | Height: | Size: 8.3 KiB |
BIN
images/CatAvatar/Bird/eyes_9.png
Normal file
After Width: | Height: | Size: 8 KiB |
BIN
images/CatAvatar/Bird/hoop_1.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
images/CatAvatar/Bird/hoop_2.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
BIN
images/CatAvatar/Bird/hoop_3.png
Normal file
After Width: | Height: | Size: 8.1 KiB |
BIN
images/CatAvatar/Bird/hoop_4.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
images/CatAvatar/Bird/hoop_5.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
images/CatAvatar/Bird/hoop_6.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
images/CatAvatar/Bird/hoop_7.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
images/CatAvatar/Bird/hoop_8.png
Normal file
After Width: | Height: | Size: 114 B |
BIN
images/CatAvatar/Bird/hoop_9.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
images/CatAvatar/Bird/tail_1.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
images/CatAvatar/Bird/tail_2.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
images/CatAvatar/Bird/tail_3.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
images/CatAvatar/Bird/tail_4.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
images/CatAvatar/Bird/tail_5.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
images/CatAvatar/Bird/tail_6.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
images/CatAvatar/Bird/tail_7.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
images/CatAvatar/Bird/tail_8.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
images/CatAvatar/Bird/tail_9.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
images/CatAvatar/Bird/wing_1.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
images/CatAvatar/Bird/wing_2.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
images/CatAvatar/Bird/wing_3.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
images/CatAvatar/Bird/wing_4.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
images/CatAvatar/Bird/wing_5.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
images/CatAvatar/Bird/wing_6.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
images/CatAvatar/Bird/wing_7.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
images/CatAvatar/Bird/wing_8.png
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
images/CatAvatar/Bird/wing_9.png
Normal file
After Width: | Height: | Size: 10 KiB |
10
images/CatAvatar/Cat/README.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Cat-Avatar-Generator by David Revoy
|
||||
|
||||
https://framagit.org/Deevad/cat-avatar-generator/
|
||||
|
||||
### License
|
||||
|
||||
Artwork by David Revoy
|
||||
https://creativecommons.org/licenses/by/4.0/
|
||||
|
||||
https://www.davidrevoy.com/article591/cat-avatar-generator
|
BIN
images/CatAvatar/Cat/accessorie_1.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
images/CatAvatar/Cat/accessorie_10.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
images/CatAvatar/Cat/accessorie_11.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
images/CatAvatar/Cat/accessorie_12.png
Normal file
After Width: | Height: | Size: 6.4 KiB |
BIN
images/CatAvatar/Cat/accessorie_13.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
images/CatAvatar/Cat/accessorie_14.png
Normal file
After Width: | Height: | Size: 8.5 KiB |
BIN
images/CatAvatar/Cat/accessorie_15.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
images/CatAvatar/Cat/accessorie_16.png
Normal file
After Width: | Height: | Size: 18 KiB |