Added GIF detection

This commit is contained in:
Marcin Kurczewski 2015-05-23 10:05:05 +02:00
parent 38bfbfb8f3
commit 5412ac14b9
15 changed files with 114 additions and 9 deletions

View file

@ -158,6 +158,9 @@
.post-small.post-type-flash .link::after {
content: 'flash';
}
.post-small.post-type-animation .link::after {
content: 'anim';
}
.post-small .action {
display: none;

View file

@ -2,7 +2,7 @@
var postContentUrl = '/data/posts/' + post.name + '?' + Math.round(Math.random() * 1000) /* reset gif animations */
var width;
var height;
if (post.contentType === 'image' || post.contentType === 'flash') {
if (post.contentType === 'image' || post.contentType === 'animation' || post.contentType === 'flash') {
width = post.imageWidth;
height = post.imageHeight;
} else {
@ -21,7 +21,7 @@
data-height="<%= height %>"
style="max-width: <%= width %>px">
<% if (post.contentType === 'image') { %>
<% if (post.contentType === 'image' || post.contentType === 'animation') { %>
<img alt="<%= post.name %>" src="<%= postContentUrl %>"/>

View file

@ -12,6 +12,7 @@ final class Post extends Entity
const POST_TYPE_FLASH = 2;
const POST_TYPE_VIDEO = 3;
const POST_TYPE_YOUTUBE = 4;
const POST_TYPE_ANIMATED_IMAGE = 5;
const FLAG_LOOP = 1;

View file

@ -37,6 +37,7 @@ class EnumHelper
'video' => Post::POST_TYPE_VIDEO,
'flash' => Post::POST_TYPE_FLASH,
'youtube' => Post::POST_TYPE_YOUTUBE,
'animation' => Post::POST_TYPE_ANIMATED_IMAGE,
];
private static $snapshotTypeMap =

View file

@ -18,6 +18,12 @@ class MimeHelper
return self::getMimeTypeFrom16Bytes(substr($buffer, 0, 16));
}
public static function isBufferAnimatedGif($buffer)
{
return strtolower(self::getMimeTypeFromBuffer($buffer)) === 'image/gif'
and preg_match_all('#\x21\xf9\x04.{4}\x00[\x2c\x21]#s', $buffer) > 1;
}
public static function isFlash($mime)
{
return strtolower($mime) === 'application/x-shockwave-flash';

View file

@ -206,13 +206,24 @@ class PostService
$post->setContentMimeType($mime);
if (MimeHelper::isFlash($mime))
{
$post->setContentType(Post::POST_TYPE_FLASH);
}
elseif (MimeHelper::isImage($mime))
$post->setContentType(Post::POST_TYPE_IMAGE);
{
$post->setContentType(
MimeHelper::isBufferAnimatedGif($content)
? Post::POST_TYPE_ANIMATED_IMAGE
: Post::POST_TYPE_IMAGE);
}
elseif (MimeHelper::isVideo($mime))
{
$post->setContentType(Post::POST_TYPE_VIDEO);
}
else
{
throw new \DomainException('Unhandled file type: "' . $mime . '"');
}
$post->setContentChecksum(sha1($content));
$this->assertNoPostWithThisContentChecksum($post);

View file

@ -41,13 +41,10 @@ final class UpgradeService
if ($this->isUpgradeNeeded($upgrade))
{
if ($verbose)
{
echo 'Running ' . get_class($upgrade) . PHP_EOL;
if (ob_get_level())
ob_flush();
flush();
}
$this->log('Running ' . get_class($upgrade));
$this->runUpgrade($upgrade);
if ($verbose)
$this->log(PHP_EOL);
}
}
}
@ -87,4 +84,12 @@ final class UpgradeService
preg_match('/(\d+)/', $className, $matches);
return intval($matches[1]);
}
private function log($message)
{
echo $message;
if (ob_get_level())
ob_flush();
flush();
}
}

View file

@ -0,0 +1,52 @@
<?php
namespace Szurubooru\Upgrades;
use Szurubooru\Dao\PostDao;
use Szurubooru\Dao\PublicFileDao;
use Szurubooru\DatabaseConnection;
use Szurubooru\Entities\Post;
use Szurubooru\Helpers\MimeHelper;
class Upgrade38 implements IUpgrade
{
private $postDao;
private $fileDao;
public function __construct(
PostDao $postDao,
PublicFileDao $fileDao)
{
$this->postDao = $postDao;
$this->fileDao = $fileDao;
}
public function run(DatabaseConnection $databaseConnection)
{
$posts = $this->postDao->findAll();
$progress = 0;
foreach ($posts as $post)
{
if ($post->getContentType() === Post::POST_TYPE_IMAGE)
{
$fullPath = $this->fileDao->getFullPath($post->getContentPath());
try
{
$contents = file_get_contents($fullPath);
}
catch (\Exception $e)
{
continue;
}
if (MimeHelper::isBufferAnimatedGif($contents))
{
$post->setContentType(Post::POST_TYPE_ANIMATED_IMAGE);
$this->postDao->save($post);
}
if (++ $progress == 100)
{
echo '.';
$progress = 0;
}
}
}
}
}

View file

@ -54,6 +54,7 @@ return [
$container->get(\Szurubooru\Upgrades\Upgrade35::class),
$container->get(\Szurubooru\Upgrades\Upgrade36::class),
$container->get(\Szurubooru\Upgrades\Upgrade37::class),
$container->get(\Szurubooru\Upgrades\Upgrade38::class),
];
}),

View file

@ -5,6 +5,19 @@ use Szurubooru\Tests\AbstractTestCase;
final class MimeHelperTest extends AbstractTestCase
{
public static function animatedGifProvider()
{
return
[
['test_files/video.mp4', false],
['test_files/static.gif', false],
['test_files/animated.gif', true],
['test_files/animated2.gif', true],
['test_files/animated3.gif', true],
['test_files/animated4.gif', true],
];
}
public function testGettingMime()
{
$expected = 'image/jpeg';
@ -38,4 +51,16 @@ final class MimeHelperTest extends AbstractTestCase
$this->assertTrue(MimeHelper::isVideo('application/ogg'));
$this->assertFalse(MimeHelper::isVideo('something else'));
}
/**
* @dataProvider animatedGifProvider
*/
public function testIsAnimatedGif($path, $expected)
{
$fullPath = __DIR__
. DIRECTORY_SEPARATOR . '..'
. DIRECTORY_SEPARATOR . $path;
$actual = MimeHelper::isBufferAnimatedGif(file_get_contents($fullPath));
$this->assertEquals($expected, $actual);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 KiB

BIN
tests/test_files/static.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB