<?php
/*
* buzzword
* Copyright (c) 2003 Jon Tai
*
* $Id: image.inc,v 1.21 2004/03/06 05:51:10 jon Exp $
*
* This file is part of buzzword.
*
* buzzword is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* buzzword is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with buzzword; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* returns all gallery images with parent $parent
*
* images are ordered by path ASC
*/
function get_gallery_images($parent) {
$images = array();
$parent = (int) $parent;
$sql = 'SELECT image_key ';
$sql .= 'FROM '.DB_PREFIX.'gallery_images ';
$sql .= "WHERE parent = $parent ";
if (!defined('ADMIN_LOGGED_IN')) {
$sql .= "AND is_private = 'N' ";
$sql .= "AND is_hidden = 'N' ";
}
$sql .= 'ORDER BY path ASC ';
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result)) {
$image = new gallery_image($row['image_key']);
if ( ($image->exists()) && ($image->is_accessible) && ($image->is_visible) )
$images[] = $image;
}
return $images;
}
function get_next_gallery_image($image) {
$parent = $image->parent->gallery_key;
$path = mysql_quote_string(basename($image->path));
$sql = 'SELECT image_key ';
$sql .= 'FROM '.DB_PREFIX.'gallery_images ';
$sql .= "WHERE parent = $parent ";
$sql .= "AND path > $path ";
if (!defined('ADMIN_LOGGED_IN')) {
$sql .= "AND is_private = 'N' ";
$sql .= "AND is_hidden = 'N' ";
}
$sql .= 'ORDER BY path ASC ';
$sql .= 'LIMIT 1';
$result = mysql_query($sql);
$row = mysql_fetch_assoc($result);
return ($row) ? new gallery_image($row['image_key']) : FALSE;
}
function get_prev_gallery_image($image) {
$parent = $image->parent->gallery_key;
$path = mysql_quote_string(basename($image->path));
$sql = 'SELECT image_key ';
$sql .= 'FROM '.DB_PREFIX.'gallery_images ';
$sql .= "WHERE parent = $parent ";
$sql .= "AND path < $path ";
if (!defined('ADMIN_LOGGED_IN')) {
$sql .= "AND is_private = 'N' ";
$sql .= "AND is_hidden = 'N' ";
}
$sql .= 'ORDER BY path DESC ';
$sql .= 'LIMIT 1';
$result = mysql_query($sql);
$row = mysql_fetch_assoc($result);
return ($row) ? new gallery_image($row['image_key']) : FALSE;
}
class gallery_image {
function gallery_image($image_key) {
$this->image_key = (int) $image_key;
$row = get_record('gallery_image', $this->image_key);
if (!$row) {
$sql = 'SELECT is_private, is_hidden, title, description, path, parent, orientation ';
$sql .= 'FROM '.DB_PREFIX.'gallery_images ';
$sql .= "WHERE image_key = {$this->image_key} ";
$result = mysql_query($sql);
$row = mysql_fetch_assoc($result);
mysql_free_result($result);
if ($row)
cache_record('gallery_image', $this->image_key, $row);
}
$this->exists = is_array($row);
$this->is_private = ($row) ? ($row['is_private'] == 'Y') : FALSE;
$this->is_hidden = ($row) ? ($row['is_hidden'] == 'Y') : FALSE;
$this->title = ($row) ? $row['title'] : 'image';
$this->description = ($row) ? $row['description'] : '';
$this->path = ($row) ? $row['path'] : '';
$this->parent = ($row) ? $row['parent'] : 0;
$this->orientation = ($row) ? $row['orientation'] : 0;
$this->is_accessible = (defined('ADMIN_LOGGED_IN')) ? TRUE : !$this->is_private;
$this->is_visible = (defined('ADMIN_LOGGED_IN')) ? TRUE : !$this->is_hidden;
// inherit parents' permissions
$this->parent = new gallery_gallery($this->parent);
$this->path = $this->parent->path.'/'.$this->path;
if (!$this->parent->is_accessible)
$this->is_accessible = FALSE;
}
function create() {
$image_key = $this->image_key;
$is_private = mysql_quote_string(($this->is_private) ? 'Y' : 'N');
$is_hidden = mysql_quote_string(($this->is_hidden) ? 'Y' : 'N');
$title = mysql_quote_string($this->title);
$description = mysql_quote_string($this->description);
$path = mysql_quote_string(basename($this->path));
$parent = $this->parent->gallery_key;
$orientation = $this->orientation;
$sql = 'INSERT INTO '.DB_PREFIX.'gallery_images ';
$sql .= '(image_key, is_private, is_hidden, title, description, path, parent, orientation) VALUES ';
$sql .= "($image_key, $is_private, $is_hidden, $title, $description, $path, $parent, $orientation)";
mysql_query($sql);
$this->exists = TRUE;
cache_relevance_keywords('gallery_image', $this->image_key, get_relevance_keywords(strtoupper($this->title).'.'.$this->title.'.'.$this->description));
flush_record('gallery_image', $this->image_key);
}
function update() {
$image_key = $this->image_key;
$is_private = mysql_quote_string(($this->is_private) ? 'Y' : 'N');
$is_hidden = mysql_quote_string(($this->is_hidden) ? 'Y' : 'N');
$title = mysql_quote_string($this->title);
$description = mysql_quote_string($this->description);
$path = mysql_quote_string(basename($this->path));
$parent = $this->parent->gallery_key;
$orientation = $this->orientation;
$sql = 'UPDATE '.DB_PREFIX.'gallery_images SET ';
$sql .= "is_private = $is_private, ";
$sql .= "is_hidden = $is_hidden, ";
$sql .= "title = $title, ";
$sql .= "description = $description, ";
$sql .= "path = $path, ";
$sql .= "parent = $parent, ";
$sql .= "orientation = $orientation ";
$sql .= "WHERE image_key = $image_key";
mysql_query($sql);
cache_relevance_keywords('gallery_image', $this->image_key, get_relevance_keywords(strtoupper($this->title).'.'.$this->title.'.'.$this->description));
flush_record('gallery_image', $this->image_key);
}
function destroy() {
$sql = 'DELETE FROM '.DB_PREFIX.'gallery_images ';
$sql .= "WHERE image_key = {$this->image_key} ";
mysql_query($sql);
$this->exists = FALSE;
$comments = get_gallery_image_comments($this);
foreach ($comments as $comment)
$comment->destroy();
// hack to unset highlights. actually it's a pretty
// clean hack; it's only a hack because gallery objects
// should technically be manipulated only through the
// gallery class
$sql = 'UPDATE '.DB_PREFIX.'gallery_galleries ';
$sql .= 'SET highlight = 0';
$sql .= "WHERE highlight = {$this->image_key} ";
mysql_query($sql);
flush_relevance_keywords('gallery_image', $this->image_key);
flush_record('gallery_image', $this->image_key);
}
// whether or not the image exists
function exists() {
return ($this->is_accessible) ? ($this->exists && is_file($this->path)) : FALSE;
}
function get_display_restrictions() {
if ($this->is_private)
return 'image is private';
if ($this->is_hidden)
return 'image is hidden';
return 'no restrictions';
}
function get_display_title() {
return $this->title;
}
function get_display_short_title($length = FALSE) {
return ($length === FALSE) ?
str_trunc($this->title, get_pref('buzzword_short_title_length'), TRUE):
str_trunc($this->title, $length, TRUE);
}
function get_display_description() {
return longtext_hook(nl2p($this->description));
}
function get_display_short_description($length = FALSE) {
return ($length === FALSE) ?
nl2p(str_trunc($this->description, get_pref('buzzword_short_desc_length'), FALSE)):
nl2p(str_trunc($this->description, $length, FALSE));
}
function get_display_date_created() {
return date(get_pref('buzzword_date_format'), $this->parent->created);
}
function get_display_time_created() {
return date(get_pref('buzzword_time_format'), $this->parent->created);
}
function get_display_date_modified() {
return date(get_pref('buzzword_date_format'), $this->parent->modified);
}
function get_display_time_modified() {
return date(get_pref('buzzword_time_format'), $this->parent->modified);
}
function get_display_relevance() {
$relevance = "<p style=\"clear: both;\">\n";
$relevance .= "<a href=\"../gallery/image.php?i={$this->image_key}\"><img \n";
$relevance .= " src=\"../gallery/thumb.php?i={$this->image_key}\" ".$this->get_alt()." \n";
$relevance .= " border=\"0\" ".$this->get_thumb_half_size()." class=\"gallery-thumb-halfsize\"></a>\n";
$relevance .= "<a href=\"../gallery/image.php?i={$this->image_key}\">".$this->get_display_short_title(get_pref('buzzword_short_title_length') - round(get_pref('gallery_thumb_width') / 16))."</a><br>\n";
$relevance .= $this->get_display_date_created()."<br>\n";
$relevance .= "</p>\n";
return $relevance;
}
function get_display_terse_relevance() {
return "<a href=\"../gallery/image.php?i={$this->image_key}\">".$this->get_display_short_title()."</a><br>\n";
}
// get image dimensions
function get_image_size() {
if (!$this->exists())
return FALSE;
return getimagesize($this->path);
}
// get image's MIME content type
function get_content_type() {
if (!$this->exists())
return FALSE;
$image_size = $this->get_image_size();
switch ($image_size[2]) {
case 1:
return 'image/gif';
break;
case 2:
return 'image/jpeg';
break;
case 3:
return 'image/png';
break;
case 4:
return 'application/x-shockwave-flash';
break;
case 6:
return 'image/bmp';
break;
case 7:
case 8:
return 'image/tiff';
break;
default:
return 'application/octet-stream';
break;
}
}
// determine if image has changed since thumbnail was generated
function get_thumb_checksum() {
if (!$this->exists())
return FALSE;
return get_pref('gallery_thumb_quality').get_pref('gallery_thumb_width').filemtime($this->path).filesize($this->path);
}
// retrieve the image's thumbnail
function get_thumb() {
if (!$this->exists())
return FALSE;
$sql = 'SELECT thumbnail, thumbnail_checksum, UNIX_TIMESTAMP(thumbnail_created) AS thumbnail_created ';
$sql .= 'FROM '.DB_PREFIX.'gallery_images ';
$sql .= "WHERE image_key = {$this->image_key} ";
$result = mysql_query($sql);
$row = mysql_fetch_assoc($result);
// no thumbnail exists or file was modified after thumbnail was created
if ( ($row['thumbnail'] == '') || ($row['thumbnail_checksum'] != $this->get_thumb_checksum()) ) {
// create a temporary file
$tempnam = tempnam('/tmp', 'thumb-');
// get size of original image
$image_size = $this->get_image_size();
// resize the image (use imagemagick)
$command = '"'.get_pref('gallery_convert_path').'"';
$command .= ' -quality '.get_pref('gallery_thumb_quality');
if(!($image_size[0] < get_pref('gallery_image_width')))
$command .= ' -geometry '.get_pref('gallery_thumb_width').'x'.round($image_size[1] * get_pref('gallery_thumb_width') / $image_size[0]);
$command .= ' -rotate '.$this->orientation;
$command .= ' "'.$this->path.'"';
$command .= ' "'.$tempnam.'"';
exec($command, $output, $exitcode);
if ($exitcode)
display_error("exec($command) failed with exit code $exitcode, exiting\n<br><br>\n".join("<br>\n", $output));
// strip the exif headers from the image
$command = '"'.get_pref('gallery_jhead_path').'"';
$command .= ' -dc';
$command .= ' -de';
$command .= ' "'.$tempnam.'"';
exec($command, $output, $exitcode);
// this is a non-fatal error, ignore it
// if ($exitcode)
// display_error("exec($command) failed with exit code $exitcode, exiting\n<br><br>\n".join("<br>\n", $output));
// read the image file into a string
$fp = fopen($tempnam, 'r');
$contents = fread($fp, filesize($tempnam));
fclose($fp);
// prepare thumbnail for db
$thumbnail = mysql_quote_string(base64_encode($contents));
$checksum = mysql_quote_string($this->get_thumb_checksum());
// cache the thumbnail into the db
$sql = 'UPDATE '.DB_PREFIX.'gallery_images SET ';
$sql .= "thumbnail = $thumbnail, ";
$sql .= "thumbnail_checksum = $checksum, ";
$sql .= "thumbnail_created = NOW() ";
$sql .= "WHERE image_key = {$this->image_key} ";
$result = mysql_query($sql);
// remove the temporary file
unlink($tempnam);
return array($contents, time());
}
return array(base64_decode($row['thumbnail']), $row['thumbnail_created']);
}
// determine if image has changed since display image was generated
function get_display_checksum() {
if (!$this->exists())
return FALSE;
return get_pref('gallery_image_quality').get_pref('gallery_image_width').filemtime($this->path).filesize($this->path);
}
// retrieve the image's display image
function get_display() {
if (!$this->exists())
return FALSE;
$sql = 'SELECT display, display_checksum, UNIX_TIMESTAMP(display_created) AS display_created ';
$sql .= 'FROM '.DB_PREFIX.'gallery_images ';
$sql .= "WHERE image_key = {$this->image_key} ";
$result = mysql_query($sql);
$row = mysql_fetch_assoc($result);
// no display image exists or file was modified after display image was created
if ( ($row['display'] == '') || ($row['display_checksum'] != $this->get_display_checksum()) ) {
// create a temporary file
$tempnam = tempnam('/tmp', 'display-');
// get size of original image
$image_size = $this->get_image_size();
// resize the image (use imagemagick)
$command = '"'.get_pref('gallery_convert_path').'"';
$command .= ' -quality '.get_pref('gallery_image_quality');
// only down-size images; don't up-size
if(!($image_size[0] < get_pref('gallery_image_width')))
$command .= ' -geometry '.get_pref('gallery_image_width').'x'.round($image_size[1] * get_pref('gallery_image_width') / $image_size[0]);
$command .= ' -rotate '.$this->orientation;
$command .= ' "'.$this->path.'"';
$command .= ' "'.$tempnam.'"';
exec($command, $output, $exitcode);
if ($exitcode)
display_error("exec($command) failed with exit code $exitcode, exiting\n<br><br>\n".join("<br>\n", $output));
// strip the exif headers from the image
$command = '"'.get_pref('gallery_jhead_path').'"';
$command .= ' -dc';
$command .= ' -de';
$command .= ' "'.$tempnam.'"';
exec($command, $output, $exitcode);
// this is a non-fatal error, ignore it
// if ($exitcode)
// display_error("exec($command) failed with exit code $exitcode, exiting\n<br><br>\n".join("<br>\n", $output));
// read the image file into a string
$fp = fopen($tempnam, 'r');
$contents = fread($fp, filesize($tempnam));
fclose($fp);
// prepare display image for db
$display = mysql_quote_string(base64_encode($contents));
$checksum = mysql_quote_string($this->get_display_checksum());
// cache the display image into the db
$sql = 'UPDATE '.DB_PREFIX.'gallery_images SET ';
$sql .= "display = $display, ";
$sql .= "display_checksum = $checksum, ";
$sql .= "display_created = NOW() ";
$sql .= "WHERE image_key = {$this->image_key} ";
$result = mysql_query($sql);
// remove the temporary file
unlink($tempnam);
return array($contents, time());
}
return array(base64_decode($row['display']), $row['display_created']);
}
// flush the cached thumbnail and/or display image
function clear_cache() {
$sql = 'UPDATE '.DB_PREFIX.'gallery_images SET ';
$sql .= "thumbnail_checksum = '', ";
$sql .= "display_checksum = '' ";
$sql .= "WHERE image_key = {$this->image_key} ";
$result = mysql_query($sql);
}
// get image's exif info
function get_exif() {
if (!$this->exists())
return FALSE;
// exif data is only in TIFs and JPGs
if (!preg_match('/\.(jpe?g|tiff?)/i', $this->path))
return array();
if (function_exists('exif_read_data')) {
$output = array();
// use built-in PHP EXIF support, thanks Dom Scott
if ($exif_data = exif_read_data($this->path, 'EXIF', TRUE)) {
if (isset($exif_data['IFD0']['Make']))
$output[] = 'Camera make: '.$exif_data['IFD0']['Make'];
if (isset($exif_data['IFD0']['Model']))
$output[] = 'Camera model: '.$exif_data['IFD0']['Model'];
if (isset($exif_data['IFD0']['Software']))
$output[] = 'Camera software: '.$exif_data['IFD0']['Software'];
if (isset($exif_data['IFD0']['DateTime']))
$output[] = 'Date/Time: '.$exif_data['IFD0']['DateTime'];
if ( (isset($exif_data['COMPUTED']['Width'])) && (isset($exif_data['COMPUTED']['Height'])) )
$output[] = 'Resolution: '.$exif_data['COMPUTED']['Width'].'x'.$exif_data['COMPUTED']['Height'];
if (isset($exif_data['EXIF']['Flash']))
$output[] = ($exif_data['EXIF']['Flash']) ? 'Flash used: Yes' : 'Flash used: No';
if (isset($exif_data['EXIF']['FocalLength'])) {
$focal_fractions = explode('/', $exif_data['EXIF']['FocalLength']);
$focal_length = $focal_fractions[0] / $focal_fractions[1];
$focal_data = 'Focal length: '.number_format($focal_length, 1).'mm';
if (isset($exif_data['COMPUTED']['CCDWidth'])) {
$focal_factor = 35 / $exif_data['COMPUTED']['CCDWidth'];
$focal_data .= ' (35mm equivalent: '.number_format(($focal_length * $focal_factor), 1).'mm)';
}
$output[] = $focal_data;
}
if (isset($exif_data['COMPUTED']['CCDWidth']))
$output[] = 'CCD Width: '.$exif_data['COMPUTED']['CCDWidth'];
if (isset($exif_data['COMPUTED']['ExposureTime'])) {
$output[] = 'Exposure time: '.$exif_data['COMPUTED']['ExposureTime'];
} else if (isset($exif_data['EXIF']['ExposureTime'])) {
$output[] = 'Exposure time: '.$exif_data['EXIF']['ExposureTime'];
}
if (isset($exif_data['COMPUTED']['ApertureFNumber']))
$output[] = 'Aperature: '.$exif_data['COMPUTED']['ApertureFNumber'];
if (isset($exif_data['COMPUTED']['FocusDistance']))
$output[] = 'Focus Distance: '.$exif_data['COMPUTED']['FocusDistance'];
if (isset($exif_data['EXIF']['MeteringMode']))
$output[] = 'Metering Mode: '.$exif_data['EXIF']['MeteringMode'];
if (isset($exif_data['EXIF']['ISOSpeedRatings']))
$output[] = 'ISO equivalent: '.$exif_data['EXIF']['ISOSpeedRatings'];
if (isset($exif_data['IFD0']['Copyright']))
$output[] = 'Copyright: '.$exif_data['IFD0']['Copyright'];
}
} else {
// fall back on jhead
$command = '"'.get_pref('gallery_jhead_path').'"';
$command .= ' "'.$this->path.'"';
exec($command, $output, $exitcode);
if ($exitcode)
display_error("exec($command) failed with exit code $exitcode, exiting\n<br><br>\n".join("<br>\n", $output));
}
return $output;
}
// display exif data
function get_display_exif() {
$lines = $this->get_exif();
$newstring = '';
foreach ($lines as $line) {
$line = preg_replace('/\s*:/', ':', trim($line));
if ( ($line != '') && (!preg_match('/file\s*(name|size|date)/i', $line)) )
$newstring .= "$line<br>\n";
}
return strtolower($newstring);
}
// get image's display size
function get_display_size() {
if (!$this->exists())
return FALSE;
$image_size = $this->get_image_size();
// only down-size images; don't up-size
if (!($image_size[0] < get_pref('gallery_image_width'))) {
if ( ($this->orientation == 0) || ($this->orientation == 180) )
return 'width="'.get_pref('gallery_image_width').'" height="'.round($image_size[1] * get_pref('gallery_image_width') / $image_size[0]).'"';
if ( ($this->orientation == 90) || ($this->orientation == 270) )
return 'width="'.round($image_size[1] * get_pref('gallery_image_width') / $image_size[0]).'" height="'.get_pref('gallery_image_width').'"';
} else {
if ( ($this->orientation == 0) || ($this->orientation == 180) )
return 'width="'.$image_size[0].'" height="'.$image_size[1].'"';
if ( ($this->orientation == 90) || ($this->orientation == 270) )
return 'width="'.$image_size[1].'" height="'.$image_size[0].'"';
}
return '';
}
// get image's thumbnail size
function get_thumb_size() {
if (!$this->exists())
return FALSE;
$image_size = $this->get_image_size();
// only down-size images; dont upsize
if (!($image_size[0] < get_pref('gallery_thumb_width'))) {
if ( ($this->orientation == 0) || ($this->orientation == 180) )
return 'width="'.get_pref('gallery_thumb_width').'" height="'.round($image_size[1] * get_pref('gallery_thumb_width') / $image_size[0]).'"';
if ( ($this->orientation == 90) || ($this->orientation == 270) )
return 'width="'.round($image_size[1] * get_pref('gallery_thumb_width') / $image_size[0]).'" height="'.get_pref('gallery_thumb_width').'"';
} else {
if ( ($this->orientation == 0) || ($this->orientation == 180) )
return 'width="'.$image_size[0].'" height="'.$image_size[1].'"';
if ( ($this->orientation == 90) || ($this->orientation == 270) )
return 'width="'.$image_size[1].'" height="'.$image_size[0].'"';
}
return '';
}
// get image's thumbnail size, halved
function get_thumb_half_size() {
if (!$this->exists())
return FALSE;
$image_size = $this->get_image_size();
if ( ($this->orientation == 0) || ($this->orientation == 180) )
return 'width="'.round(get_pref('gallery_thumb_width') / 2).'" height="'.round($image_size[1] * get_pref('gallery_thumb_width') / $image_size[0] / 2).'"';
if ( ($this->orientation == 90) || ($this->orientation == 270) )
return 'width="'.round($image_size[1] * get_pref('gallery_thumb_width') / $image_size[0] / 2).'" height="'.round(get_pref('gallery_thumb_width') / 2).'"';
return '';
}
// get image's alt tag
function get_alt() {
$alt = htmlspecialchars(strip_tags($this->title));
return "alt=\"$alt\" title=\"$alt\"";
}
}
?>