Liipimaginebundle: Provide image width and height in <img> html tag

Created on 5 Oct 2011  路  28Comments  路  Source: liip/LiipImagineBundle

See https://github.com/avalanche123/AvalancheImagineBundle/issues/20

I will try to contribute the code for this later.

New Feature 馃啎

Most helpful comment

To resolve it, I created a twig filter :

<?php 
// src/AppBundle/Twig/PhotoInfos.php
namespace AppBundle\Twig;

class PhotoInfos extends \Twig_Extension
{
    public function getFilters()
    {
        return array(
            new \Twig_SimpleFilter('height', array($this, 'heightFilter')),
        );
    }

    public function heightFilter($relativeSrc)
    {
        list($width, $height) = getimagesize($relativeSrc);
        return $height;
    }

    public function getName()
    {
        return 'photo_infos';
    }
}

In service.yml

app.twig_extension:
        class: AppBundle\Twig\PhotoInfos
        public: false
        tags:
            - { name: twig.extension }

And using it :

<img src="{{ asset('img/'~project.photos.first.photoFileName)|imagine_filter('grid_list') }}" alt="l'heureux nouveau" width="302" height="{{ asset('img/'~project.photos.first.photoFileName)|imagine_filter('grid_list')|height }}"  />

All 28 comments

would be great

After some thought I think this shouldn't belong to LiipImagineBundle as this is completly standalone feature. So I wrote small separate bundle: EstrisaTwigImageTagBundle. Integration with Imagine was not yet tested but as it works with Assetic, there should be no problems.

@lsmith77: if you are interested, I would be thankful for some code review of the library and feeback regarding the code. For a young not-so-experienced programmer any feedback is much appreciated! Thanks.

i will try to find some time in the coming days.

CC @dbu

@mheleniak A point about your documentation: the asset function in Twig has nothing to do with Assetic.

@stof Fixed. If you find something more, let me know by creating an issue. Thanks.

i am reopening .. i need to review the issue .. i am not entirely confused at first sight that this should be handled by a separate bundle ..

Ok.

Anything new regarding this?

ah right .. dropped of my radar .. will get back to you this week.

if i am reading the code right, it will actually fetch the image from the url to determine the dimensions. while i can certainly see this as being useful in cases where the output is cached, it seems to add a lot of overhead in a lot of other use cases.

therefore i think we should also add a loader aware twig extension that will use the configured loader/filter to load the image.

that being said in my application my frontends never have the images locally, because they are served from the backend while the frontend html is always cached in varnish. in this setup your approach makes a lot of sense.

my current approach is sharing the filter configuration between the frontend and backend and then using a twig macro to determine the expected output size based on the configuration, but this obviously doesn't work for cases where users are requesting the original size. it also creates a bit of a tight coupling between specific configurations and my twig macro.

so overall i find your solution interesting and would like to see it added to this bundle. but i would also think that many users who serve their images from the same app would like to see a twig filter that would load, filter and optionally cache the image in order to determine the dimensions and optionally warm the cache in one swoop.

this is digressing from the original topic of the issue, but you talk about caching here: i think we also need a nice way for cache invalidation and optionally active cache checks. as far as i understand, once generated, the images never expire from the cache. it would be simple to have something that can decide if the original image has a more recent timestamp than the cached one. this would help in situations where you do not have tight control over what is uploaded into your system.

btw, warming all of the cache can potentially be very heavy, if there are a lot of images. so it definitely should not happen on the standard cache:warmup event.

imho this is beyond the scope of the bundle. use an HTTP cache to do TTL or invalidation. you can set cache headers by extending the controller or by using LiipCacheControlBundle.

someone did submit a CLI command to the AvalancheImagineBundle to simply purge the entire cache and I think that would be good to have.

Lukas

On 29.10.2011, at 16:19, David [email protected] wrote:

this is digressing from the original topic of the issue, but you talk about caching here: i think we also need a nice way for cache invalidation and optionally active cache checks. as far as i understand, once generated, the images never expire from the cache. it would be simple to have something that can decide if the original image has a more recent timestamp than the cached one. this would help in situations where you do not have tight control over what is uploaded into your system.

btw, warming all of the cache can potentially be very heavy, if there are a lot of images. so it definitely should not happen on the standard cache:warmup event.

Reply to this email directly or view it on GitHub:
https://github.com/liip/LiipImagineBundle/issues/2#issuecomment-2565059

i am not talking about client side caching, just about the filesystem cache of imagine, which is never invalidated afaik. i will try to create a proper issue for this one of these days. lets focus on the width/height topic here.

i was also talking about the server side cache. we have a "stupid" server side cache. if you need more use an HTTP cache like varnish.

Lukas

On 29.10.2011, at 17:55, David [email protected] wrote:

i am not talking about client side caching, just about the filesystem cache of imagine, which is never invalidated afaik. i will try to create a proper issue for this one of these days. lets focus on the width/height topic here.

Reply to this email directly or view it on GitHub:
https://github.com/liip/LiipImagineBundle/issues/2#issuecomment-2565473

@lsmith77

but i would also think that many users who serve their images from the same app would like to see a twig filter that would load, filter and optionally cache the image in order to determine the dimensions and optionally warm the cache in one swoop.

The cache could be file cache or HTTP level cache (Symfony2 proxy, Varnish). The approach which you suggests will work only for file cache. I don't think that's useful change. Keep in mind that current implementation fetches image so we can be sure that images are available. What's the benefit then?

Current implementation is completly standalone and can be used even for static images without Imagine so I think there is no advantage in merging this bundle with LiipImagineBundle.

if i am reading the code right, it will actually fetch the image from the url to determine the dimensions. while i can certainly see this as being useful in cases where the output is cached, it seems to add a lot of overhead in a lot of other use cases.

Can you elaborate? Do you have any suggestions to reduce the overhead? I can see some improvement if we add another caching layer for dimensions matching given url... e.g. same product photos are shown on several pages (category listing page, search results page, product page) or can be used twice on given page. I will try to think of best method for caching this in S2. Any other ideas or suggestions?

my point is there are two viable approaches:
the one in your bundle and the other basically loading the image + applying the filters so that the image size can be determined inside the original request.

and with the later approach if the user has file system caching enabled then we might as well cache the image.

now i think it would make sense to provide both via the same api with a simple flag to decide if to load the image remotely or locally. actually the filter could even try to determine automatically if its a local or a remote image.

Lukas

On 29.10.2011, at 19:34, Mateusz Heleniak [email protected] wrote:

@lsmith77

but i would also think that many users who serve their images from the same app would like to see a twig filter that would load, filter and optionally cache the image in order to determine the dimensions and optionally warm the cache in one swoop.

The cache could be file cache or HTTP level cache (Symfony2 proxy, Varnish). The approach which you suggests will work only for file cache. I don't think that's useful change. Keep in mind that current implementation fetches image so we can be sure that images are available. What's the benefit then?

Current implementation is completly standalone and can be used even for static images without Imagine so I think there is no advantage in merging this bundle with LiipImagineBundle.

if i am reading the code right, it will actually fetch the image from the url to determine the dimensions. while i can certainly see this as being useful in cases where the output is cached, it seems to add a lot of overhead in a lot of other use cases.

Can you elaborate? Do you have any suggestions to reduce the overhead? I can see some improvement if we add another caching layer for dimensions matching given url... e.g. same product photos are shown on several pages (category listing page, search results page, product page) or can be used twice on given page. I will try to think of best method for caching this in S2. Any other ideas or suggestions?

Reply to this email directly or view it on GitHub:
https://github.com/liip/LiipImagineBundle/issues/2#issuecomment-2565913

for this Bundle I still want:
1) a way to get the dimensions by applying the filter during html generation
2) ideally integrate the twig extension from EstrisaTwigImageTagBundle

@lsmith77

2) ideally integrate the twig extension from EstrisaTwigImageTagBundle

As I said in my comment earlier this is completely standalone approach and can also be used e.g. for static layout images. So it does not require LiipImagineBundle IMHO merging does not give any benefits.

well the benefit is that we can provide a single twig function that handles both cases. on top of that it would be one less bundle the user needs to install. now you can argue that there might be users that only need the ability to fetch the dimensions of remote images and therefore it makes sense to keep the feature separately available .. i am not sure how many users really require this alone.

What's the status on this, the bundle mheleniak provided is no longer available

oh .. that is a pitty .. @mheleniak can you shed some light on this?
at any rate .. this functionality hasnt been integrated into the Bundle yet .. I would appreciate it if someone could look into it.

Hi. Come on - this was 10 months ago! Why it is not available? I moved my projects to BitBucket like 8-9? months ago.. and cleaned up old/unused/legacy packages.. and as you can see nobody really missed it. I think the code was so small that it was not of any benefit.

@mheleniak can you add a link?

Guess it's not developed?

Is there any solution to this problem of getting the image dimension of the cached image?

You can resolve the url of cache image, then load the image content to php memory and get width and height using Imagine library for example, It is not optimal I must admit so you use it carefully.

I dont see any other solutions to it for now.

To resolve it, I created a twig filter :

<?php 
// src/AppBundle/Twig/PhotoInfos.php
namespace AppBundle\Twig;

class PhotoInfos extends \Twig_Extension
{
    public function getFilters()
    {
        return array(
            new \Twig_SimpleFilter('height', array($this, 'heightFilter')),
        );
    }

    public function heightFilter($relativeSrc)
    {
        list($width, $height) = getimagesize($relativeSrc);
        return $height;
    }

    public function getName()
    {
        return 'photo_infos';
    }
}

In service.yml

app.twig_extension:
        class: AppBundle\Twig\PhotoInfos
        public: false
        tags:
            - { name: twig.extension }

And using it :

<img src="{{ asset('img/'~project.photos.first.photoFileName)|imagine_filter('grid_list') }}" alt="l'heureux nouveau" width="302" height="{{ asset('img/'~project.photos.first.photoFileName)|imagine_filter('grid_list')|height }}"  />

I know this has been stale since 2015 but I just wanted to provide some clarity if people stumble across this answer as I have.

The issue with the controller solution here is if we decide that the cached images should be protected (for example, so only users who own the image are able to access it). In that instance the recommendation appears to be to create a custom controller which handles the permissions before resolving the file as detailed in 2016 here https://github.com/liip/LiipImagineBundle/issues/817#issuecomment-257194522

Using the solution to get the file data in this way is not longer a valid solution.

I am looking to have more information about the filtered image to give to a user as well. I'd like dimensions, mime type (easy enough to know from the original file) and also the file size.

I'm investigating hooking into getting the correct CacheResolver for the given filter to resolve the file. It may be that we aren't on a local filesystem and instead perhaps storing on S3, and then another file system for a different filter... I think there must be a way to do this whereby we resolve the cacheresolver for the filter and then can get the image. 馃

* EDIT *
So for those finding this I've just traced and the ResolverInterface that cache resolvers implement does not specify a need to be able to get the binary it seems. The resolve functionality is to resolve a URL to the file. So for public S3 instances and such you would get a URL directly to the cached resource. It will save the file in the filesystem provided if it does not exist though after checking the isStored method return value. For my use case I think I'll have to restrict users to using cache resolvers with an extended interface to be able to retrieve the file and provide the data I'm after. Unless I can hook into a way of saving this data directly in the database at the point where the binary is first created... A bit late now but perhaps the second option would be more flexible. Hopefully this puts someone else on the right path in future.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sebastianblum picture sebastianblum  路  6Comments

dariuszp picture dariuszp  路  4Comments

danaki picture danaki  路  6Comments

fueguino84 picture fueguino84  路  3Comments

fabianbartsch picture fabianbartsch  路  3Comments