Example #1
0
File: map2d.go Project: quag/mcobj
func useChunk(chunk *Chunk, img *image.NRGBA, xoffset, zoffset int) error {
	var r, openErr = chunk.Open()
	if openErr != nil {
		return openErr
	}
	defer r.Close()

	var c, nbtErr = nbt.ReadChunkNbt(r)
	if nbtErr != nil {
		return nbtErr
	}

	blocks := Blocks(c.Blocks)

	for x := 0; x < 16; x++ {
		for z := 0; z < 16; z++ {
			column := blocks.Column(x, z)
			v := uint16(0)
			for y := 127; y > 0; y-- {
				if column[y] != 0 {
					v = column[y]
					break
				}
			}
			//fmt.Printf("%7x", color[v&0xff])
			img.Set(xoffset+x, zoffset+z, rgb(color[v&0xff]))
			//fmt.Printf("%7x", img.At(x, z))
		}
		//fmt.Println()
	}

	//fmt.Println()
	return nil
}
Example #2
0
func drawRect(img *image.NRGBA, r image.Rectangle, c color.Color) {
	for i := r.Min.X; i <= r.Max.X; i++ {
		for j := r.Min.Y; j <= r.Max.Y; j++ {
			img.Set(i, j, c)
		}
	}
}
Example #3
0
func setPixel(i *image.NRGBA, x, y int) {
	for zx := 1; zx < 9; zx++ {
		for zy := 1; zy < 9; zy++ {
			i.Set(x*10+zx, y*10+zy, color.RGBA{0, 0, 0, 255})
		}
	}
}
Example #4
0
func render(img *image.NRGBA, startY, limitY int, c chan int) {
	for y := startY; y < limitY; y++ {
		for x := 0; x < img.Rect.Dx(); x++ {
			p := vec.Vec3{float32(float32(x)/float32(img.Rect.Dx()-1) - 0.5),
				float32(-(float32(y)/float32(img.Rect.Dy()-1) - 0.5)),
				-float32(0.8)}
			d := p.Normalized()

			dist, obj := distanceFieldObject(p)
			step := 0
			for ; step < 63 && dist > -0.005*p.Z; step++ {
				// Error decreases 1/d, so keep min step proportional to d for constant screen-space error
				p = p.Add(d, math32.Maxf(-0.005*p.Z, dist))
				if p.Z < -60 {
					break
				}
				dist, obj = distanceFieldObject(p)
			}

			if dist <= -0.01*p.Z {
				n := fieldNormalAt(distanceField, p)
				// compute ambient occlusion before doing bump mapping
				ao := math32.Minf(ambientOcclusion(p, n), 1.0)

				dnoise := fieldNormalAt(noise.Fbm, p)
				const N = 0.3
				n = n.Vtrans(dnoise.Scale(N)).Normalized()

				distfade := math32.Expf(0.07 * (p.Z + 6))
				/*lit := float32(1.0)*/
				lit := math32.Maxf(0, n.Z)
				/*tex := float32(0.8)*/
				tex := (0.4*(math32.Sinf(2*(p.X+1.4*p.Y)+2*noise.Fbm(p))+1) + 0.2)
				v := tex * (lit*0.6 + 0.3) * (ao * ao * ao) * distfade

				col := obj.Color()
				img.Set(x, y, color.NRGBA{
					/*uint8(math32.Minf(float32(step)*4+255*v, 255)),*/
					uint8(255 * v * col[0]),
					uint8(255 * v * col[1]),
					uint8(255 * v * col[2]),
					/*uint8(255*ao),*/
					255})
			} else {
				/*img.Set(x, y, image.RGBAColor{uint8(step * 4), 0, 0, 255})*/
				img.Set(x, y, color.NRGBA{0, 0, 0, 255})
			}
		}
	}
	c <- 1
}
Example #5
0
func setPixelBytes(img image.NRGBA, pixel LsbPixel, byt byte) {
	rgba := img.NRGBAAt(pixel.GetX(), pixel.GetY())
	switch pixel.GetLayer() {
	case "r":
		rgba.R = byt
	case "g":
		rgba.G = byt
	case "b":
		rgba.B = byt
	case "a":
		rgba.A = byt
	}
	img.Set(pixel.GetX(), pixel.GetY(), rgba)
}
Example #6
0
func fillGradient(img *image.NRGBA, room *houseconf.Room, reading float64) {
	tx := ifZero(room.Therm.X, room.Rect.X+(room.Rect.W/2))
	ty := ifZero(room.Therm.Y, room.Rect.Y+(room.Rect.H/2))

	for i := 0; i < room.Rect.W; i++ {
		for j := 0; j < room.Rect.H; j++ {
			px, py := room.Rect.X+i, room.Rect.Y+j
			xd, yd := float64(px-tx), float64(py-ty)
			distance := math.Sqrt(xd*xd + yd*yd)
			relevance := 1.0 - (distance / conf.MaxRelevantDistance)
			if relevance < 0 {
				relevance = 0
			}

			img.Set(px, py, getFillColor(room, reading, relevance))
		}
	}
}
Example #7
0
func mandel(img *image.NRGBA) {
	for y := 0; y < img.Rect.Dy(); y++ {
		for x := 0; x < img.Rect.Dx(); x++ {
			zr := lerp(float32(x)/float32(img.Rect.Dx()-1), -2, 0.5)
			zc := lerp(float32(y)/float32(img.Rect.Dy()-1), -1.2, 1.2)

			zir, zic := float32(0.0), float32(0.0)
			c := 0
			for c < ITERATIONS && zir*zir+zic*zic < 4 {
				zir, zic = zir*zir-zic*zic+zr, 2*zir*zic+zc
				c++
			}

			if c < ITERATIONS {
				img.Set(x, y, color.NRGBA{255, 0, 0, 255})
			} else {
				img.Set(x, y, color.NRGBA{255, 255, 0, 255})
			}
		}
	}
}
Example #8
0
func rotate(im image.Image, angle int) image.Image {
	var rotated *image.NRGBA
	// trigonometric (i.e counter clock-wise)
	switch angle {
	case 90:
		newH, newW := im.Bounds().Dx(), im.Bounds().Dy()
		rotated = image.NewNRGBA(image.Rect(0, 0, newW, newH))
		for y := 0; y < newH; y++ {
			for x := 0; x < newW; x++ {
				rotated.Set(x, y, im.At(newH-1-y, x))
			}
		}
	case -90:
		newH, newW := im.Bounds().Dx(), im.Bounds().Dy()
		rotated = image.NewNRGBA(image.Rect(0, 0, newW, newH))
		for y := 0; y < newH; y++ {
			for x := 0; x < newW; x++ {
				rotated.Set(x, y, im.At(y, newW-1-x))
			}
		}
	case 180, -180:
		newW, newH := im.Bounds().Dx(), im.Bounds().Dy()
		rotated = image.NewNRGBA(image.Rect(0, 0, newW, newH))
		for y := 0; y < newH; y++ {
			for x := 0; x < newW; x++ {
				rotated.Set(x, y, im.At(newW-1-x, newH-1-y))
			}
		}
	default:
		return im
	}
	return rotated
}
Example #9
0
func drawSparklines(i *image.NRGBA, room *houseconf.Room, roomReadings []reading) {
	// Not interested in plotting fewer than two points
	if len(roomReadings) < 2 {
		return
	}

	sparkh := ifZero(room.Spark.H, 20)
	sparkx := ifZero(room.Spark.X, room.Rect.X)
	sparky := ifZero(room.Spark.Y, (room.Rect.Y+room.Rect.H)-sparkh)

	high, low := math.SmallestNonzeroFloat64, math.MaxFloat64

	for _, r := range roomReadings {
		high = math.Max(high, r.reading)
		low = math.Min(low, r.reading)
	}

	if (high - low) < float64(sparkh) {
		avg := high - ((high - low) / 2.0)
		low = avg + (float64(sparkh) / 2.0)
		high = avg - (float64(sparkh) / 2.0)
	}

	for pos, r := range roomReadings {
		x := len(roomReadings) - pos + sparkx - 1
		heightPercent := (r.reading - low) / (high - low)
		y := int((float64(sparky) + float64(sparkh)) - (float64(sparkh) * heightPercent))
		if y > sparky+sparkh {
			y = sparky + sparkh
		}
		if y < sparky {
			y = sparky
		}

		i.Set(x, y, color.Gray{127})
	}
}
Example #10
0
File: palette.go Project: xrstf/rct
func drawText(x int, y int, text string, img *image.NRGBA, color color.RGBA) {
	charWidth := 8
	charHeight := 7

	for _, character := range []byte(text) {
		pattern := bitmaps[character]

		for i := 0; i < charHeight; i++ {
			for j := 0; j < charWidth; j++ {
				pixel := pattern[i*charWidth+j]

				if pixel > 0 {
					img.Set(x+j, y+i, color)
				}
			}
		}

		// we drew a character, so advance
		x += charWidth

		// spacing in between each character
		x++
	}
}
Example #11
0
func drawIsometricCube(out *image.NRGBA, x, y, w, h int, src image.Image, top, left, right image.Rectangle) {
	for tx := 0; tx < w/2; tx++ {
		for ty := 0; ty < h/2; ty++ {
			col := src.At(
				left.Min.X+int((float64(tx)/float64(w/2))*float64(left.Dx())),
				left.Min.Y+int((float64(ty)/float64(h/2))*float64(left.Dy())),
			)
			if _, _, _, a := col.RGBA(); a == 0xFFFF {
				out.Set(
					x+tx,
					(h/4)+y+ty+int(float64(tx)*0.5),
					col,
				)
			}

			col = src.At(
				right.Min.X+int((float64(tx)/float64(w/2))*float64(right.Dx())),
				right.Min.Y+int((float64(ty)/float64(h/2))*float64(right.Dy())),
			)
			if _, _, _, a := col.RGBA(); a == 0xFFFF {
				out.Set(
					x+tx+(w/2),
					(h/4)+y+ty+int(float64((w/2)-tx)*0.5),
					col,
				)
			}
		}
	}

	for ttx := -1; ttx < (w/2)+1; ttx++ {
		for tty := -1; tty < (h/2)+1; tty++ {
			tx, ty := clamp(ttx, 0, w/2), clamp(tty, 0, h/2)
			col := src.At(
				top.Min.X+int((float64(tx)/float64(w/2))*float64(top.Dx())),
				top.Min.Y+int((float64(ty)/float64(h/2))*float64(top.Dy())),
			)
			if _, _, _, a := col.RGBA(); a == 0xFFFF {
				out.Set(
					x+1+ttx+tty,
					(h/4)+y+int(float64(ttx)*0.5-0.75-float64(tty)*0.5),
					col,
				)
			}
		}
	}
}
Example #12
0
func (d *decoder) idatReader(idat io.Reader) os.Error {
	r, err := zlib.NewInflater(idat)
	if err != nil {
		return err
	}
	defer r.Close()
	bpp := 0 // Bytes per pixel.
	maxPalette := uint8(0)
	var (
		rgba     *image.RGBA
		nrgba    *image.NRGBA
		paletted *image.Paletted
	)
	switch d.colorType {
	case ctTrueColor:
		bpp = 3
		rgba = d.image.(*image.RGBA)
	case ctPaletted:
		bpp = 1
		paletted = d.image.(*image.Paletted)
		maxPalette = uint8(len(paletted.Palette) - 1)
	case ctTrueColorAlpha:
		bpp = 4
		nrgba = d.image.(*image.NRGBA)
	}
	// cr and pr are the bytes for the current and previous row.
	// The +1 is for the per-row filter type, which is at cr[0].
	cr := make([]uint8, 1+bpp*d.width)
	pr := make([]uint8, 1+bpp*d.width)

	for y := 0; y < d.height; y++ {
		// Read the decompressed bytes.
		_, err := io.ReadFull(r, cr)
		if err != nil {
			return err
		}

		// Apply the filter.
		cdat := cr[1:]
		pdat := pr[1:]
		switch cr[0] {
		case ftNone:
			// No-op.
		case ftSub:
			for i := bpp; i < len(cdat); i++ {
				cdat[i] += cdat[i-bpp]
			}
		case ftUp:
			for i := 0; i < len(cdat); i++ {
				cdat[i] += pdat[i]
			}
		case ftAverage:
			for i := 0; i < bpp; i++ {
				cdat[i] += pdat[i] / 2
			}
			for i := bpp; i < len(cdat); i++ {
				cdat[i] += uint8((int(cdat[i-bpp]) + int(pdat[i])) / 2)
			}
		case ftPaeth:
			for i := 0; i < bpp; i++ {
				cdat[i] += paeth(0, pdat[i], 0)
			}
			for i := bpp; i < len(cdat); i++ {
				cdat[i] += paeth(cdat[i-bpp], pdat[i], pdat[i-bpp])
			}
		default:
			return FormatError("bad filter type")
		}

		// Convert from bytes to colors.
		switch d.colorType {
		case ctTrueColor:
			for x := 0; x < d.width; x++ {
				rgba.Set(x, y, image.RGBAColor{cdat[3*x+0], cdat[3*x+1], cdat[3*x+2], 0xff})
			}
		case ctPaletted:
			for x := 0; x < d.width; x++ {
				if cdat[x] > maxPalette {
					return FormatError("palette index out of range")
				}
				paletted.SetColorIndex(x, y, cdat[x])
			}
		case ctTrueColorAlpha:
			for x := 0; x < d.width; x++ {
				nrgba.Set(x, y, image.NRGBAColor{cdat[4*x+0], cdat[4*x+1], cdat[4*x+2], cdat[4*x+3]})
			}
		}

		// The current row for y is the previous row for y+1.
		pr, cr = cr, pr
	}
	return nil
}
Example #13
0
/**
 * 绘制圆
 *
 **/
