]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Dynamically generate thumbnails (see full text)
authorMikael Nordfeldth <mmn@hethane.se>
Mon, 21 Apr 2014 18:39:28 +0000 (20:39 +0200)
committerMikael Nordfeldth <mmn@hethane.se>
Mon, 21 Apr 2014 18:46:11 +0000 (20:46 +0200)
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.

14 files changed:
EVENTS.txt
actions/attachment_thumbnail.php
classes/File.php
classes/File_oembed.php
classes/File_thumbnail.php
lib/attachmentlist.php
lib/default.php
lib/imagefile.php
lib/inlineattachmentlist.php
lib/mediafile.php
lib/oembedhelper.php
plugins/Bookmark/forms/bookmark.php
plugins/VideoThumbnails/VideoThumbnailsPlugin.php
scripts/upgrade.php

index 4d1215f6e03580a003a7c01c9eaaa2f74cb134cd..32bbcdde999f6f26e1cbae2eaca91f4dff2979b1 100644 (file)
@@ -1442,6 +1442,6 @@ OtherAccountProfiles: Hook to add account profiles to a user account profile blo
             image: mini image for the profile
 
 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.
 - $media:   MIME media type ('image', 'video', 'audio' etc.)
index 6e8baeee7aa75324826817cb4d7284c7f86d4511..0353fa18ff7d1e165923942e9c0ad80d1a3c288d 100644 (file)
@@ -42,15 +42,16 @@ class Attachment_thumbnailAction extends AttachmentAction
 {
     protected $thumb_w = null;  // max width
     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())
     {
         parent::prepare($args);
 
-        foreach (array('w', 'h', 'a') as $attr) {
-            $this->{"thumb_$attr"} = $this->arg($attr);
-        }
+        $this->thumb_w = $this->int('w');
+        $this->thumb_h = $this->int('h');
+        $this->thumb_c = $this->boolean('c');
+
         return true;
     }
 
@@ -77,7 +78,7 @@ class Attachment_thumbnailAction extends AttachmentAction
     function showCore()
     {
         // 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'));
     }
 }
index 7748fe83f9fd30223ac77d3bddb5119e1102e771..9c04228735e35004e4438267d87b82cf0ce3a46c 100644 (file)
@@ -47,6 +47,8 @@ class File extends Managed_DataObject
                 'date' => array('type' => 'int', 'description' => 'date of resource according to http query'),
                 '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'),
+                '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'),
             ),
@@ -432,32 +434,118 @@ class File extends Managed_DataObject
 
     /**
      * 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 $height int   Max height of thumbnail in pixels. If null, set to $width
+     * @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, square-crop to $width)
+     * @param $crop   bool  Crop to the max-values' aspect ratio
      *
      * @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) {
-            $width = common_config('attachments', 'thumb_width');
-            $height = common_config('attachments', 'thumb_height');
-            $square = common_config('attachments', 'thumb_square');
-        } elseif ($height === null) {
-            $square = true;
+            $width = common_config('thumbnail', 'width');
+            $height = common_config('thumbnail', 'height');
+            $crop = common_config('thumbnail', 'crop');
+        }
+
+        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,
                         'width'  => $width,
-                        'height' => $square ? $width : $height);
+                        'height' => $height);
         $thumb = File_thumbnail::pkeyGet($params);
         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;
     }
 
+    /**
+     * 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()
     {
         return self::path($this->filename);
index 11d054aa4d745845c1c42852567ea86db44793fa..cb8420e352c6bc297335f9d3481e95d7683fddf9 100644 (file)
@@ -69,8 +69,8 @@ class File_oembed extends Managed_DataObject
 
     function _getOembed($url) {
         $parameters = array(
-            'maxwidth' => common_config('attachments', 'thumb_width'),
-            'maxheight' => common_config('attachments', 'thumb_height'),
+            'maxwidth' => common_config('thumbnail', 'width'),
+            'maxheight' => common_config('thumbnail', 'height'),
         );
         try {
             return oEmbedHelper::getObject($url, $parameters);
index 7c0f7477e591dcc18b0e3e971902cbe9f0d1c561..ba3bf138dc16cdb30a3c9876eb5622566954ae87 100644 (file)
@@ -27,19 +27,13 @@ require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
 
 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 $file_id;                         // int(4)  primary_key not_null
     public $url;                             // varchar(255)  unique_key
-    public $width;                           // int(4)
-    public $height;                          // int(4)
+    public $width;                           // int(4)  primary_key
+    public $height;                          // int(4)  primary_key
     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()
     {
         return array(
@@ -50,7 +44,10 @@ class File_thumbnail extends Managed_DataObject
                 'height' => array('type' => 'int', 'description' => 'height of thumbnail'),
                 '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(
                 '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->height = intval($height);
         $tn->insert();
+        return $tn;
     }
 
     public function getUrl()
index 1b323cd2a148b62fb895d36a5d25cd4951f371ca..073581593381fb3ea3405286d663b71670ae8705 100644 (file)
@@ -201,34 +201,14 @@ class AttachmentListItem extends Widget
     }
 
     function showRepresentation() {
-        $thumb = $this->getThumbInfo();
-        if ($thumb instanceof File_thumbnail) {
+        try {
+            $thumb = $this->attachment->getThumbnail();
             $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.
      *
@@ -342,10 +322,12 @@ class Attachment extends AttachmentListItem
                 case 'video/quicktime':
                 case 'video/webm':
                     $mediatype = common_get_mime_media($this->attachment->mimetype);
-                    $thumb = $this->getThumbInfo();
-                    $poster = ($thumb instanceof File_thumbnail)
-                                ? $thumb->getUrl()
-                                : null;
+                    try {
+                        $thumb = $this->attachment->getThumbnail();
+                        $poster = $thumb->getUrl();
+                    } catch (Exception $e) {
+                        $poster = null;
+                    }
                     $this->out->elementStart($mediatype,
                                         array('class'=>'attachment_player',
                                             'poster'=>$poster,
index 6efeb406c47d58f7fc5df412e13576f0a440c563..8ac1fa8bbba7e3d8eaba66d8e082c735bc185539 100644 (file)
@@ -250,11 +250,13 @@ $default =
               'monthly_quota' => 15000000,
               'uploads' => true,
               '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.
               ),
+        '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' =>
         array('desclimit' => null),
         'group' =>
index 1648980c18c9d4276f13ba4e35a858da071e619f..a4b77702ec5816c1dcd2a1d12e7abf2fb0f8deff 100644 (file)
@@ -28,9 +28,7 @@
  * @link      http://status.net/
  */
 
-if (!defined('STATUSNET') && !defined('LACONICA')) {
-    exit(1);
-}
+if (!defined('GNUSOCIAL')) { exit(1); }
 
 /**
  * A wrapper on uploaded files
@@ -335,6 +333,77 @@ class ImageFile
 
         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
@@ -432,4 +501,4 @@ if(!function_exists('imagecreatefrombmp')){
         //    Return image-object
         return $image;
     }
-}
+}   // if(!function_exists('imagecreatefrombmp'))
index a0243c825f673cffcfbf5398555ace1321540a8f..622252324f05832e52d0a91ac08dab4339152d83 100644 (file)
@@ -62,7 +62,7 @@ class InlineAttachmentListItem extends AttachmentListItem
 
     function show()
     {
-        $this->thumb = parent::getThumbInfo();
+        $this->thumb = $this->attachment->getThumbnail();
         if (!empty($this->thumb)) {
             parent::show();
         }
index 1791b1a6981d5dd58d5f580452c9932cea84302f..e1a9d1247c9001f5b29d164317db5fffcd5ca830 100644 (file)
@@ -41,7 +41,6 @@ class MediaFile
     var $fileurl       = null;
     var $short_fileurl = null;
     var $mimetype      = null;
-    var $thumbnailRecord = null;
 
     function __construct(Profile $scoped, $filename = null, $mimetype = null)
     {
@@ -50,12 +49,6 @@ class MediaFile
         $this->filename   = $filename;
         $this->mimetype   = $mimetype;
         $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',
                                     array('attachment' => $this->fileRecord->id));
@@ -110,109 +103,6 @@ class MediaFile
         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)
     {
         $this->maybeAddRedir($file->id, $short);
index 6b5b8d34f2bd2139b82f2a817e0574a994df1675..fab1131648d3df255a5953986f2b71822fdc77b0 100644 (file)
@@ -246,8 +246,8 @@ class oEmbedHelper
         if (isset($data->thumbnail_url)) {
             if (!isset($data->thumbnail_width)) {
                 // !?!?!
-                $data->thumbnail_width = common_config('attachments', 'thumb_width');
-                $data->thumbnail_height = common_config('attachments', 'thumb_height');
+                $data->thumbnail_width = common_config('thumbnail', 'width');
+                $data->thumbnail_height = common_config('thumbnail', 'height');
             }
         }
 
index f577a3247791c2c2382388ee29c39f4b3f3d4216..23ef6940ed1e603125564caa470753dc1cd22979 100644 (file)
@@ -190,8 +190,8 @@ class BookmarkForm extends Form
 
     function scaleImage($width, $height)
     {
-        $maxwidth = common_config('attachments', 'thumb_width');
-        $maxheight = common_config('attachments', 'thumb_height');
+        $maxwidth = common_config('thumbnail', 'width');
+        $maxheight = common_config('thumbnail', 'height');
 
         if ($width > $height && $width > $maxwidth) {
             $height = (int) ((((float)$maxwidth)/(float)($width))*(float)$height);
index 42f45571eb60dba51cec227af06624cf3e8297f8..a8f4dcbb5f2de5321bf2fa73798b808b4c77fcd7 100644 (file)
@@ -44,7 +44,7 @@ class VideoThumbnailsPlugin extends Plugin
      * and disregard any cropping or scaling in the resulting file, as
      * 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.
         // If that's a problem, let's fix it in the calling function.
index 9ae95e2562cf9e047fd54f51bca77e4b778b72f3..adce2555efabb84c6fcb37f01175089951461c3a 100644 (file)
@@ -43,6 +43,7 @@ function main()
         fixupNoticeConversation();
         initConversation();
         fixupGroupURI();
+        fixupFileGeometry();
 
         initGroupProfileId();
         initLocalGroup();
@@ -414,4 +415,33 @@ function initProfileLists()
     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();