1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-26 16:52:41 +01:00

Improve image thumbnailing and increase the size of Macro thumbnails

Summary:
Alternate proposal for D3635.

  - Works better with small images.
  - Produces a predictable thumbnail size.
  - Somewhat reasonable output on 3000x10 images.
  - Increase the size of Macro thumbnails to 240px.

Test Plan: {F20497}

Reviewers: vrana, chad

Reviewed By: vrana

CC: aran

Differential Revision: https://secure.phabricator.com/D3638
This commit is contained in:
epriestley 2012-10-08 13:26:10 -07:00
parent 74644d5210
commit 85d6f7a66e
6 changed files with 81 additions and 28 deletions

View file

@ -47,6 +47,20 @@ final class PhabricatorImageTransformer {
)); ));
} }
public function executePreviewTransform(
PhabricatorFile $file,
$size) {
$image = $this->generatePreview($file, $size);
return PhabricatorFile::newFromFileData(
$image,
array(
'name' => 'preview-'.$file->getName(),
));
}
private function crudelyCropTo(PhabricatorFile $file, $x, $min_y, $max_y) { private function crudelyCropTo(PhabricatorFile $file, $x, $min_y, $max_y) {
$data = $file->loadFileData(); $data = $file->loadFileData();
$img = imagecreatefromstring($data); $img = imagecreatefromstring($data);
@ -86,27 +100,56 @@ final class PhabricatorImageTransformer {
$x = imagesx($src); $x = imagesx($src);
$y = imagesy($src); $y = imagesy($src);
$scale = min($x / $dx, $y / $dy); $scale = min(($dx / $x), ($dy / $y), 1);
$dst = imagecreatetruecolor($dx, $dy); $dst = imagecreatetruecolor($dx, $dy);
imagesavealpha($dst, true); imagesavealpha($dst, true);
imagefill($dst, 0, 0, imagecolorallocatealpha($dst, 0, 0, 0, 127)); imagefill($dst, 0, 0, imagecolorallocatealpha($dst, 255, 255, 255, 127));
// If we need to chop off some pixels, chop them off from the sides instead $sdx = $scale * $x;
// of scaling in on <0, 0>. $sdy = $scale * $y;
$sdx = $scale * $dx;
$sdy = $scale * $dy;
imagecopyresampled( imagecopyresampled(
$dst, $dst,
$src, $src,
($dx - $sdx) / 2, ($dy - $sdy) / 2,
0, 0, 0, 0,
($x - $sdx) / 2, ($y - $sdy) / 2, $sdx, $sdy,
$dx, $dy, $x, $y);
$sdx, $sdy);
return $dst; return $dst;
} }
private function generatePreview(PhabricatorFile $file, $size) {
$data = $file->loadFileData();
$src = imagecreatefromstring($data);
$x = imagesx($src);
$y = imagesy($src);
$scale = min($size / $x, $size / $y, 1);
$dx = max($size / 4, $scale * $x);
$dy = max($size / 4, $scale * $y);
$dst = imagecreatetruecolor($dx, $dy);
imagesavealpha($dst, true);
imagefill($dst, 0, 0, imagecolorallocatealpha($dst, 255, 255, 255, 127));
$sdx = $scale * $x;
$sdy = $scale * $y;
imagecopyresampled(
$dst,
$src,
($dx - $sdx) / 2, ($dy - $sdy) / 2,
0, 0,
$sdx, $sdy,
$x, $y);
return $this->saveImageDataInAnyFormat($dst, $file->getMimeType());
}
private function saveImageDataInAnyFormat($data, $preferred_mime = '') { private function saveImageDataInAnyFormat($data, $preferred_mime = '') {
switch ($preferred_mime) { switch ($preferred_mime) {
case 'image/gif': // GIF doesn't support true color. case 'image/gif': // GIF doesn't support true color.

View file

@ -55,6 +55,12 @@ final class PhabricatorFileTransformController
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
switch ($this->transform) { switch ($this->transform) {
case 'thumb-220x165':
$xformed_file = $this->executeThumbTransform($file, 220, 165);
break;
case 'preview-220':
$xformed_file = $this->executePreviewTransform($file, 220);
break;
case 'thumb-160x120': case 'thumb-160x120':
$xformed_file = $this->executeThumbTransform($file, 160, 120); $xformed_file = $this->executeThumbTransform($file, 160, 120);
break; break;
@ -133,6 +139,11 @@ final class PhabricatorFileTransformController
return id(new AphrontRedirectResponse())->setURI($uri); return id(new AphrontRedirectResponse())->setURI($uri);
} }
private function executePreviewTransform(PhabricatorFile $file, $size) {
$xformer = new PhabricatorImageTransformer();
return $xformer->executePreviewTransform($file, $size);
}
private function executeThumbTransform(PhabricatorFile $file, $x, $y) { private function executeThumbTransform(PhabricatorFile $file, $x, $y) {
$xformer = new PhabricatorImageTransformer(); $xformer = new PhabricatorImageTransformer();
return $xformer->executeThumbTransform($file, $x, $y); return $xformer->executeThumbTransform($file, $x, $y);

View file

@ -315,6 +315,13 @@ final class PhabricatorFile extends PhabricatorFileDAO {
return '/file/xform/thumb-160x120/'.$this->getPHID().'/'; return '/file/xform/thumb-160x120/'.$this->getPHID().'/';
} }
public function getPreview220URI() {
return '/file/xform/preview-220/'.$this->getPHID().'/';
}
public function getThumb220x165URI() {
return '/file/xform/thumb-220x165/'.$this->getPHID().'/';
}
public function isViewableInBrowser() { public function isViewableInBrowser() {
return ($this->getViewableMimeType() !== null); return ($this->getViewableMimeType() !== null);

View file

@ -99,8 +99,8 @@ final class PhabricatorMacroListController
$item = new PhabricatorPinboardItemView(); $item = new PhabricatorPinboardItemView();
if ($file) { if ($file) {
$item->setImageURI($file->getThumb160x120URI()); $item->setImageURI($file->getThumb220x165URI());
$item->setImageSize(160, 120); $item->setImageSize(220, 165);
if ($file->getAuthorPHID()) { if ($file->getAuthorPHID()) {
$author_handle = $this->getHandle($file->getAuthorPHID()); $author_handle = $this->getHandle($file->getAuthorPHID());
$item->appendChild( $item->appendChild(
@ -112,7 +112,6 @@ final class PhabricatorMacroListController
'div', 'div',
array(), array(),
'Created on '.$datetime)); 'Created on '.$datetime));
} }
$item->setURI($this->getApplicationURI('/edit/'.$macro->getID().'/')); $item->setURI($this->getApplicationURI('/edit/'.$macro->getID().'/'));
$item->setHeader($macro->getName()); $item->setHeader($macro->getName());

View file

@ -68,9 +68,7 @@ final class PhabricatorRemarkupRuleEmbedFile
return $this->getEngine()->storeText($link); return $this->getEngine()->storeText($link);
} }
$attrs = array( $attrs = array();
'class' => 'phabricator-remarkup-embed-image',
);
switch ($options['size']) { switch ($options['size']) {
case 'full': case 'full':
@ -79,9 +77,7 @@ final class PhabricatorRemarkupRuleEmbedFile
break; break;
case 'thumb': case 'thumb':
default: default:
$attrs['src'] = $file->getThumb160x120URI(); $attrs['src'] = $file->getPreview220URI();
$attrs['width'] = 160;
$attrs['height'] = 120;
$link = $file->getBestURI(); $link = $file->getBestURI();
break; break;
} }
@ -92,8 +88,9 @@ final class PhabricatorRemarkupRuleEmbedFile
$embed = phutil_render_tag( $embed = phutil_render_tag(
'a', 'a',
array( array(
'href' => $link, 'href' => $link,
'target' => '_blank', 'class' => 'phabricator-remarkup-embed-image',
'target' => '_blank',
), ),
$embed); $embed);
} }

View file

@ -219,14 +219,10 @@
margin: .5em 1em 0; margin: .5em 1em 0;
} }
img.phabricator-remarkup-embed-image { .phabricator-remarkup-embed-image {
display: inline; display: inline-block;
border: 2px solid white; border: 3px solid white;
background: white; box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.20);
box-shadow: 1px 1px 6px rgba(0,0,0,.5);
-moz-box-shadow: 1px 1px 6px rgba(0,0,0,.5);
-webkit-box-shadow: 1px 1px 6px rgba(0,0,0,.5);
} }
.phabricator-remarkup table.remarkup-table { .phabricator-remarkup table.remarkup-table {