From 613e69cdea7e3ef1c035cdc55ae44ae93bc04aa5 Mon Sep 17 00:00:00 2001 From: SamuelOPH <samueloph@gmail.com> Date: Wed, 10 Feb 2016 09:59:51 -0500 Subject: [PATCH] More dynamic cover improvements - Expanded configuration documentation - Added more color-oriented configuration options - Some fixes to text sizing --- config/vufind/config.ini | 35 ++- module/VuFind/src/VuFind/Cover/Generator.php | 213 ++++++++++++------- 2 files changed, 173 insertions(+), 75 deletions(-) diff --git a/config/vufind/config.ini b/config/vufind/config.ini index 7d5efceaf33..fe191b8d162 100644 --- a/config/vufind/config.ini +++ b/config/vufind/config.ini @@ -669,18 +669,47 @@ authors = Wikipedia [DynamicCovers] ; Font files specified here should exist in the css/font subdirectory of a theme. ; Some options are available by default inside the root theme. +; +; Covers are generated using title and author name, it will try to display everything +; by doing the following: break the title into lines, and if the title is too long +; it will display ellipses at the last line. +; Author names will be resized to the minFontSize option if needed, and if that +; don't make it fit, it will align left sided. +; +; Both author and title colors are independently customizable through these four +; options: +; authorFillColor,titleFillColor: the main color used, you can use any of the 16 +; named colors from HTML4. +; authorBorderColor,titleBorderColor: the color used to make border, you can use +; any of the 16 named colors from HTML4, or "none" if you don't want any border. +; +; maxLines: The maximum number of title lines to be displayed (excluding final ellipses) +; +; fontSize: Controls the maximum font size presented in the cover +; minFontSize: The minimum font size author names can be, in order to display +; as much as possible. +; +; bgColor: When using solid covers, you may also choose a background color, being +; the default a pseudo-random generated color (the same for grid covers), the values +; accepted are the same as the other color options. +; ;authorFont = "Roboto-Light.ttf" ;titleFont = "RobotoCondensed-Bold.ttf" ;textAlign = center ;fontSize = 9 ;minFontSize = 8 ;maxLines = 4 - ;lightness = 220 ;saturation = 80 ;size = 128 ;topPadding = 19 +;bottomPadding = 3 ;wrapWidth = 110 +;titleFillColor = black +;titleBorderColor = none +;authorFillColor = white +;authorBorderColor = black +;bgColor = random ; This section is needed for Buchhandel.de cover loading. You need an authentication ; token. It may also be necessary to customize your templates in order to comply with @@ -688,7 +717,7 @@ authors = Wikipedia ; details before turning this on. [Buchhandel] url = "https://api.vlb.de/api/v1/cover/" -; token = "XXXXXX-XXXX-XXXXX-XXXXXXXXXXXX" +; token = "XXXXXX-XXXX-XXXXX-XXXXXXXXXXXX" ; Possible HathiRights options = pd,ic,op,orph,und,umall,ic-world,nobody,pdus,cc-by,cc-by-nd, ; cc-by-nc-nd,cc-by-nc,cc-by-nc-sa,cc-by-sa,orphcand,cc-zero,und-world,icus @@ -1060,7 +1089,7 @@ era = true ; allow browsing of era subdivisions ; <result_limit> most popular entries -- it only affects display order. ;alphabetical_order = true -; This section controls the availability of export methods. +; This section controls the availability of export methods. ; ; Each entry may be a comma-separated list of contexts in which the export ; option will be presented. Valid options: diff --git a/module/VuFind/src/VuFind/Cover/Generator.php b/module/VuFind/src/VuFind/Cover/Generator.php index b0f6dd25a8b..19927689a61 100644 --- a/module/VuFind/src/VuFind/Cover/Generator.php +++ b/module/VuFind/src/VuFind/Cover/Generator.php @@ -26,7 +26,6 @@ * @link http://vufind.org/wiki/use_of_external_content Wiki */ namespace VuFind\Cover; -use VuFindCode\ISBN, Zend\Log\LoggerInterface, ZendService\Amazon\Amazon; /** * Dynamic Book Cover Generator @@ -45,14 +44,41 @@ class Generator * @var array */ protected $settings = []; + + /** + * Title's fill color + * + * @var int + */ + protected $titleFillColor; + + /** + * Title's border color + * + * @var int + */ + protected $titleBorderColor; + /** - * Reserved color + * Author's fill color + * + * @var int */ - protected $black; + protected $authorFillColor; + /** - * Reserved color + * Author's border color + * + * @var int */ - protected $white; + protected $authorBorderColor; + + /** + * Base for image + * + * @var resource + */ + protected $im; /** * Constructor @@ -75,7 +101,12 @@ class Generator 'textAlign' => 'center', 'titleFont' => 'DroidSerif-Bold.ttf', 'topPadding' => 19, + 'bottomPadding' => 3, 'wrapWidth' => 80, + 'titleFillColor' => 'black', + 'titleBorderColor' => 'none', + 'authorFillColor' => 'white', + 'authorBorderColor' => 'black' ]; foreach ($settings as $i => $setting) { $default[$i] = $setting; @@ -83,10 +114,70 @@ class Generator $default['authorFont'] = $this->fontPath($default['authorFont']); $default['titleFont'] = $this->fontPath($default['titleFont']); $this->settings = (object) $default; + + // Create image + if (!($this->im = imagecreate($this->settings->size, $this->settings->size)) + ) { + throw new \Exception("Cannot Initialize new GD image stream"); + } + // Get all colors + $this->titleFillColor = $this->getColor($this->settings->titleFillColor); + $this->titleBorderColor = $this->getColor($this->settings->titleBorderColor); + $this->authorFillColor = $this->getColor($this->settings->authorFillColor); + $this->authorBorderColor = $this->getColor( + $this->settings->authorBorderColor + ); } /** - * Generates a dynamic cover image from elements of the book + * Check and allocates color + * + * @param string $color Legal color name from HTML4 + * + * @return allocated color + */ + protected function getColor($color) + { + switch (strtolower($color)){ + case 'black': + return imagecolorallocate($this->im, 0, 0, 0); + case 'silver': + return imagecolorallocate($this->im, 192, 192, 192); + case 'gray': + return imagecolorallocate($this->im, 128, 128, 128); + case 'white': + return imagecolorallocate($this->im, 255, 255, 255); + case 'maroon': + return imagecolorallocate($this->im, 128, 0, 0); + case 'red': + return imagecolorallocate($this->im, 255, 0, 0); + case 'purple': + return imagecolorallocate($this->im, 128, 0, 128); + case 'fuchsia': + return imagecolorallocate($this->im, 255, 0, 255); + case 'green': + return imagecolorallocate($this->im, 0, 128, 0); + case 'lime': + return imagecolorallocate($this->im, 0, 255, 0); + case 'olive': + return imagecolorallocate($this->im, 128, 128, 0); + case 'yellow': + return imagecolorallocate($this->im, 255, 255, 0); + case 'navy': + return imagecolorallocate($this->im, 0, 0, 128); + case 'blue': + return imagecolorallocate($this->im, 0, 0, 255); + case 'teal': + return imagecolorallocate($this->im, 0, 128, 128); + case 'aqua': + return imagecolorallocate($this->im, 0, 255, 255); + default: + return false; + } + } + + /** + * Generates a dynamic cover image from elements of the item * * @param string $title Title of the book * @param string $author Author of the book @@ -116,29 +207,20 @@ class Generator */ protected function generateSolid($title, $author, $callnumber) { - $half = $this->settings->size / 2; $box = $this->settings->size / 8; - // Create image - if (!($im = imagecreate($this->settings->size, $this->settings->size))) { - throw new \Exception("Cannot Initialize new GD image stream"); - } - // this->white backdrop - $this->white = imagecolorallocate($im, 255, 255, 255); - // this->black - $this->black = imagecolorallocate($im, 0, 0, 0); // Generate seed from callnumber, title back up $seed = $this->createSeed($title, $callnumber); // Number to color, hsb to control saturation and lightness $color = $this->makeHSBColor( - $im, + $this->im, $seed % 256, $this->settings->saturation, $this->settings->lightness ); // Fill solid color imagefilledrectangle( - $im, + $this->im, 0, 0, $this->settings->size, @@ -146,17 +228,17 @@ class Generator $color ); - $this->drawTitle($im, $title, $box); - $this->drawAuthor($im, $author); + $this->drawTitle($this->im, $title, $box); + $this->drawAuthor($this->im, $author); // Output png CHECK THE PARAM ob_start(); - imagepng($im); + imagepng($this->im); $img = ob_get_contents(); ob_end_clean(); // Clear memory - imagedestroy($im); + imagedestroy($this->im); // GTFO return $img; } @@ -176,15 +258,6 @@ class Generator $half = $this->settings->size / 2; $box = $this->settings->size / 8; - // Create image - if (!($im = imagecreate($this->settings->size, $this->settings->size))) { - throw new \Exception("Cannot Initialize new GD image stream"); - } - // this->white backdrop - $this->white = imagecolorallocate($im, 255, 255, 255); - // this->black - $this->black = imagecolorallocate($im, 0, 0, 0); - // Generate seed from callnumber, title back up $seed = $this->createSeed($title, $callnumber); // Number to color, hsb to control saturation and lightness @@ -294,7 +367,7 @@ class Generator $text = $words[$i]; $line .= $text . ' '; $textWidth = $this->textWidth( - $line, + rtrim($line, ' '), $this->settings->titleFont, $this->settings->fontSize ); @@ -302,15 +375,14 @@ class Generator // Print black with white border $this->drawText( $im, - $pline, - 3, + rtrim($pline, ' '), $this->settings->topPadding + $lineHeight * $lineCount, $this->settings->titleFont, $this->settings->fontSize, - $this->black, - $this->white + $this->titleFillColor, + $this->titleBorderColor ); - $line = $text . " "; + $line = $text . ' '; $lineCount++; } $i++; @@ -318,26 +390,24 @@ class Generator // Print the last words $this->drawText( $im, - $line, - 3, + rtrim($line, ' '), $this->settings->topPadding + $lineHeight * $lineCount, $this->settings->titleFont, $this->settings->fontSize, - $this->black, - $this->white + $this->titleFillColor, + $this->titleBorderColor ); // Add ellipses if we've truncated if ($i < count($words) - 1) { $this->drawText( $im, '...', - 5, $this->settings->topPadding + $this->settings->maxLines * $lineHeight, $this->settings->titleFont, $this->settings->fontSize + 1, - $this->black, - $this->white + $this->titleFillColor, + $this->titleBorderColor ); } } @@ -355,31 +425,33 @@ class Generator // Scale author to fit by incrementing fontsizes down $fontSize = $this->settings->fontSize; do { - $txtWidth = $this->textWidth( + $fontSize--; + $textWidth = $this->textWidth( $author, - $this->settings->titleFont, + $this->settings->authorFont, $fontSize ); - $fontSize--; - } while ($txtWidth > $this->settings->wrapWidth); - // white text, black outline - $fontSize = ++$fontSize < $this->settings->minFontSize - ? $this->settings->fontSize - : $fontSize; + } while ($textWidth > $this->settings->wrapWidth && + $fontSize > $this->minFontSize + ); // Too small to read? Align left - $alignment = $fontSize < $this->settings->minFontSize + $textWidth = $this->textWidth( + $author, + $this->settings->authorFont, + $fontSize + ); + $align = $textWidth > $this->settings->size ? 'left' : null; $this->drawText( $im, $author, - 5, - $this->settings->size - 3, + $this->settings->size - $this->settings->bottomPadding, $this->settings->authorFont, $fontSize, - $this->white, - $this->black, - $alignment + $this->authorFillColor, + $this->authorBorderColor, + $align ); } @@ -410,7 +482,7 @@ class Generator protected function textWidth($text, $font, $size) { $p = imagettfbbox($size, 0, $font, $text); - return $p[2] - $p[0] - 4; + return $p[2] - $p[0]; } /** @@ -418,7 +490,6 @@ class Generator * * @param GCImage $im Image object * @param string $text Text to render - * @param integer $x Left position * @param integer $y Top position * @param string $font Full path to font * @param integer $fontSize Size of the font @@ -428,30 +499,28 @@ class Generator * * @return void */ - protected function drawText($im, $text, $x, $y, + protected function drawText($im, $text, $y, $font, $fontSize, $mcolor, $scolor = false, $align = null ) { - $txtWidth = $this->textWidth( + $textWidth = $this->textWidth( $text, - $this->settings->titleFont, - $this->settings->fontSize + $font, + $fontSize ); - if ($txtWidth > $this->settings->size) { + if ($textWidth > $this->settings->size) { $align = 'left'; - $x = 0; } if (null == $align) { $align = $this->settings->textAlign; } + if ($align == 'left') { + $x = 0; + } if ($align == 'center') { - $p = imagettfbbox($fontSize, 0, $this->settings->titleFont, $text); - $txtWidth = $p[2] - $p[0] - 4; - $x = ($this->settings->size - $txtWidth) / 2; + $x = ($this->settings->size - $textWidth) / 2; } if ($align == 'right') { - $p = imagettfbbox($fontSize, 0, $this->settings->titleFont, $text); - $txtWidth = $p[2] - $p[0] - 4; - $x = $this->settings->size - $txtWidth - $x; + $x = $this->settings->size - $textWidth; } // Generate 5 lines of text, 4 offset in a border color @@ -538,4 +607,4 @@ class Generator return imagecolorallocate($im, $v, $p, $q); } } -} \ No newline at end of file +} -- GitLab