Imageflow

Optimal images at incredible speeds

Deploy Imageflow

Imageflow

ebfork/imageflow-dotnet-server

Just deployed

/app/imageflow_cache

Serving optimized and correctly sized images is the fastest way to a quicker, more profitable site or app. 60% of website bytes are from images.

Imageflow edits and optimizes images so quickly you can do it on-demand. No need to manually generate every size/format combination of every image.

If you’re using ImageMagick, switch to imageflow_tool and get higher-quality images with smaller file sizes — up to 17x faster.

Most people prefer on-demand image processing, as it greatly simplifies web development.

Deploying

Imageflow can be accessed at /u/. Images must be signed to avoid processing for non-customers. Images can be signed using the following procedure:

  1. URLSafe base64 encode the image url (remove trailing =s)
  2. Using a HMAC encoder with SHA-256, encode the result of your base64 encoder using the following procedure:
public static string SignString(string data, string key, int signatureLengthInBytes) {
      if (signatureLengthInBytes < 1 || signatureLengthInBytes > 32) throw new ArgumentOutOfRangeException(nameof(signatureLengthInBytes));
     HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
     byte[] hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
     byte[] shorterHash = new byte[signatureLengthInBytes];
     Array.Copy(hash, shorterHash, signatureLengthInBytes);
     return EncodingUtils.ToBase64U(shorterHash);
}
  1. get the file extension of the original url
  2. combine them: base64url.signature.extension

See available transforms and filtering here

here is a complete implementation in c#:

using Imazen.Common.Helpers;
using System;
using System.Collections.Generic;
using System.IO;

public class Program
{
	public static void Main()
	{
		Console.Write(String.Join(".",EncodeAndSignUrl("image url", "key").ToArray()));
	}
	private static string SanitizeImageExtension(string extension)
	{
		extension = extension.ToLowerInvariant().TrimStart('.');
		switch (extension)
		{
			case "png":
				return "png";
			case "gif":
				return "gif";
			case "webp":
				return "webp";
			case "jpeg":
			case "jfif":
			case "jif":
			case "jfi":
			case "jpe":
				return "jpg";
			default:
				return null;
		}
	}

	public static List EncodeAndSignUrl(string url, string key)
	{
		var uri = new Uri(url);
		var path = uri.AbsolutePath;
		var extension = Path.GetExtension(path);
		var sanitizedExtension = SanitizeImageExtension(extension) ?? "jpg";
		var data = EncodingUtils.ToBase64U(url);
		var sig = Signatures.SignString(data, key, 8);
		var e = new List()
		{
			data,
			sig,
			sanitizedExtension
		};
		return e;
	}
}

Template Content

More templates in this category

View Template

ReadySet

A lightweight caching engine for Postgres


View Template

Flare

A modern, lightning-fast file sharing platform built for self-hosting


View Template

EdgeDB

EdgeDB template based on their Docker deployment guide