Dynamically generate thumbnails (see full text)
The File object now stores width and height of files that can supply this kind of information. Formats which we can not read natively in PHP do not currently benefit from this. However an event hook will be introduced later. The CreateFileImageThumbnail event is renamed to: CreateFileImageThumbnailSource to clarify that the hooks should not generate their own thumbnails but only the source image. Also it now accepts File objects, not MediaFile objects. The thumbnail generation is documented in the source code. For developers, call 'getThumbnail' on a File object and hope for the best. Default thumbnail sizes have increased to be more appealing.
This commit is contained in:
parent
7f3611c51c
commit
d59eb5e184
|
@ -1442,6 +1442,6 @@ OtherAccountProfiles: Hook to add account profiles to a user account profile blo
|
||||||
image: mini image for the profile
|
image: mini image for the profile
|
||||||
|
|
||||||
CreateFileImageThumbnailSource: Hook to create image thumbnail source from a File
|
CreateFileImageThumbnailSource: Hook to create image thumbnail source from a File
|
||||||
- $file: MediaFile object with related metadata
|
- $file: 'File' object to source the image from
|
||||||
- &$imgPath: Path to image file which can be used as source for our thumbnail algorithm.
|
- &$imgPath: Path to image file which can be used as source for our thumbnail algorithm.
|
||||||
- $media: MIME media type ('image', 'video', 'audio' etc.)
|
- $media: MIME media type ('image', 'video', 'audio' etc.)
|
||||||
|
|
|
@ -42,15 +42,16 @@ class Attachment_thumbnailAction extends AttachmentAction
|
||||||
{
|
{
|
||||||
protected $thumb_w = null; // max width
|
protected $thumb_w = null; // max width
|
||||||
protected $thumb_h = null; // max height
|
protected $thumb_h = null; // max height
|
||||||
protected $thumb_a = null; // "aspect ratio" (more like "square", 1 or 0)
|
protected $thumb_c = null; // crop?
|
||||||
|
|
||||||
protected function prepare(array $args=array())
|
protected function prepare(array $args=array())
|
||||||
{
|
{
|
||||||
parent::prepare($args);
|
parent::prepare($args);
|
||||||
|
|
||||||
foreach (array('w', 'h', 'a') as $attr) {
|
$this->thumb_w = $this->int('w');
|
||||||
$this->{"thumb_$attr"} = $this->arg($attr);
|
$this->thumb_h = $this->int('h');
|
||||||
}
|
$this->thumb_c = $this->boolean('c');
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +78,7 @@ class Attachment_thumbnailAction extends AttachmentAction
|
||||||
function showCore()
|
function showCore()
|
||||||
{
|
{
|
||||||
// Returns a File_thumbnail object or throws exception if not available
|
// Returns a File_thumbnail object or throws exception if not available
|
||||||
$thumbnail = $this->attachment->getThumbnail($this->thumb_w, $this->thumb_h, $this->thumb_a);
|
$thumbnail = $this->attachment->getThumbnail($this->thumb_w, $this->thumb_h, $this->thumb_c);
|
||||||
$this->element('img', array('src' => $thumbnail->getUrl(), 'alt' => 'Thumbnail'));
|
$this->element('img', array('src' => $thumbnail->getUrl(), 'alt' => 'Thumbnail'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
108
classes/File.php
108
classes/File.php
|
@ -47,6 +47,8 @@ class File extends Managed_DataObject
|
||||||
'date' => array('type' => 'int', 'description' => 'date of resource according to http query'),
|
'date' => array('type' => 'int', 'description' => 'date of resource according to http query'),
|
||||||
'protected' => array('type' => 'int', 'description' => 'true when URL is private (needs login)'),
|
'protected' => array('type' => 'int', 'description' => 'true when URL is private (needs login)'),
|
||||||
'filename' => array('type' => 'varchar', 'length' => 255, 'description' => 'if a local file, name of the file'),
|
'filename' => array('type' => 'varchar', 'length' => 255, 'description' => 'if a local file, name of the file'),
|
||||||
|
'width' => array('type' => 'int', 'description' => 'width in pixels, if it can be described as such and data is available'),
|
||||||
|
'height' => array('type' => 'int', 'description' => 'height in pixels, if it can be described as such and data is available'),
|
||||||
|
|
||||||
'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
|
'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
|
||||||
),
|
),
|
||||||
|
@ -432,32 +434,118 @@ class File extends Managed_DataObject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the attachment's thumbnail record, if any.
|
* Get the attachment's thumbnail record, if any.
|
||||||
|
* Make sure you supply proper 'int' typed variables (or null).
|
||||||
*
|
*
|
||||||
* @param $width int Max width of thumbnail in pixels
|
* @param $width int Max width of thumbnail in pixels. (if null, use common_config values)
|
||||||
* @param $height int Max height of thumbnail in pixels. If null, set to $width
|
* @param $height int Max height of thumbnail in pixels. (if null, square-crop to $width)
|
||||||
|
* @param $crop bool Crop to the max-values' aspect ratio
|
||||||
*
|
*
|
||||||
* @return File_thumbnail
|
* @return File_thumbnail
|
||||||
*/
|
*/
|
||||||
public function getThumbnail($width=null, $height=null)
|
public function getThumbnail($width=null, $height=null, $crop=false)
|
||||||
{
|
{
|
||||||
|
if ($this->width < 1 || $this->height < 1) {
|
||||||
|
// Old files may have 0 until migrated with scripts/upgrade.php
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if ($width === null) {
|
if ($width === null) {
|
||||||
$width = common_config('attachments', 'thumb_width');
|
$width = common_config('thumbnail', 'width');
|
||||||
$height = common_config('attachments', 'thumb_height');
|
$height = common_config('thumbnail', 'height');
|
||||||
$square = common_config('attachments', 'thumb_square');
|
$crop = common_config('thumbnail', 'crop');
|
||||||
} elseif ($height === null) {
|
}
|
||||||
$square = true;
|
|
||||||
|
if ($height === null) {
|
||||||
|
$height = $width;
|
||||||
|
$crop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get proper aspect ratio width and height before lookup
|
||||||
|
list($width, $height, $x, $y, $w2, $h2) =
|
||||||
|
ImageFile::getScalingValues($this->width, $this->height, $width, $height, $crop);
|
||||||
|
|
||||||
|
// Doublecheck that parameters are sane and integers.
|
||||||
|
if ($width < 1 || $width > common_config('thumbnail', 'maxsize')
|
||||||
|
|| $height < 1 || $height > common_config('thumbnail', 'maxsize')) {
|
||||||
|
// Fail on bad width parameter.
|
||||||
|
throw new ServerException('Bad thumbnail width or height parameter');
|
||||||
}
|
}
|
||||||
|
|
||||||
$params = array('file_id'=> $this->id,
|
$params = array('file_id'=> $this->id,
|
||||||
'width' => $width,
|
'width' => $width,
|
||||||
'height' => $square ? $width : $height);
|
'height' => $height);
|
||||||
$thumb = File_thumbnail::pkeyGet($params);
|
$thumb = File_thumbnail::pkeyGet($params);
|
||||||
if ($thumb === null) {
|
if ($thumb === null) {
|
||||||
// generate a new thumbnail for desired parameters
|
try {
|
||||||
|
$thumb = $this->generateThumbnail($width, $height, $crop);
|
||||||
|
} catch (UnsupportedMediaException $e) {
|
||||||
|
// FIXME: Add "unknown media" icon or something
|
||||||
|
} catch (ServerException $e) {
|
||||||
|
// Probably a remote media file, maybe not available locally
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return $thumb;
|
return $thumb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate and store a thumbnail image for the uploaded file, if applicable.
|
||||||
|
* Call this only if you know what you're doing.
|
||||||
|
*
|
||||||
|
* @param $width int Maximum thumbnail width in pixels
|
||||||
|
* @param $height int Maximum thumbnail height in pixels, if null, crop to $width
|
||||||
|
*
|
||||||
|
* @return File_thumbnail or null
|
||||||
|
*/
|
||||||
|
protected function generateThumbnail($width, $height, $crop)
|
||||||
|
{
|
||||||
|
$imgPath = null;
|
||||||
|
$media = common_get_mime_media($this->mimetype);
|
||||||
|
$width = intval($width);
|
||||||
|
if ($height === null) {
|
||||||
|
$height = $width;
|
||||||
|
$crop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Event::handle('CreateFileImageThumbnailSource', array($this, &$imgPath, $media))) {
|
||||||
|
switch ($media) {
|
||||||
|
case 'image':
|
||||||
|
$imgPath = $this->getPath();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new UnsupportedMediaException(_('Unsupported media format.'), $this->getPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!file_exists($imgPath)) {
|
||||||
|
throw new ServerException(sprintf('Thumbnail source is not stored locally: %s', $imgPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$image = new ImageFile($this->id, $imgPath);
|
||||||
|
} catch (UnsupportedMediaException $e) {
|
||||||
|
// Avoid deleting the original
|
||||||
|
if ($image->getPath() != $this->getPath()) {
|
||||||
|
$image->unlink();
|
||||||
|
}
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
|
||||||
|
list($width, $height, $x, $y, $w2, $h2) =
|
||||||
|
$image->scaleToFit($width, $height, $crop);
|
||||||
|
|
||||||
|
$outname = "thumb-{$width}x{$height}-" . $this->filename;
|
||||||
|
$outpath = self::path($outname);
|
||||||
|
|
||||||
|
$image->resizeTo($outpath, $width, $height, $x, $y, $w2, $h2);
|
||||||
|
|
||||||
|
// Avoid deleting the original
|
||||||
|
if ($image->getPath() != $this->getPath()) {
|
||||||
|
$image->unlink();
|
||||||
|
}
|
||||||
|
return File_thumbnail::saveThumbnail($this->id,
|
||||||
|
self::url($outname),
|
||||||
|
$width, $height);
|
||||||
|
}
|
||||||
|
|
||||||
public function getPath()
|
public function getPath()
|
||||||
{
|
{
|
||||||
return self::path($this->filename);
|
return self::path($this->filename);
|
||||||
|
|
|
@ -69,8 +69,8 @@ class File_oembed extends Managed_DataObject
|
||||||
|
|
||||||
function _getOembed($url) {
|
function _getOembed($url) {
|
||||||
$parameters = array(
|
$parameters = array(
|
||||||
'maxwidth' => common_config('attachments', 'thumb_width'),
|
'maxwidth' => common_config('thumbnail', 'width'),
|
||||||
'maxheight' => common_config('attachments', 'thumb_height'),
|
'maxheight' => common_config('thumbnail', 'height'),
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
return oEmbedHelper::getObject($url, $parameters);
|
return oEmbedHelper::getObject($url, $parameters);
|
||||||
|
|
|
@ -27,19 +27,13 @@ require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
|
||||||
|
|
||||||
class File_thumbnail extends Managed_DataObject
|
class File_thumbnail extends Managed_DataObject
|
||||||
{
|
{
|
||||||
###START_AUTOCODE
|
|
||||||
/* the code below is auto generated do not remove the above tag */
|
|
||||||
|
|
||||||
public $__table = 'file_thumbnail'; // table name
|
public $__table = 'file_thumbnail'; // table name
|
||||||
public $file_id; // int(4) primary_key not_null
|
public $file_id; // int(4) primary_key not_null
|
||||||
public $url; // varchar(255) unique_key
|
public $url; // varchar(255) unique_key
|
||||||
public $width; // int(4)
|
public $width; // int(4) primary_key
|
||||||
public $height; // int(4)
|
public $height; // int(4) primary_key
|
||||||
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
|
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
|
||||||
|
|
||||||
/* the code above is auto generated do not remove the tag below */
|
|
||||||
###END_AUTOCODE
|
|
||||||
|
|
||||||
public static function schemaDef()
|
public static function schemaDef()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
|
@ -50,7 +44,10 @@ class File_thumbnail extends Managed_DataObject
|
||||||
'height' => array('type' => 'int', 'description' => 'height of thumbnail'),
|
'height' => array('type' => 'int', 'description' => 'height of thumbnail'),
|
||||||
'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
|
'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
|
||||||
),
|
),
|
||||||
'primary key' => array('file_id'),
|
'primary key' => array('file_id', 'width', 'height'),
|
||||||
|
'indexes' => array(
|
||||||
|
'file_thumbnail_file_id_idx' => array('file_id'),
|
||||||
|
),
|
||||||
'foreign keys' => array(
|
'foreign keys' => array(
|
||||||
'file_thumbnail_file_id_fkey' => array('file', array('file_id' => 'id')),
|
'file_thumbnail_file_id_fkey' => array('file', array('file_id' => 'id')),
|
||||||
)
|
)
|
||||||
|
@ -99,6 +96,7 @@ class File_thumbnail extends Managed_DataObject
|
||||||
$tn->width = intval($width);
|
$tn->width = intval($width);
|
||||||
$tn->height = intval($height);
|
$tn->height = intval($height);
|
||||||
$tn->insert();
|
$tn->insert();
|
||||||
|
return $tn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getUrl()
|
public function getUrl()
|
||||||
|
|
|
@ -201,34 +201,14 @@ class AttachmentListItem extends Widget
|
||||||
}
|
}
|
||||||
|
|
||||||
function showRepresentation() {
|
function showRepresentation() {
|
||||||
$thumb = $this->getThumbInfo();
|
try {
|
||||||
if ($thumb instanceof File_thumbnail) {
|
$thumb = $this->attachment->getThumbnail();
|
||||||
$this->out->element('img', array('alt' => '', 'src' => $thumb->getUrl(), 'width' => $thumb->width, 'height' => $thumb->height));
|
$this->out->element('img', array('alt' => '', 'src' => $thumb->getUrl(), 'width' => $thumb->width, 'height' => $thumb->height));
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// Image representation unavailable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Pull a thumbnail image reference for the given file, and if necessary
|
|
||||||
* resize it to match currently thumbnail size settings.
|
|
||||||
*
|
|
||||||
* @return File_Thumbnail or false/null
|
|
||||||
*/
|
|
||||||
function getThumbInfo()
|
|
||||||
{
|
|
||||||
$thumbnail = File_thumbnail::getKV('file_id', $this->attachment->id);
|
|
||||||
if ($thumbnail) {
|
|
||||||
$maxWidth = common_config('attachments', 'thumb_width');
|
|
||||||
$maxHeight = common_config('attachments', 'thumb_height');
|
|
||||||
if ($thumbnail->width > $maxWidth) {
|
|
||||||
$thumb = clone($thumbnail);
|
|
||||||
$thumb->width = $maxWidth;
|
|
||||||
$thumb->height = intval($thumbnail->height * $maxWidth / $thumbnail->width);
|
|
||||||
return $thumb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $thumbnail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* start a single notice.
|
* start a single notice.
|
||||||
*
|
*
|
||||||
|
@ -342,10 +322,12 @@ class Attachment extends AttachmentListItem
|
||||||
case 'video/quicktime':
|
case 'video/quicktime':
|
||||||
case 'video/webm':
|
case 'video/webm':
|
||||||
$mediatype = common_get_mime_media($this->attachment->mimetype);
|
$mediatype = common_get_mime_media($this->attachment->mimetype);
|
||||||
$thumb = $this->getThumbInfo();
|
try {
|
||||||
$poster = ($thumb instanceof File_thumbnail)
|
$thumb = $this->attachment->getThumbnail();
|
||||||
? $thumb->getUrl()
|
$poster = $thumb->getUrl();
|
||||||
: null;
|
} catch (Exception $e) {
|
||||||
|
$poster = null;
|
||||||
|
}
|
||||||
$this->out->elementStart($mediatype,
|
$this->out->elementStart($mediatype,
|
||||||
array('class'=>'attachment_player',
|
array('class'=>'attachment_player',
|
||||||
'poster'=>$poster,
|
'poster'=>$poster,
|
||||||
|
|
|
@ -250,11 +250,13 @@ $default =
|
||||||
'monthly_quota' => 15000000,
|
'monthly_quota' => 15000000,
|
||||||
'uploads' => true,
|
'uploads' => true,
|
||||||
'show_thumbs' => true, // show thumbnails in notice lists for uploaded images, and photos and videos linked remotely that provide oEmbed info
|
'show_thumbs' => true, // show thumbnails in notice lists for uploaded images, and photos and videos linked remotely that provide oEmbed info
|
||||||
'thumb_width' => 150,
|
|
||||||
'thumb_height' => 150,
|
|
||||||
'thumb_square' => true,
|
|
||||||
'process_links' => true, // check linked resources for embeddable photos and videos; this will hit referenced external web sites when processing new messages.
|
'process_links' => true, // check linked resources for embeddable photos and videos; this will hit referenced external web sites when processing new messages.
|
||||||
),
|
),
|
||||||
|
'thumbnail' =>
|
||||||
|
array('crop' => false, // overridden to true if thumb height === null
|
||||||
|
'maxsize' => 500, // thumbs bigger than this will not be generated
|
||||||
|
'width' => 500,
|
||||||
|
'height' => 250),
|
||||||
'application' =>
|
'application' =>
|
||||||
array('desclimit' => null),
|
array('desclimit' => null),
|
||||||
'group' =>
|
'group' =>
|
||||||
|
|
|
@ -28,9 +28,7 @@
|
||||||
* @link http://status.net/
|
* @link http://status.net/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
if (!defined('GNUSOCIAL')) { exit(1); }
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A wrapper on uploaded files
|
* A wrapper on uploaded files
|
||||||
|
@ -335,6 +333,77 @@ class ImageFile
|
||||||
|
|
||||||
return $num;
|
return $num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function scaleToFit($maxWidth=null, $maxHeight=null, $crop=null)
|
||||||
|
{
|
||||||
|
return self::getScalingValues($this->width, $this->height,
|
||||||
|
$maxWidth, $maxHeight, $crop);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets scaling values for images of various types. Cropping can be enabled.
|
||||||
|
*
|
||||||
|
* Values will scale _up_ to fit max values if cropping is enabled!
|
||||||
|
* With cropping disabled, the max value of each axis will be respected.
|
||||||
|
*
|
||||||
|
* @param $width int Original width
|
||||||
|
* @param $height int Original height
|
||||||
|
* @param $maxW int Resulting max width
|
||||||
|
* @param $maxH int Resulting max height
|
||||||
|
* @param $crop int Crop to the size (not preserving aspect ratio)
|
||||||
|
*/
|
||||||
|
public static function getScalingValues($width, $height,
|
||||||
|
$maxW=null, $maxH=null,
|
||||||
|
$crop=null)
|
||||||
|
{
|
||||||
|
$maxW = $maxW ?: common_config('thumbnail', 'width');
|
||||||
|
$maxH = $maxH ?: common_config('thumbnail', 'height');
|
||||||
|
|
||||||
|
if ($maxW < 1 || ($maxH !== null && $maxH < 1)) {
|
||||||
|
throw new ServerException('Bad parameters for ImageFile::getScalingValues');
|
||||||
|
} elseif ($maxH === null) {
|
||||||
|
// if maxH is null, we set maxH to equal maxW and enable crop
|
||||||
|
$maxH = $maxW;
|
||||||
|
$crop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cropping data (for original image size). Default values, 0 and null,
|
||||||
|
// imply no cropping and with preserved aspect ratio (per axis).
|
||||||
|
$cx = 0; // crop x
|
||||||
|
$cy = 0; // crop y
|
||||||
|
$cw = null; // crop area width
|
||||||
|
$ch = null; // crop area height
|
||||||
|
|
||||||
|
if ($crop) {
|
||||||
|
$s_ar = $width / $height;
|
||||||
|
$t_ar = $maxW / $maxH;
|
||||||
|
|
||||||
|
$rw = $maxW;
|
||||||
|
$rh = $maxH;
|
||||||
|
|
||||||
|
// Source aspect ratio differs from target, recalculate crop points!
|
||||||
|
if ($s_ar > $t_ar) {
|
||||||
|
$cx = floor($width / 2 - $height * $t_ar / 2);
|
||||||
|
$cw = ceil($height * $t_ar);
|
||||||
|
} elseif ($s_ar < $t_ar) {
|
||||||
|
$cy = floor($height / 2 - $width / $t_ar / 2);
|
||||||
|
$ch = ceil($width / $t_ar);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$rw = $maxW;
|
||||||
|
$rh = ceil($height * $rw / $width);
|
||||||
|
|
||||||
|
// Scaling caused too large height, decrease to max accepted value
|
||||||
|
if ($rh > $maxH) {
|
||||||
|
$rh = $maxH;
|
||||||
|
$rw = ceil($width * $rh / $height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array(intval($rw), intval($rh),
|
||||||
|
intval($cx), intval($cy),
|
||||||
|
is_null($cw) ? null : intval($cw),
|
||||||
|
is_null($ch) ? null : intval($ch));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//PHP doesn't (as of 2/24/2010) have an imagecreatefrombmp so conditionally define one
|
//PHP doesn't (as of 2/24/2010) have an imagecreatefrombmp so conditionally define one
|
||||||
|
@ -432,4 +501,4 @@ if(!function_exists('imagecreatefrombmp')){
|
||||||
// Return image-object
|
// Return image-object
|
||||||
return $image;
|
return $image;
|
||||||
}
|
}
|
||||||
}
|
} // if(!function_exists('imagecreatefrombmp'))
|
||||||
|
|
|
@ -62,7 +62,7 @@ class InlineAttachmentListItem extends AttachmentListItem
|
||||||
|
|
||||||
function show()
|
function show()
|
||||||
{
|
{
|
||||||
$this->thumb = parent::getThumbInfo();
|
$this->thumb = $this->attachment->getThumbnail();
|
||||||
if (!empty($this->thumb)) {
|
if (!empty($this->thumb)) {
|
||||||
parent::show();
|
parent::show();
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,6 @@ class MediaFile
|
||||||
var $fileurl = null;
|
var $fileurl = null;
|
||||||
var $short_fileurl = null;
|
var $short_fileurl = null;
|
||||||
var $mimetype = null;
|
var $mimetype = null;
|
||||||
var $thumbnailRecord = null;
|
|
||||||
|
|
||||||
function __construct(Profile $scoped, $filename = null, $mimetype = null)
|
function __construct(Profile $scoped, $filename = null, $mimetype = null)
|
||||||
{
|
{
|
||||||
|
@ -50,12 +49,6 @@ class MediaFile
|
||||||
$this->filename = $filename;
|
$this->filename = $filename;
|
||||||
$this->mimetype = $mimetype;
|
$this->mimetype = $mimetype;
|
||||||
$this->fileRecord = $this->storeFile();
|
$this->fileRecord = $this->storeFile();
|
||||||
try {
|
|
||||||
$this->thumbnailRecord = $this->storeThumbnail();
|
|
||||||
} catch (UnsupportedMediaException $e) {
|
|
||||||
// FIXME: Add "unknown media" icon or something
|
|
||||||
$this->thumbnailRecord = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->fileurl = common_local_url('attachment',
|
$this->fileurl = common_local_url('attachment',
|
||||||
array('attachment' => $this->fileRecord->id));
|
array('attachment' => $this->fileRecord->id));
|
||||||
|
@ -110,109 +103,6 @@ class MediaFile
|
||||||
return $file;
|
return $file;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate and store a thumbnail image for the uploaded file, if applicable.
|
|
||||||
*
|
|
||||||
* @return File_thumbnail or null
|
|
||||||
*/
|
|
||||||
function storeThumbnail($maxWidth=null, $maxHeight=null, $square=true)
|
|
||||||
{
|
|
||||||
$imgPath = null;
|
|
||||||
$media = common_get_mime_media($this->mimetype);
|
|
||||||
|
|
||||||
if (Event::handle('CreateFileImageThumbnailSource', array($this, &$imgPath, $media))) {
|
|
||||||
switch ($media) {
|
|
||||||
case 'image':
|
|
||||||
$imgPath = $this->getPath();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new UnsupportedMediaException(_('Unsupported media format.'), $this->getPath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!file_exists($imgPath)) {
|
|
||||||
throw new ServerException(sprintf('Thumbnail source is not stored locally: %s', $imgPath));
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$image = new ImageFile($this->fileRecord->id, $imgPath);
|
|
||||||
} catch (UnsupportedMediaException $e) {
|
|
||||||
// Avoid deleting the original
|
|
||||||
if ($image->getPath() != $this->getPath()) {
|
|
||||||
$image->unlink();
|
|
||||||
}
|
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
|
|
||||||
$outname = File::filename($this->scoped, 'thumb-' . $this->filename, $this->mimetype);
|
|
||||||
$outpath = File::path($outname);
|
|
||||||
|
|
||||||
$maxWidth = $maxWidth ?: common_config('attachments', 'thumb_width');
|
|
||||||
$maxHeight = $maxHeight ?: common_config('attachments', 'thumb_height');
|
|
||||||
list($width, $height, $x, $y, $w2, $h2) =
|
|
||||||
$this->scaleToFit($image->width, $image->height,
|
|
||||||
$maxWidth, $maxHeight,
|
|
||||||
common_config('attachments', 'thumb_square'));
|
|
||||||
|
|
||||||
$image->resizeTo($outpath, $width, $height, $x, $y, $w2, $h2);
|
|
||||||
|
|
||||||
// Avoid deleting the original
|
|
||||||
if ($image->getPath() != $this->getPath()) {
|
|
||||||
$image->unlink();
|
|
||||||
}
|
|
||||||
return File_thumbnail::saveThumbnail($this->fileRecord->id,
|
|
||||||
File::url($outname),
|
|
||||||
$width,
|
|
||||||
$height);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This will give parameters to scale up if max values are larger than original
|
|
||||||
function scaleToFit($width, $height, $maxWidth=null, $maxHeight=null, $square=true)
|
|
||||||
{
|
|
||||||
if ($width <= 0 || $height <= 0
|
|
||||||
|| ($maxWidth !== null && $maxWidth <= 0)
|
|
||||||
|| ($maxHeight !== null && $maxHeight <= 0)) {
|
|
||||||
throw new ServerException('Bad scaleToFit parameters for MediaFile');
|
|
||||||
} elseif ($maxWidth === null) {
|
|
||||||
// maxWidth must be a positive number
|
|
||||||
throw new ServerException('MediaFile::scaleToFit maxWidth is null');
|
|
||||||
} elseif ($square || $maxHeight === null) {
|
|
||||||
// if square thumb ratio or if maxHeight is null,
|
|
||||||
// we set maxHeight to equal maxWidth
|
|
||||||
$maxHeight = $maxWidth;
|
|
||||||
$square = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cropping data
|
|
||||||
$cx = 0; // crop x
|
|
||||||
$cy = 0; // crop y
|
|
||||||
$cw = null; // crop area width
|
|
||||||
$ch = null; // crop area height
|
|
||||||
|
|
||||||
if ($square) {
|
|
||||||
// resulting width and height
|
|
||||||
$rw = $maxWidth;
|
|
||||||
$rh = $maxHeight;
|
|
||||||
|
|
||||||
// minSide will determine the smallest image size
|
|
||||||
// and crop-values are determined from this
|
|
||||||
$minSide = $width > $height ? $height : $width;
|
|
||||||
$cx = $width / 2 - $minSide / 2;
|
|
||||||
$cy = $height / 2 - $minSide / 2;
|
|
||||||
$cw = $minSide;
|
|
||||||
$ch = $minSide;
|
|
||||||
} else {
|
|
||||||
// resulting sizes
|
|
||||||
$rw = $maxWidth;
|
|
||||||
$rh = floor($height * $maxWidth / $width);
|
|
||||||
|
|
||||||
if ($rh > $maxHeight) {
|
|
||||||
$rw = floor($width * $maxHeight / $height);
|
|
||||||
$rh = $maxHeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return array($rw, $rh, $cx, $cy, $cw, $ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
function rememberFile($file, $short)
|
function rememberFile($file, $short)
|
||||||
{
|
{
|
||||||
$this->maybeAddRedir($file->id, $short);
|
$this->maybeAddRedir($file->id, $short);
|
||||||
|
|
|
@ -246,8 +246,8 @@ class oEmbedHelper
|
||||||
if (isset($data->thumbnail_url)) {
|
if (isset($data->thumbnail_url)) {
|
||||||
if (!isset($data->thumbnail_width)) {
|
if (!isset($data->thumbnail_width)) {
|
||||||
// !?!?!
|
// !?!?!
|
||||||
$data->thumbnail_width = common_config('attachments', 'thumb_width');
|
$data->thumbnail_width = common_config('thumbnail', 'width');
|
||||||
$data->thumbnail_height = common_config('attachments', 'thumb_height');
|
$data->thumbnail_height = common_config('thumbnail', 'height');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -190,8 +190,8 @@ class BookmarkForm extends Form
|
||||||
|
|
||||||
function scaleImage($width, $height)
|
function scaleImage($width, $height)
|
||||||
{
|
{
|
||||||
$maxwidth = common_config('attachments', 'thumb_width');
|
$maxwidth = common_config('thumbnail', 'width');
|
||||||
$maxheight = common_config('attachments', 'thumb_height');
|
$maxheight = common_config('thumbnail', 'height');
|
||||||
|
|
||||||
if ($width > $height && $width > $maxwidth) {
|
if ($width > $height && $width > $maxwidth) {
|
||||||
$height = (int) ((((float)$maxwidth)/(float)($width))*(float)$height);
|
$height = (int) ((((float)$maxwidth)/(float)($width))*(float)$height);
|
||||||
|
|
|
@ -44,7 +44,7 @@ class VideoThumbnailsPlugin extends Plugin
|
||||||
* and disregard any cropping or scaling in the resulting file, as
|
* and disregard any cropping or scaling in the resulting file, as
|
||||||
* that will be handled in the core thumbnail algorithm.
|
* that will be handled in the core thumbnail algorithm.
|
||||||
*/
|
*/
|
||||||
public function onCreateFileImageThumbnailSource(MediaFile $file, &$imgPath, $media=null)
|
public function onCreateFileImageThumbnailSource(File $file, &$imgPath, $media=null)
|
||||||
{
|
{
|
||||||
// The calling function might accidentally pass application/ogg videos.
|
// The calling function might accidentally pass application/ogg videos.
|
||||||
// If that's a problem, let's fix it in the calling function.
|
// If that's a problem, let's fix it in the calling function.
|
||||||
|
|
|
@ -43,6 +43,7 @@ function main()
|
||||||
fixupNoticeConversation();
|
fixupNoticeConversation();
|
||||||
initConversation();
|
initConversation();
|
||||||
fixupGroupURI();
|
fixupGroupURI();
|
||||||
|
fixupFileGeometry();
|
||||||
|
|
||||||
initGroupProfileId();
|
initGroupProfileId();
|
||||||
initLocalGroup();
|
initLocalGroup();
|
||||||
|
@ -414,4 +415,33 @@ function initProfileLists()
|
||||||
printfnq("DONE.\n");
|
printfnq("DONE.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Added as we now store interpretd width and height in File table.
|
||||||
|
*/
|
||||||
|
function fixupFileGeometry()
|
||||||
|
{
|
||||||
|
printfnq("Ensuring width and height is set for supported local File objects...");
|
||||||
|
|
||||||
|
$file = new File();
|
||||||
|
$file->whereAdd('filename IS NOT NULL'); // local files
|
||||||
|
$file->whereAdd('width IS NULL OR width = 0');
|
||||||
|
|
||||||
|
if ($file->find()) {
|
||||||
|
while ($file->fetch()) {
|
||||||
|
// Add support for video sizes too
|
||||||
|
try {
|
||||||
|
$image = new ImageFile($file->id, $file->getPath());
|
||||||
|
} catch (UnsupportedMediaException $e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$orig = clone($file);
|
||||||
|
$file->width = $image->width;
|
||||||
|
$file->height = $image->height;
|
||||||
|
$file->update($orig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printfnq("DONE.\n");
|
||||||
|
}
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user