Skip to content

Commit

Permalink
added text align option, right crop, and updated readme
Browse files Browse the repository at this point in the history
  • Loading branch information
erikaheidi committed Jun 11, 2021
1 parent b560dac commit a6eee4f
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 17 deletions.
88 changes: 85 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

# gdaisy

An image templating system based on PHP-GD to dynamically generate image banners and covers.
A highly experimental image templating system based on PHP-GD to dynamically generate image banners and covers.

## Installation

Expand All @@ -16,7 +16,7 @@ composer require erikaheidi/gdaisy

### 2. Once it's installed, you can run the default script to generate an example cover based on meta tags.

Gdaisy comes with a little example script that generates a header image adequately sized for Twitter, based on a default template. The `vendor/bin/gdaisy generate` script expects the URL to fetch as first parameter and the output path as second parameter, as follows:
Gdaisy comes with an example script that generates a header image adequately sized for Twitter, based on a default template. The `vendor/bin/gdaisy generate` script expects the URL to fetch as first parameter and the output path as second parameter, as follows:

```shell
./vendor/bin/gdaisy generate https://www.digitalocean.com/community/tutorials/how-to-set-up-visual-studio-code-for-php-projects output.png
Expand All @@ -28,5 +28,87 @@ This will generate the following image:
<img src="https://user-images.githubusercontent.com/293241/121399169-77403880-c956-11eb-8aba-f2383e260ef0.png" alt="gdaisy generated cover image">
</p>

The example generation script is defined in `vendor/erikaheidi/gdaisy/bin/gdaisy`, and the default template is defined in `vendor/erikaheidi/gdaisy/resources/templates/article_preview.json`. You can use those as base to build your own image templates, using differet content sources.
The example generation script is defined in `vendor/erikaheidi/gdaisy/bin/gdaisy`.

## Creating Templates

Consider the following `basic.json` template example:

```json
{
"width": 600,
"height": 600,
"background": "FFFFFF",
"elements": {
"title": {
"type": "text",
"properties": {
"pos_x": 50,
"pos_y": 20,
"size": 30,
"color": "666666",
"max_width": 500,
"align": "center"
}
},
"thumbnail": {
"type": "image",
"properties": {
"pos_x": 50,
"pos_y": 50,
"width": 500,
"height": 500
}
}
}
}
```

This template has two elements: `title` (type `text`) and `thumbnail` (type `image`).

**Template Properties:**

- `width`: Resulting image width
- `height`: Resulting image height
- `background`: Resulting image background

**Text Properties:**

- `pos_x`: X coordinate (bottom left X coordinate for the base of text)
- `pos_y`: Y coordinate (botom left Y coordinate for the base of text)
- `size`: Text size
- `color`: Text Color (hex)
- `max_width` (optional): Maximum text width - text will be broken down into multiple lines when set
- `align` (optional): Text align, possible values are `left`(default), `center`, or `right`.
- `font`: path to font file (ttf)

**Image Properties:**

- `pos_x`: X coordinate (top left corner) where the image will be applied
- `pos_y`: Y coordinate (top left corner) where the image will be applied,
- `width`: width (will proportially resize to fit)
- `height`: height (will proportially resize to fit)
- `image_file` (optional): when set, will use this image, otherwise you'll have to provide this as parameter when applying the template
- `crop` (optional): when set to `center`, will resize-crop while centering the image. Default is `left`, can also be set to `right`.

Following, a PHP script to generate a new image based on the example template:

```php
<?php

use GDaisy\Template;

require __DIR__. '/vendor/autoload.php';

$template = Template::create(__DIR__ . '/resources/templates/basic.json');

$template->apply("thumbnail", [
"image_file" => __DIR__ . '/resources/images/gdaisy.png'
])->apply("title", [
"text" => "generated with gdaisy"
]);

