Turned out to be easier than I thought... because openSCAD now can handle faces with more that 3 vertices, I could throw out all Philipp's stuff that I didn't understand. Here's working version:

#!/usr/bin/python

import sys

import png

import urllib

from math import *

from pyopenscad import *

# Wrap a 2D image around a conic surface

# Based on source code by Philipp Tiefenbacher (wizard23)

#

# Frank van der Hulst

# 11 July 2016

# Usage: python conewrap.py imgFile bottomRadius topRadius > output.scad

# Global variables

numRows = 0

numCols = 0

minRadius = 0

# Read a grey-scale PNG and return a table (array of arrays) of pixel values

def getPNG(filename):

r=png.Reader(file=urllib.urlopen(filename))

data = r.read()

pixel = data[2]

raw = []

for row in pixel:

r = []

raw.append(r)

for px in row:

r.append(px)

return raw

# Project a pixel from the bitmap onto a conic surface

# Each pixel represents a unit square

# The height describes the horizontal distance of that pixel from the surface of the cone. Where the cone is reasonably steep, this approximates to how high

# the image is embossed on the cone's surface (positive z values), or how deeply it is recessed into the surface (negative z values)

# bottomRadius and topRadius are the radii of the circles at the bottom and top of the conic fragment. They may be equal for a cylinder, or topRadius may be larger or smaller than bottomRadius.

# topRadius may be zero to produce an actual cone. If bottomRadius < the minimum radius to map the image (e.g. the image is 256 pixels wide && bottomRadius < 40.74 (256/2*pi)), bottomRadius is increased

# cylRange is the fraction (0-1) of the cylinder the image should be wrapped around (e.g. 0.25 means wrapi it around 90 degrees)

def projectCone(x, y, height, bottomRadius, topRadius, cylRange):

# Calculate radial for wrapping

a = x*2*pi/numCols*cylRange

# Calculate distance from axis... linear interpolation between top and bottom radius of the cone

r = topRadius + (bottomRadius-topRadius) * (numRows-y)*1.0/numRows + height

# Calculate 3D coordinate of this point

return [r*cos(a), r*sin(a), y]

# Map the pixMap onto a conic surface with the given radii

def mapImage(pixMap, bottomRadius, topRadius):

minRadius=numCols/(2*pi)

if (bottomRadius < minRadius):

bottomRadius = minRadius

cylRange = minRadius*1.0/bottomRadius

# Generate all the points for the surface

pts = []

for y in xrange(0, numRows):

# Generate a "circle" of points for this layer

for x in xrange(0, numCols):

# Pixels range in value from 0-255, where 0 = black and 255 = white

p = projectCone(x, y, -pixMap[y][x]/255.0, bottomRadius, topRadius, cylRange)

pts.append(p)

# Generate bottom face: A face is 4 indices of points

faces = []

bottom=[]

for x in xrange(0, numCols):

bottom.append(x)

bottom.append(0)

faces.append(bottom)

# Generate all the faces: A face is 4 indices of points

for y in range(0, numRows-1):

for x in range(0, numCols):

p1 = y*numCols+(x+1)%numCols

p2 = y*numCols+x

p3 = (y+1)*numCols+x

p4 = (y+1)*numCols + (x+1)%numCols

f = [p1, p2, p3, p4]

faces.append(f)

# Generate top face if this not a complete cone... NB reverse direction

if (topRadius != 0):

top=[]

for x in xrange(0, numCols):

top.append(numRows*numCols - x)

top.append(numRows*numCols)

faces.append(top)

return polyhedron(pts, faces, 6)

if (len(sys.argv) !=4):

print "Usage: python ", sys.argv[0], "imgFile bottomRadius topRadius > output.scad"

print "e.g. python ", sys.argv[0], "santa-claus-grey.png 45 0 > santa.scad"

exit()

# File to project must be 8-bit greyscale

imgFile = sys.argv[1]

# Radius of the bottom of the cone... if it is less than minRadius, the cone will be expanded to minRadius. If greater than minRadius, a D-shaped partial cone will be produced

# Zero means the output cone's radius will be adjusted to wrap the image exactly once around the cone

coneRadius = float(sys.argv[2])

# Radius of the top of the cone... may be zero

topRadius = float(sys.argv[3])

# Read pixel map from PNG file

pixMap = getPNG(imgFile)

# Flip image upside-down

pixMap.reverse()

numCols = len(pixMap[0])

numRows = len(pixMap)

result = mapImage(pixMap, coneRadius, topRadius)

import time

print time.strftime("// Generated: %Y-%m-%d %H:%M")

print "// Source file: ", imgFile

print "// Image Height = ", numRows

print "// Image Width = ", numCols

print "// Minimum cylinder radius = ", minRadius

print "// Cylinder radius = ", coneRadius

print "$fa=2; $fs=0.5;\n"

print result.render()