-
Notifications
You must be signed in to change notification settings - Fork 531
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FEATURE] Introduce image metadata #266
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
<?php | ||
namespace Imagine\Image\Metadata; | ||
|
||
/* | ||
* This file is part of the Imagine package. | ||
* | ||
* (c) Bulat Shakirzyanov <mallluhuct@gmail.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
use Imagine\Image\ImageInterface; | ||
|
||
/** | ||
* Metadata driven by Exif information | ||
*/ | ||
class ExifMetadata implements MetadataInterface | ||
{ | ||
/** | ||
* @var ImageInterface | ||
*/ | ||
protected $image; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
protected $exifData; | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function __construct(ImageInterface $image) | ||
{ | ||
$this->image = $image; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getOrientation() | ||
{ | ||
if ($this->exifData === null) { | ||
$this->initialize(); | ||
} | ||
if (isset($this->exifData['Orientation'])) { | ||
return $this->exifData['Orientation']; | ||
} | ||
return null; | ||
} | ||
|
||
/** | ||
* Prepares the EXIF data, used for lazy-loading. | ||
* Should be called at first of any getter operation to make sure the exifData array is filled. | ||
*/ | ||
protected function initialize() | ||
{ | ||
$exifData = exif_read_data('data://image/jpeg;base64,' . base64_encode($this->image->get('jpg'))); | ||
if ($exifData !== false) { | ||
$this->exifData = $exifData; | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<?php | ||
namespace Imagine\Image\Metadata; | ||
|
||
/* | ||
* This file is part of the Imagine package. | ||
* | ||
* (c) Bulat Shakirzyanov <mallluhuct@gmail.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
use Imagine\Image\ImageInterface; | ||
|
||
/** | ||
* An interface for Image Metadata | ||
*/ | ||
interface MetadataInterface | ||
{ | ||
/** | ||
* Constants representing how the orientation of the actual scene is mapped onto the presented image, | ||
* inspired by Exif's Orientation tag | ||
* @see http://sylvana.net/jpegcrop/exif_orientation.html | ||
*/ | ||
const ORIENTATION_NORMAL = 1; | ||
const ORIENTATION_FLIPPED_HORIZONTALLY = 2; | ||
const ORIENTATION_ROTATED_180 = 3; | ||
const ORIENTATION_FLIPPED_VERTICALLY = 4; | ||
const ORIENTATION_ROTATED_MINUS90_FLIPPED_VERTICALLY = 5; | ||
const ORIENTATION_ROTATED_MINUS90 = 6; | ||
const ORIENTATION_ROTATED_90_FLIPPED_VERTICALLY = 7; | ||
const ORIENTATION_ROTATED_90 = 8; | ||
|
||
/** | ||
* @param ImageInterface $image | ||
*/ | ||
public function __construct(ImageInterface $image); | ||
|
||
/** | ||
* Returns an orientation integer inspired by Exif's Orientation tag | ||
* | ||
* @return integer | ||
*/ | ||
public function getOrientation(); | ||
} |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
<?php | ||
namespace Imagine\Test\Image; | ||
|
||
/* | ||
* This file is part of the Imagine package. | ||
* | ||
* (c) Bulat Shakirzyanov <mallluhuct@gmail.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
use Imagine\Image\Metadata\ExifMetadata; | ||
use Imagine\Image\Metadata\MetadataInterface; | ||
|
||
/** | ||
*/ | ||
class ExifMetadataTest extends \PHPUnit_Framework_TestCase | ||
{ | ||
/** | ||
* @test | ||
*/ | ||
public function getOrientationReturnsNullIfNoRotationIsGiven() | ||
{ | ||
$metadata = new ExifMetadata($this->getImageMock('large.jpg')); | ||
$this->assertNull($metadata->getOrientation()); | ||
} | ||
|
||
/** | ||
* @test | ||
*/ | ||
public function getOrientationReturnsCorrectRotationIfExifDataSaysSo() | ||
{ | ||
$metadata = new ExifMetadata($this->getImageMock('exifOrientation/90.jpg')); | ||
$this->assertSame(MetadataInterface::ORIENTATION_ROTATED_MINUS90, $metadata->getOrientation()); | ||
} | ||
|
||
/** | ||
* Gets an image mock for use with the ExifMetadata constructor | ||
* | ||
* @param string $fixtureImage | ||
* @return \Imagine\Image\ImageInterface | ||
*/ | ||
protected function getImageMock($fixtureImage) | ||
{ | ||
$mock = $this->getMock('Imagine\Image\ImageInterface'); | ||
$mock->expects($this->atLeastOnce())->method('get')->with('jpg')->will($this->returnValue(file_get_contents('tests/Imagine/Fixtures/' . $fixtureImage))); | ||
return $mock; | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in case the image is big, this will use a lot of memory (base64 will use 33% more memory than the image has in size).
Would it make sense to dump the image to a file (if it is not already one) and let
exif_read_data
read from the file? This would not eat php's memory, but might be slower.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
another alternative would be to use a stream-filter for base64-encoding. this will help against memory limitations without the need to dump the file.. use something like the following with an in-memory stream:
stream_filter_append($fh, 'convert.base64-encode');
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, that's right.
I've propose an enhancement on top of this PR (see https://github.com/afoeder/Imagine/pull/1) that address this comment (in case
ImagineInterface::open
is used)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your proposition is smart. I'll fix my PR with it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@staabm I've tried your proposition, but as long as
exif_read_data
does not accept streams, the data URI must be computed before calling this function. I can't figure how we could youstream_filter_append
as you mentioned. See :There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@evert any idea whats going on in the example above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using the stream filter doesn't make much sense here. You're not saving any memory by letting a stream filter do the encoding, rather than base64 encode, because the input (
$data
) and the output (thedata://
url) are still strings.However, i think the reason the stream filter is failing, is because you probably need to use
STREAM_FILTER_WRITE
instead.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohhh right, it won't save memory until
exif_read_data
will accept a stream.... Will try your fix nevertheless, thanks.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tested it now and it works when used like this:
I measured memory consumption with the teststring
$data = str_repeat('lalaaaa', 5000);
and it seems that using the in-memory stream consumes even more memory - I think mainly because of the buffer not beeing free'd yet.To put it into a nutshell: atm there is no benefit when using streams here. I would leave it as is, until
exif_read_data
supports streams or someone encounters the problem of insufficient memory and then one could reconsider using a tempfile for this to cut memory consumption by ~75%There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm available for contract work to write a pure-php implemenation for reading exif data using streams ;) should be no more than 5 hours