$template->write('output.png');
echo "Finished.\n";
```

14 changes: 8 additions & 6 deletions bin/gdaisy
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,15 @@ $gdaisy->registerCommand('generate', function() use ($gdaisy, $input) {

$title = $tags['twitter:title'] ?? get_page_title($url) ?? 'Gdaisy';
$description = $tags['twitter:description'] ?? $tags['description'] ?? 'Generated with erikaheidi/gdaisy';
$elements = [
'title' => [ "text" => html_entity_decode($title, ENT_QUOTES) ],
'description' => [ "text" => html_entity_decode($description . '...', ENT_QUOTES) ],
'thumbnail' => [ "image_file" => $image_file]
];

$template->build($elements);
$template->apply("title", [
"text" => html_entity_decode($title, ENT_QUOTES)
])->apply("description", [
"text" => html_entity_decode($description . '...', ENT_QUOTES)
])->apply("thumbnail", [
"image_file" => $image_file
]);

$template->write($dest);
$gdaisy->getPrinter()->info("Image saved to $dest.");

Expand Down
5 changes: 5 additions & 0 deletions src/ImagePlaceholder.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ public function apply($resource, array $params = [])
$copy_x = ($original_w / 2) - ($this->width / 2);
$copy_y = ($original_h / 2) - ($this->height / 2);
}

if ($this->crop === "right") {
$copy_x = $this->width - $original_w;
$copy_y = $this->height - $original_h;
}
}

imagecopyresized(
Expand Down
4 changes: 3 additions & 1 deletion src/Template.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,16 @@ public function write(string $path)
imagepng($this->getResource(), $path);
}

public function apply(string $key, array $params = [])
public function apply(string $key, array $params = []): Template
{
/** @var PlaceholderInterface $placeholder */
$placeholder = $this->getPlaceholder($key);

if ($placeholder) {
$placeholder->apply($this->getResource(), $params);
}

return $this;
}

public function getResource()
Expand Down
33 changes: 26 additions & 7 deletions src/TextPlaceholder.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class TextPlaceholder implements PlaceholderInterface

public ?int $max_width;

public string $align;

public int $size;

static int $spacing = 2;
Expand All @@ -27,6 +29,7 @@ public function __construct(array $params = [])
$this->font = __DIR__ . '/../' . $font;
$this->color = $params['color'] ?? "000000";
$this->max_width = $params['max_width'] ?? null;
$this->align = $params['align'] ?? 'left';
}

public function apply($resource, array $params = [])
Expand All @@ -37,18 +40,34 @@ public function apply($resource, array $params = [])
$width = $size[2] - $size[0];
$height = ($size[7] - $size[1]) * -1;

if ($this->max_width) {
if ($width > $this->max_width) {
$max_letters = (strlen($params['text']) * $this->max_width) / $width;
$wrapped = wordwrap($params['text'], $max_letters, "#");
$lines = explode("#", $wrapped);
}
if (!$this->max_width) {
$this->max_width = imagesx($resource);
}

if ($width > $this->max_width) {
$max_letters = (strlen($params['text']) * $this->max_width) / $width;
$wrapped = wordwrap($params['text'], $max_letters, "#");
$lines = explode("#", $wrapped);
}

$count = 1;
foreach ($lines as $text) {
$pos_y = $this->pos_y + ($count * $height) + self::$spacing;
imagettftext($resource, $this->size, 0, $this->pos_x, $pos_y, $color, $this->font, $text);
$pos_x = $this->pos_x;

if ($this->align != "left") {
$size = imagettfbbox($this->size, 0, $this->font, $params['text']);

if ($this->align === "center") {
$pos_x = (($this->pos_x + $this->max_width) / 2) - (($size[2] - $size[0]) / 2);
}

if ($this->align === "right") {
$pos_x = ($this->pos_x + $this->max_width) - ($size[2] - $size[0]);
}
}

imagettftext($resource, $this->size, 0, $pos_x, $pos_y, $color, $this->font, $text);
$count++;
}
}
Expand Down

0 comments on commit a6eee4f

Please sign in to comment.