func drawCircle(output *image.NRGBA, xc, yc int, radius float64) {
	x, y := 0, 0
	r2 := radius * radius
	c := color.RGBA{175, 0, 255, 255}
	//绘制圆的四个方向的定点
	output.Set(xc, yc+int(radius), c)
	output.Set(xc, yc-int(radius), c)
	output.Set(xc+int(radius), yc, c)
	output.Set(xc-int(radius), yc, c)

	x = 1
	y = int(math.Sqrt(r2-1) + 0.5)

	for x < y {
		output.Set(xc+x, yc+y, c)
		output.Set(xc+x, yc-y, c)
		output.Set(xc-x, yc+y, c)
		output.Set(xc-x, yc-y, c)
		output.Set(xc+y, yc+x, c)
		output.Set(xc+y, yc-x, c)
		output.Set(xc-y, yc+x, c)
		output.Set(xc-y, yc-x, c)
		x += 1
		y = (int)(math.Sqrt(r2-float64(x)*float64(x)) + 0.5)
	}
	if x == y {
		output.Set(xc+x, yc+y, c)
		output.Set(xc+x, yc-y, c)
		output.Set(xc-x, yc+y, c)
		output.Set(xc-x, yc-y, c)
	}
}
Example #14
0
func (s *Scene) SetColor(i, j int, u, v float64, img *image.NRGBA) {
	c := s.Evaluate(u, v).NRGBA()
	img.Set(i, j, c)
}
Example #15
0
func (d *decoder) idatReader(idat io.Reader) (image.Image, os.Error) {
	r, err := zlib.NewReader(idat)
	if err != nil {
		return nil, err
	}
	defer r.Close()
	bitsPerPixel := 0
	maxPalette := uint8(0)
	var (
		gray     *image.Gray
		rgba     *image.RGBA
		paletted *image.Paletted
		nrgba    *image.NRGBA
		gray16   *image.Gray16
		rgba64   *image.RGBA64
		nrgba64  *image.NRGBA64
		img      image.Image
	)
	switch d.cb {
	case cbG1, cbG2, cbG4, cbG8:
		bitsPerPixel = d.depth
		gray = image.NewGray(d.width, d.height)
		img = gray
	case cbGA8:
		bitsPerPixel = 16
		nrgba = image.NewNRGBA(d.width, d.height)
		img = nrgba
	case cbTC8:
		bitsPerPixel = 24
		rgba = image.NewRGBA(d.width, d.height)
		img = rgba
	case cbP1, cbP2, cbP4, cbP8:
		bitsPerPixel = d.depth
		paletted = image.NewPaletted(d.width, d.height, d.palette)
		img = paletted
		maxPalette = uint8(len(d.palette) - 1)
	case cbTCA8:
		bitsPerPixel = 32
		nrgba = image.NewNRGBA(d.width, d.height)
		img = nrgba
	case cbG16:
		bitsPerPixel = 16
		gray16 = image.NewGray16(d.width, d.height)
		img = gray16
	case cbGA16:
		bitsPerPixel = 32
		nrgba64 = image.NewNRGBA64(d.width, d.height)
		img = nrgba64
	case cbTC16:
		bitsPerPixel = 48
		rgba64 = image.NewRGBA64(d.width, d.height)
		img = rgba64
	case cbTCA16:
		bitsPerPixel = 64
		nrgba64 = image.NewNRGBA64(d.width, d.height)
		img = nrgba64
	}
	bytesPerPixel := (bitsPerPixel + 7) / 8

	// cr and pr are the bytes for the current and previous row.
	// The +1 is for the per-row filter type, which is at cr[0].
	cr := make([]uint8, 1+(bitsPerPixel*d.width+7)/8)
	pr := make([]uint8, 1+(bitsPerPixel*d.width+7)/8)

	for y := 0; y < d.height; y++ {
		// Read the decompressed bytes.
		_, err := io.ReadFull(r, cr)
		if err != nil {
			return nil, err
		}

		// Apply the filter.
		cdat := cr[1:]
		pdat := pr[1:]
		switch cr[0] {
		case ftNone:
			// No-op.
		case ftSub:
			for i := bytesPerPixel; i < len(cdat); i++ {
				cdat[i] += cdat[i-bytesPerPixel]
			}
		case ftUp:
			for i := 0; i < len(cdat); i++ {
				cdat[i] += pdat[i]
			}
		case ftAverage:
			for i := 0; i < bytesPerPixel; i++ {
				cdat[i] += pdat[i] / 2
			}
			for i := bytesPerPixel; i < len(cdat); i++ {
				cdat[i] += uint8((int(cdat[i-bytesPerPixel]) + int(pdat[i])) / 2)
			}
		case ftPaeth:
			for i := 0; i < bytesPerPixel; i++ {
				cdat[i] += paeth(0, pdat[i], 0)
			}
			for i := bytesPerPixel; i < len(cdat); i++ {
				cdat[i] += paeth(cdat[i-bytesPerPixel], pdat[i], pdat[i-bytesPerPixel])
			}
		default:
			return nil, FormatError("bad filter type")
		}

		// Convert from bytes to colors.
		switch d.cb {
		case cbG1:
			for x := 0; x < d.width; x += 8 {
				b := cdat[x/8]
				for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ {
					gray.Set(x+x2, y, image.GrayColor{(b >> 7) * 0xff})
					b <<= 1
				}
			}
		case cbG2:
			for x := 0; x < d.width; x += 4 {
				b := cdat[x/4]
				for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ {
					gray.Set(x+x2, y, image.GrayColor{(b >> 6) * 0x55})
					b <<= 2
				}
			}
		case cbG4:
			for x := 0; x < d.width; x += 2 {
				b := cdat[x/2]
				for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ {
					gray.Set(x+x2, y, image.GrayColor{(b >> 4) * 0x11})
					b <<= 4
				}
			}
		case cbG8:
			for x := 0; x < d.width; x++ {
				gray.Set(x, y, image.GrayColor{cdat[x]})
			}
		case cbGA8:
			for x := 0; x < d.width; x++ {
				ycol := cdat[2*x+0]
				nrgba.Set(x, y, image.NRGBAColor{ycol, ycol, ycol, cdat[2*x+1]})
			}
		case cbTC8:
			for x := 0; x < d.width; x++ {
				rgba.Set(x, y, image.RGBAColor{cdat[3*x+0], cdat[3*x+1], cdat[3*x+2], 0xff})
			}
		case cbP1:
			for x := 0; x < d.width; x += 8 {
				b := cdat[x/8]
				for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ {
					idx := b >> 7
					if idx > maxPalette {
						return nil, FormatError("palette index out of range")
					}
					paletted.SetColorIndex(x+x2, y, idx)
					b <<= 1
				}
			}
		case cbP2:
			for x := 0; x < d.width; x += 4 {
				b := cdat[x/4]
				for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ {
					idx := b >> 6
					if idx > maxPalette {
						return nil, FormatError("palette index out of range")
					}
					paletted.SetColorIndex(x+x2, y, idx)
					b <<= 2
				}
			}
		case cbP4:
			for x := 0; x < d.width; x += 2 {
				b := cdat[x/2]
				for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ {
					idx := b >> 4
					if idx > maxPalette {
						return nil, FormatError("palette index out of range")
					}
					paletted.SetColorIndex(x+x2, y, idx)
					b <<= 4
				}
			}
		case cbP8:
			for x := 0; x < d.width; x++ {
				if cdat[x] > maxPalette {
					return nil, FormatError("palette index out of range")
				}
				paletted.SetColorIndex(x, y, cdat[x])
			}
		case cbTCA8:
			for x := 0; x < d.width; x++ {
				nrgba.Set(x, y, image.NRGBAColor{cdat[4*x+0], cdat[4*x+1], cdat[4*x+2], cdat[4*x+3]})
			}
		case cbG16:
			for x := 0; x < d.width; x++ {
				ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
				gray16.Set(x, y, image.Gray16Color{ycol})
			}
		case cbGA16:
			for x := 0; x < d.width; x++ {
				ycol := uint16(cdat[4*x+0])<<8 | uint16(cdat[4*x+1])
				acol := uint16(cdat[4*x+2])<<8 | uint16(cdat[4*x+3])
				nrgba64.Set(x, y, image.NRGBA64Color{ycol, ycol, ycol, acol})
			}
		case cbTC16:
			for x := 0; x < d.width; x++ {
				rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1])
				gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3])
				bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5])
				rgba64.Set(x, y, image.RGBA64Color{rcol, gcol, bcol, 0xffff})
			}
		case cbTCA16:
			for x := 0; x < d.width; x++ {
				rcol := uint16(cdat[8*x+0])<<8 | uint16(cdat[8*x+1])
				gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3])
				bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5])
				acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7])
				nrgba64.Set(x, y, image.NRGBA64Color{rcol, gcol, bcol, acol})
			}
		}

		// The current row for y is the previous row for y+1.
		pr, cr = cr, pr
	}
	return img, nil
}
Example #16
0
func createElevs(targetDir string) {
	type sourceRec struct {
		dirPath   string
		filePath  string
		fileTime  time.Time
		byteOrder binary.ByteOrder
		fileLen   int64
	}
	var srcBasePath = "/media/hdx/elev_raw/"
	var force = []string{ /*"N64W024"*/ }
	var initSourceRec = func(dirRelPath string) *sourceRec {
		return &sourceRec{path.Join(srcBasePath, dirRelPath), "", time.Time{}, binary.LittleEndian, 0}
	}
	var fexts = []string{".hgt", ".hgt.le", ".HGT", ".HGT.LE"}
	var srcRecs = map[string]*sourceRec{"": initSourceRec(""), "bathy": initSourceRec("bathy/hgt"), "srtm": initSourceRec("srtm/hgt"), "rmw": initSourceRec("rmw3"), "vfp": initSourceRec("vfp")}
	var lola numutil.Dvec2
	var fp, fbName, skey, nkey string
	var hasBathy, hasElev bool
	var srec *sourceRec
	var newest, srtmTime time.Time
	var pngMakers = 0
	var pngChan = make(chan bool)
	var makePng = func(outFilePath string, elevFile *sourceRec, bathyFilePath string) {
		var ps, ps1, psx = 1200, 1201, 1200 * 2400
		var bathyLandVal int16 = 0
		var bathyMapping = []int16{-4500, -2500, -9500, -6500, -10500, -3500, bathyLandVal, -5500, -7500, -200, -8500, -1500, -750}
		var pngSize = image.Rect(0, 0, ps, ps)
		var px, py int
		var bv, ev, fv int16
		var srcFile, bathFile, pngFile *os.File
		var err error
		var pngImage *image.NRGBA
		fmt.Println(outFilePath)
		if pngFile, err = os.Create(outFilePath); err != nil {
			fmt.Println("PANIC", err)
			panic(err)
		}
		if bathFile, err = os.Open(bathyFilePath); err != nil {
			bathFile = nil
		}
		if srcFile, err = os.Open(elevFile.filePath); err != nil {
			srcFile = nil
		}
		if (bathFile != nil) || (srcFile != nil) {
			pngImage = image.NewNRGBA(pngSize)
			for py = 0; py < pngSize.Max.Y; py++ {
				for px = 0; px < pngSize.Max.X; px++ {
					if (bathFile == nil) || !fileutil.ReadFromBinary(bathFile, int64((math.Floor(float64(py)/40)*30)+math.Floor(float64(px)/40))*2, binary.LittleEndian, &bv) {
						bv = bathyLandVal
					} else {
						bv = bathyMapping[bv]
					}
					if (srcFile == nil) || !fileutil.ReadFromBinary(srcFile, (int64((py*coreutil.Ifi(int(elevFile.fileLen) == psx, ps, ps1))+px)*2) /*+ coreutil.Ifl(int(elevFile.fileLen) == psx, 0, 2402)*/, elevFile.byteOrder, &ev) {
						ev = -32768
					}
					fv = coreutil.Ifs(bv == bathyLandVal, ev, coreutil.Ifs((ev != 0) && (ev > bv), ev, bv))
					pngImage.Set(px, py, color.NRGBA{0, byte(fv), byte(fv >> 8), 255})
				}
			}
			if bathFile != nil {
				bathFile.Close()
			}
			if srcFile != nil {
				srcFile.Close()
			}
			err = png.Encode(pngFile, pngImage)
			if err != nil {
				fmt.Println("PANIC", err)
				panic(err)
			}
		}
		pngFile.Close()
		pngChan <- true
	}
	var goMakePng = func(outFilePath string, elevFile *sourceRec, bathyFilePath string) {
		for pngMakers >= 8 {
			<-pngChan
			pngMakers--
		}
		pngMakers++
		go makePng(outFilePath, elevFile, bathyFilePath)
	}
	srtmTime = time.Date(2008, 10, 15, 12, 30, 30, 500, time.Local)
	for lola.Y = geoutil.LatMin; lola.Y < geoutil.LatMax; lola.Y++ {
		for lola.X = geoutil.LonMin; lola.X < geoutil.LonMax; lola.X++ {
			fbName = geoutil.LoLaFileName(lola.X, lola.Y)
			if (len(force) == 0) || (stringutil.InSliceAt(force, fbName) >= 0) {
				fp = path.Join(targetDir, fbName)
				for skey, srec = range srcRecs {
					if len(skey) > 0 {
						srec.filePath, srec.fileTime, srec.fileLen = fileutil.FileExistsPath(srec.dirPath, fbName, fexts, true, false)
						if skey == "srtm" {
							srec.fileTime = srtmTime
						}
					}
				}
				newest = time.Time{}
				nkey = ""
				for skey, srec = range srcRecs {
					if (len(skey) > 0) && (skey != "bathy") && (len(srec.filePath) > 0) && (srec.fileTime.After(newest)) {
						newest = srec.fileTime
						nkey = skey
						if strings.HasSuffix(strings.ToLower(srec.filePath), ".hgt.le") {
							srec.byteOrder = binary.LittleEndian
						} else {
							srec.byteOrder = binary.BigEndian
						}
					}
				}
				if hasBathy, hasElev = len(srcRecs["bathy"].filePath) > 0, len(nkey) > 0; hasBathy || hasElev {
					goMakePng(fp, srcRecs[nkey], srcRecs["bathy"].filePath)
				} else {
					fmt.Println("\tNO BATHY, NO ELEV!\n")
				}
				if (len(srcRecs["rmw"].filePath) > 0) && (len(srcRecs["srtm"].filePath) > 0) && (len(srcRecs["vfp"].filePath) > 0) {
					goMakePng(path.Join(targetDir+"_rsv", fbName+"."+nkey+".r.png"), srcRecs["rmw"], srcRecs["bathy"].filePath)
					goMakePng(path.Join(targetDir+"_rsv", fbName+"."+nkey+".s.png"), srcRecs["srtm"], srcRecs["bathy"].filePath)
					goMakePng(path.Join(targetDir+"_rsv", fbName+"."+nkey+".v.png"), srcRecs["vfp"], srcRecs["bathy"].filePath)
				} else if (len(srcRecs["rmw"].filePath) > 0) && (len(srcRecs["vfp"].filePath) > 0) {
					goMakePng(path.Join(targetDir+"_rv", fbName+"."+nkey+".r.png"), srcRecs["rmw"], srcRecs["bathy"].filePath)
					goMakePng(path.Join(targetDir+"_rv", fbName+"."+nkey+".v.png"), srcRecs["vfp"], srcRecs["bathy"].filePath)
				} else if (len(srcRecs["rmw"].filePath) > 0) && (len(srcRecs["srtm"].filePath) > 0) {
					goMakePng(path.Join(targetDir+"_rs", fbName+"."+nkey+".r.png"), srcRecs["rmw"], srcRecs["bathy"].filePath)
					goMakePng(path.Join(targetDir+"_rs", fbName+"."+nkey+".s.png"), srcRecs["srtm"], srcRecs["bathy"].filePath)
				} else if (len(srcRecs["vfp"].filePath) > 0) && (len(srcRecs["srtm"].filePath) > 0) {
					goMakePng(path.Join(targetDir+"_sv", fbName+"."+nkey+".v.png"), srcRecs["vfp"], srcRecs["bathy"].filePath)
					goMakePng(path.Join(targetDir+"_sv", fbName+"."+nkey+".s.png"), srcRecs["srtm"], srcRecs["bathy"].filePath)
				}
			}
		}
	}
}
func (d *decoder) idatReader(idat io.Reader) (image.Image, os.Error) {
	r, err := zlib.NewReader(idat)
	if err != nil {
		return nil, err
	}
	defer r.Close()
	bpp := 0 // Bytes per pixel.
	maxPalette := uint8(0)
	var (
		gray     *image.Gray
		rgba     *image.RGBA
		paletted *image.Paletted
		nrgba    *image.NRGBA
		gray16   *image.Gray16
		rgba64   *image.RGBA64
		nrgba64  *image.NRGBA64
		img      image.Image
	)
	switch d.cb {
	case cbG8:
		bpp = 1
		gray = image.NewGray(d.width, d.height)
		img = gray
	case cbTC8:
		bpp = 3
		rgba = image.NewRGBA(d.width, d.height)
		img = rgba
	case cbP8:
		bpp = 1
		paletted = image.NewPaletted(d.width, d.height, d.palette)
		img = paletted
		maxPalette = uint8(len(d.palette) - 1)
	case cbTCA8:
		bpp = 4
		nrgba = image.NewNRGBA(d.width, d.height)
		img = nrgba
	case cbG16:
		bpp = 2
		gray16 = image.NewGray16(d.width, d.height)
		img = gray16
	case cbTC16:
		bpp = 6
		rgba64 = image.NewRGBA64(d.width, d.height)
		img = rgba64
	case cbTCA16:
		bpp = 8
		nrgba64 = image.NewNRGBA64(d.width, d.height)
		img = nrgba64
	}
	// cr and pr are the bytes for the current and previous row.
	// The +1 is for the per-row filter type, which is at cr[0].
	cr := make([]uint8, 1+bpp*d.width)
	pr := make([]uint8, 1+bpp*d.width)

	for y := 0; y < d.height; y++ {
		// Read the decompressed bytes.
		_, err := io.ReadFull(r, cr)
		if err != nil {
			return nil, err
		}

		// Apply the filter.
		cdat := cr[1:]
		pdat := pr[1:]
		switch cr[0] {
		case ftNone:
			// No-op.
		case ftSub:
			for i := bpp; i < len(cdat); i++ {
				cdat[i] += cdat[i-bpp]
			}
		case ftUp:
			for i := 0; i < len(cdat); i++ {
				cdat[i] += pdat[i]
			}
		case ftAverage:
			for i := 0; i < bpp; i++ {
				cdat[i] += pdat[i] / 2
			}
			for i := bpp; i < len(cdat); i++ {
				cdat[i] += uint8((int(cdat[i-bpp]) + int(pdat[i])) / 2)
			}
		case ftPaeth:
			for i := 0; i < bpp; i++ {
				cdat[i] += paeth(0, pdat[i], 0)
			}
			for i := bpp; i < len(cdat); i++ {
				cdat[i] += paeth(cdat[i-bpp], pdat[i], pdat[i-bpp])
			}
		default:
			return nil, FormatError("bad filter type")
		}

		// Convert from bytes to colors.
		switch d.cb {
		case cbG8:
			for x := 0; x < d.width; x++ {
				gray.Set(x, y, image.GrayColor{cdat[x]})
			}
		case cbTC8:
			for x := 0; x < d.width; x++ {
				rgba.Set(x, y, image.RGBAColor{cdat[3*x+0], cdat[3*x+1], cdat[3*x+2], 0xff})
			}
		case cbP8:
			for x := 0; x < d.width; x++ {
				if cdat[x] > maxPalette {
					return nil, FormatError("palette index out of range")
				}
				paletted.SetColorIndex(x, y, cdat[x])
			}
		case cbTCA8:
			for x := 0; x < d.width; x++ {
				nrgba.Set(x, y, image.NRGBAColor{cdat[4*x+0], cdat[4*x+1], cdat[4*x+2], cdat[4*x+3]})
			}
		case cbG16:
			for x := 0; x < d.width; x++ {
				ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
				gray16.Set(x, y, image.Gray16Color{ycol})
			}
		case cbTC16:
			for x := 0; x < d.width; x++ {
				rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1])
				gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3])
				bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5])
				rgba64.Set(x, y, image.RGBA64Color{rcol, gcol, bcol, 0xffff})
			}
		case cbTCA16:
			for x := 0; x < d.width; x++ {
				rcol := uint16(cdat[8*x+0])<<8 | uint16(cdat[8*x+1])
				gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3])
				bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5])
				acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7])
				nrgba64.Set(x, y, image.NRGBA64Color{rcol, gcol, bcol, acol})
			}
		}

		// The current row for y is the previous row for y+1.
		pr, cr = cr, pr
	}
	return img, nil
}