# gImage

Definition: | include xpGUI.e sequence img = gImage_from_XPM(sequence xpm), atom transparent_colour=XPG_WHITE) [Other methods of creating a gImage are expected to be added in the future.]
Description: | Creates a platform-specific GdkPixbuf/DIBitmap/HtmlCanvas that can later be drawn onto a gCanvas, or put on a gButton(), gMenu() [leaf nodes only], or gTabs(), or [the very same one] used on all four. xpm: a [locally defined constant] text or sequence of text strings in human readable form (but not a filename). transparent_colour: mainly intended for internal use. (see technicalia). Note that a gImage is not an interface element and cannot be directly added to a layout hierarchy. A gButton(), gMenu(), or gTabs() can accept an xpm string directly and invoke gImage_from_XPM() automatically with when needed the most apt transparent_colour. Of course a gCanvas is regularly blanked, whereas that would only happen to a gImage when deliberate and explicit. Likewise a gCanvas is usually resizeable, whereas a gImage is totally fixed, albeit you might not always want to use all of it. gImageDraw(sequence image, gdx canvas, atom x=0, y=0) This routine should (probably) only ever be invoked from within a REDRAW handler. Any fractional part of x and y (which locate a top left corner on the canvas) is automatically truncated/ignored. ? The ability to transfer some smaller region of image has not yet (bar just now) even been considered, let alone implemented.
pwa/p2js: | Supported.
See Also: | gCanvas
Example: |
    -- demo\xpGUI\gImage.exw
    include xpGUI.e
    constant cut_xpm_txt = """
    19 15 2 1
    . c None
    * c #0000FF
    ...............*...
    .............**....
    ............**.....
    ...........**......
    ..........**.......
    .****....**.....***
    *...**..**...****..
    *...***********....
    .****...****.......
    .......**..........
    ......***..........
    .....*..*..........
    ....*...*..........
    ....*..*...........
    ....***............
    """
    constant cut_xpm = gImage_from_XPM(cut_xpm_txt)

    procedure redraw(gdx canvas, integer w, h)
        gImageDraw(cut_xpm,canvas,w/2-9,h/2-7)
    end procedure

    gdx canvas = gCanvas(redraw),
        dialog = gDialog(canvas,`gImage`,`SIZE=240x80`)
    gSetAttribute(canvas,"BGCLR",XPG_LIGHT_PARCHMENT)
    gShow(dialog)
    gMainLoop()
Notes: | Application icons are usually 32x32. Toolbar bitmaps are 24x24 or smaller. Menu bitmaps and small icons are 16x16 or smaller. Transparent pixels are identified using the colour "None". The first line of an xpm is <wide> <tall> <colours> <chars per pixel> [<hotspot x> <y>]. Currently limited to 1 char per pixel (via an explicit assert), which means 93 possible colours (>1 is just a matter of testing). [No attempt has yet been made to utilise a hotspot in any way.] The colour codes part consists of <colours> lines, each being <code> <key> <colour>. Only the c key is currently supported (not m/s/g4/g), and as above code can currently only be a single character. The colour code can be None for transparency or a hex RGB code (no other [symbolic] names or HSV codes). The pixels part consists of <tall> lines, each being <wide> * <chars per pixel> long. It is considered a very bad idea to try and use spaces anywhere in that, given they could very easily get mangled into tab characters, and worse, with no indication of how many spaces each tab character represents, or any clue where any of the tabstops might be. No extensions are supported (such as XPMEXT or XPMENDEXT). There is no use of, nor any replication of any of the functions or structures of xpmlib [except probably within and private to GTK]. Images created with gImage can be reused in different elements.
Technicalia | Other methods of creating images, perhaps from standard phix sequences or encoded binary strings, and ways of manipulating them, are expected to appear in a later version. While I have shied away from it, there is no real reason why gCanvasText() [renamed?] should not be able to draw onto a gImage, as long as the latter is an appropriate backend-specific thing [and not a phix sequence of pixels]. That could mean resurecting the gdc type (still there in the source code and docs, but commented out in both), and probably renaming all the canvas primitives... Internally, the transparent_colour parameter is set to the (currently private) colours XPG_BTN_BG, XPG_MENUBG, XPG_BTN_IA for inactive buttons, and XPG_MENUHLT for highlit menus, instead of (nearly always) creating (wrong pseudo-transparency) bitmaps that will never actually be used. It is not massively important, quite the opposite. GTK, HTML/JS, and gImageDraw() all handle transparency properly, however that is not the case for buttons and menu items under WinAPI, hence xpGUI creates bitmaps with the specified "background" (when needed both BG and IA/HLT) and uses them instead. Under WinAPI, xpGUI.e maintains a mini-cache of images for each background colour - see xpm_clrs, under GTK each entry is always length 1. Otherwise transparent_colour is (almost/effectively) completely ignored in all other cases (ie the first three just mentioned), though might still go kaboom should you throw XPG_BLACK/NULL at it, so dont do dat, and in fact XPG_WHITE was chosen so it could try all 16,777,215 available colours when looking for an unused one. Supplying the wrong transparent_colour should not be noticeable, just waste a tiny (very tiny) wee bit of memory, whereas obviously and in contrast defining the xpm itself wrong would be very noticeable, more often than not. To avoid pointless CORS violations (I take a very dim view of stupid localhost restrictions), xpGUI is much more concerned with loading images from locally defined data rather than file. At this point in time only xpm is supported. There are plenty of online converters for creating xpm from any image, which will have to suffice, for now at least. Longer term I would not mind handling svg and/or a standalone utility to convert other formats into a suitable/shortest source code snippet, especially png, with jpg, gif, ico, and bmp (etc) being a much lower priority. You could of course use get_text() to open an xpm file, but that would be desktop/Phix only, and may as well just open that file in an editor and copy/paste the contents into a source file, as a string constant. Makes shipping and installing the final product a tad easier, too.