src/includes/classes/Core/Utils/Image.php
public function texturize(array $args): bool
    {
        if (!class_exists('Imagick')) {
            return false;
        }
        $default_args = [
            'file'   => '',
            'format' => '',

            'size'   => 0,
            'width'  => 0,
            'height' => 0,

            'output_file'   => '',
            'output_format' => '',
        ];
        $args += $default_args; // Defaults.
        $args = $this->parseFormatArgs($args);

        if (!is_file($args['file']) || !$args['format']) {
            return false; // Not possible.
        } elseif (!$args['output_file'] || !$args['output_format']) {
            return false; // Not possible.
        }
        $args['size']   = max(1, (int) $args['size']);
        $args['width']  = max(1, (int) ($args['width'] ?: $args['size']));
        $args['height'] = max(1, (int) ($args['height'] ?: $args['size']));

        $output_file_existed_prior = is_file($args['output_file']);

        try { // Catch exceptions.
            if ($args['format'] === 'svg' && $args['output_format'] === 'svg') {
                $xml = new \DOMDocument('1.0', 'utf-8');
                $svg = ['texture_nodes' => []];

                if (!$xml->load($args['file'])) {
                    throw $this->c::issue('SVG load failure.');
                } elseif (!($svg['tag'] = $xml->getElementsByTagName('svg')->item(0))) {
                    throw $this->c::issue('SVG tag parse failure.');
                }
                while ($svg['tag']->hasChildNodes()) {
                    $svg['texture_nodes'][] = $svg['tag']->firstChild;
                    $svg['tag']->removeChild($svg['tag']->firstChild);
                }
                $svg['defs']    = $xml->createElement('defs');
                $svg['texture'] = $xml->createElement('pattern');
                $svg['rect']    = $xml->createElement('rect');

                $svg['tag']->appendChild($svg['defs']);
                $svg['defs']->appendChild($svg['texture']);
                $svg['tag']->appendChild($svg['rect']);

                $svg['texture']->setAttribute('id', 'texture');
                $svg['texture']->setAttribute('patternUnits', 'userSpaceOnUse');
                $svg['texture']->setAttribute('width', $svg['tag']->getAttribute('width'));
                $svg['texture']->setAttribute('height', $svg['tag']->getAttribute('height'));

                foreach ($svg['texture_nodes'] as $_texture_node) {
                    $svg['texture']->appendChild($_texture_node);
                } // unset($_texture_node); // Housekeeping.

                $svg['rect']->setAttribute('width', '100%');
                $svg['rect']->setAttribute('height', '100%');
                $svg['rect']->setAttribute('fill', 'url(#texture)');

                $svg['tag']->setAttribute('width', (string) $args['width']);
                $svg['tag']->setAttribute('height', (string) $args['height']);

                if (file_put_contents($args['output_file'], $xml->saveXML()) === false) {
                    throw $this->c::issue('SVG save failure.');
                }
                return true; // Success.
            } else {
                $image = new \Imagick();
                $image->setBackgroundColor('transparent');
                $image->readImage($args['format'].':'.$args['file']);

                $canvas = new \Imagick(); // To hold texturization.
                $canvas->newImage($args['width'], $args['height'], 'transparent', $args['output_format']);

                $image = $canvas->textureImage($image);
                $image->writeImage($args['output_format'].':'.$args['output_file']);

                return true; // Success.
            }
        } catch (\Throwable $Exception) {
            if (!$output_file_existed_prior && is_file($args['output_file'])) {
                unlink($args['output_file']);
            }
            return false;
        }
    }
public function texturize(array $args): bool
    {
        if (!class_exists('Imagick')) {
            return false;
        }
        $default_args = [
            'file'   => '',
            'format' => '',

            'size'   => 0,
            'width'  => 0,
            'height' => 0,

            'output_file'   => '',
            'output_format' => '',
        ];
        $args += $default_args; // Defaults.
        $args = $this->parseFormatArgs($args);

        if (!is_file($args['file']) || !$args['format']) {
            return false; // Not possible.
        } elseif (!$args['output_file'] || !$args['output_format']) {
            return false; // Not possible.
        }
        $args['size']   = max(1, (int) $args['size']);
        $args['width']  = max(1, (int) ($args['width'] ?: $args['size']));
        $args['height'] = max(1, (int) ($args['height'] ?: $args['size']));

        $output_file_existed_prior = is_file($args['output_file']);

        try { // Catch exceptions.
            if ($args['format'] === 'svg' && $args['output_format'] === 'svg') {
                $xml = new \DOMDocument('1.0', 'utf-8');
                $svg = ['texture_nodes' => []];

                if (!$xml->load($args['file'])) {
                    throw $this->c::issue('SVG load failure.');
                } elseif (!($svg['tag'] = $xml->getElementsByTagName('svg')->item(0))) {
                    throw $this->c::issue('SVG tag parse failure.');
                }
                while ($svg['tag']->hasChildNodes()) {
                    $svg['texture_nodes'][] = $svg['tag']->firstChild;
                    $svg['tag']->removeChild($svg['tag']->firstChild);
                }
                $svg['defs']    = $xml->createElement('defs');
                $svg['texture'] = $xml->createElement('pattern');
                $svg['rect']    = $xml->createElement('rect');

                $svg['tag']->appendChild($svg['defs']);
                $svg['defs']->appendChild($svg['texture']);
                $svg['tag']->appendChild($svg['rect']);

                $svg['texture']->setAttribute('id', 'texture');
                $svg['texture']->setAttribute('patternUnits', 'userSpaceOnUse');
                $svg['texture']->setAttribute('width', $svg['tag']->getAttribute('width'));
                $svg['texture']->setAttribute('height', $svg['tag']->getAttribute('height'));

                foreach ($svg['texture_nodes'] as $_texture_node) {
                    $svg['texture']->appendChild($_texture_node);
                } // unset($_texture_node); // Housekeeping.

                $svg['rect']->setAttribute('width', '100%');
                $svg['rect']->setAttribute('height', '100%');
                $svg['rect']->setAttribute('fill', 'url(#texture)');

                $svg['tag']->setAttribute('width', (string) $args['width']);
                $svg['tag']->setAttribute('height', (string) $args['height']);

                if (file_put_contents($args['output_file'], $xml->saveXML()) === false) {
                    throw $this->c::issue('SVG save failure.');
                }
                return true; // Success.
            } else {
                $image = new \Imagick();
                $image->setBackgroundColor('transparent');
                $image->readImage($args['format'].':'.$args['file']);

                $canvas = new \Imagick(); // To hold texturization.
                $canvas->newImage($args['width'], $args['height'], 'transparent', $args['output_format']);

                $image = $canvas->textureImage($image);
                $image->writeImage($args['output_format'].':'.$args['output_file']);

                return true; // Success.
            }
        } catch (\Throwable $Exception) {
            if (!$output_file_existed_prior && is_file($args['output_file'])) {
                unlink($args['output_file']);
            }
            return false;
        }
    }
Texturize image.

@since 17xxxx Imagick utils.

@param array $args Named arguments.

@return bool True on success.