Creating image cones- as ornament or stress-buster!

At a time of stressful changes in our world, I used my previously published code to generate conical images of current political figures- and of attractive but politically-ignorant animals. It implements the idea that an image, usually thought of as a Cartesian set of ( x, y) pixels, is equally representable as a polar ( r, theta) set. Just re-plot with same ( or different, scaled) radius, but with the 360 degree angle reduced a bit. Leave a glueing-tab when cutting out. They view un-distorted from directly in front, and weirdly viewed from sides. Print on larger paper to make a mask. They also work well as a 3D mobile if two are stuck back-to-back.

You can decorate a room with the product, or slap/punch it flat in a moment of catharsis. It's a distraction, anyway!

I don't wish to offend anyone's political sensitivities. Using POTUS as an image is no more significant than that my favourite image for this is a dog... In the zip version on my site I include dogs, seals, cows, mice, politicians ( US and UK), etc to get your creative juices going.

You need 200x200 bmp images, ideally cropped to a circle. You really want a frontal view, with nose/mouth/eyes/muzzle/teeth central. It helps to boost brightness and/or contrast. You can alter two variables in the code which control how much the radius is scaled, and how much the 'fan' of r,theta samples is reduced in theta ( which means a larger gap, so a taller, skinnier cone).

Run the program with a suitable image, selected via the dropdown menu. Click the button to transform. Drop the menu again to save as a renamed image. Print it via your favourite painting or DTP software- I generally print them A4 via Libre Office. Enjoy!


Present version of LB code.

Subject to continued change. Feel free to experiment. Code and example images will be on my site.

Note for coders.

It's a useful demonstration of 'GetPixel' in LB. You may notice it works 'backwards'. If you scan the source systematically and plot each (transformed) coordinate you'll get gaps in the result. I scan the RESULT's x/y space and look up the nearest SOURCE point, so there are no gaps. It might be better to generate a weighted average of pixels since this way you seldom look back at the 'centre of a pixel', but I can't see noticeable improvements at the scale I'm using, and it slows the transforming.


    '   **********************************************************
    '   **                                                      **
    '   **   Conical.bas    tenochtitlanuk    21012017          **
    '   **                                                      **
    '   **   To-dos: add angle variable. Scale up output?       **
    '   **                                                      **
    '   **********************************************************


    global pi: pi =4 *atn( 1)
    global image$

    WindowWidth  = 824
    WindowHeight = 500

    graphicbox #w.gb1   2, 2, 400, 400
    graphicbox #w.gb2 410, 2, 400, 400

    button #w.b1, "Convert", [convert], LR, 420, 20

    menu #w, "File",    "Load Image", loadImage,     "Screensave", scrSve,      "Exit", quit

    nomainwin


    open "Inverse circle image" for window as #w

    #w "trapclose [quit]"

    #w.gb1 "down"
    loadbmp "scr", "splashLH.bmp"
    #w.gb1 "drawbmp scr 0 0"

    #w.gb2 "down"
    loadbmp "scr", "splashRH.bmp"
    #w.gb2 "drawbmp scr 0 0"

    handleg1  =hwnd( #w.gb1)
    calldll  #user32, "GetDC", handleg1 as ulong, hDC1 as ulong

    wait

[convert]
    #w.gb2 "fill white"
    for yN =-150 to 150 step 1
        for xN =-150 to 150 step 1
            scan
            if xN =0 and yN =0 then [skip]
            rO      =0.6 *( xN^2 +yN^2)^0.5     '   radius scaled up     by 1 /0.6 to increase result size
            th      =ATAN2( xN, yN)
            tht     =th *1.4                    '   angle scaled down    by 1 /1.4 ( use eg 1.7 for tall steep cone)
            if tht >2 *pi then [skip]
            xO      =int( rO *sin( tht))
            yO      =int( rO *cos( tht))
            xs      =xO +200
            ys      =yO +200
            calldll #gdi32, "GetPixel", hDC1 as ulong, xs as long, ys as long, pixcol as ulong
            bl = int(  pixcol /2^16): gr = int( (pixcol -bl *2^16) / 2^8): re = int(  pixcol -bl *2^16 -gr *2^8)

            #w.gb2 "color "; str$( re) +" " +str$( gr) +" " +str$( bl)
            #w.gb2 "set "; int( 200 +xN); " "; 200 +int( yN)

            scan
          [skip]
        next xN
    next yN

    #w.gb2   "flush"

    wait


function ATAN2( y, x)
    Result$ = "Undetermined"
    If ( x =0) and ( y >0) then ATAN2 = pi /2:      Result$ ="Determined"
    if ( x =0) and ( y <0) then ATAN2 =3 * pi /2:   Result$ ="Determined"
    if ( x >0) and ( y =0) then ATAN2 =0:           Result$ ="Determined"
    if ( x <0) and ( y =0) then ATAN2 =pi:          Result$ ="Determined"

    If Result$ <>"Determined" then
        if x =0 and y =0 then
            ATAN2 =0
        else
            BaseAngle =ATN( abs( y) /abs( x))
            If ( x >0) and ( y >0) then ATAN2 =       BaseAngle
            If ( x <0) and ( y >0) then ATAN2 = pi   -BaseAngle
            If ( x <0) and ( y <0) then ATAN2 = pi   +BaseAngle
            If ( x >0) and ( y <0) then ATAN2 = 2*pi -BaseAngle
        end if
    end if
End Function

sub scrSve
    #w.gb2 "getbmp scr 0 0 400 400"
    bmpsave "scr", word$( image$, 1, ".") +"Cone.bmp"
end sub

sub loadImage
    filedialog "Load image", "*.bmp", image$
    if image$ ="" then end
    loadbmp "target", image$
    #w.gb1   "fill white ; drawbmp target 100 100 ; flush"
end sub

sub quit 'h$
    callDll #user32, "ReleaseDC", handleg1 as ulong, hDC1 as ulong, result as long
    close #w
    end
end sub

[quit]
    callDll #user32, "ReleaseDC", handleg1 as ulong, hDC1 as ulong, result as long
    close #w
    end