Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Better image preloading order #10

Closed
pisi opened this Issue Dec 16, 2010 · 11 comments

Comments

Projects
None yet
3 participants
Owner

pisi commented Dec 16, 2010

Olivier de Broqueville expressed an idea to improve preloading of images by changing the order of loading the frames. He suggested loading the very first image, then the ones to the left and right and progressively continue.

For example (36 frames total, first frame is 1) the loading order would be:

1, 2, 36, 3, 35, 4, 34, 5, 33, 6, 32, 7, 31, 8, 30...

Please vote for this issue!

@ghost ghost assigned pisi May 8, 2011

that would be cool!

cindreta commented Nov 2, 2011

yes this would be a great idea to implement.

Owner

pisi commented Nov 2, 2011

Well, good then I'm working on this feature these days ;)

pisi added a commit that referenced this issue Nov 3, 2011

`$.reel.math.spread` added - accepts an sequence Array, options Objec…
…t and reference to the instance data storage retrieval `get` method. It is then supposed to resort input sequence in better preloading order and return the reordered sequence Array. This one puts first the initial frame and adds one more opposite the initial one. This way it divides the range into two segments and then continues dividing them in halves again and again gradually increasing the image fidelity. #10

pisi added a commit that referenced this issue Nov 3, 2011

As we are now progressively increasing the fidelity, we should be abl…
…e to start the (opening) animation right away without waiting for the preload to finish. #10

pisi added a commit that referenced this issue Nov 3, 2011

As the instance is playing when fully loaded it is not desirable for …
…sequences to set the transparent image `src` attribute, because it introduces a brief flash of void. So we apply it only for sprites. #10

pisi added a commit that referenced this issue Nov 3, 2011

Playing the animation prior preload is complete exhibits caching prob…
…lems - didn't go well. Reverting (at least for tests comparison). #10

pisi added a commit that referenced this issue Nov 4, 2011

Current algorithm was great for single-row setups, whereas multi-row …
…and dual-orbit setups suffered a bit from the even spreading across all rows*frames. Therefore it has been adjusted to better fit multi-rows so that the initial row is completely spread first and the rest of rows follow. This results in much faster availability of the possibly animated initial row. #10

pisi added a commit that referenced this issue Nov 4, 2011

In order to accomodate multi-row tests, the test has been tweaked als…
…o. Also the tested function has been run twice before - fixed. The fix introduced different way of receiving the result by using instance's `.data("images")` instead of calling the function to get the result directly - this however holds whole paths as strings, so adjusting the expected values to be strings instead of numbers for the `deepEqual` comparison. #10

pisi added a commit that referenced this issue Nov 4, 2011

pisi added a commit that referenced this issue Nov 4, 2011

Current algorithm was great for single-row setups, whereas multi-row …
…and dual-orbit setups suffered a bit from the even spreading across all rows*frames. Therefore it has been adjusted to better fit multi-rows so that the initial row is completely spread first and the rest of rows follow. This results in much faster availability of the possibly animated initial row. #10

pisi added a commit that referenced this issue Nov 4, 2011

In order to accomodate multi-row tests, the test has been tweaked als…
…o. Also the tested function has been run twice before - fixed. The fix introduced different way of receiving the result by using instance's `.data("images")` instead of calling the function to get the result directly - this however holds whole paths as strings, so adjusting the expected values to be strings instead of numbers for the `deepEqual` comparison. #10

pisi added a commit that referenced this issue Nov 4, 2011

pisi added a commit that referenced this issue Nov 4, 2011

pisi added a commit that referenced this issue Nov 4, 2011

Changed the initial segmenting from 2 to 4, so by default 4 frames pe…
…r row 90° apart are loaded first and then the "resolution" increases until it's 1:1. #10
Owner

pisi commented Nov 4, 2011

Folks, I soon abandoned the original idea (but that doesn't make it bad at all - it just seems far to linear to me now ;).

Instead, I wanted to build up a solution, which would load the frames in more of a scattered fashion, where the loading "penalty" would be evenly spread amongst all. This way, instead of one large shrinking gap of missing frames, there will be many small shrinking gaps spread evenly across the entire 360° spectrum. Resulting in perceived lower rotation fidelity/quality/smoothness instead of an apparent gap.

So, I tailored a mechanism, which aims to accomplish it. First it queues up one frame each 90° (very rough rotation, but already possible) and then it works with these 4 resulting segments. By progressively halving them, segments are gradually and evenly filled up, increasing the fidelity and smoothnes of the rotation. Speaking in degrees:

  1. First the initial frame would be loaded,
  2. Next are the three remaining: 90°, 180° and 270°,
  3. Then each ninety degree segment is divided in half: 45°, 135°, 225° and 315°,
  4. Then again all segments in half: 22.5°, 67.5°, 112.5°, 157.5°, 202.5°, 247.5°, 292.5° and 337.5°,
  5. And it goes on like this until all frames are queued.

You can see it in action on http://test.vostrel.cz/jquery.reel/test/sampler.html - for sequences the bottom-most section "Images" features all frames in order of preloading (via new data key .data("images")).

For multi-row and dual-orbit movies, the mechanism is the very same with just one difference, that the initial row is queued first and all remaining follow.

I'm pretty happy with the outcome so far. What do you think?

Owner

pisi commented Nov 4, 2011

... and for those wanting to grab the code to test it themselves, it is being developed in a 10-preload-order branch.

cindreta commented Nov 5, 2011

wow your approach does seem to load better, and it has sense. very very nice work.

sidenote: performance wise it's always good to set the width and height tags of the image. so is there a way for jquery reel to add width and hight to the images created from jquery reel array. it can use the same width and height of the main "img" on which the jquery reel is initialised.

thank's man. keep up the good work.

cindreta commented Nov 5, 2011

another question: now what if i was to load a 1x1px(base64 encoded inline image) image for the main and apply the jquery reel on it with a different set of images. would it load eaven faster?

Owner

pisi commented Nov 5, 2011

I've made a little visualisation to help us better understand the so called Increasing Fidelity approach:

Increasing Fidelity Preload Order

From the vis I recognize one possible weakness - the directionality of the (clockwise) queuing. It is still too linear to me, but it'll do.

@cindreta, you are right! Loading with defined dimensions is indeed faster, when the image is to be rendered (not our case, I'm afraid), but I guess it won't hurt and is worth the try. Thanks, it's a good one :)

@cindreta, to your other question: yes, it should be faster. But frankly, saving 1 frame from let's say 36 total isn't a big deal I guess. On the other hand having the entire images sequence array of base64 encoded images would sure be a blast.

pisi added a commit that referenced this issue Nov 5, 2011

As suggested by @cindreta added `width` and `height` attributes to th…
…e preload placeholder `<img>`s to possibly facilitate the speed benefit of loading images with pre-defined dimensions. Using stage dimensions. #10

pisi added a commit that referenced this issue Nov 6, 2011

Isolated the former `spread()` now called `fidelity()` along with `li…
…near()` (which just outputs the input) inside new `$.reel.preload` collection of possible preloading routines. User can now choose one of `"linear"` or `"fidelity"` (or any othe custom for that matter) preloading order using the new `preload` option. Incorrect values are corrected to the default `"fidelity"`. #10
Owner

pisi commented Nov 6, 2011

As a part of this issue a new preload option has been added accepting a preloading mode name String:

  • "linear" - the one going one by one from frame one till the end.
  • "fidelity" - the new one - lo-fi growing to hi-fi

As I want to leave the preloading logic ideally completely up to you, you can set up your own custom preload order function. It has to be defined as a member of $.reel.preload object. Let's say your new mode will be called "my_preload":

$.reel.preload.my_preload = function( sequence, options, get ){
    /*
        Actions performed to reorder the linear input sequence
    */
    return sequence;
}

For the mode to be used, you then set the preload option to "my_preload":

$('#my_image').reel({
    preload: "my_preload"
});

Pull requests with better preloading orders will be warmly welcome! ;)

pisi added a commit that referenced this issue Nov 8, 2011

Current algorithm was great for single-row setups, whereas multi-row …
…and dual-orbit setups suffered a bit from the even spreading across all rows*frames. Therefore it has been adjusted to better fit multi-rows so that the initial row is completely spread first and the rest of rows follow. This results in much faster availability of the possibly animated initial row. #10

pisi added a commit that referenced this issue Nov 8, 2011

In order to accomodate multi-row tests, the test has been tweaked als…
…o. Also the tested function has been run twice before - fixed. The fix introduced different way of receiving the result by using instance's `.data("images")` instead of calling the function to get the result directly - this however holds whole paths as strings, so adjusting the expected values to be strings instead of numbers for the `deepEqual` comparison. #10

pisi added a commit that referenced this issue Nov 8, 2011

pisi added a commit that referenced this issue Nov 8, 2011

pisi added a commit that referenced this issue Nov 8, 2011

Changed the initial segmenting from 2 to 4, so by default 4 frames pe…
…r row 90° apart are loaded first and then the "resolution" increases until it's 1:1. #10

pisi added a commit that referenced this issue Nov 8, 2011

As suggested by @cindreta added `width` and `height` attributes to th…
…e preload placeholder `<img>`s to possibly facilitate the speed benefit of loading images with pre-defined dimensions. Using stage dimensions. #10

pisi added a commit that referenced this issue Nov 8, 2011

Isolated the former `spread()` now called `fidelity()` along with `li…
…near()` (which just outputs the input) inside new `$.reel.preload` collection of possible preloading routines. User can now choose one of `"linear"` or `"fidelity"` (or any othe custom for that matter) preloading order using the new `preload` option. Incorrect values are corrected to the default `"fidelity"`. #10

pisi added a commit that referenced this issue Nov 9, 2011

Current algorithm was great for single-row setups, whereas multi-row …
…and dual-orbit setups suffered a bit from the even spreading across all rows*frames. Therefore it has been adjusted to better fit multi-rows so that the initial row is completely spread first and the rest of rows follow. This results in much faster availability of the possibly animated initial row. #10

pisi added a commit that referenced this issue Nov 9, 2011

In order to accomodate multi-row tests, the test has been tweaked als…
…o. Also the tested function has been run twice before - fixed. The fix introduced different way of receiving the result by using instance's `.data("images")` instead of calling the function to get the result directly - this however holds whole paths as strings, so adjusting the expected values to be strings instead of numbers for the `deepEqual` comparison. #10

pisi added a commit that referenced this issue Nov 9, 2011

pisi added a commit that referenced this issue Nov 9, 2011

pisi added a commit that referenced this issue Nov 9, 2011

pisi added a commit that referenced this issue Nov 9, 2011

Changed the initial segmenting from 2 to 4, so by default 4 frames pe…
…r row 90° apart are loaded first and then the "resolution" increases until it's 1:1. #10

pisi added a commit that referenced this issue Nov 9, 2011

As suggested by @cindreta added `width` and `height` attributes to th…
…e preload placeholder `<img>`s to possibly facilitate the speed benefit of loading images with pre-defined dimensions. Using stage dimensions. #10

pisi added a commit that referenced this issue Nov 9, 2011

Isolated the former `spread()` now called `fidelity()` along with `li…
…near()` (which just outputs the input) inside new `$.reel.preload` collection of possible preloading routines. User can now choose one of `"linear"` or `"fidelity"` (or any othe custom for that matter) preloading order using the new `preload` option. Incorrect values are corrected to the default `"fidelity"`. #10

pisi added a commit that referenced this issue Nov 9, 2011

As suggested by @cindreta added `width` and `height` attributes to th…
…e preload placeholder `<img>`s to possibly facilitate the speed benefit of loading images with pre-defined dimensions. Using stage dimensions. #10

nice, than you man :) gonna go implement the new version right away

