<?php
class Album {
public function __construct($album, $images, $fish) {
$this->name = $album;
$this->title = PRETTYTITLES === true ? makePrettyTitle($album) : $album;
$this->title = $album;
foreach ($images as $image) {
if (is_dir($image)) continue;
$baseimg = basename($image);
$imgname = strip_ext($baseimg);
if (is_readable("$album/thumbs/$imgname.png") || isValidImage($image)) $this->images[] = $baseimg;
}
$this->imagecount = count($this->images);
if (!$fish || $fish === $album) $this->addCaptions($album);
if (is_array($GLOBALS['passwords']) && $GLOBALS['passwords'][$album]) $this->password = $GLOBALS['passwords'][$album];
}
public function addCaptions($album) {
$file = @file($album . '/' . $album . '.txt', FILE_SKIP_EMPTY_LINES);
if ($file) {
foreach ($file as $line) {
$bits = parseLine($line);
if ($bits) $data[$bits[0]] = $bits[1];
}
}
foreach ((array)$this->images as $image) { // cast to array if $this->images is empty to stop foreach throwing an error
if ($data[$image]) $this->captions[$image] = ampquot($data[$image]);
elseif (FNORD === true) $this->captions[$image] = $GLOBALS['fnord']->fnord();
else $this->captions[$image] = $image;
}
}
}
class Shampoo {
public function __construct($fish) {
$this->title = $GLOBALS['title'];
$ignore = $GLOBALS['folderstoignore'];
$albums = glob("*", GLOB_ONLYDIR);
if (is_array($ignore)) $albums = array_diff($albums, $ignore);
if (!in_array($fish, $albums)) unset($fish);
foreach ($albums as $album) {
if (is_readable($album)) {
$this->albumlist[] = $album;
$images = (array)glob("$album/*.*");
if ($fish === $album && !$images) unset($fish);
$this->$album = new Album($album, $images, $fish);
}
}
if ($fish && $this->$fish && $this->$fish->imagecount > 0) $this->album = $fish;
else unset($fish);
if (is_readable(INDEX)) {
foreach (file(INDEX, FILE_SKIP_EMPTY_LINES) as $line) {
$bits = parseLine($line);
if ($bits && $bits[0] && $this->$bits[0]) {
$this->$bits[0]->title = $bits[1] ? trim(htmlspecialchars($bits[1], ENT_COMPAT)) : trim($bits[0]);
$this->$bits[0]->description = ampquot(trim($bits[2]));
}
}
}
switch(SORTBY) {
case 'title': usort($this->albumlist, array($this, 'titleSort')); break;
case 'name': sort($this->albumlist); break;
case 'date': usort($this->albumlist, 'dateSort'); break;
}
}
public function makeMenu() {
foreach ($this->albumlist as $album) {
$html .= ' <li><a href="' . $album . '/"';
if ($this->album === $album) $html .= ' class="current"';
$pic = $this->$album->imagecount === 1 ? 'picture' : 'pictures';
$html .= ' title="' . $this->$album->imagecount . $pic . '">' . $this->$album->title;
if ($this->$album->password && !$_SESSION['access'][$album]) $html .= ' <img src="img/lock.gif" width="8" height="10" title="Private album - you will be asked for a password" alt="(Private)">';
$html .= "</a></li>\n";
}
$this->register_var('albumlist', ltrim($html));
}
public function showList() {
$this->register_var('content', (string)$GLOBALS['toptext'] . "\n <ul id=\"albumarray\">\n");
$listcount = 0;
foreach ($this->albumlist as $key => $album) {
if ($this->$album->password && !$_SESSION['access'][$album]) continue;
$icount = $this->$album->imagecount;
$desc = $this->$album->description;
$images = (array)$this->$album->images; // cast to array so shuffle won't fail on this being null if no images in album
$title = $this->$album->title;
if (RANDOM === true) shuffle($images);
$cls = $listcount % 2 ? ' class="odd"' : '';
$listcount++;
$howmany = $icount === 1 ? 'One picture' : "$icount pictures";
$buff = " <li$cls>
<h3><a href=\"{$this->$album->name}/\" title=\"Open $title\">$title <span>» Open album</span></a></h3>
<p class=\"imagecount\">$howmany</p>\n";
if ($icount > 0) {
$buff .= " <div>\n";
$classextra = '';
foreach ($images as $key => $image) {
$caption = $this->$album->captions[$image];
$imgname = strip_ext($image);
$thumbpath = "$album/thumbs/$imgname.png";
if (!file_exists($thumbpath) && !createThumb($album, $image)) continue;
$title = htmlspecialchars(strip_tags($caption), ENT_COMPAT, 'UTF-8');
if ($key > 3) $classextra = ' thumbhide';
$size = @getimagesize($thumbpath);
$buff .= ' <a href="' . "$album/" . fakeUrl($image) . '" title="' . $title . '" rel="' . $album . '" class="thickbox' . $classextra . '"><img src="' . $thumbpath . '" alt="' . truncate($title) . '" ' . $size[3] . "></a>\n <p>$caption</p>\n";
if ($key === PERALBUM - 1) break;
}
$buff .= " </div>\n";
}
else $buff .= " <p>This album is devoid of images!</p>\n";
if (DESCRIPTIONS === true && $desc) {
$c = strlen($desc) > 750 ? ' class="columnar"' : '';
$buff .= " <p$c>$desc</p>\n";
}
$this->register_var('content', $buff . " </li>\n");
}
$this->register_var('content', " </ul>\n");
}
public function albumate($fish) {
$album = $this->album;
if ($this->$album->password) {
if ($_POST['password']) {
if (!$_SESSION['access']) $_SESSION['access'] = array();
if ($_POST['password'] === $this->$album->password) $_SESSION['access'][$album] = true;
else $pass = false;
}
if (!$_SESSION['access'][$album]) {
$this->makeHeadLink('up', './', 'List of albums');
$this->register_var('header', '<a href="./" title="Front page">' . $this->title . '</a> » ' . $this->{$this->album}->title);
$html = " <form action=\"$album/\" method=\"post\" id=\"blockade\">\n";
if ($pass === false) $html .= ' <p class="error">Wrong password entered. Please note it is case sensitive.</p>'."\n";
$html .= " <p>This is a private album. To see it you must enter a password.</p>\n <label>Password: <input type=\"password\" name=\"password\"></label>\n <input value=\"Go\" type=\"submit\">\n </form>\n";
$this->register_var('content', $html);
return;
}
}
$icount = $this->$album->imagecount;
if ($_POST['imageno'] && is_numeric($_POST['imageno'])) {
if ($_POST['imageno'] <= $icount) {
header('Location:' . BASE . $this->album . '/' . fakeUrl($this->$album->images[$_POST['imageno'] - 1]));
}
}
$this->makeHeadLink('top', './', 'List of albums');
$desc = $this->$album->description;
$howmany = $icount > 1 ? "$icount pictures" : 'One picture';
$this->register_var('content', "<p class=\"imagecount\">$howmany</p>\n");
if ($desc) {
if (strlen($desc) > 350) $c = ' class="columnar"';
$this->register_var('content', " <p$c>$desc</p>\n");
}
if (is_numeric($fish[1]) || empty($fish[1])) $this->thumbView((int)$fish[1]);
else $this->singleImageView($fish[1]);
$this->gen($fish[1]);
}
public function thumbView($page) {
$this->makeHeadLink('up', './', 'List of albums');
$this->register_var('header', '<a href="./" title="Front page">' . $this->title . '</a> » ' . $this->{$this->album}->title);
$this->options = $GLOBALS['options'];
$ppp = $_POST['perpage'];
$spp = $_SESSION['perpage'];
$scpp = $_SESSION['customperpage'];
$this->oldtoshow = $this->toshow = $spp ? ($spp === 'custom' && $scpp ? $scpp : $spp) : DEFAULTTHUMBS;
if ($ppp && in_array($ppp, $this->options)) {
if ($ppp === 'custom') {
$pcpp = (int)$_POST['customperpage'];
if (!in_array($pcpp, $this->options) && $pcpp > 0) {
$_SESSION['perpage'] = $ppp;
$this->toshow = $_SESSION['customperpage'] = $pcpp;
}
elseif ($pcpp > 0) {
$this->toshow = $_SESSION['perpage'] = $pcpp;
unset($_SESSION['customperpage']);
}
}
else $this->toshow = $_SESSION['perpage'] = (int)$ppp;
}
if ($this->toshow < 1) $this->toshow = DEFAULTTHUMBS;
$this->pages = (int)ceil($this->{$this->album}->imagecount / $this->toshow);
$page = min(max($page, 1), $this->pages);
$this->startmark = $this->oldtoshow * ($page - 1);
$this->currentpage = (int)ceil($this->startmark / $this->toshow) + 1;
$this->startmark = $this->toshow * ($this->currentpage - 1);
$this->endmark = min($this->{$this->album}->imagecount, $this->startmark + $this->toshow);
$this->options();
if ($this->currentpage > 1) {
$this->makePageNavLink('prev', $this->currentpage-1);
$this->makeHeadLink('first', $this->album . '/1/', 'First page of thumbs');
$this->makeHeadLink('prev', $this->album . '/' . $this->currentpage-1 . '/', 'Page '. ($this->currentpage-1));
}
if ($this->currentpage < $this->pages) {
$this->makePageNavLink('next', $this->currentpage+1, $this->pages);
$this->makeHeadLink('next', $this->album . '/' . $this->currentpage+1 . '/', 'Page '. ($this->currentpage+1));
$this->makeHeadLink('last', $this->album . '/' . $this->pages . '/', 'Last page of thumbs');
}
$buff = ' <ul id="thumbarray">' . "\n";
for ($i = $this->startmark; $i < $this->endmark ; $i++) {
$image = $this->{$this->album}->images[$i];
$imgsrc = $this->album . '/thumbs/' . strip_ext($image) . '.png';
if (!is_file($imgsrc) && !createThumb($this->album, $image)) continue;
$buff .= " <li> \n <a href=\"" . $this->album . '/' . fakeUrl($image) . '"';
$caption = $this->{$this->album}->captions[$image];
$title = strip_tags($caption);
$alt = truncate($title);
$caption = truncate($caption);
$size = @getimagesize($imgsrc);
$buff .= ' class="thickbox" title="' . $title . '">
<span><img src="' . $imgsrc . "\" alt=\"$alt\" $size[3]></span>
<span class=\"caption\">$caption</span>\n";
$datetime = getExif($this->album . "/$image", true);
if ($datetime) $buff .= " <span class=\"exif\">Taken $datetime</span>\n";
$buff .= " </a> \n";
$buff .= " </li> \n";
}
$this->register_var('content', $buff . ' </ul>' . "\n");
}
public function options() {
$buff = ' <div id="bar">' . "\n";
$imagecount = $this->{$this->album}->imagecount;
if ($this->pages > 1) {
$buff .= " <span><strong> </strong>Page</span>\n <div>\n <ol";
if ($this->pages > 9) $buff .= ' class="doubledigits"';
$buff .= ">\n";
for ($i = 1; $i <= $this->pages; $i++) {
$c = $i === $this->currentpage ? ' class="current"' : '';
$buff .= " <li$c><a href=\"{$this->album}/$i/\">$i</a></li>\n";
}
$buff .= " </ol>\n </div>\n";
$info = $this->startmark + 1 === $imagecount ? "<strong>the last lonely image</strong>" : (strval($this->toshow) === "1" ? "image <strong>" . ($this->starmark + 1) . "</strong>" : "images <strong>" . ($this->startmark + 1) . "</strong> to <strong>{$this->endmark}</strong>");
$buff .= " <span>of <strong>{$this->pages}</strong> showing $info</span>\n";
}
else {
$buff .= ' <span>';
if ($imagecount === 1) $buff .= 'The one and only image in this album';
else $buff .= "All <strong>$imagecount</strong> images displayed";
$buff .= "</span>\n";
}
$buff .= ' <form method="post" action="' . "{$this->album}/{$this->currentpage}/\">
<fieldset>
<legend>Settings</legend>\n";
$buff .= ' <label for="perpage">Thumbs per page:</label>
<select name="perpage" id="perpage"';
if ($_SESSION['perpage'] === 'custom') $buff .= ' class="custom"';
$buff .= '>' . "\n";
foreach ($this->options as $o) {
if ($o === 'custom') continue;
$buff .= " <option value=\"$o\"";
$perpage = in_array($this->toshow, $this->options) ? $this->toshow : 'custom';
$buff .= (string)$o === (string)$perpage ? ' selected="selected">' : '>';
$buff .= $o;
$buff .= "</option>\n";
}
$buff .= ' </select>' . "\n";
if ((string)$perpage === 'custom') $buff .= ' <input type="text" maxlength="3" value="'.$_SESSION['customperpage'].'" name="customperpage">' . "\n";
$buff .= ' <input type="image" src="img/right.png" alt="Go">
</fieldset>
</form>
</div>' . "\n";
$this->register_var('content', $buff);
}
public function makePageNavLink($dir, $index, $pages = false) {
if (!$pages) {
$anchortitle = $index > 1 ? 'Previous' : 'First';
$anchortitle .= " {$this->toshow} images";
}
else {
if ($index === $pages) {
$dregs = $this->{$this->album}->imagecount - ($this->toshow * $index + 1);
$anchortitle = $dregs > 1 ? "Last $dregs images" : "Last page, last image";
}
else $anchortitle = "Next {$this->toshow} images";
}
if ($index > 9) $nd = ' doubledigits';
$buff = ' <div class="pagination ' . $dir . $nd . '">
<a href="' . $this->album . '/' . $index . '/" title="' . $anchortitle . '">' . "\n";
while ($s++ < 2) {
if ($s === 2) $dir = 'page';
$buff .= " <span>";
foreach (str_split($dir) as $letter) $buff .= "<span>$letter</span>";
$buff .= "</span>\n";
}
$this->register_var('content', $buff . " </a>\n <a href=\"{$this->album}/$index/\">$index</a>\n </div>\n");
}
public function singleImageView($image) {
$images = $this->{$this->album}->images;
$captions = $this->{$this->album}->captions;
$imagecount = $this->{$this->album}->imagecount;
$albumname = $this->{$this->album}->name;
$this->makeHeadLink('up', $albumname . '/', $this->{$this->album}->title);
$this->register_var('header', '<a href="./" title="Front page">' . $this->title . '</a> » <a href="' . $albumname . '/">' . $this->{$this->album}->title . '</a>');
$current = $image ? (int)array_search(realUrl($image), $images) : 0;
$buff = " <div id=\"view\">\n";
$buff .= " <form action=\"{$_SERVER['REQUEST_URI']}/\" method=\"post\">\n <fieldset>\n <legend>Browse by position</legend>\n <label>Go to # <input type=\"text\" name=\"imageno\"> / $imagecount</label>\n <input type=\"image\" src=\"img/right.png\" alt=\"Go\"> </fieldset>\n </form>\n";
$buff .= " <p>\n";
if ($current > 0) {
$this->makeHeadLink('first', $albumname . '/' . fakeUrl($images[0]), ampquot(strip_tags($captions[$images[0]])));
$this->makeHeadLink('prev', $albumname . '/' . fakeUrl($images[$current-1]), ampquot(strip_tags($captions[$images[$current-1]])));
$buff .= ' <a href="' . $this->album . '/' . fakeUrl($images[$current-1]) . '" title="' . strip_tags($captions[$images[$current-1]]) . "\">« Prev</a>\n";
}
$buff .= " Image " . ($current + 1) . " of $imagecount\n";
if ($current < $imagecount - 1) {
$this->makeHeadLink('next', $this->album . '/' . fakeUrl($images[$current+1]), ampquot(strip_tags($captions[$images[$current+1]])));
$this->makeHeadLink('last', $this->album . '/' . fakeUrl($images[$imagecount-1]), ampquot(strip_tags($captions[$images[$imagecount-1]])));
$buff .= ' <a href="' . $this->album . '/' . fakeUrl($images[$current+1]) . '" title="' . strip_tags($captions[$images[$current+1]]) . "\">Next »</a>\n";
}
$buff .= " </p>\n";
$size = getimagesize($this->album . '/' . $images[$current]);
$buff .= ' <img src="' . $this->album . '/' . $images[$current] . '" alt="' . strip_tags($captions[$images[$current]]) . '" ' . $size[3] . '>' . "\n";
if (EXIF === true) {
$exifdata = getExif($this->album . '/' . $images[$current], false);
if ($exifdata) {
$buff .= ' <div class="exif">' . "\n" .
' <h4>EXIF data</h4>' . "\n" .
" <dl>\n";
foreach ($exifdata as $label => $value) {
$buff .= " <dt>$label:</dt>\n" .
" <dd>$value</dd>\n";
}
$buff .= " </dl>\n" .
" </div>\n";
}
}
$buff .= ' <p class="caption">' . $captions[$images[$current]] . '</p>
<div class="thumbs">
<ul>' . "\n";
for ($i = max($current-2, 0), $j = min($current+3, $imagecount); $i < $j; $i++) {
$image = $images[$i];
$imgname = strip_ext($image);
$imagehref = fakeUrl($image);
$actclass = $i === $current ? ' class="active"' : null;
$title = strip_tags($captions[$image]);
$buff .= " <li$actclass>
<a href=\"" . $this->album . "/$imagehref\" title=\"$title\"><img src=\"" . $this->album . "/thumbs/$imgname.png\" alt=\"" . truncate($title) . "\"></a>
<span>".($i+1)."</span>
</li>\n";
}
$this->register_var('content', $buff . " </ul>\n </div>\n </div>\n");
$this->addBodyClass($_SESSION['topbit']);
}
public function randomImage($album) {
if (!$album || !$this->$album) {
$album = $this->albumlist;
shuffle($album);
$album = $album[0];
}
$images = $this->$album->images;
shuffle($images);
$thumb = $album . '/thumbs/' . strip_ext($images[0]) . '.png';
return array("$album/{$images[0]}", $thumb, $this->$album->captions[$images[0]], $album, $this->$album->title, $images[0]);
}
public function titleSort($a, $b) {
return $this->$a->title > $this->$b->title ? 1 : -1;
}
public function gen() {
if (!$this->album) return;
if ($this->currentpage && $this->currentpage !== $_SESSION['oldcurrentpage']) {
$_SESSION['oldcurrentpage'] = $this->currentpage;
$this->addHeadCSS("#bar div:hover ol {\n top:-".(($this->currentpage - 1) * 1.3)."em;\n}");
}
if (filemtime('settings.php') > SETTINGSFILEMTIME + 1) {
$buffer .= "ul#thumbarray li a span {\n width:".(TMAXWIDTH)."px;\n height:".TMAXHEIGHT."px;\n line-height:".TMAXHEIGHT."px;\n}\n";
$buffer .= "ul#thumbarray li a span.caption {\n width:".(TMAXWIDTH + 24)."px;\n}\n";
$buffer .= "#view .thumbs ul li a {\n height:".(TMAXHEIGHT + 30)."px;\n line-height:".(TMAXHEIGHT + 30)."px;\n}\n";
$settings = file_get_contents('settings.php');
$settings = preg_replace("/define\('SETTINGSFILEMTIME', \d+/", "define('SETTINGSFILEMTIME', " . time(), $settings);
file_put_contents('settings.php', $settings);
}
if (!empty($buffer)) {
$css = file_get_contents('shampoo.css');
file_put_contents('shampoo.css' , substr($css, 0, strpos($css, '/* GENERATED STUFF */', filesize('shampoo.css') - 300)) . "/* GENERATED STUFF */\n" . $buffer);
$this->register_var('cssfilemtime', '?' . time());
}
}
public function addHeadCSS($css) {
$curcss = $this->cache['headCSS'];
if ($curcss) {
$curcss = str_replace('<style type=\"text/css\">', '', $curcss);
$curcss = str_replace('</style>', '', $curcss);
$curcss = "\n " . trim($curcss);
}
$css = str_replace("\n", "\n ", $css);
$curcss = " <style type=\"text/css\">$curcss\n $css\n </style>\n";
$this->register_var('headCSS', $curcss);
}
public function addBodyClass($class) {
if (!$class) return;
$cur = trim($this->cache['bodyclass'], '"');
if (!$cur) $cur = ' class="' . $class . '"';
else $cur .= " $class\"";
$this->register_var('bodyclass', $cur, true);
}
public function makeHeadLink($rel, $href, $title) {
$this->register_var('links', " <link rel=\"$rel\" href=\"$href\" title=\"$title\">\n");
}
public function register_var($name, $value, $overwrite = false) {
if ($overwrite) $this->cache[$name] = $value;
else $this->cache[$name] .= $value;
}
public function output() {
$template = file_get_contents('shampoo.inc') or exit('<br><b>Script stopped</b>: Check that the template file exists (default name is shampoo.inc) and that it is in the right directory (the same one as index.php)');
$r = preg_match_all('/{(\w+)}/', $template, $matches);
foreach ($matches[1] as $match) {
$template = str_replace("{{$match}}", rtrim($this->cache[$match]), $template);
}
$template = preg_replace("/\n\s*\n/m", "\n", $template);
echo utf8_encode($template);
}
}
/* FUNCTIONS */
function makePrettyTitle($title) {
$title = preg_split('/[\s+\-_]+/', trim(htmlspecialchars($title, ENT_COMPAT, 'UTF-8')));
foreach ($title as $k => $t) {
$title[$k] = ucfirst($t);
}
return implode(' ', $title);
}
function ampquot($str) {
return str_replace(array('&', '"'), array('&', '"'), $str);
}
function dateSort($a, $b) {
return filemtime($a) < filemtime($b) ? 1 : -1;
}
function truncate($string) {
if (strlen($string) > 70) return array_shift(explode("\n", wordwrap($string, 70))) . '...';
return $string;
}
function isValidImage($image) {
if (strrchr($image, '.') === '.txt') return false;
$a = @getimagesize($image);
if (($a[2] > 0 && $a[2] < 4) || strpos($image, 'bmp') > 0) return true;
}
function parseLine($line) {
$line = utf8_decode(ltrim($line, "\xef\xbb\xbf")); // BOM must be removed, otherwise first line gets skipped
if (strpos($line, "//") === 0) return false;
return array_map('trim', explode("|", $line));
}
function realUrl($url) {
return substr_replace($url, '.', strrpos($url, '_'), 1);
}
function fakeUrl($url) {
return substr_replace($url, '_', strrpos($url, '.'), 1);
}
function strip_ext($str) {
return substr($str, 0, strrpos($str, '.'));
}
function createThumb($album, $img) {
$imgname = strip_ext($img);
if (!is_dir("$album/thumbs")) {
mkdir("$album/thumbs");
}
if (strpos($img, ' ') > -1) {
$oldimg = $img;
$img = str_replace(' ', '_', trim($img));
$res = rename("$album/$oldimg", "$album/$img");
if ($res !== true) $img = $oldimg;
}
$img = "$album/$img";
list($width, $height, $type) = @getimagesize($img);
if ($width === false) return log_error("$img isn't a valid image or it doesn't exist");
if (TMAXWIDTH < $width && $width >= $height) {
$thumbwidth = TMAXWIDTH;
$thumbheight = ($thumbwidth / $width) * $height;
}
elseif (TMAXHEIGHT < $height && $height >= $width) {
$thumbheight = TMAXHEIGHT;
$thumbwidth = ($thumbheight /$height) * $width;
}
else {
$thumbheight = $height;
$thumbwidth = $width;
}
$imgbuffer = imagecreatetruecolor($thumbwidth, $thumbheight);
switch($type) {
case 1: $image = imagecreatefromgif($img); break;
case 2: $image = imagecreatefromjpeg($img); break;
case 3: $image = imagecreatefrompng($img); break;
case 6: $image = imagecreatefrombmp($img); break;
case 15: $image = imagecreatefromwbmp($img); break;
default: return log_error("Tried to create thumbnail from $img: not a valid image");
}
if (!$image) return log_error("Image creation from $img failed for an unknown reason. Probably not a valid image.");
else {
imagecopyresampled($imgbuffer, $image, 0, 0, 0, 0, $thumbwidth, $thumbheight, $width, $height);
$output = imagepng($imgbuffer, "$album/thumbs/$imgname.png", 9);
imagedestroy($imgbuffer);
return $output;
}
}
function getExif($image, $onlydatetime) {
$ex = @exif_read_data($image, 0);
if ($ex === false) return false;
if ($ex['DateTimeOriginal']) {
list($date, $time) = explode(' ', $ex['DateTimeOriginal']);
$datetime = date("j M Y", strtotime(str_replace(":", "/", $date))) . ', ' . substr($time, 0, 5);
if (!$onlydatetime) $exifdata['Taken'] = $datetime;
}
if ($onlydatetime) return $datetime;
if ($ex['Width']) $exifdata['Width'] = $ex['Width'];
if ($ex['Height']) $exifdata['Height'] = $ex['Height'];
if ($ex['Make'] || $ex['Model']) {
if (strpos($ex['Model'], $ex['Make']) === 0) $exifdata['Camera'] = $ex['Model'];
else {
if ($ex['Make']) $exifdata['Make'] = $ex['Make'];
if ($ex['Model']) $exifdata['Model'] = $ex['Model'];
}
}
if ($ex['ExposureTime']) {
$z = explode('/', $ex['ExposureTime']);
if ($z[0] / $z[1] < 1) $exifdata['Exposure Length'] = sprintf('1/%d sec.', $z[1] / $z[0]);
else $exifdata['Exposure Length'] = sprintf('%d sec.', $z[0] / $z[1]);
}
if ($ex['FocalLength']) {
$z = explode('/', $ex['FocalLength']);
$exifdata['Focal Length'] = sprintf('%.1f mm', $z[0] / $z[1]);
}
if ($ex['COMPUTED']['ApertureFNumber'] || $ex['ApertureFNumber'] || $ex['FNumber']) {
if ($ex['COMPUTED']['ApertureFNumber']) $exifdata['Aperture'] = $ex['COMPUTED']['ApertureFNumber'];
else {
$z = $ex['FNumber'] || $ex['ApertureFNumber'];
$z = explode('/', $z);
$exifdata['Aperture'] = sprintf('f/%.01f', pow(2, $z[0] / $z[1] / 2));
}
}
if ($ex['ISOSpeedRatings']) {
$exifdata['ISO Speed'] = $ex['ISOSpeedRatings'];
}
if ($ex['Flash']) {
switch($ex['Flash']) {
case 0x0000:
case 0x0010:
case 0x0018:
case 0x0020:
case 0x0058: $exifdata['Flash'] = 'Not fired'; break;
default: $exifdata['Flash'] = 'Fired';
}
}
return count($exifdata) > 0 ? $exifdata : false;
}
function imagecreatefrombmp($filename) { // Written by D H Kold (dhkold.com)
if (!$handle = fopen($filename, "rb")) return false; //Open file in binary mode
//1 : Load file headers
$file = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($handle, 14));
if ($file['file_type'] != 19778) return false;
//2 : Load BMP headers
$bmp = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'.
'/Vcompression/Vsize_bitmap/Vhoriz_resolution'.
'/Vvert_resolution/Vcolors_used/Vcolors_important', fread($handle, 40));
$bmp['colors'] = pow(2, $bmp['bits_per_pixel']);
if ($bmp['size_bitmap'] == 0) $bmp['size_bitmap'] = $file['file_size'] - $file['bitmap_offset'];
$bmp['bytes_per_pixel'] = $bmp['bits_per_pixel']/8;
$bmp['bytes_per_pixel2'] = ceil($bmp['bytes_per_pixel']);
$bmp['decal'] = ($bmp['width']*$bmp['bytes_per_pixel'] / 4);
$bmp['decal'] -= floor($bmp['width'] * $bmp['bytes_per_pixel'] / 4);
$bmp['decal'] = 4 - (4 * $bmp['decal']);
if ($bmp['decal'] == 4) $bmp['decal'] = 0;
//3 : Load palette colours
if ($bmp['colors'] < 16777216) {
$palette = unpack('V' . $bmp['colors'], fread($handle, $bmp['colors']*4));
}
//4 : Image creation
$img = fread($handle, $bmp['size_bitmap']);
$vide = chr(0);
$res = imagecreatetruecolor($bmp['width'], $bmp['height']);
$p = 0;
$y = $bmp['height'] - 1;
while ($y >= 0) {
$x = 0;
while ($x < $bmp['width']) {
if ($bmp['bits_per_pixel'] == 24)
$color = unpack("V", substr($img, $p, 3) . $vide);
elseif ($bmp['bits_per_pixel'] == 16) {
$color = unpack("n", substr($img, $p, 2));
$color[1] = $palette[$color[1]+1];
}
elseif ($bmp['bits_per_pixel'] == 8) {
$color = unpack("n", $vide . substr($img, $p, 1));
$color[1] = $palette[$color[1] + 1];
}
elseif ($bmp['bits_per_pixel'] == 4) {
$color = unpack("n", $vide . substr($img, floor($p), 1));
if (($p * 2) % 2 == 0) $color[1] = ($color[1] >> 4) ;
else $color[1] = ($color[1] & 0x0F);
$color[1] = $palette[$color[1] + 1];
}
elseif ($bmp['bits_per_pixel'] == 1) {
$color = unpack("n", $vide . substr($img, floor($p), 1));
if (($p*8)%8 == 0) $color[1] = $color[1] >>7;
elseif (($p*8)%8 == 1) $color[1] = ($color[1] & 0x40)>>6;
elseif (($p*8)%8 == 2) $color[1] = ($color[1] & 0x20)>>5;
elseif (($p*8)%8 == 3) $color[1] = ($color[1] & 0x10)>>4;
elseif (($p*8)%8 == 4) $color[1] = ($color[1] & 0x8)>>3;
elseif (($p*8)%8 == 5) $color[1] = ($color[1] & 0x4)>>2;
elseif (($p*8)%8 == 6) $color[1] = ($color[1] & 0x2)>>1;
elseif (($p*8)%8 == 7) $color[1] = ($color[1] & 0x1);
$color[1] = $palette[$color[1]+1];
}
else return false;
imagesetpixel($res, $x, $y, $color[1]);
$x++;
$p += $bmp['bytes_per_pixel'];
}
$y--;
$p += $bmp['decal'];
}
fclose($handle);
return $res;
}
function log_error($error) {
file_put_contents('errors.log', $error . "\r\n", FILE_APPEND);
return false;
}
?>