Skip to content

Instantly share code, notes, and snippets.

@mauron85
Last active October 21, 2019 18:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mauron85/de2f0c5c4ffb2c459499b16e37ac1a38 to your computer and use it in GitHub Desktop.
Save mauron85/de2f0c5c4ffb2c459499b16e37ac1a38 to your computer and use it in GitHub Desktop.
Serve newest camera jpg snapshot
<?php
define('MIN_HOUR', 6);
define('MAX_HOUR', 18);
define('SNAPSHOT_DIR', 'cam');
define('SNAPSHOT_PATTERN', '/camera[0-9]*_([0-9]+)\.jpg/');
define('SECONDS_TO_CACHE', 660); // 11 minutes
define('PLACEHOLDER_TEXT', 'Stream is over for today. We will be back at 6:00am.');
$now = time();
$currentYear = date('Y', $now);
$currentMonth = date('m', $now);
$currentDay = date('d', $now);
$currentHour = date('G', $now);
$currentMinute = intval(date('i', $now));
if ($currentHour >= MAX_HOUR || $currentHour < MIN_HOUR) {
$lastModifiedTime = mktime(MAX_HOUR, 0, 0, date('n', $now), date('j', $now), date('Y', $now));
$expireTime = mktime(MIN_HOUR, 0, 0, date('n', $now), date('j', $now), date('Y', $now));
if ($currentHour >= MAX_HOUR) {
$expireTime = strtotime('+1 day', $expireTime);
}
if ($currentHour < MIN_HOUR) {
$lastModifiedTime = strtotime('-1 day', $lastModifiedTime);
}
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModifiedTime) . ' GMT');
header('Expires: ' . gmdate('D, d M Y H:i:s', $expireTime) . ' GMT');
header('X-Stream-Status: offline');
show_placeholder(PLACEHOLDER_TEXT);
exit;
}
$dir = realpath(__DIR__) . DIRECTORY_SEPARATOR . SNAPSHOT_DIR
. DIRECTORY_SEPARATOR . $currentYear
. DIRECTORY_SEPARATOR . $currentMonth
. DIRECTORY_SEPARATOR . $currentDay;
// get array of files within $dir, alphabetically sorted descending (newest first)
$files = @scandir($dir, 1);
if ($files === false) {
show_placeholder(PLACEHOLDER_TEXT);
exit(1);
}
// get most recent uploaded image
$image = get_latest_image($files, 60, $now);
if ($image === false) {
show_placeholder(PLACEHOLDER_TEXT);
exit(1);
}
list($file, $fileTimestamp) = $image;
$filePath = $dir . DIRECTORY_SEPARATOR . $file;
$lastModified = gmdate('D, d M Y H:i:s', $fileTimestamp) . ' GMT';
$expire = gmdate('D, d M Y H:i:s', $fileTimestamp + SECONDS_TO_CACHE) . ' GMT';
header('Content-type: image/jpeg');
header('Content-Length: ' . filesize($filePath));
header('Last-Modified: ' . $lastModified);
header('Expires: ' . $expire);
header('Pragma: cache');
readfile($filePath);
function get_latest_image($files, $minAge, $now) {
foreach ($files as $file) {
if (preg_match(SNAPSHOT_PATTERN, $file, $matches) === 1) {
$fileDate = date_create_from_format('YmdHis', $matches[1]);
$fileTimestamp = date_timestamp_get($fileDate);
// make sure file is older than $minAge to prevent serving not fully uploaded images
if (($now - $fileTimestamp) >= $minAge) {
return array($file, $fileTimestamp);
}
}
}
return false;
}
function show_placeholder($text) {
/**
* Dynamic Dummy Image Generator — as seen on DummyImage.com
*
* This script enables you to create placeholder images in a breeze.
* Please refer to the README on how to use it.
*
* (Original idea by Russel Heimlich. When I first published this script,
* DummyImage.com was not Open Source, so I had to write a small script to
* replace the function on my own server.)
*
* @author Fabian Beiner <fb@fabianbeiner.de>
* @license MIT
* @link https://github.com/FabianBeiner/PHP-Dummy-Image-Generator/
* @version 0.3.0 <2017-12-26>
*/
/**
* Handle the “size” parameter.
*/
$size = '640x480';
list($imgWidth, $imgHeight) = explode('x', $size . 'x');
if ($imgHeight === '') {
$imgHeight = $imgWidth;
}
$filterOptions = array(
'options' => array(
'min_range' => 0,
'max_range' => 9999
)
);
if (filter_var($imgWidth, FILTER_VALIDATE_INT, $filterOptions) === false) {
$imgWidth = '640';
}
if (filter_var($imgHeight, FILTER_VALIDATE_INT, $filterOptions) === false) {
$imgHeight = '480';
}
/**
* Handle the “type” parameter.
*/
$type = 'png';
/**
* Handle the “text” parameter.
*/
$encoding = mb_detect_encoding($text, 'UTF-8, ISO-8859-1');
if ($encoding !== 'UTF-8') {
$text = mb_convert_encoding($text, 'UTF-8', $encoding);
}
$text = mb_encode_numericentity($text,
array(0x0, 0xffff, 0, 0xffff),
'UTF-8');
/**
* Handle the “bg” parameter.
*/
$bg = '000000';
list($bgRed, $bgGreen, $bgBlue) = sscanf($bg, '%02x%02x%02x');
/**
* Handle the “color” parameter.
*/
$color = 'FFFFFF';
list($colorRed, $colorGreen, $colorBlue) = sscanf($color, '%02x%02x%02x');
/**
* Define the typeface settings.
*/
$fontFile = realpath(__DIR__) . DIRECTORY_SEPARATOR . 'RobotoMono-Regular.ttf';
if ( ! is_readable($fontFile)) {
$fontFile = 'arial';
}
$fontSize = round(($imgWidth - 50) / 8);
if ($fontSize <= 9) {
$fontSize = 9;
}
/**
* Generate the image.
*/
$image = imagecreatetruecolor($imgWidth, $imgHeight);
$colorFill = imagecolorallocate($image, $colorRed, $colorGreen, $colorBlue);
$bgFill = imagecolorallocate($image, $bgRed, $bgGreen, $bgBlue);
imagefill($image, 0, 0, $bgFill);
$textBox = imagettfbbox($fontSize, 0, $fontFile, $text);
while ($textBox[4] >= $imgWidth) {
$fontSize -= round($fontSize / 2);
$textBox = imagettfbbox($fontSize, 0, $fontFile, $text);
if ($fontSize <= 9) {
$fontSize = 9;
break;
}
}
$textWidth = abs($textBox[4] - $textBox[0]);
$textHeight = abs($textBox[5] - $textBox[1]);
$textX = ($imgWidth - $textWidth) / 2;
$textY = ($imgHeight + $textHeight) / 2;
imagettftext($image, $fontSize, 0, $textX, $textY, $colorFill, $fontFile, $text);
/**
* Return the image and destroy it afterwards.
*/
switch ($type) {
case 'png':
header('Content-Type: image/png');
imagepng($image, null, 9);
break;
case 'gif':
header('Content-Type: image/gif');
imagegif($image);
break;
case 'jpg':
case 'jpeg':
header('Content-Type: image/jpeg');
imagejpeg($image);
break;
}
imagedestroy($image);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment