Jump to content

Recommended Posts

Posted

If a bitmap is used just one single time, it would reduce http requests if Processwire would automatically encode the bitmap into the html.

Posted

Both would probably be doable, though a massive use of data URIs would probably also necessitate caching them, or processing time and memory use may lead to performance issues.

Here's a small example Textformatter module that converts image links in HTML fields to data URIs. You can set a size limit in the module configuration so any images equal or bigger in file size aren't converted. The default is really conservative (16kB) since not requesting larger images through regular client caching will do more for recurring visitors than saving them a roundtrip but squeezing the images over the wire with every page reload.

 

<?php namespace ProcessWire;

/**
 * Proof-of-concept module for the ProcessWire CMS
 *
 * Implements a textformatter for HTML fields that turns regular src URLs to
 * inline data URIs to avoid separate http requests.
 *
 * The default maximum size for images to inline is 16kB.
 * Feel free to raise this in the module's configuration.
 *
 * This code comes without restrictions or warranties.
 */

class TextformatterImgDataUri extends Textformatter implements Module, ConfigurableModule {

	protected static $defaultDataUriLimit = 8192;

	public static function getModuleInfo() {
		return array(
			"title"			=>	"Textformatter Image Data URI",
			"summary"		=>	"Replace image URIs in HTML body with their encoded data URI to speed up page loads",
			"version"		=>	"0.0.6",
		);
	}
	
	public function __construct() {
		$this->dataUriLimit = self::$defaultDataUriLimit;
	}
	
	public function format(&$str) {
		$src = preg_replace_callback('/(<img[^>]+(?<!-)src=)(["\'])(.*?)(\\2)([^>]*>)/', function($match) {
			// Only use files in site/assets/files
			if(strpos($match[3], $this->config->urls->assets) === 0) {
				// Translate url to paths
				$filepath = str_replace($this->config->urls->files, $this->config->paths->files, $match[3]);
				
				// If pagefileSecure is active, the path prefix probably needs to be inserted
				if(!file_exists($filepath) && $this->config->pagefileSecure && strpos($filepath, $this->config->paths->files . $this->config->pagefileSecurePathPrefix) !== 0)
				{
					$filepath = str_replace($this->config->paths->files, $this->config->paths->files . $this->config->pagefileSecurePathPrefix, $filepath);
					//$this->log->save('imgdatauri', sprintf(_("Added pagefileSecurePathPrefix to file path %s"), $filepath));
				}
				
				// If the file isn't found, we return the original url
				if(! file_exists($filepath)) {
					//$this->log->save('imgdatauri', sprintf(_("File %s not found"), $filepath));
					return $match[0];
				}
				
				// Only output images inline that are smaller than the value set in the module's configuration
				$fsize = filesize($filepath);
				if($fsize >= $this->dataUriLimit) {
					//$this->log->save('imgdatauri', sprintf(_("File %s too big, %d >= %d"), $filepath, $fsize, $this->dataUriLimit));
					return $match[0];
				}
				
				// On windows, make sure extension php_fileinfo.dll is loaded
				$mime = mime_content_type($filepath);
				$dataUri = "data:$mime;base64," . base64_encode(file_get_contents($filepath));
				return $match[1] . $match[2] . $dataUri . $match[4] . ' data-orig-src="' . $match[3] . '"' . $match[5];
			}
			//$this->log->save('imgdatauri', sprintf(_('Not an img with src: %s'), $match[0]));
			return $match[0];
		}, $str);
		$str = $src;
	}


	public function formatValue(Page $page, Field $field, &$value) {
		$this->format($value); 
	}


	public function getModuleConfigInputfields() {
		$wrap = new InputfieldWrapper();
		
		$f = $this->modules->get("InputfieldInteger");
		$f->label = _("Maximum size to convert");
		$f->attr('name', 'dataUriLimit');
		$f->attr('value', $this->dataUriLimit);
		$f->description = _("Images smaller than the value entered here in bytes will included directly in the HTML (base64 encoded data uri) instead of their links. Note that this text formatter only affects images under site/assets/files");
		$wrap->append($f);
		
		return $wrap;
	}

	
}

 

  • Like 5
  • 5 years later...
Posted

@BitPoet It's been a while, but would you consider publishing this module to github + the PW modules directory? That would make it more discoverable for PW folks.

Thanks for the code though!

Posted
2 hours ago, netcarver said:

would you consider publishing this module to github + the PW modules directory?

Published to GitHub and pending approval in the module directory.

  • Like 1
  • Thanks 1

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...