func Encode(img image.Image, format string) ([]byte, error) {
	tmp := toNRGBA(img)
	i := C.mapnik_image_from_raw(
		(*C.uint8_t)(unsafe.Pointer(&tmp.Pix[0])),
		C.int(tmp.Bounds().Dx()),
		C.int(tmp.Bounds().Dy()),
	)
	defer C.mapnik_image_free(i)
	cformat := C.CString(format)
	b := C.mapnik_image_to_blob(i, cformat)
	if b == nil {
		return nil, errors.New("mapnik: " + C.GoString(C.mapnik_image_last_error(i)))
	}
	C.free(unsafe.Pointer(cformat))
	defer C.mapnik_image_blob_free(b)
	return C.GoBytes(unsafe.Pointer(b.ptr), C.int(b.len)), nil
}
Encode image.Image with Mapniks image encoder.
This is optimized for *image.NRGBA or *image.RGBA.
package mapnik
import "C"
import (
	"errors"
	"fmt"
	"image"
	"image/color"
	"image/draw"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"unsafe"
)
type LogLevel int
var (
	None  = LogLevel(C.MAPNIK_NONE)
	Debug = LogLevel(C.MAPNIK_DEBUG)
	Warn  = LogLevel(C.MAPNIK_WARN)
	Error = LogLevel(C.MAPNIK_ERROR)
)
var (
	fontPath   = "/usr/local/lib/mapnik/fonts"
	pluginPath = "/usr/local/lib/mapnik/input"
)
func init() {
	if err := RegisterDatasources(pluginPath); err != nil {
		fmt.Fprintf(os.Stderr, "MAPNIK: %s\n", err)
	}
	if err := RegisterFonts(fontPath); err != nil {
		fmt.Fprintf(os.Stderr, "MAPNIK: %s\n", err)
	}
}
func RegisterDatasources(path string) error {
	fileInfos, err := ioutil.ReadDir(path)
	if err != nil {
		return err
	}
	for _, file := range fileInfos {
		cs := C.CString(filepath.Join(path, file.Name()))
		defer C.free(unsafe.Pointer(cs))
		if C.mapnik_register_datasource(cs) == 0 {
			e := C.GoString(C.mapnik_register_last_error())
			if e != "" {
				return errors.New("registering datasources: " + e)
			}
			return errors.New("error while registering datasources")
		}
	}
	return nil
}
func RegisterFonts(path string) error {
	fileInfos, err := ioutil.ReadDir(path)
	if err != nil {
		return err
	}
	for _, file := range fileInfos {
		fullPath := filepath.Join(path, file.Name())
		if !isFontFile(fullPath) {
			continue
		}
		cs := C.CString(fullPath)
		defer C.free(unsafe.Pointer(cs))
		if C.mapnik_register_font(cs) == 0 {
			e := C.GoString(C.mapnik_register_last_error())
			if e != "" {
				return errors.New("registering fonts: " + e)
			}
			return errors.New("error while registering fonts")
		}
	}
	return nil
}
func isFontFile(path string) bool {
	ext := strings.ToLower(filepath.Ext(path))
	return (ext == ".ttf" ||
		ext == ".otf" ||
		ext == ".woff" ||
		ext == ".ttc" ||
		ext == ".pfa" ||
		ext == ".pfb" ||
		ext == ".dfont")
}
func LogSeverity(level LogLevel) {
	C.mapnik_logging_set_severity(C.int(level))
}
type version struct {
	Numeric int
	Major   int
	Minor   int
	Patch   int
	String  string
}
var Version version
func init() {
	Version.Numeric = int(C.mapnik_version)
	Version.Major = int(C.mapnik_version_major)
	Version.Minor = int(C.mapnik_version_minor)
	Version.Patch = int(C.mapnik_version_patch)
	Version.String = fmt.Sprintf("%d.%d.%d", Version.Major, Version.Minor, Version.Patch)
}
type Map struct {
	m           *C.struct__mapnik_map_t
	width       int
	height      int
	layerStatus []bool
}
func New() *Map {
	return &Map{
		m:      C.mapnik_map(C.uint(800), C.uint(600)),
		width:  800,
		height: 600,
	}
}
func NewSized(width, height int) *Map {
	return &Map{
		m:      C.mapnik_map(C.uint(width), C.uint(height)),
		width:  width,
		height: height,
	}
}
func (m *Map) lastError() error {
	return errors.New("mapnik: " + C.GoString(C.mapnik_map_last_error(m.m)))
}
func (m *Map) Load(stylesheet string) error {
	cs := C.CString(stylesheet)
	defer C.free(unsafe.Pointer(cs))
	if C.mapnik_map_load(m.m, cs) != 0 {
		return m.lastError()
	}
	C.mapnik_apply_layer_off_hack(m.m)
	return nil
}
func (m *Map) Resize(width, height int) {
	C.mapnik_map_resize(m.m, C.uint(width), C.uint(height))
	m.width = width
	m.height = height
}
func (m *Map) Free() {
	C.mapnik_map_free(m.m)
	m.m = nil
}
func (m *Map) SRS() string {
	return C.GoString(C.mapnik_map_get_srs(m.m))
}
func (m *Map) SetSRS(srs string) {
	cs := C.CString(srs)
	defer C.free(unsafe.Pointer(cs))
	C.mapnik_map_set_srs(m.m, cs)
}
func (m *Map) ScaleDenominator() float64 {
	return float64(C.mapnik_map_get_scale_denominator(m.m))
}
func (m *Map) ZoomAll() error {
	if C.mapnik_map_zoom_all(m.m) != 0 {
		return m.lastError()
	}
	return nil
}
func (m *Map) ZoomTo(minx, miny, maxx, maxy float64) {
	bbox := C.mapnik_bbox(C.double(minx), C.double(miny), C.double(maxx), C.double(maxy))
	defer C.mapnik_bbox_free(bbox)
	C.mapnik_map_zoom_to_box(m.m, bbox)
}
func (m *Map) BackgroundColor() color.NRGBA {
	c := color.NRGBA{}
	C.mapnik_map_background(m.m, (*C.uint8_t)(&c.R), (*C.uint8_t)(&c.G), (*C.uint8_t)(&c.B), (*C.uint8_t)(&c.A))
	return c
}
func (m *Map) SetBackgroundColor(c color.NRGBA) {
	C.mapnik_map_set_background(m.m, C.uint8_t(c.R), C.uint8_t(c.G), C.uint8_t(c.B), C.uint8_t(c.A))
}
func (m *Map) printLayerStatus() {
	n := C.mapnik_map_layer_count(m.m)
	for i := 0; i < int(n); i++ {
		fmt.Println(
			C.GoString(C.mapnik_map_layer_name(m.m, C.size_t(i))),
			C.mapnik_map_layer_is_active(m.m, C.size_t(i)),
		)
	}
}
func (m *Map) storeLayerStatus() {
	if len(m.layerStatus) > 0 {
		return  
	}
	m.layerStatus = m.currentLayerStatus()
}
func (m *Map) currentLayerStatus() []bool {
	n := C.mapnik_map_layer_count(m.m)
	active := make([]bool, n)
	for i := 0; i < int(n); i++ {
		if C.mapnik_map_layer_is_active(m.m, C.size_t(i)) == 1 {
			active[i] = true
		}
	}
	return active
}
func (m *Map) resetLayerStatus() {
	if len(m.layerStatus) == 0 {
		return  
	}
	n := C.mapnik_map_layer_count(m.m)
	if int(n) > len(m.layerStatus) {
		return
	}
	for i := 0; i < int(n); i++ {
		if m.layerStatus[i] {
			C.mapnik_map_layer_set_active(m.m, C.size_t(i), 1)
		} else {
			C.mapnik_map_layer_set_active(m.m, C.size_t(i), 0)
		}
	}
	m.layerStatus = nil
}
type Status int
const (
	Exclude Status = -1
	Default Status = 0
	Include Status = 1
)
type LayerSelector interface {
	Select(layername string) Status
}
type SelectorFunc func(string) Status
func (f SelectorFunc) Select(layername string) Status {
	return f(layername)
}
func (m *Map) SelectLayers(selector LayerSelector) bool {
	m.storeLayerStatus()
	selected := false
	n := C.mapnik_map_layer_count(m.m)
	for i := 0; i < int(n); i++ {
		layerName := C.GoString(C.mapnik_map_layer_name(m.m, C.size_t(i)))
		switch selector.Select(layerName) {
		case Include:
			selected = true
			C.mapnik_map_layer_set_active(m.m, C.size_t(i), 1)
		case Exclude:
			C.mapnik_map_layer_set_active(m.m, C.size_t(i), 0)
		case Default:
			selected = true
		}
	}
	return selected
}
func (m *Map) ResetLayers() {
	m.resetLayerStatus()
}
func (m *Map) SetMaxExtent(minx, miny, maxx, maxy float64) {
	C.mapnik_map_set_maximum_extent(m.m, C.double(minx), C.double(miny), C.double(maxx), C.double(maxy))
}
func (m *Map) ResetMaxExtent() {
	C.mapnik_map_reset_maximum_extent(m.m)
}
type RenderOpts struct {
	Scale float64
	ScaleFactor float64
	Format string
}
func (m *Map) Render(opts RenderOpts) ([]byte, error) {
	scaleFactor := opts.ScaleFactor
	if scaleFactor == 0.0 {
		scaleFactor = 1.0
	}
	i := C.mapnik_map_render_to_image(m.m, C.double(opts.Scale), C.double(scaleFactor))
	if i == nil {
		return nil, m.lastError()
	}
	defer C.mapnik_image_free(i)
	if opts.Format == "raw" {
		size := 0
		raw := C.mapnik_image_to_raw(i, (*C.size_t)(unsafe.Pointer(&size)))
		return C.GoBytes(unsafe.Pointer(raw), C.int(size)), nil
	}
	var format *C.char
	if opts.Format != "" {
		format = C.CString(opts.Format)
	} else {
		format = C.CString("png256")
	}
	b := C.mapnik_image_to_blob(i, format)
	if b == nil {
		return nil, errors.New("mapnik: " + C.GoString(C.mapnik_image_last_error(i)))
	}
	C.free(unsafe.Pointer(format))
	defer C.mapnik_image_blob_free(b)
	return C.GoBytes(unsafe.Pointer(b.ptr), C.int(b.len)), nil
}
func (m *Map) RenderImage(opts RenderOpts) (*image.NRGBA, error) {
	scaleFactor := opts.ScaleFactor
	if scaleFactor == 0.0 {
		scaleFactor = 1.0
	}
	i := C.mapnik_map_render_to_image(m.m, C.double(opts.Scale), C.double(scaleFactor))
	if i == nil {
		return nil, m.lastError()
	}
	defer C.mapnik_image_free(i)
	size := 0
	raw := C.mapnik_image_to_raw(i, (*C.size_t)(unsafe.Pointer(&size)))
	b := C.GoBytes(unsafe.Pointer(raw), C.int(size))
	img := &image.NRGBA{
		Pix:    b,
		Stride: int(m.width * 4),
		Rect:   image.Rect(0, 0, int(m.width), int(m.height)),
	}
	return img, nil
}
func (m *Map) RenderToFile(opts RenderOpts, path string) error {
	scaleFactor := opts.ScaleFactor
	if scaleFactor == 0.0 {
		scaleFactor = 1.0
	}
	cs := C.CString(path)
	defer C.free(unsafe.Pointer(cs))
	var format *C.char
	if opts.Format != "" {
		format = C.CString(opts.Format)
	} else {
		format = C.CString("png256")
	}
	defer C.free(unsafe.Pointer(format))
	if C.mapnik_map_render_to_file(m.m, cs, C.double(opts.Scale), C.double(scaleFactor), format) != 0 {
		return m.lastError()
	}
	return nil
}
func (m *Map) SetBufferSize(s int) {
	C.mapnik_map_set_buffer_size(m.m, C.int(s))
}