Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

endless looping GIFs with PillowWriter#11789

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
jklymak merged 8 commits intomatplotlib:masterfromt-makaro:master
Oct 16, 2018
Merged

endless looping GIFs with PillowWriter#11789

jklymak merged 8 commits intomatplotlib:masterfromt-makaro:master
Oct 16, 2018

Conversation

t-makaro
Copy link
Contributor

@t-makarot-makaro commentedJul 28, 2018
edited
Loading

PR Summary

Closes#11787 .Adds an optional parameter to PillowWriter that will set the number of times that a GIF will loop for. Defaults to 0 meaning endless looping. Previously defaulted to 1 (never looping) without a way to change it. API change removed.

Makes PillowWriter produce endless looping gifs like ImageMagickWriter and ImageMagickFileWriter.

PR Checklist

  • [ ] Has Pytest style unit tests
  • Code is PEP 8 compliant
  • New features are documented, with examples if plot related
  • Documentation is sphinx and numpydoc compliant
  • Added an entry to doc/users/next_whats_new/ if major new feature (follow instructions in README.rst there)
  • [ ] Documented in doc/api/api_changes.rst if API changed in a backward-incompatible way
  • API consistency

@t-makaro
Copy link
ContributorAuthor

t-makaro commentedJul 28, 2018
edited
Loading

Checklist 1: I have no idea how I would create a pytest for this.

Checklist 3,4: I want to add the loop parameter to thePillowWrite.__init__ docstring, but I believe that I would have to copy the entire docstring fromMovieWriter.__init__, and then add the extra parameter, so that the sphinx-autodoc will work properly. That's that best way I can think of doing it, is it?

Checklist 5: It's a minor new feature. So, I shouldn't add this?
Checklist 6: It is an api change, but it shouldn't break anything? Like who relied on a gif that only looped once?

@jklymak
Copy link
Member

  1. can you interrogate the gif header for the loop parameter? Probably not so important for a test here.

3/4 Maybe just in the MovieWriter doc string say that loop exists if the writer is Pillow. For triple bonus points you could look into the other writers and see if there is a loop method for those.
5/6 I think a whats new entry is good, but no need for an API entry - thats generally only if API is changed, not if some is added.

@WeatherGod
Copy link
Member

WeatherGod commentedJul 28, 2018 via email

In some respects, this could be considered a bugfix. The original gifwriter that uses ImageMagick produces endless loop GIFs. I don't thinkthere is an API parameter for that writer as well.
On Sat, Jul 28, 2018 at 9:34 AM, Jody Klymak ***@***.***> wrote: 1. can you interrogate the gif header for the loop parameter? Probably not so important for a test here. 3/4 Maybe just in the MovieWriter doc string say that loop exists if the writer is Pillow. For triple bonus points you could look into the other writers and see if there is a loop method for those. 5/6 I think a whats new entry is good, but no need for an API entry - thats generally only if API is changed, not if some is added. — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub <#11789 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/AARy-EvtAIRCtbVQ0avD7vZOmx1C2g9Vks5uLGhZgaJpZM4Vk6qM> .

@jklymak
Copy link
Member

Oh, well in that case it’d be good to quickly go through the writers and document their behaviour.

@t-makaro
Copy link
ContributorAuthor

I thought that I'd take a crack a setting the number of loops with ImageMagickWriter. I attempted to modifythis line, but the gif still looped infinitely despitethis doc. I'll stick with just modifying PillowWriter.

@t-makaro
Copy link
ContributorAuthor

Warning, treated as error:/home/circleci/project/doc/users/next_whats_new/endless_gif.rst:document isn't included in any toctree

I think this is just since the next_whats_new toctree is commented out inwhats_new.rst

Copy link
Contributor

@anntzeranntzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

anyone can dismiss once comments handled

@@ -557,6 +557,7 @@ def isAvailable(cls):
def __init__(self, *args, **kwargs):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

__init__(self, *args, loop=False, **kwargs)
or at least make it a boolean.

Argument needs to be documented in some docstring.

Please check for API consistency across writers; if the behavior of other writers is to loop then the default should be changed here.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

The Pillow image.save function takes theloop parameter as an integer, so a gif could be make to loop a set number of times. Also,loop=False might make sense in the docstring, butloop=self.loop whereself.loop isFalse is an endless loop sinceFalse==0. I suppose I could change it toloop=not self.loop, but should we not allow setting to loop say 5 times?

I'll change it to a Boolean if you still want. (I suppose no one needs a gif to loop exactly 137 times!)

I like the move to theloop kwarg in the__init__ function definition. I'll do that for sure.

HTMLWriter and ImageMagick both default to looping I believe, but the ffmpegwriter writing to a .mp4 wouldn't loop. Whether defaulting to loop or not really depends on the format. Gif's should loop, mp4's can't. Different formats have different looping properties (HTMLWriter has a 'reflect' option, so it has adefault_mode parameter that takes a string instead of aloop parameter.

I'll default it to looping (unless you object).

I know that I need to put it in a docstring, but I'm having difficulty figuring out where. I'm not familiar with sphinx-autodoc. I really could use help here. I could write an entire new docstring based off the base class and add the parameter. Or I could do as@jklymak suggested, but then other writers would have a "loop parameter only available in PillowWriter".

@@ -0,0 +1,7 @@
Looping GIFs with PillowWriter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Something went wrong with the formatting.

Copy link
ContributorAuthor

@t-makarot-makaroJul 28, 2018
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I think the file has windows line endings. I will change that. Other than that I don't know.

@jklymak
Copy link
Member

I think you could accept a Boolean and convert to an integer internally; just check if a Boolean. OTOH it’s a bit confusing that 0 is loop and 1 is loop only once. Agree that specifying the number loops is desiarable option

@t-makaro
Copy link
ContributorAuthor

t-makaro commentedJul 28, 2018
edited
Loading

I suppose I could do

self.loop = not loop if isintance(loop, bool) else loop

then set the default toloop=True. Then in whatever docstring say that it accepts a Boolean or an integer that specifies number of loops. This way it is clear that True is endless, False is once, and an integer >=1 is an integer.

What do people think?

@jklymak
Copy link
Member

More that I think about it maybe just make it an integer and value error on anything else so the Boolean doesn’t get passed by accident. Maybe just lay out the options here and folks can vote 🗳 (I’d do it but am on phone). Sorry to drag out a simple change but may as well get it right.

@t-makaro
Copy link
ContributorAuthor

t-makaro commentedJul 28, 2018
edited
Loading

Option 1:
Booleans only.
Pros:

  • Simple.

Cons:

  • can't set a finite >= 1 integer of loops to display.

Implemented as

self.loop=notloop

Option 2:
ints (this is what it currently is, but without the ValueError)
Pros:

  • Can set a finite >= 1 integer of loops to display.

Cons:

  • 0 == infinity

Implemented as

# can't use isinstance since bools are intsiftype(loop)==int:self.loop=loopelse:raiseValueError("loop must be an int")

Option 3:
Both bools and ints
Pros:

  • simple True is endless and False plays once
  • finite number of loops is possible

Cons:

  • We have to explain that both are excepted.

Implemented as

self.loop=notloopifisinstance(loop,bool)elseloop

Documentation will be updated to reflect whatever choice.
I'm in favour of option 2 or 3.

@tacaswelltacaswell added this to thev3.1 milestoneJul 28, 2018
@jklymak
Copy link
Member

I vote 2 + ValueError, just because I think loop=False will actually pass loop=0 if its not caught, but I may be wrong.

@t-makaro
Copy link
ContributorAuthor

I added the ValueError. If we did want to support both bools and ints in the future, then it is easier to add that, then it is to remove support for bools after the fact.

dopplershift
dopplershift previously approved these changesJul 31, 2018
Copy link
Contributor

@dopplershiftdopplershift left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

👍 on the functionality. Minor tweak to theint check if you're interested.

@@ -554,7 +554,38 @@ def isAvailable(cls):
return False
return True

def __init__(self, *args, **kwargs):
def __init__(self, *args, loop=0, **kwargs):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

So much easier to do this now that we're Python 3 only.

output file. Some keys that may be of use include:
title, artist, genre, subject, copyright, srcform, comment.
'''
if type(loop) == int:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

ifnotisinstance(loop,int):raiseValueError(...)self.loop=loop

?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

bools are ints. Sonot isinstance(True, int) will return false. Which will result in passing a value ofTrue aka1 to loop which won't loop, but one would expect loop=True to loop. See my option 3 for a way to implement support for both bools and ints, but this will force justints.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Though I suppose

iftype(loop)!=int:raiseValueError(...)self.loop=loop

But it only saves one of code, and I don't really feel like pushing another commit to this unless I have too 😛.

@dopplershift
Copy link
Contributor

One other question on further thought: since this is not a boolean flag, but a number of loops, should the parameter beloops rather thanloop?

@t-makaro
Copy link
ContributorAuthor

That's not a bad point. But I think that the pluralloops makes the fact that a value of 0 results in endless looping make even less sense. Pillow uses the parameter nameloop, maybe we should just stick with that.

@fredrik-1
Copy link
Contributor

I am looking through the animation module at the moment and based on the available options in all writers at the moment I would say that we could just add unlimited looping also in the pillow writer without any option to change it. Most people want it anyway (but I am not against the option).

I think that a refractoring or at least change in documentation about kwargs should be done in the animation module. At the moment the parameters to the pillow writer are something like,
codec, fps, bitrate, extra_args, metadata but the only one that are not ignored isfps.

So a new API or documentation that clearly show what options that are used in a writer and adding new relevant options should be good.

I have started to change some of the documentation to show which kwargs that are actually used and how.

I would suggest to just add the unlimited looping functionality in a pr and the rest in other prs. Do this really need a test?

loop: int
The number of times that the gif will loop.
A value of 0 is endless.
codec: string or None, optional
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

The rest of the options are just ignored in the pillow writer so I don't think that they should be documented.

@fredrik-1
Copy link
Contributor

fredrik-1 commentedAug 12, 2018
edited
Loading

I thought that I'd take a crack a setting the number of loops with ImageMagickWriter. I attempted to modify this line, but the gif still looped infinitely despite this doc. I'll stick with just modifying PillowWriter.

Changing that line worked for me. I think that both the pillow- and imagemagick writer API should be the same.

One possibility that are not perfect but is in accordance with the current implementation is to put the new kwarg inmoviewriter and just put better documentation in the subclasses which kwargs that are used in that writer.

When both imagemagick and pillow seems to use ints for number of loops with 0 as infinity I think that we should stick to that notation.

Edit:
I would even say that this pr and the extra kwargs in the HTMLWriter breaks the API. It is with those changes not possible to get the same functionality fromanim.save(name, writer=writer_obj, ...) andanim.save(name, writer=string_name_of_writer, ...).

So I believe that all new kwargs should be inMovieWriter andanimation.save

@t-makaro
Copy link
ContributorAuthor

t-makaro commentedSep 18, 2018
edited
Loading

Sorry it's been a while.

In the interest in getting this bug fix done (and leaving me time for my thousand other projects), I've removed all API changes. This PR now does 2 things:

  1. Makes gifs with PillowWriter loop endlessly. Consistent withImageMagickWriter andImageMagickFileWriter.
  2. Adds a simple docstring to PillowWriter.

I'll leave any refractoring/API changes to someone more familiar with this API than me. This PR is now the minimum needed to fix#11789. The suggestedloop keyword argument can be added later.

----------
fps: int
Framerate for the gif.
'''
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

kill the docstring as well for now?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Sure.

Endless Looping GIFs with PillowWriter
--------------------------------------

We acknowledge that most people want to watch a gif more than once. Saving an animatation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

typo (animatation)

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Silly me. Fixed.

Copy link
Contributor

@anntzeranntzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

modulo typo in whatsnew

@anntzeranntzer dismisseddopplershift’sstale reviewSeptember 19, 2018 08:54

@dopplershift I dismissed your review as the scope of the PR has changed; can you check it again?

@t-makaro
Copy link
ContributorAuthor

Ok, I fixed the typo. I believe the doc failures are due to sphinx 1.8.0.

@QuLogic
Copy link
Member

We should have fixed the doc builds now; can you rebase to see if everything's working again?

@t-makaro
Copy link
ContributorAuthor

Last time I tried to rebase a fork, I really messed up the commit history. Any advice?

@jklymak
Copy link
Member

You should have branched your fork before submitting this PR. Right now your PR is based on your master branch, and that will make your life hard.

After that, you'd best givehttps://matplotlib.org/devel/gitwash/index.html a thorough look. In particular pay attention to backing up your branch.

With your setup, I would do:

git checkout mastergit checkout -b backup-of-master  # this will save your bacon if you mess up.git checkout master    # get back to the changes you made in this PRgit fetch upstream   # if you haven't set your 'upstream' remote, then you need to do that first.  git rebase upstream/master  # you don't have any conflicts so this should be smoothgit push origin master --force

If you mess up:

git checkout mastergit reset --hard backup-of-master

will get you locally back to where you were.

t-makaro reacted with thumbs up emoji

@QuLogic
Copy link
Member

This is some redundant branch switching:

git checkout -b backup-of-master # this will save your bacon if you mess up.git checkout master # get back to the changes you made in this PR

git branch backup-of-master will create a branch and not switch to it.

jklymak reacted with thumbs up emoji

@t-makaro
Copy link
ContributorAuthor

@jklymak Your advice seems to have worked. Thank you. I've rebased.

@dstansby
Copy link
Member

Can whoever merges this squash-merge it?

@jklymakjklymak merged commit566bd8b intomatplotlib:masterOct 16, 2018
thoo added a commit to thoo/matplotlib that referenced this pull requestOct 18, 2018
* master: (51 commits)  Disable sticky edge accumulation if no autoscaling.  Avoid quadratic behavior when accumulating stickies.  Rectified plot error (matplotlib#12501)  endless looping GIFs with PillowWriter (matplotlib#11789)  TST: add test for re-normalizing image  FIX: colorbar re-check norm before draw for autolabels  Fix search for sphinx >=1.8 (matplotlib#12216)  Fix some flake8 issues  Don't handle impossible values for `align` in hist()  DOC: add section about test / doc dependencies  DOC: clarify time windows for support  TST: test colorbar tick labels correct  FIX: make minor ticks formatted with science formatter as well  DOC: clarify what 'minor version' means  Adjust the widths of the messages during the build.  Simplify radar_chart example.  Fix duplicate condition in pathpatch3d example (matplotlib#12495)  Fix typo in documentation  FIX: make unused spines invisible  Kill FontManager.update_fonts.  ...
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@fredrik-1fredrik-1fredrik-1 left review comments

@anntzeranntzeranntzer approved these changes

@dstansbydstansbydstansby approved these changes

@dopplershiftdopplershiftdopplershift left review comments

Assignees
No one assigned
Projects
None yet
Milestone
v3.1.0
Development

Successfully merging this pull request may close these issues.

Looping gifs with PillowWriter
10 participants
@t-makaro@jklymak@WeatherGod@dopplershift@fredrik-1@QuLogic@dstansby@anntzer@tacaswell@timhoffm

[8]ページ先頭

©2009-2025 Movatter.jp