Example #1
0
// TestMedian tests the median quantizer on png files found in the source
// directory.  Output files are prefixed with _median_.  Files begining with
// _ are skipped when scanning for input files.  Note nothing is tested
// with a fresh source tree--drop a png or two in the source directory
// before testing to give the test something to work on.  Png files in the
// parent directory are similarly used for testing.  Put files there
// to compare results of the different quantizers.
func TestMedian(t *testing.T) {
	for _, p := range glob(t) {
		f, err := os.Open(p)
		if err != nil {
			t.Log(err) // skip files that can't be opened
			continue
		}
		img, err := png.Decode(f)
		f.Close()
		if err != nil {
			t.Log(err) // skip files that can't be decoded
			continue
		}
		pDir, pFile := filepath.Split(p)
		for _, n := range []int{16, 256} {
			// prefix _ on file name marks this as a result
			fq, err := os.Create(fmt.Sprintf("%s_median_%d_%s", pDir, n, pFile))
			if err != nil {
				t.Fatal(err) // probably can't create any others
			}
			var q quant.Quantizer = median.Quantizer(n)
			if err = png.Encode(fq, q.Image(img)); err != nil {
				t.Fatal(err) // any problem is probably a problem for all
			}
		}
	}
}
Example #2
0
func main() {
	mode := flag.String("mode", "median", "'median' or 'mean' (default 'median')")
	size := flag.Int("size", 16, "Palette size (default 16)")
	flag.Parse()

	paths := flag.Args()
	if len(paths) == 0 {
		log.Fatal("No images specified")
	}

	var wg sync.WaitGroup
	wg.Add(len(paths))

	for _, path := range paths {
		go func(path string) {
			defer wg.Done()

			var buff bytes.Buffer
			buff.WriteString(fmt.Sprintf("\n%s\n", path))

			reader, err := os.Open(path)
			if err != nil {
				log.Fatal(err)
			}
			defer reader.Close()

			img, _, err := image.Decode(reader)
			if err != nil {
				log.Fatal(err)
			}

			var q quant.Quantizer
			if *mode == "median" {
				q = median.Quantizer(*size)
			} else {
				q = mean.Quantizer(*size)
			}

			pal := q.Palette(img)
			for _, c := range pal.ColorPalette() {
				r, g, b, _ := c.RGBA()
				buff.WriteString(fmt.Sprintf("#%02x%02x%02x\n", uint8(r>>8), uint8(g>>8), uint8(b>>8)))
			}

			fmt.Print(buff.String())
		}(path)
	}

	wg.Wait()
}
Example #3
0
// TestDither tests Sierra24A on png files found in the source directory.
// Output files are prefixed with _dither_256_.  Files begining with _
// are skipped when scanning for input files.  Thus nothing is tested
// with a fresh source tree--drop a png or two in the source directory
// before testing to give the test something to work on.
func TestDither(t *testing.T) {
	_, file, _, ok := runtime.Caller(0)
	if !ok {
		t.Fatal("runtime.Caller fail")
	}
	srcDir, _ := filepath.Split(file)
	// ignore file names starting with _, those are result files.
	imgs, err := filepath.Glob(srcDir + "[^_]*.png")
	if err != nil {
		t.Fatal(err)
	}
	const n = 256
	// exercise draw.Quantizer interface
	var q draw.Quantizer = median.Quantizer(n)
	// exercise draw.Drawer interface
	var d draw.Drawer = quant.Sierra24A{}
	for _, p := range imgs {
		f, err := os.Open(p)
		if err != nil {
			t.Error(err) // skip files that can't be opened
			continue
		}
		img, err := png.Decode(f)
		f.Close()
		if err != nil {
			t.Error(err) // skip files that can't be decoded
			continue
		}
		pDir, pFile := filepath.Split(p)
		// prefix _ on file name marks this as a result
		fq, err := os.Create(fmt.Sprintf("%s_dither_%d_%s", pDir, n, pFile))
		if err != nil {
			t.Fatal(err) // probably can't create any others
		}
		b := img.Bounds()
		pi := image.NewPaletted(b, q.Quantize(make(color.Palette, 0, n), img))
		d.Draw(pi, b, img, b.Min)
		if err = png.Encode(fq, pi); err != nil {
			t.Fatal(err) // any problem is probably a problem for all
		}
	}
}
Example #4
0
func BenchmarkPalette(b *testing.B) {
	var img image.Image
	for _, p := range glob(b) {
		f, err := os.Open(p)
		if err != nil {
			b.Log(err) // skip files that can't be opened
			continue
		}
		img, err = png.Decode(f)
		f.Close()
		if err != nil {
			b.Log(err) // skip files that can't be decoded
			continue
		}
		break
	}
	var q quant.Quantizer = median.Quantizer(256)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		q.Palette(img)
	}
}
Example #5
0
func (w *Weather) CreateGifImage(dateArray []string) error {
	g := &gif.GIF{
		Image:     []*image.Paletted{},
		Delay:     []int{},
		LoopCount: 0,
	}

	for _, date := range dateArray {
		srcMain, err := w.downloadImage(date, "main")
		if err != nil {
			return err
		}
		srcTokyo, err := w.downloadImage(date, "tokyo")
		if err != nil {
			return err
		}
		srcNagaoka, err := w.downloadImage(date, "nagaoka")
		if err != nil {
			return err
		}
		srcKyoto, err := w.downloadImage(date, "kyoto")
		if err != nil {
			return err
		}

		q := median.Quantizer(256)
		p := q.Quantize(make(color.Palette, 0, 256), srcMain)

		rMain := srcMain.Bounds()
		rTokyo := srcTokyo.Bounds()
		rNagaoka := srcNagaoka.Bounds()

		// 画像を合成
		minX := rMain.Min.X
		maxX := rMain.Max.X + rTokyo.Max.X
		minY := rMain.Min.Y
		maxY := rMain.Max.Y
		paletSize := image.Rect(0, 0, maxX, maxY)
		dst := image.NewPaletted(paletSize, p)

		for x := minX; x < maxX; x++ {
			divideX := x - rMain.Max.X
			for y := minY; y < maxY; y++ {
				if x < rMain.Max.X && y < rMain.Max.Y {
					// whole map
					dst.Set(x, y, srcMain.At(x, y))
				} else if x > rMain.Max.X {
					if y < rNagaoka.Max.Y {
						// nagaoka
						dst.Set(x, y, srcNagaoka.At(divideX, y))
					} else if y > rNagaoka.Max.Y && y < rNagaoka.Max.Y+rTokyo.Max.Y {
						// tokyo
						divideY := y - rNagaoka.Max.Y
						dst.Set(x, y, srcTokyo.At(divideX, divideY))
					} else if y > rNagaoka.Max.Y+rTokyo.Max.Y {
						// kyoto
						divideY := y - (rNagaoka.Max.Y + rTokyo.Max.Y)
						dst.Set(x, y, srcKyoto.At(divideX, divideY))
					}
				} else if x == rMain.Max.X /* || (x == rMain.Max.X && y == rNagaoka.Max.Y)*/ {
					// 境界線塗りつぶし
					dst.Set(x, y, color.RGBA{uint8(0), uint8(0), uint8(0), uint8(0)})
				}
			}
		}

		g.Image = append(g.Image, dst)
		g.Delay = append(g.Delay, 100)
	}

	out, err := os.Create(w.Filename + ".gif")
	if err != nil {
		return err
	}
	defer out.Close()
	err = gif.EncodeAll(out, g)
	if err != nil {
		return err
	}
	return nil
}
Example #6
0
func main() {
	flag.Parse()

	c, err := colorful.Hex(*bg)
	if err != nil {
		log.Fatal(err)
	}

	f, err := os.Open(flag.Arg(0))
	if err != nil {
		log.Fatal(err)
	}
	src, _, err := image.Decode(f)
	if err != nil {
		log.Fatal(err)
	}
	f.Close()

	g := &gif.GIF{
		Image:     []*image.Paletted{},
		Delay:     []int{},
		LoopCount: 0,
	}

	var base float64 = (math.Pi * 2) * 10 * (*speed) / 360
	if *reverse {
		base *= -1
	}

	limit := int(360 / 10 / (*speed))
	q := median.Quantizer(256)
	p := q.Quantize(make(color.Palette, 0, 256), src)
	for i := 0; i < limit; i++ {
		dst := image.NewPaletted(src.Bounds(), p)
		draw.Draw(dst, src.Bounds(), &image.Uniform{c}, image.ZP, draw.Src)
		err = graphics.Rotate(dst, src, &graphics.RotateOptions{Angle: base * float64(i)})
		if err != nil {
			log.Fatal(err)
		}
		if *zoom {
			w, h := float64(src.Bounds().Dx()), float64(src.Bounds().Dy())
			tmp := image.NewPaletted(src.Bounds(), p)
			draw.Draw(tmp, src.Bounds(), &image.Uniform{c}, image.ZP, draw.Src)
			z := float64(0.5 + float64(i)/30.0)
			graphics.I.
				Scale(z, z).
				Translate((w-w*z)/2, (h-h*z)/2).
				Transform(tmp, dst, interp.Bilinear)
			dst = tmp
		}
		g.Image = append(g.Image, dst)
		g.Delay = append(g.Delay, *delay)
	}
	out, err := os.Create(*output)
	if err != nil {
		log.Fatal(err)
	}
	defer out.Close()
	err = gif.EncodeAll(out, g)
	if err != nil {
		log.Fatal(err)
	}
}