Repository: ricardofiorani/php-legofy
Branch: master
Commit: 6c07ce6ace85
Files: 11
Total size: 19.3 KB
Directory structure:
gitextract_8uvu_bst/
├── .gitignore
├── .travis.yml
├── README.md
├── composer.json
├── docs/
│ └── EXAMPLES.md
├── phpunit.xml
├── src/
│ ├── Legofy.php
│ └── Pallete/
│ ├── ColorPalette.php
│ └── LegoPaletteInterface.php
└── tests/
├── Integration/
│ └── MainIntegrationTest.php
└── Unit/
└── Palette/
└── ColorPaletteTest.php
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.idea
composer.lock
vendor
temp
index.php
build
.env
.phpunit.result.cache
================================================
FILE: .travis.yml
================================================
dist: xenial
language: php
php:
- 7.1
- 7.2
- 7.3
- 7.4
- 8.0
# This triggers builds to run on the new TravisCI infrastructure.
# See: http://docs.travis-ci.com/user/workers/container-based-infrastructure/
sudo: false
## Cache composer
cache:
directories:
- $HOME/.composer/cache
before_script:
- travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-dist
script:
- echo "xdebug.mode=coverage" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- vendor/bin/phpcs --standard=psr2 src/
- vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover
after_script:
- |
if [[ "$TRAVIS_PHP_VERSION" != 'hhvm' && "$TRAVIS_PHP_VERSION" != '7.0' ]]; then
wget https://scrutinizer-ci.com/ocular.phar
php ocular.phar code-coverage:upload --format=php-clover coverage.clover
fi
================================================
FILE: README.md
================================================
# PHP Legofy
[](http://travis-ci.org/ricardofiorani/php-legofy)
[](https://php.net/)
[](https://packagist.org/packages/ricardofiorani/php-legofy)
[](https://packagist.org/packages/ricardofiorani/php-legofy)
[](https://github.com/php-fig-rectified/fig-rectified-standards)
### What is this ?
PHP Legofy is a PHP package that takes a static image and makes it so that it looks as if it was built out of LEGO.
It was inspired by the original Legofy made in Python https://github.com/JuanPotato/Legofy
Basically it transforms this:
![Image of a beer][beer]
Into this:
![Image of a legofied beer][lego-beer]
[beer]: ./assets/examples/beer.jpg
[lego-beer]: ./assets/examples/lego-beer.jpeg
### Requirements
* PHP ^7.1 || ^8.0
* GD or ImageMagick
> I tested it with GD only but I'm trusting intervention/image that this will work on ImageMagick as well.
### Quickstart
Via composer:
```bash
$ composer require ricardofiorani/php-legofy
```
Via source:
```bash
$ git clone git@github.com:ricardofiorani/php-legofy.git
$ cd php-legofy
$ composer install
```
### Usage:
```php
<?php
require 'vendor/autoload.php';
// The multiplier for the amount of legos on your image, or "legolution" :)
$resolutionMultiplier = 1;
// When set to true it will only use lego colors that exists in real world.
$useLegoPalette = false;
$legofy = new \RicardoFiorani\Legofy\Legofy();
// $source can be any acceptable parameter for intervention/image
// Please see http://image.intervention.io/api/make
$source = 'my/imagem/path/image.jpg';
/**
*@var Intervention\Image\Image
*/
$output = $legofy->convertToLego($source, $resolutionMultiplier, $useLegoPalette);
// Please see http://image.intervention.io/use/basics and http://image.intervention.io/use/http
echo $output->response();
```
For more examples of usage please see [the usage examples on documentation](https://github.com/ricardofiorani/php-legofy/blob/master/docs/EXAMPLES.md)
================================================
FILE: composer.json
================================================
{
"name": "ricardofiorani/php-legofy",
"description": "A PHP Port of Legofy",
"keywords": ["lego", "legofy", "gd", "imagick", "image", "effect"],
"require": {
"php": "^7.1 || ^8.0",
"intervention/image": "^2.4"
},
"require-dev": {
"phpunit/phpunit": "^7.2 || ^9.0",
"spryker/code-sniffer": "^0.15.1"
},
"autoload": {
"psr-4": {
"RicardoFiorani\\Legofy\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\RicardoFiorani\\": "tests"
}
},
"license": "MIT",
"authors": [
{
"name": "Ricardo Fiorani",
"email": "ricardo.fiorani@gmail.com"
}
],
"scripts": {
"test": "phpunit"
},
"suggest": {
"ext-gd": "to use GD library based image processing.",
"ext-imagick": "to use Imagick based image processing."
}
}
================================================
FILE: docs/EXAMPLES.md
================================================
# Examples
### Input Image:
![Image of a beer][beer]
### Example 1 - Default:
```php
<?php
require 'vendor/autoload.php';
// The multiplier for the amount of legos on your image, or "legolution" :)
$resolutionMultiplier = 1;
// When set to true it will only use lego colors that exists in real world.
$useLegoPalette = false;
$legofy = new \RicardoFiorani\Legofy\Legofy();
// $source can be any acceptable parameter for intervention/image
// Please see http://image.intervention.io/api/make
$source = 'my/imagem/path/image.jpg';
/**
*@var Intervention\Image\Image
*/
$output = $legofy->convertToLego($source, $resolutionMultiplier, $useLegoPalette);
// Please see http://image.intervention.io/use/basics and http://image.intervention.io/use/http
echo $output->response();
```
Output:
![Image of a legofied beer][lego-beer]
### Example 2 - Resolution multiplier
> Please be advised that using higher multiplers will consume more memory and CPU usage on the legofying process !
The resolution multiplier multiplies the resolution of the original source image. The default value is 1.
Please note that this value is a float, so you can set it as 1.5 for example:
![Image of a legofied beer with more res][1-5-lego-beer]
You can also set it as an 0.5 value for example:
![Image of a legofied beer with less res][0-5-lego-beer]
### Example 3 - Using the original lego color palette
On this package I also added the feature to use the [original LEGO color palette](https://github.com/JuanPotato/Legofy/blob/master/2010-LEGO-color-palette.pdf). (The same that [https://github.com/JuanPotato/Legofy](https://github.com/JuanPotato/Legofy) uses.)
```php
<?php
$legofy->convertToLego($source, $resolutionMultiplier, true);
```
Output:
![Image of a legofied beer][real-color-lego-beer]
> Please note that this implementation of color distance uses the [Euclidean method](https://en.wikipedia.org/wiki/Color_difference#Euclidean) so it might not be 100% precise for scientific purposes.
[beer]: ../assets/examples/beer.jpg
[lego-beer]: ../assets/examples/lego-beer.jpeg
[1-5-lego-beer]: ../assets/examples/res-1-5-lego-beer.jpeg
[0-5-lego-beer]: ../assets/examples/res-0-5-lego-beer.jpeg
[real-color-lego-beer]: ../assets/examples/real-color-lego-beer.jpeg
================================================
FILE: phpunit.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
verbose="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="PHP Legofy Integration Test Suite">
<directory>tests/Integration</directory>
</testsuite>
<testsuite name="PHP Legofy Unit Test Suite">
<directory>tests/Unit</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">src/</directory>
</whitelist>
</filter>
<logging>
<log type="coverage-html" target="build/coverage"/>
<log type="coverage-text" target="build/coverage.txt"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>
</logging>
</phpunit>
================================================
FILE: src/Legofy.php
================================================
<?php declare(strict_types=1);
namespace RicardoFiorani\Legofy;
use Intervention\Image\AbstractColor;
use Intervention\Image\Image;
use Intervention\Image\ImageManagerStatic;
use RicardoFiorani\Legofy\Pallete\ColorPalette;
use RicardoFiorani\Legofy\Pallete\LegoPaletteInterface;
class Legofy
{
/**
* @var Image
*/
private $brick;
/**
* @var AbstractColor
*/
private $brickAverageColor;
/**
* @var int
*/
private $brickWidth;
/**
* @var int
*/
private $brickHeight;
/**
* @var LegoPaletteInterface
*/
private $palette;
public function __construct($brickResource = null, LegoPaletteInterface $palette = null)
{
$this->setBrick(
ImageManagerStatic::make($brickResource ?? __DIR__ . '/../assets/brick.png')
);
$this->setPalette($palette ?? new ColorPalette());
}
public function setBrick(Image $brick): self
{
$this->brick = $brick;
$this->brickWidth = $brick->getWidth();
$this->brickHeight = $brick->getHeight();
return $this;
}
public function setPalette(LegoPaletteInterface $palette): self
{
$this->palette = $palette;
return $this;
}
public function getBrick(): Image
{
return $this->brick;
}
public function getPalette(): LegoPaletteInterface
{
return $this->palette;
}
public function convertToLego($resource, float $resolutionMultipler = 1, bool $legoColorsOnly = false): Image
{
$image = ImageManagerStatic::make($resource);
// Calculate how many bricks fit in the image
$amountOfBricksX = (int) round($image->getWidth() * $resolutionMultipler / $this->brickWidth);
$amountOfBricksY = (int) round($image->getHeight() * $resolutionMultipler / $this->brickHeight);
// Resize to the rounded value relative to the brick size
$image->resize($amountOfBricksX, $amountOfBricksY);
$canvas = ImageManagerStatic::canvas(
$amountOfBricksX * $this->brickWidth,
$amountOfBricksY * $this->brickHeight
);
for ($x = 0; $x < $amountOfBricksX; ++$x) {
for ($y = 0; $y < $amountOfBricksY; ++$y) {
/** @var AbstractColor $color */
$color = $image->pickColor($x, $y, "object");
if ($legoColorsOnly) {
$color = $this->palette->pickClosestColor($color);
}
$colorizedBrick = $this->colorizeBrick($color);
$canvas->insert(
$colorizedBrick,
'',
$x * $this->brickWidth,
$y * $this->brickHeight
);
}
}
return $canvas;
}
private function getAverageBrickColor(): AbstractColor
{
if (null !== $this->brickAverageColor) {
return $this->brickAverageColor;
}
return $this->brickAverageColor = (clone $this->getBrick())
->pixelate($this->brickWidth)
->blur(50)
->pickColor($this->brickWidth / 2, $this->brickHeight / 2, 'obj');
}
private function colorizeBrick(AbstractColor $color): Image
{
$brickColor = $this->getAverageBrickColor();
$colorRgba = $color->getArray();
$brickColorRgba = $brickColor->getArray();
return ImageManagerStatic::canvas(
$this->brickWidth,
$this->brickHeight,
$color->getHex('')
)->insert(
(clone $this->getBrick())->colorize(
// Picked color subtracted by the average brick color to avoid the image getting brighter
($colorRgba[0] - $brickColorRgba[1]) / 2.55,
($colorRgba[1] - $brickColorRgba[1]) / 2.55,
($colorRgba[2] - $brickColorRgba[2]) / 2.55
)
);
}
}
================================================
FILE: src/Pallete/ColorPalette.php
================================================
<?php declare(strict_types=1);
namespace RicardoFiorani\Legofy\Pallete;
use Intervention\Image\AbstractColor;
class ColorPalette implements LegoPaletteInterface
{
private const PALETTE = [
'024' => [
254,
196,
1,
],
'106' => [
231,
100,
25,
],
'021' => [
222,
1,
14,
],
'221' => [
222,
56,
139,
],
'023' => [
1,
88,
168,
],
'028' => [
1,
124,
41,
],
'119' => [
149,
185,
12,
],
'192' => [
92,
29,
13,
],
'018' => [
214,
115,
65,
],
'001' => [
244,
244,
244,
],
'026' => [
2,
2,
2,
],
'226' => [
255,
255,
153,
],
'222' => [
238,
157,
195,
],
'212' => [
135,
192,
234,
],
'037' => [
1,
150,
37,
],
'005' => [
217,
187,
124,
],
'283' => [
245,
193,
137,
],
'208' => [
228,
228,
218,
],
'191' => [
244,
155,
1,
],
'124' => [
156,
1,
198,
],
'102' => [
72,
140,
198,
],
'135' => [
95,
117,
140,
],
'151' => [
96,
130,
102,
],
'138' => [
141,
117,
83,
],
'038' => [
168,
62,
22,
],
'194' => [
156,
146,
145,
],
'154' => [
128,
9,
28,
],
'268' => [
45,
22,
120,
],
'140' => [
1,
38,
66,
],
'141' => [
1,
53,
23,
],
'312' => [
170,
126,
86,
],
'199' => [
77,
94,
87,
],
'308' => [
49,
16,
7,
],
'044' => [
249,
239,
105,
],
'182' => [
236,
118,
14,
],
'047' => [
231,
102,
72,
],
'041' => [
224,
42,
41,
],
'113' => [
238,
157,
195,
],
'126' => [
156,
149,
199,
],
'042' => [
182,
224,
234,
],
'043' => [
80,
177,
232,
],
'143' => [
206,
227,
246,
],
'048' => [
99,
178,
110,
],
'311' => [
153,
255,
102,
],
'049' => [
241,
237,
91,
],
'111' => [
166,
145,
130,
],
'040' => [
238,
238,
238,
],
'131' => [
141,
148,
150,
],
'297' => [
170,
127,
46,
],
'148' => [
73,
63,
59,
],
'294' => [
254,
252,
213,
],
];
/**
* @link https://stackoverflow.com/questions/4485229/rgb-to-closest-predefined-color
*/
public function pickClosestColor(AbstractColor $color): AbstractColor
{
$distances = [];
$colorArray = $color->getArray();
foreach (self::PALETTE as $colorIdentifier => $colorSchema) {
$rDistance = $colorSchema[0] - $colorArray[0];
$gDistance = $colorSchema[1] - $colorArray[1];
$bDistance = $colorSchema[2] - $colorArray[2];
$distance = ($rDistance * .299) ** 2 + ($gDistance * .587) ** 2 + ($bDistance * .114) ** 2;
$distances[$colorIdentifier] = $distance;
}
asort($distances);
$colorIdentifier = array_keys($distances)[0];
$color->initFromRgb(...self::PALETTE[$colorIdentifier]);
return $color;
}
}
================================================
FILE: src/Pallete/LegoPaletteInterface.php
================================================
<?php declare(strict_types=1);
namespace RicardoFiorani\Legofy\Pallete;
use Intervention\Image\AbstractColor;
interface LegoPaletteInterface
{
public function pickClosestColor(AbstractColor $color): AbstractColor;
}
================================================
FILE: tests/Integration/MainIntegrationTest.php
================================================
<?php declare(strict_types=1);
namespace Tests\RicardoFiorani\Integration;
use Intervention\Image\Image;
use PHPUnit\Framework\TestCase;
use RicardoFiorani\Legofy\Legofy;
use RicardoFiorani\Legofy\Pallete\LegoPaletteInterface;
class MainIntegrationTest extends TestCase
{
public function testMainFunctionality()
{
$legofier = new Legofy();
TestCase::assertInstanceOf(Image::class, $legofier->getBrick());
TestCase::assertInstanceOf(LegoPaletteInterface::class, $legofier->getPalette());
$originalSource = __DIR__ . '/../../assets/examples/beer.jpg';
$result = $legofier->convertToLego($originalSource);
TestCase::assertInstanceOf(Image::class, $result);
TestCase::assertNotEmpty($result->psrResponse()->getBody()->getContents());
}
public function testWorksOnLegoColorOnly()
{
$legofier = new Legofy();
TestCase::assertInstanceOf(Image::class, $legofier->getBrick());
TestCase::assertInstanceOf(LegoPaletteInterface::class, $legofier->getPalette());
$originalSource = __DIR__ . '/../../assets/examples/beer.jpg';
$result = $legofier->convertToLego($originalSource, 1, true);
TestCase::assertInstanceOf(Image::class, $result);
TestCase::assertNotEmpty($result->psrResponse()->getBody()->getContents());
}
}
================================================
FILE: tests/Unit/Palette/ColorPaletteTest.php
================================================
<?php declare(strict_types=1);
namespace Tests\RicardoFiorani\Unit\Palette;
use Intervention\Image\Gd\Color;
use PHPUnit\Framework\TestCase;
use RicardoFiorani\Legofy\Pallete\ColorPalette;
class ColorPaletteTest extends TestCase
{
/**
* @dataProvider colorProvider
*/
public function testGetsRightColor(array $colors, array $input, $expected)
{
$colorPalette = new ColorPalette($colors);
$outputColor = $colorPalette->pickClosestColor(new Color($input));
$outputColorArray = $outputColor->getArray();
$this->assertEquals($expected[0], $outputColorArray[0]);
$this->assertEquals($expected[1], $outputColorArray[1]);
$this->assertEquals($expected[2], $outputColorArray[2]);
}
public function colorProvider()
{
return [
//Whole set
[
//Palette
[
'024' => [254, 196, 1,],
'106' => [231, 100, 25,],
'021' => [222, 1, 14,],
],
//input color
[253, 194, 2],
//expected color
[254, 196, 1,]
],
//Whole set
[
//Palette
[
'024' => [254, 196, 1,],
'106' => [231, 100, 25,],
'021' => [222, 1, 14,],
],
//input color
[224, 5, 22],
//expected color
[222, 1, 14,]
],
];
}
}
gitextract_8uvu_bst/
├── .gitignore
├── .travis.yml
├── README.md
├── composer.json
├── docs/
│ └── EXAMPLES.md
├── phpunit.xml
├── src/
│ ├── Legofy.php
│ └── Pallete/
│ ├── ColorPalette.php
│ └── LegoPaletteInterface.php
└── tests/
├── Integration/
│ └── MainIntegrationTest.php
└── Unit/
└── Palette/
└── ColorPaletteTest.php
SYMBOL INDEX (19 symbols across 5 files)
FILE: src/Legofy.php
class Legofy (line 11) | class Legofy
method __construct (line 38) | public function __construct($brickResource = null, LegoPaletteInterfac...
method setBrick (line 47) | public function setBrick(Image $brick): self
method setPalette (line 56) | public function setPalette(LegoPaletteInterface $palette): self
method getBrick (line 63) | public function getBrick(): Image
method getPalette (line 68) | public function getPalette(): LegoPaletteInterface
method convertToLego (line 73) | public function convertToLego($resource, float $resolutionMultipler = ...
method getAverageBrickColor (line 113) | private function getAverageBrickColor(): AbstractColor
method colorizeBrick (line 125) | private function colorizeBrick(AbstractColor $color): Image
FILE: src/Pallete/ColorPalette.php
class ColorPalette (line 7) | class ColorPalette implements LegoPaletteInterface
method pickClosestColor (line 270) | public function pickClosestColor(AbstractColor $color): AbstractColor
FILE: src/Pallete/LegoPaletteInterface.php
type LegoPaletteInterface (line 7) | interface LegoPaletteInterface
method pickClosestColor (line 9) | public function pickClosestColor(AbstractColor $color): AbstractColor;
FILE: tests/Integration/MainIntegrationTest.php
class MainIntegrationTest (line 10) | class MainIntegrationTest extends TestCase
method testMainFunctionality (line 12) | public function testMainFunctionality()
method testWorksOnLegoColorOnly (line 26) | public function testWorksOnLegoColorOnly()
FILE: tests/Unit/Palette/ColorPaletteTest.php
class ColorPaletteTest (line 9) | class ColorPaletteTest extends TestCase
method testGetsRightColor (line 14) | public function testGetsRightColor(array $colors, array $input, $expec...
method colorProvider (line 26) | public function colorProvider()
Condensed preview — 11 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (21K chars).
[
{
"path": ".gitignore",
"chars": 74,
"preview": ".idea\ncomposer.lock\nvendor\ntemp\nindex.php\nbuild\n.env\n.phpunit.result.cache"
},
{
"path": ".travis.yml",
"chars": 854,
"preview": "dist: xenial\nlanguage: php\n\nphp:\n - 7.1\n - 7.2\n - 7.3\n - 7.4\n - 8.0\n \n# This triggers builds to run on the new Tra"
},
{
"path": "README.md",
"chars": 2327,
"preview": "# PHP Legofy\n[](http://travis-ci.o"
},
{
"path": "composer.json",
"chars": 924,
"preview": "{\n \"name\": \"ricardofiorani/php-legofy\",\n \"description\": \"A PHP Port of Legofy\",\n \"keywords\": [\"lego\", \"legofy\","
},
{
"path": "docs/EXAMPLES.md",
"chars": 2264,
"preview": "# Examples\n\n### Input Image:\n![Image of a beer][beer]\n\n### Example 1 - Default:\n```php\n<?php\nrequire 'vendor/autoload.ph"
},
{
"path": "phpunit.xml",
"chars": 1038,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit bootstrap=\"vendor/autoload.php\"\n backupGlobals=\"false\"\n "
},
{
"path": "src/Legofy.php",
"chars": 3973,
"preview": "<?php declare(strict_types=1);\n\nnamespace RicardoFiorani\\Legofy;\n\nuse Intervention\\Image\\AbstractColor;\nuse Intervention"
},
{
"path": "src/Pallete/ColorPalette.php",
"chars": 5118,
"preview": "<?php declare(strict_types=1);\n\nnamespace RicardoFiorani\\Legofy\\Pallete;\n\nuse Intervention\\Image\\AbstractColor;\n\nclass C"
},
{
"path": "src/Pallete/LegoPaletteInterface.php",
"chars": 223,
"preview": "<?php declare(strict_types=1);\n\nnamespace RicardoFiorani\\Legofy\\Pallete;\n\nuse Intervention\\Image\\AbstractColor;\n\ninterfa"
},
{
"path": "tests/Integration/MainIntegrationTest.php",
"chars": 1352,
"preview": "<?php declare(strict_types=1);\n\nnamespace Tests\\RicardoFiorani\\Integration;\n\nuse Intervention\\Image\\Image;\nuse PHPUnit\\F"
},
{
"path": "tests/Unit/Palette/ColorPaletteTest.php",
"chars": 1581,
"preview": "<?php declare(strict_types=1);\n\nnamespace Tests\\RicardoFiorani\\Unit\\Palette;\n\nuse Intervention\\Image\\Gd\\Color;\nuse PHPUn"
}
]
About this extraction
This page contains the full source code of the ricardofiorani/php-legofy GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 11 files (19.3 KB), approximately 5.4k tokens, and a symbol index with 19 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.