Inherit/extend Uint8Array -- how?

Posted on
  • I'm trying to make a "class" called Color that is a 4-element Uint8Array. The point here is compactness -- I'm trying to minimize the memory footprint, which still having my own "object" with lots of goodness in terms of "methods" on an instance of Color (things like accessing the color as an RGB or HSB 8/8/8 bit triple in 3 of the 4 elements -- the 4th (actually first) specifies the format of the three color values).

    What I can't figure out is how to call Uint8Array from my Color constructor to return an array as a Color class object that can be indexed and behave like a regular Uint8Array, while responding to my custom "methods" in the prototype. So it can be used like this:

    c = new Color([0,100,100,100]); //returns a Uint8Array of [0,100,100,100] that is type Color
    /* invert color */
    c[1] = 255 - c[1];
    c[2] = 255 - c[2];
    c[3] = 255 - c[3];
    /* get HSB version of color from method attached to Color proto */
    c_hsb = c.RGBtoHSB();
    

    Here's how this is set up:

    function Color(c) {
        //what do I do here with 'c' to initialize and return a byte array initialized with 'c', that will return 'true' for 'instanceof(Color)'?
    }
    function proto(){};
    proto.prototype = Uint8Array.prototype;
    Color.prototype = new proto();
    
    a = new Color([255,255,255]);
    

    Of course, with nothing in the Color constructor bur with the Uint8Array prototype inherited, returns an empty object for the assignment to 'a' on the last line -- not surprising. If I do the following:

    function Color(c) {
        return new Uint8Array(c);
    }
    

    In the constructor, I get a Uint8Array type object back, not Color type object (which doesn't surprise me). So, none of the "methods" that are a part of the Color prototype are accessible (except through directly calling them as Color.prototype.method()).

    Any help?

  • Unfortunately, one of the reasons Uint8Array is compact is because it doesn't store class info inside the structure (that might not be 100% JS compliant I'm afraid, but it does save memory). You could just add your functions to Uint8Array.prototype instead?

    However, it looks like you're storing 4 x 8 bit numbers for the colour? In which case you could use a simple number instead - which is even more compact - and just shift the colours in/out as needed.

    So you could just add to Number.prototype and your colours would be super compact, using just one variable per whole colour. It's actually pretty neat - but obviously you'd want to be careful with your naming so it didn't interfere with other things.

  • Thanks for the quick reply, Gordon. I have considered the solution of simply extending the Uint8Array prototype, and in the end of that's the only way, I'll do it. Memory footprint trumps OO elegance for this sort of application.

    I've not given up yet, though. Check out this: Extending JavaScript Arrays While Keeping Native Bracket-Notation Functionality

    I'm playing with this idea as we speak, and will report back on the memory usage if successful. If I can get it to allocate the same amount of memory per instance as simply creating a 4-element Uint8Array -- solved!

    If that doesn't work, I'll take a look at the packing approach you talk about -- a "color" in this scheme is 4 bytes -- one word. A less elegant solution is to simply add member to the Uint8Array prototype called 'color', then bury all the color-related methods in there as properties of the color object, on the prototype.

  • @dwallersv, which consuming methods do you have in mind, that would be simpler in providing the arguments using this Color object?

  • Hey guys!

    I decided to just go with extending Uint8Array by adding my color methods to the prototype. Decided I needed to "get in the MCU thinking mode" -- i.e. small footprint design, rather than my bias toward "elegance".

    Been coding Android stuff for years, memory footprint not really an issue. Rather, elegance, simplicity of interfaces, clever OO design, etc. were important.

    With such a tiny amout of memory to fit in, this has to be very memory efficient to leave room for the actual application!

    Anyway, as I said, moved on... just got the GUI library working with the new, compact Uint8Array(4) type of color "object". Going to shoot a quick video, post and puff up my chest for a bit. It's pretty cool. Watch for the thread over in the General section in an hour or so :-)

  • @dwallersv, like your turn in the road... I do not want to drum my chest, but I'm comforted by

    Decided I needed to "get in the MCU thinking mode" -- i.e. small footprint design, rather than my bias toward "elegance".

    I may have forced myself to go that route earlier... not voluntary, but by some sound, wise (and 'mindfully gentle' shoe horning - say 'kick a..') comments from @Gordon.

    MCs ARE a different world. It does not mean that all good things have to be dropped... some times it is just the 'outward' form, but not the thinking/design inside/behind the endeavour.

    My fight for staying as much as elegant, clean, API/interface-ing, 00-driven in the GUI came to an earlier 'give-in' than yours. I recall some discussion in the main thread about that. Though just recently - after reading @JumJum's contributions of building your own Espruino extension - natively - encouraged me to think about GUI again: having somewhere a fast buffer (add-on to the Espruino boards) and map very fast the changed area into the buffer of the display (DMA-ish). This way an overlay is possible, as well as writing to overlayed areas... (without 'redrawing/rerendering from non-visual source data').

    On the other hand: does a device like Espruino have to do all this work... of a windowing system? ...I'm not so sure about... I'd rather go - for achieving luxury, shiny UIs) - for including powerful servers/services on the internet as well as equally powerful end-devices/user-devices, such as smart phones and tablets... Even if IT IS possible to serve all from the MC, the MC is becomes more and more just a m2m component, and in the whole fabric of ms, some connect to the all-interconnected-world.

    Going for a hybrid, combining approach that includes all kinds of (readily available) devices and infrastructure is the current trend, also the path that Espruino puck.js has taken: BLE <- >hub <-> Internet <-> powerful end-device/user-device. Sensors and BLE battery powered and operational over years without changing the battery, BLE/Internet hub wire-powered, and powerful, universal end-device/user-device battery driven again, but 'constantly' recharged. Displays just suck the life out of a non-wired power source.

    There are though always niches that 'cannot follow the trend'... rightly so.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Inherit/extend Uint8Array -- how?

Posted by Avatar for dwallersv @dwallersv

Actions