Git Product home page Git Product logo

Comments (12)

IonoclastBrigham avatar IonoclastBrigham commented on May 31, 2024 1

Possibly we could use (or extract code from) this project: https://github.com/cbowdon/gif-image The last update was from 2012, so it might require some coddling to get it working with Racket 6.x, but possibly we could fork and take over this project too, if it seems salvageable as a whole, rather than just 1 or 2 files or functions.

From the README:

There's plenty of "make animated GIF" apps around, but none that let you split an existing animated GIF up, play around with it and then reassemble it... Racket already includes good procedures for creating GIFs (the file/gif module) but none for taking them apart. So this is something new.

I haven't looked closely at this, but I don't think it handles putting the animation on the screen. That still leaves us to design and implement a robust gif renderer, but I think that could be a valuable spinoff project in and of itself, based on how little my initial searches have turned up.

My first impulse is to subclass and extend canvas% and/or bitmap%. The exact implementation would depend on exactly how we loaded and manipulated the frame data. But I think a gif-aware extension to canvas% would be a pretty swell thing to have. If you intercept calls to load-image or whatever it is, you don't have to worry about synchronizing a render thread with every single event that tries to shove a png on the screen, because the canvas would manage that internally. And I think we can do a lot better than "draw a frame every half second" if we have access to the actual embedded frame timing (which I'm just assuming we'll be able to extract).

Thoughts?

from ivy.

lehitoskin avatar lehitoskin commented on May 31, 2024 1

I messaged the owner of gif-image some time ago about implementing the optimization detection, but he hasn't responded. I recoil at the thought of teaching myself the GIF spec when so much work has been done by others already, so unless or until cbowdon responds and can add what we need, a C library is probably the next best thing.

  • Hopefully the library has few dependencies itself (for packaging with Windows)
  • We would need to get a byte string back from the library, then we can load it into a bitmap or pict
  • A list of frame pixels would be the simplest - gif-image allows for us to get the individual frame delays, so if the library can do that as well, that would be excellent. I imagine if it cannot, then we can supplement that by keeping gif-image for that alone.
  • Drawing to a canvas% or a dc% from C is "probably" possible, but the amount of work required wouldn't be worth it, I think. Having a library that returns a list (or array) of frame bytes would be easiest for me to work with.

As for what library we might look into, with zero investigation I'm going to give libvips an honorable mention. It supports a whole bunch of different formats including GIF.

from ivy.

lehitoskin avatar lehitoskin commented on May 31, 2024

I once made a script that drew each frame of a dissected gif onto a canvas such that after every 0.5 seconds it would load the next frame; however, this was only possible because I had manually dissected the gif beforehand. I remember bringing up this issue before with the people in the Racket IRC channel, but they just let me in on displaying animation in canvases by setting it to an infinite loop.

e.g.

(send canvas set-on-paint!
      (λ ()
        (define dc (send canvas get-dc))
        (define frames (list "frame1.jpg" "frame2.jpg" "frame3.jpg" "frame4.jpg"))
        (define len (length frames))
        (define bmp (make-object bitmap% 50 50))
        (let loop ([frame (first frames)]
                   [i 0])
          (send bmp load-file frame)
          (send dc draw-bitmap bmp 0 0)
          (sleep 1/2)
          (if (>= i len)
              (loop (list-ref frames 0) 0)
              (loop (list-ref frames i) (add1 i))))))

The on-paint procedure could be put in a separate thread and then we could kill the thread once we want to move to another image --- or do anything else. The biggest problem would be getting those frames out of that gif.

The libraries, mrlib/gif and file/gif, are related to gifs but the first one is for saving to disk and the second one is confusing to reason about.

[Edit: library ordering]

from ivy.

lehitoskin avatar lehitoskin commented on May 31, 2024

That's an excellent find! I should have searched through github looking for something myself :P

Hmmm... Perhaps a subclass of bitmap% where we could add 'gif/animation to the list of accepted kind s. A subclass of canvas% would also probably need a subclass of dc%, since that's what we talk to when we want to draw-bitmap or draw-pict.

from ivy.

lehitoskin avatar lehitoskin commented on May 31, 2024

I pushed my WIP code to the animated-gif branch (which uses my fork of the gif-image library). Check it out, but make sure to run it from a terminal. DrRacket will simply error with "out of memory", but running from the terminal will give different errors.

from ivy.

IonoclastBrigham avatar IonoclastBrigham commented on May 31, 2024

So as you'd indicated elsewhere, this works wonderfully, when it works. Some files give weird results. And some just throw an error and break the app.

As such, personally I'd be okay with making this perhaps an optional feature. We can catch those errors, and just fall back on the old way of displaying the first frame if the animation fails.
Perhaps a new "View > GIF Animation" toggle-able menu item, disabled by default.

This would be a good candidate for integration into a more comprehensive Error / Alert system in the UI, so the user knows that yes, we're trying to load the animation, but we're just showing the first frame because of an error we caught. Bonus points if this is easily visible but out of the way and requires no interaction (i.e. not a modal dialog!)

from ivy.

lehitoskin avatar lehitoskin commented on May 31, 2024

Perhaps the message could be placed in the status bar, right in the middle? Something along the lines of "GIF fallback mode".

As for the error/alert system, what I had in mind was indeed a dialog box - do you think that's the wrong way to go?

from ivy.

IonoclastBrigham avatar IonoclastBrigham commented on May 31, 2024

Well I think we'd just want a little indicator somewhere on the UI. A modal would be super annoying if it popped every time you failed to animate a gif, especially if you were just trying to skip through a huge folder of them or something.

Perhaps we're talking about two different systems here, to communicate with the user in different ways.

from ivy.

IonoclastBrigham avatar IonoclastBrigham commented on May 31, 2024

So gif-image's support for the gif standard seems pretty incomplete, or perhaps there's some common but off-spec encoders out there that it's not handling gracefully. In either case it's failing on files that work just fine basically everywhere else, which is unacceptable. That leaves us to either (a) expand / debug the library ourselves, probably requiring a lot of hours tinkering and poring through file format definition documents, or (b) find a replacement.

It's probably worth seeing if it can be fixed easily, but my inclination is toward (b). Based on my initial search, it doesn't seem like there's much out there to be had, for Racket. Thus, we'll likely need to find something written in C and use FFI to wrap it in a tidy racket interface like what you did for SVG support.

So, a few questions for you, @lehitoskin:

  • What would be the requirements of such a library?
  • What kind of data would you need to get back from it, to load frames into a pict% / bitmap% / whatever?
  • Do we just want an array/list of frame pixels so we can do whatever we need to with them, or would it be nice to have something that will handle the animation thread for us, maybe with a draw callback?
  • Is it even possible to draw into a canvas% / dc% from C code, or would we need to call across the C/Racket barrier into a function that would do the drawing for us?

from ivy.

IonoclastBrigham avatar IonoclastBrigham commented on May 31, 2024

Oh, and it looks like libvips already has SWIG integration. It might be pretty simple to get it to generate the Racket bindings for us.

from ivy.

lehitoskin avatar lehitoskin commented on May 31, 2024

lol jk. I just looked at the hex for a few GIF files and accidentally stumbled upon the Graphics Control Extension.

from ivy.

lehitoskin avatar lehitoskin commented on May 31, 2024

Fulfilled in 836ff0f

from ivy.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.