Owner

pisi commented Nov 21, 2011

Glad you like it. Merging it into development.

@pisi pisi closed this Nov 21, 2011

pisi added a commit that referenced this issue Dec 30, 2011

1.2 ALPHA is out!
Just missing annotations examples - the'll be in the beta.

Changes:

* Non-`wheelable` Reels now allow scrolling of the page when wheeling above the Reel instance.
* New option `attr` allows to set custom attributes of the IMG tag (useful for re-using DOM nodes).
* Instances being re-instantiated now perform automatic teardown (GH-62).
* Proper image preload events unbinding on teardown (GH-64).
* Option `scrollable` can disable page scrolling (if needed) on touch devices.
* New event `"openingDone"` now announces the end of opening animation (GH-65).
* Internal event `slide` renamed to `pan` (GH-51).
* Actual frame number is manifested with a wrapper class name, e.g. `frame-8` (GH-69).
* Improved order of preloaded images gradually increasing fidelity of the image, thus the name `"fidelity"` and this mode is now default. The former order is designated `"linear". Preloading mode is chosen by new `preload` option accepting a mode name. (GH-10).
* Deprecated options `hotspot`, `tooltip` and `reversed` have been removed.
* Bare click on left/right half of the image steps the Reel one frame forward/back. Set `steppable` to false to disable. Comes with `"stepLeft"` and `"stepRight"` events (GH-20).
* Custom text/graphics can augment the frames using the brand new `annotations` feature (GH-36).
* New complementary `.unreel()` function to revert effects of `.reel()` on the DOM.
* Control event `play` now accepts optional `speed` parameter.
* Mouse cursor is now customizable with the new `cursor` option. The new failsafe cursor is now `"move"`.

pisi added a commit that referenced this issue Jul 16, 2012

When testing I discovered a flaw in the `spread` preloading mechanism…
…. Sample with 6*20 frames revealed a insufficient covering of few frames following the first prioritized row. #10

To resolve this I added a switch, which makes each pass be first substracted from the base, then added, substracted, added... This way has no problems with covering even dark corners ;) Also the rounding now happens only on granule itself, not on the whole result, which had a negative effect of rounding negative numbers in a unsuitable way (-2.5 got rounded to -2, whereas I'd like -3 for the purpose).

pisi added a commit that referenced this issue Jul 16, 2012

Reel 1.2
========

Lovely new features:
* in-picture annotations
* new image preloading method
* frame by frame stepping
* new data change model
* full documentation
* jQuery 1.5+

New options:
* `annotations`, `attr`, `cursor`, `steppable`, improved `images`

New events:
* `stepLeft`, `stepRight`, `openingDone`, improved `play`

New methods:
* `.unreel()`, improved `.reel()`

Includes fixes for issues #10, #20, #36, #51, #62, #64, #65, #69, #103, #110, #111, #113, #115, #117, #122, #124, #125, #126

Enjoy!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment