• Color parsing

    From Kirkman@GUARDIAN to All on Sunday, December 03, 2017 13:21:29
    Quick question for DM or echicken or whoever:

    If I have a Synchronet color value that's already been set (for example, I read the .attr of a character in a frame), how can I parse it to determine the foreground color and background color?

    I imagine it requires using bitwise operators. I've never really understood that part.

    --Josh

    ////--------------------------------------------------
    BiC -=- http://breakintochat.com -=- bbs wiki and blog

    ---
    ■ Synchronet
  • From echicken@ECBBS to Kirkman on Sunday, December 03, 2017 15:28:23
    Re: Color parsing
    By: Kirkman to All on Sun Dec 03 2017 13:21:29

    If I have a Synchronet color value that's already been set (for example, I read the .attr of a character in a frame), how can I parse it to determine the foreground color and background color?

    I imagine it requires using bitwise operators. I've never really understood that part.

    A colour attribute byte has a bunch of information packed into it, so you need to mask out various subfields to see what values they hold.

    The foreground colour is in the lower three bits of the byte.

    var fg = attr&7; // 7 is essentially (1<<0)|(1<<1)|(1<<2)

    The 'high' (or 'bold' or 'bright') status of the foreground colour is in bit 3:

    var b = attr&HIGH; // Bright if > 0; HIGH is 8 or (1<<3) or 0x08

    The background colour is bits 4 through 6:

    var bg = attr&(7<<4);

    Lastly there's the BLINK attribute, 128 or (1<<7) or 0x80:

    var blink = attr&BLINK; // Blinking if > 0, else this is inoffensive text.

    When you want to parse it there are a few options:

    switch (fg|b) {
    case BLUE:
    break;
    case LIGHTBLUE:
    break;
    // and so on
    default:
    break;
    }

    switch (bg) {
    case BG_BLUE:
    break;
    // and so on
    default:
    break;
    }

    You could get away with using the same switch () for either one, but you would have to shift the bg value over. The background colours are the same as the foreground colours, just shifted 4 bits to the left:

    function get_colour(c) {
    switch (c) {
    case BLUE:
    break;
    case LIGHTBLUE:
    break;
    // and so on
    default:
    break;
    }
    }

    var fgc = get_colour(fg|b);
    var bgc = get_colour(bg>>4);

    Bitwise stuff takes some getting used to, but is easy enough once you get the hang of it.

    (I may have made several mistakes in the above, I'm just going from memory.)

    ---
    echicken
    electronic chicken bbs - bbs.electronicchicken.com - 416-273-7230
    ■ Synchronet ■ electronic chicken bbs - bbs.electronicchicken.com
  • From echicken@ECBBS to Kirkman on Sunday, December 03, 2017 15:32:27
    Re: Color parsing
    By: echicken to Kirkman on Sun Dec 03 2017 15:28:23

    switch (fg|b) {

    That was meant to be 'switch (fg | b)'. I forgot about pipe codes in messages.

    var fgc = get_colour(fg|b);

    Likewise, 'get_colour(fg | b)'.

    ---
    echicken
    electronic chicken bbs - bbs.electronicchicken.com - 416-273-7230
    ■ Synchronet ■ electronic chicken bbs - bbs.electronicchicken.com
  • From Kirkman@GUARDIAN to echicken on Sunday, December 03, 2017 14:36:33
    Re: Color parsing
    By: echicken to Kirkman on Sun Dec 03 2017 03:28 pm

    The foreground colour is in the lower three bits of the byte.
    var fg = attr&7; // 7 is essentially (1<<0)|(1<<1)|(1<<2)

    Wow, that was fast! Thanks, echicken.

    I was looking around online and experimenting with a bitwise calculator, and I ended up doing something like this:

    // Use bitwise AND with a mask to get the four rightmost bits.
    // dec 15 | bin 00001111 | hex 0xf
    var fg = theAttr & 15;

    // Use bitwise AND with a mask to get the four leftmost bits.
    // dec 240 | bin 11110000 | hex 0xf0
    var bg = theAttr & 240;

    I think it's working, but I have other issues in my code to sort out before I can say 100%.

    Then I'm doing fg = fg & 7 to change high colors into low equivalents.

    --Josh

    ////--------------------------------------------------
    BiC -=- http://breakintochat.com -=- bbs wiki and blog

    ---
    ■ Synchronet
  • From Digital Man to Kirkman on Sunday, December 03, 2017 13:12:23
    Re: Color parsing
    By: Kirkman to echicken on Sun Dec 03 2017 02:36 pm

    Re: Color parsing
    By: echicken to Kirkman on Sun Dec 03 2017 03:28 pm

    The foreground colour is in the lower three bits of the byte.
    var fg = attr&7; // 7 is essentially (1<<0)|(1<<1)|(1<<2)

    Wow, that was fast! Thanks, echicken.

    I was looking around online and experimenting with a bitwise calculator, and I ended up doing something like this:

    // Use bitwise AND with a mask to get the four rightmost bits.
    // dec 15 | bin 00001111 | hex 0xf
    var fg = theAttr & 15;

    // Use bitwise AND with a mask to get the four leftmost bits.
    // dec 240 | bin 11110000 | hex 0xf0
    var bg = theAttr & 240;

    I think it's working, but I have other issues in my code to sort out before I can say 100%.

    Then I'm doing fg = fg & 7 to change high colors into low equivalents.

    It's a little odd to be using decimal numbers in bit-wise operations (e.g. 0xf0 makes more sense than 240, given the context).

    But I would usually use macros or constants for these magic numbers anyway. Like so (in JS):

    const BG_COLOR = 0x70;
    const FG_COLOR = 0x07;

    The BLINK and HIGH bit values are already defined in sbbsdefs.js (along with all the color bit values).

    Anyway, so parsing the foreground color with the high/bright flag:

    var fg_color = attr & (FG_COLOR | HIGH);

    var bg_color = attr & BG_COLOR; // exclude the blink flag

    To convert the background color to a foreground color, just shift-right 4-bits.

    var color = bg_color >> 4; // move the upper nibble to the lower

    Then you could compare 'color' against the color values defined in sbbsdefs.js (e.g. RED, BLUE, etc.).

    To convert a foreground color to a background color, shift-left:

    var bg_color = (color & FG_COLOR) << 4;

    If you know that "color" won't include the HIGH flag or any other values than 0-7, then you don't need the "& FG_COLOR" part.

    And the reason for all this madness? https://en.wikipedia.org/wiki/Color_Graphics_Adapter
    :-)

    digital man

    Synchronet "Real Fact" #64:
    Synchronet PCMS (introduced w/v2.0) is Programmable Command and Menu Structure. Norco, CA WX: 67.9°F, 56.0% humidity, 0 mph ESE wind, 0.00 inches rain/24hrs