Optical Illusion Mode - Extreme Rotation!

Really pleased with the results so far with the new images. In the library this one is called “Black Star Acid 2”.

ok, these images bring up some interesting questions … about what works, and what doesn’t and also speed of rotation.

however really to discuss this, I think we all need to see it in action.
so Ive uploaded 2 versions of this to patchstorage, one with 320x320 the other 640x640


the patch is the same, its just what is in the images directory…
… and you can add your own images, just by adding PNGs to that directory … just make sure they have transparent backgrounds.

(just be aware ETC loads all images and all modes, so you can run out of memory if your overzealous :wink: )

to use trigger, changes image - knob1 is speed of rotation, and of course you can change the background colour.

(the two phenakistoscope in the 320 version, will stop knob1 ~ 33%)

ok, so some of my observations… (some of which are probably personal preference )

  • 640x640 , looks nice but is half the frame rate, im only getting around 15 FPS, compared to 30 on 320x320
    … however its arguable if this matters
    I think it probably comes does to … do you want to do anything else with the CPU or not? if you do, then 640 doesnt give you any headroom

  • some things work really well at many speed, others work in quite small windows , where tiny change have some quite subtle and interesting effects.

  • speed… some work well really fast, others seem to work better at quite slow speeds

  • it needs to be in a bound circle, any square edge spoils the effect

… if watch these spinning for too long, it’ll probably drive you crazy :crazy_face: :dizzy_face: :nauseated_face:

hopefully if you play with these, they give you ideas on might work, and also what might be worth modulating… i.e. how do we bring music into the equation…

as i said before the code is trivial, so Id also recommend running up ETC_Web, and playing with it a bit,
in particular:
angle -= (etc.knob1 * 180)

the 180 is the the maximum amount of rotation per frame… so if you want more sensitivity on the knob, which works with some discs well, then reduce 180 to say 60 or whatever…

also as I said @mkunoff you can try different images etc, if you want to see if prepping them differently has an effect or not. (Id say the smaller the image in size, the higher the fps you’ll get)

anyway, i’ll be interested to hear what people think, then we can look to take it further.

You really are so generous doing this. I really really appreciate it!

Can you confirm the dimensions of the image are the cause of the drop in FPS? These images are 24-bit. Would 8 bit improve FPS?

Also, were you able to use the 8-bit 2-color PNG? I got the impression that you would be able to apply color to it. Was that your idea? The sharp look of the images is degraded some when you reduce the color pallete to such a extreme, but I can apply some dither to compensate. If you think it will work, that would be really amazing.

ok, so concentrating on just 3 images (640)

contrazt-01-640.png - 30fps
contrazt-02-640.png - 15fps
8bit_2-colour / contrazt-01-2col-640 - 30fps

(id assume looking at it, contrazt-01-640.png is also 8bit, due to file size)

as i said, I suspect it mainly file size, the more number of bits due to colour, or resolution, the more work the rotation is.

how much does resolution matter, is an interesting question, when the discs are spinning often you cannot focus on the, but sometimes they are really obvious, ( I also think/assume the rotation brings in some artefacts)

btw: you should look at contrazt-02-640.png, you’ll see the ‘centre circle’ has some kind of colour artefacts, not too noticeable when on a white background but quite noticeable if you change the background colour.

also I need to see it on the projector, of course, these artefacts will scale… that said perhaps the projector is not quite as sharp.
also if you switched the image regularly, i guess you might not even get time to notice.

Sorry to keep asking - what about applying color to the 8-bit 2-color image? Possible? Thanks!

Thanks for adding them @thetechnobear :wink: lets get spinning and go :crazy_face:

1 Like

ok, yes… if its an indexed 8 bit image , like 8bit_2-colour, then yes, I can change the colour ,
tested and confirmed :slight_smile:

so that 8bit format , looks like a good one to choose…
its fast and its flexible, i think given we want animation, this is what we need.

btw: tried on my projector (cheap/small) and its definitely a different experience to using on a TV monitor : )

1 Like

Wooooot!! Yes!! I’m out running holiday errands, but I’ll be checking this out tonight. Can’t wait!!!

After some quick tests, I can safely say 8-bit color is the way to go. In this example we’re getting smooth performance from a 640x640 indexed color image. (More indexed color experiments pending!)

1 Like

Good news! Even 8-bit 256 color (with transparency) works great. Output file is a quarter the size of the 24-bit version. I’ll have to play around with dithering settings a bit, but I’m already very happy with the results.

1 Like

OK, so I think I will provide both sets of images (320 and 640 sizes) organized in 8-bit/2-color and 8-bit/full color, with transparency in most cases. I’m pulling some of the images which aren’t working and will likely introduce some new ones!

1 Like

so had a further play with colour palettes

this is potentially quite a fun area to mess with in ETC, as its low cpu… (not just for spinning discs)
as above, I was using monochrome, such that I could turn the black areas to any colour, which is fun for colour animation

then I thought, why not use coloured images with a small colour palette and then start altering other colours in the colour palette, and its seems to work pretty well… and of course gives an extra dimension to play with with sound
(Im interested in what modulation possibilities work, so that the image appears to be connected to the music)

anyway so far , it sees to work best on images that have a restricted palette, just because its simpler to select the index, and also because with a smaller palette theres less dithering… though this is actually more a function of how you prep the images.

Man, it keeps getting better! You do the coding , I’ll prep the images! :wink:
Jus’ kidding, I can’t wait to play around with these patches, but for now it seems I’m more valuable prepping and testing images. I’ll get some 3-4 color examples ready and share them asap.

For this thread we can stick to rotational methods, but your new discovery already has me thinking! Who knew lo-fi color would be so versatile? lol

Happy New Year!
I have revised the images for this project. They are all indexed color PNGs. (No more 24-bit color) For now, these are all 640px sized, but I think the performance on these will be good and 320 may not even be needed. There is a variety of 2-color, 4-color and 32 color images, all with transparency (alpha). I also removed some images which just were not a good fit.

New zip attached! >> images.zip (387.8 KB)


@thetechnobear - I think these new images will work much better than the previous set. Could you update the patch on patch storage?

What do you think is next? How can we apply audio to this patch? I was thinking thinking of a few possibilities/suggestions:

Audio triggers:

  • increment image
  • random image color (8-bit 2-color)

Knob controls:

  • rotation speed
  • image scale
  • image position
  • image color fine control (8-bit 2-color)

ok, Ive updated this on patchstorage here

new images (thanks to @mkunoff) , new controls and now audio input.

controls are:
knob 1 – rotation speed
knob 2 – image
knob 3 – colour index for colour change
knob 4 – ‘foreground’ colour

midi note or audio trig – switch image
audio input – adds to rotation speed

with the limited amount of controls available on the ETC , when I played with it, this seemed the best combo

rotation speed is constant (k1) if you don’t audio coming in, or influenced by the audio volume if you do, seems to work best with ‘beats’

image selection on k2 (but you can increment with audio trig, or midi) , this was because its pretty important for scenes to be able to choose which image you want.

note: image offset cant be stored (due to the way etc works) , so when storing in a scene, you will want to make sure you have not used midi note or audio trig to advance the image. ie. its is the ‘base image index’ that is stored, from there audio trigs and midi trigs will advance the image.

foreground colour and colour work together, this one is fun…
so you select any colour (images should use indexed colour palette) and get it replaced by the foreground colour - varying this by scene, or by when switching images can produce some nice effects.

note: foreground colour, can be one of the cycling colours too.

its pretty sensitive to audio input levels, as this is changing speed rotation, and audio trigs will switch images, so experimentation is necessary.
also rotation is pretty important for this ‘effect’, and has ‘sweet spots’ - so when using audio rotation, its good to also play with knob1.

as I said, having played with the images and sound going thru these seemed to be the best combo, sure other controls would be nice, by given the ETC only has 4 knobs we are limited.

of course, using the ETC web editor its easy for users to create their own variations, if they would prefer to substitute other controls on the knobs


personalised hacks , to get you started

so ETC is all about customising modes to your taste, and music styles… so heres a couple of hacks to get your going and make this yours :slight_smile:

the most obvious one is knob 1…
currently its a constant rotation + audio angle

    chg =   ((etc.knob1 * 180) + audioangle)  

this is so that it can be used without audio input (i.e. constant rotation)

however, some users may prefer to only have it rotating IF there is audio and then use k1 as a scaling factor for the rotation, to do this change the above to:

    chg =   (etc.knob1 * audioangle)  

also if you dont want audio trigs to switch images only midi notes
then change

    if etc.audio_trig or etc.midi_note_new :


    if etc.midi_note_new :

WOW!!! :heart_eyes::hugs:

I’m sitting at my desk at work reading this and I’m starting to feel sick. Might need to leave work early… :smiling_imp::clown_face:

Thank you - thank you - thank you!! I’m going to repay you somehow for this. I’ll start by curating more images. There are some interesting possibilities with the color index idea, that i can take full advantage of. This first set images is just the beginning! Happy Friday!

1 Like

Played with this over the weekend and it’s really awesome. The real winner imo is being able to cycle through the color index. @thetechnobear

It seems this code is responsible for cycling through the color index, yes? Can you give me a little more explanation what is happening here so I can potentially use it on other patches (including ones which don’t rotate.)?

if angle < -360 : angle += 360
    origimg = images[image_index] 
    img = pygame.transform.rotate(images[image_index],angle)
        cidx = 1
        pal = len(origimg.get_palette())
        cidx = int(round(etc.knob3 * pal,0))
        cidx = 0

Also, considering I want to expand further on the “SpinningDiscs” image set, do you think it makes sense to provide the image set on patchstorage.com?

1 Like

easy question first… yes , I think it makes sense to provide the images separately :slight_smile:

colour palette code , is just this bit

        cidx = 1
        pal = len(origimg.get_palette())
        cidx = int(round(etc.knob3 * pal,0))
        cidx = 0

it needs to be in a try/except block, to handle the case where the there is no colour pallet e.g. just a plane rgb image

        pal = len(origimg.get_palette())
        cidx = int(round(etc.knob3 * pal,0))

knob values are 0 to 1, so we simply use the position of the knobs (say half way around = 0.5) and then multiply this by the number of colour in the palette.

then the set_pallette_at, simply changes the colour at that position… with a colour selected by knob4 (this is what etc.color_picker() does)

a couple of things:

  • colour_picker() , has a few basic colours in some positions, but in other positions it returns different values each time its called, so each frame (the colour can be entirely random or just a subset, see the etc_system.py for the code) , thats how you get the changing colours.
  • colour palettes
    ok, a bit of background, just in case someone reads this, and is not clear on what the colour palette is.
    when you save an image with a colour pallet what it does is build a table (the palette) which has all the colour used (more accurately , you specify the max number of colours e.g 1 bit or 8bit, so 2 or 256 colours) , then each pixel is stored as an index into that table… eg. black might be at 0, a shade of red at 5… so to switch colours, you just need to update the palette, e.g. so that pallet[0] = blue , and now all the black turns to blue.
    (the original intention of colour palettes was to save memory, since there are a large number of pixels, so if you save just an index, thats a lot less memory than saving the rgb colour … its kind of a compression algorithm)

Thank you so much @thetechnobear!

The image set is now uploaded to patchstorage.com - https://patchstorage.com/spinningdiscs-image-set/

1 Like