mIRC Home    About    Download    Register    News    Help

Print Thread
#273916 28/04/26 08:10 PM
Joined: Jul 2006
Posts: 4,062
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,062
I'm making a separate, proper request, because the other one about GIF was a bit all over the place.

So basically both /drawpic -o N and $pic(,N).delay are too slow in execution to be able to properly animate most animated GIF which have approximately constant delay of 30-40 ms between frame.
You can check their timing in pretty much any script made to animate a GIF, I'll post the script from Khaled:

Code
test {
  %fname = $getdir $+ mircnow5.gif
  echo fname: %fname
  if ($exists(%fname)) {
    showgif
    return
  }
  var %url = https://www.mirc.com/images/mircnow5.gif
  echo urlget: $urlget(%url,gf,%fname,showgif)
}
showgif {
  if (!$exists(%fname)) return

  %icons = $pic(%fname).icons
  echo icons: %icons

  if (%icons > 0) {
    %frames = $pic(%fname).frames
    echo frames: %frames

    if (%frames > 0) {
      %w = $calc($pic(%fname).width + 20)
      %h = $calc($pic(%fname).height + 20)

      window -pf @test 10 10 %w %h
      drawrect -fr @test $rgb(255,255,255) 1 0 0 %w %h

      %i = 0
      .timergif -m 1 0 showframe
    }
  }
}
showframe {
  if (!$window(@test)) return

  drawrect -nfr @test $rgb(255,255,255) 1 0 0 %w %h
  drawpic -to @test $rgb(0,255,0) 10 10 %i %fname

  %delay = $pic(%fname,%i).delay
  echo i: %i delay: %delay
  .timergif -m 1 %delay showframe

  inc %i
  if (%i >= %frames) %i = 0
}
Again, the mircnow5.gif from mIRC displays fine but that's because delays are huge, or they isn't enough fast frames to notice, or maybe there's another reason but when you're working with more regular gif like the one I tested here https://tenor.com/view/johnny-laugh-four-gif-7446278225827837893, the animation is extremely slow.
I can't stress enough how slow it renders such gif even on modern hardware.
In my test, both /drawpic -o and $pic().delay at frame 1 takes 30ms to execute, and the more the frame number increase, the slow them both become, with /drawpic taking up to 60-70ms to render on the last frame (frame 71th) and $pic().delay taking up to 60ms on that last frame.
Caching the frame and the $pic().delay values and drawing them with drawcopy allows one to animate any GIF properly. But the initialization and caching processus, in my example, means that I'm waiting 3-4 seconds from the moment I want to animate the gif and when it actually starts to display, 3-4 seconds where mIRC is unresponsive in a loop /drawpicing and caching $pic().delay.

I suppose this slowdown is due to mIRC or the GIF lib having to open/close the file twice (/drawpic and $pic()) per frame. Whereas a typical external application displaying an animated GIF wouldn't have to interface anything for a scripting language, so the file is kept open (and more optimization may occur).

Would it be possible to improve the interfacing with the scripting language by keeping the file open ?

/gifopen <handle> <filename>
/drawpic -Ho .... <handle>
$gif(<handle>,N).delay
$gif(<handle>).frames
$gif(<handle>).width
$gif(<handle>).height

Last edited by Khaled; 29/04/26 05:53 AM.

#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Wims #273917 29/04/26 11:55 AM
Joined: Dec 2002
Posts: 3,907
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 3,907
The /drawpic command is a basic image loading command that loads and displays images in windows. It most definitely was not designed to animate images at web browser-level speeds :-) If I remember rightly, the Icon and GIF support was originally added to allow scripters to animate small images in games. It does have a small built-in cache that was designed to allow quick display of previously loaded images but a decision was made long ago not to apply the cache to icons or gifs, since these can have large numbers of frames that fill/overwrite the small cache very quickly. Let's see - this is going to require a bit of time-travel, like your other question about the zero-indexing - the cache cannot be extended because it is bitmap based, which used up memory quickly. Interestingly, looking at the code, it looks like memory was such an issue when /drawpic was added that if there is a memory allocation error during image loading, it will empty the cache one bitmap at a time and retry loading the image again until the cache is completely emptied, before giving up. /drawpic's implementation is a combination of so many design decisions made over decades of adding and extending different features at different times. To implement what you are requesting would actually require a complete rewrite of almost every aspect of /drawpic, including the way GIFs are loaded, the way images are cached, and so on. There are no plans to do this. If you need to display images more quickly, your script will need to cache them itself.

Last edited by Khaled; 29/04/26 04:31 PM.
Joined: Jul 2006
Posts: 4,062
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,062
I see.

mIRC is moving to 64 bits where memory will no longer be an issue so I think it's fine to increase the cache and allow GIF's frame to be cached, I think it's only fair to increase such limit that were made decade ago with different consideration in mind, regardless of this topic.
But I must admit that I would still not be satisfied with a gif showing slowly first and then getting better, I want to display a GIF with normal speed and normal wait from the start.

If you were to animate the GIF natively, it should then be at browser-level speed, so that's ultimately my suggestion.


#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Wims #273923 08/05/26 07:34 AM
Joined: Dec 2002
Posts: 3,907
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 3,907
I think what you are asking for is a built-in image/video viewer/control that just iterates through frames automatically beyond script control. /drawpic's purpose is to display a single image - when it is asked to draw the Nth frame of a GIF/WEBP file, every delta frame preceeding the Nth frame has to be combined up to frame N, depending on key frames, due to the underlying format of GIF/WEBP.

After 30 years, the probability of adding a native GIF control to mIRC is mind-bogglingly close to zero. It's still possible but the odds are so small that we're likely to approach the heat death of the universe, with just enough time left to make a nice cup of tea, before it happens. If you can wait that long, I'll add it to my to-do list :-)

That said, I did some performance profiling and saw a few places where /drawpic can be improved. Changes so far:

1) $pic() was partially reloading images to get width / height / frame / delay values. I have extended the bitmap cache to store these values.

2) The bitmap cache was using too much memory. I have added real-time LZ4 compression/decompression to bitmaps stored in the cache. The performance hit is negligible in the context of timer / script parsing / image display.

3) Because of the LZ4 compression, cache size has been increased from 50 to 500 and GIF/WEBP with mutiple frames are now cached. The LZ4 compression means that the chess gif file example has gone from using 300MB+ when all frames are loaded to just 30MB.

4) I have added a /drawpic -p switch that, when used with -c, will pre-cache all frames by adding them to the bitmap cache on first load as fast as the GIF/WEBP library can manage. This incurs a short delay. But /drawpic will be zippy afterwards.

That's about as much speed as I can squeeze out of this feature, given /drawpic's purpose. See the next beta for these changes.

Joined: Jul 2006
Posts: 4,062
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,062
Thanks for looking into it, everything seems to work as expected, it takes 260ms to load all the frames initially with drawpic -cp (for the laugh.gif, instead of 3 seconds with /drawpic, an hidden picture window and a while loop), after that all the drawpic are done within 2ms (usually under) and the display is smooth.

One question though, can you explain why (change %f accordingly):
//drawpic -c | var %f C:\Users\Ouims\Downloads\laugh.gif,%a 0,%b $pic(%f).frames | while (%a < %b) { var %t $ticksqpc,%d $pic(%f,%a).delay | echo -sg %a : %d in $calc($ticksqpc - %t) | inc %a }
The first call to $pic(,0).delay takes 0ms while the remaining call to $pic(,N).delay with N between 1- take between 4 and 6 ms constantly. This is unexpected.
Quote
0 : 30 in 0
1 : 40 in 6
2 : 30 in 6
3 : 30 in 5
4 : 40 in 6
5 : 30 in 5
6 : 30 in 5
7 : 40 in 6
8 : 30 in 5


#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Wims #273926 09/05/26 02:32 PM
Joined: Dec 2002
Posts: 3,907
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 3,907
If you use $pic() without having cached the whole file first with drawpic -cp, it will need to request the value by re-opening the image every time. I expected this and changed the GIF/WEBP code to only minimally open the image, just enough to get basic information from it, which is why it is far faster than before, but still takes slightly longer after the first index.

Apart from that, note that the multimedia timer is intentionally implemented as a windows message and is throttled to prevent it taking over the GUI, since mIRC is a single-threaded application. This means it is subject to all kinds of delays, eg. there are 50+ other timer-based features/events that are also vying for control. The script parser speed is also subject to the whims of the windows memory allocator. So timers at the level of single-digit millisecond times are unlikely to be consistent. There is no minimum delay - the multimedia timer triggers as fast as Windows and Windows messaging allow. The throttle is that it allows the processing of other windows messages as well.

Aaand... I think we are done with this particular discussion. Enjoy your weekend everyone.

Last edited by Khaled; 10/05/26 06:11 PM.
Joined: Jan 2012
Posts: 388
Pan-dimensional mouse
Offline
Pan-dimensional mouse
Joined: Jan 2012
Posts: 388
mIRC v7.83.5171 | Windows 11 x64

I also recently encountered animation lag while creating a similar script when caching was limited to a small amount. But after the release of a new beta version with improved caching, I decided to retest. I slightly modified the script's source code so that the window would open when clicking a link. Now, after preloading (warming up) all the file's frames using the command /drawpic -cp, the animation plays very quickly, without stuttering, and most likely, in quality it is the same or very close to the animation displayed in the browser. The only problem is that if file is very large, there will be a slight delay before the animation displays the first time you run it. However, can try to smooth this out with double buffering or do not display the window until the file is split into individual frames and fully cached.

Video demonstration from the screen: Test animation in mIRC

Overall this is a significant improvement and I'm happy with how animated files are now displayed in the picture window. This is amazing! Thank.


🌐 https://forum.epicnet.ru 📜 irc.epicnet.ru 6667 #Code | mIRC scripts, help, discuss, examples
Joined: Jul 2006
Posts: 4,062
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,062
Quote
Apart from that, note that the multimedia timer is intentionally implemented as a windows message and is throttled to prevent it taking over the GUI, since mIRC is a single-threaded application. This means it is subject to all kinds of delays, eg. there are 50+ other timer-based features/events that are also vying for control. The script parser speed is also subject to the whims of the windows memory allocator. So timers at the level of single-digit millisecond times are unlikely to be consistent.
I didn't say anything about timers wink

But I've been working with fast multimedia timers in mIRC for a long time, I've seen them evolving.
Back in the days, the best scripters were saying that /timer -ho 1 0 was a way to execute something immediately after the end of the script, well that's certainly not true anymore grin.

Quote
and is throttled to prevent it taking over the GUI, since mIRC is a single-threaded application. This means it is subject to all kinds of delays, eg. there are 50+ other timer-based features/events that are also vying for control.
Right, about that, I have a few observations to make:
-I believe the throttle is on 5ms
-I assume most other timer based features are there only when you're connected to a server.

Now:
//set -u2 %t $ticksqpc | .timer -ho 50 1 echo -sg $!calc($ticksqpc - % $+ t ) $(|) set -u2 % $+ t $!ticksqpc
For me on windows 10, I get (connected to one server) :
Quote
2, 5, 4, 3, 4, 4, 2, 4, 3, 4, 4, 4, 6, 3, 5, 5, 3, 5, 5, 5, 2, 4, 6, 4, 4, 1, 6, 5, 5, 4, 5....
I'm not sure how the throttle is meant to work but if it's supposed to make the next trigger under 5ms impossible, it's not really working (you can even get 0ms sometimes in there), can you elaborate on these timings ?
And it was discussed before but the -c switch (added to -ho) allows one to completely bypass this throttle and get results where most of the results will show 0ms, with '-cho N 0' you get several calls to your alias within the same millisecond.
Meaning that if someone wants a repeated 3ms timer, they can use -cho with 1ms and then do the math with $ticksqpc, and probably get a better result than with -ho N 3, though it's much heavier for mIRC to handle.


#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Khaled #273930 Yesterday at 07:55 AM
Joined: Jan 2012
Posts: 388
Pan-dimensional mouse
Offline
Pan-dimensional mouse
Joined: Jan 2012
Posts: 388
We'll probably also need some additional properties for the identifier:

  • $pic(filename).cache - returns a BOOL value of 1 (true) or 0 (false) indicating whether the file is in the cache or not.
  • $pic(filename).cachesize - returns a INT or FLOAT value representing the amount of cache space occupied by the specified file.



Currently, every time the script is run, before the animation starts to loop, the command is executed /drawpic -cp, which is not needed for files that are in the cache.
This can be avoided by adding a condition to the code that checks whether the file is in the cache, to prevent lag/pause due to unnecessary re-caching.

Example:
Code
if (!$pic(filename).cache) { drawpic -cp @IMG 0 0 $qt(filename) }


🌐 https://forum.epicnet.ru 📜 irc.epicnet.ru 6667 #Code | mIRC scripts, help, discuss, examples
Epic #273931 Yesterday at 01:17 PM
Joined: Jul 2006
Posts: 4,062
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,062
Quote
Currently, each time the script is executed, the image is cached again using /drawpic -cp, even though it may have been cached before and there is no need to do so.
The -p switch is already checking whether or not the frames have been cached.

Last edited by Wims; 1 hour ago.

#mircscripting @ irc.swiftirc.net == the best mIRC help channel

Link Copied to Clipboard