// Transforms gray input image color depth to the palette defined in p // The algorithm simply assigns the nearest palette color to each pixel, // without distributing error in any way, so expect color banding func ditheringAverage(img *image.Gray, p *color.Palette) { size := img.Bounds() for y := size.Min.Y; y < size.Max.Y; y++ { for x := size.Min.X; x < size.Max.X; x++ { c1 := img.GrayAt(x, y) c2 := p.Convert(c1).(color.Gray) img.SetGray(x, y, c2) } } }
// count = le nombre d'images func myGetImages(panneau image.Image, location image.Point, level uint8) []string { var p color.Palette p = palette.Plan9 col := panneau.At(location.X, location.Y) //return GetImages(col, -1, c) //return (ResizeImage(shuffle(myUri), math.Exp2(level))) id := p.Index(col) resp, _ := http.Get("https://flag-42.appspot.com/sendlinks?col=" + strconv.Itoa(id) + "&count=" + string(-1)) data, _ := ioutil.ReadAll(resp.Body) var v []string json.Unmarshal(data, &v) log.Print("%#v", v) return v }
func dealExtremeSetColor(d hid.Device, c color.Color) error { palette := color.Palette{ color.RGBA{0x00, 0x00, 0x00, 0x00}, color.RGBA{0x00, 0xff, 0x00, 0xff}, color.RGBA{0xff, 0x00, 0x00, 0xff}, color.RGBA{0x00, 0x00, 0xff, 0xff}, color.RGBA{0x00, 0xff, 0xff, 0xff}, color.RGBA{0x00, 0xff, 0xff, 0xff}, color.RGBA{0xff, 0xff, 0x00, 0xff}, color.RGBA{0xff, 0x00, 0xff, 0xff}, color.RGBA{0xff, 0xff, 0xff, 0xff}, } return d.Write([]byte{0x00, byte(palette.Index(c))}) }
func blyncDevSetColor(d hid.Device, c color.Color) error { palette := color.Palette{ color.RGBA{0x00, 0x00, 0x00, 0x00}, // black color.RGBA{0xff, 0xff, 0xff, 0xff}, // white color.RGBA{0x00, 0xff, 0xff, 0xff}, // cyan color.RGBA{0xff, 0x00, 0xff, 0xff}, // magenta color.RGBA{0x00, 0x00, 0xff, 0xff}, // blue color.RGBA{0xff, 0xff, 0x00, 0xff}, // yellow color.RGBA{0x00, 0xff, 0x00, 0xff}, // lime color.RGBA{0xff, 0x00, 0x00, 0xff}, // red } value := byte((palette.Index(c) * 16) + 127) return d.Write([]byte{0x00, 0x55, 0x53, 0x42, 0x43, 0x00, 0x40, 0x02, value}) }
func AddImage(link string, col color.Color, c appengine.Context) error { var p color.Palette //get the index of the nearest color in a our color palette (256 colors) p = palette.Plan9 id := p.Index(col) //initalize the struct to be stored img := models.Image{ Date: time.Now(), Color: id, Link: link, } //add the struct to the database _, err := service.AddData(img, c) return err }
// NewScheme creates a color scheme using the colors in m, following the base // color scheme. func NewScheme(m image.Image, base color.Palette) color.Palette { p, counts := colors(m) ccs := make([]colorCount, len(base)) for c, count := range counts { // TODO: Try organizing colors by hue instead of Euclidean // distance - maybe use luminance for black/white i := base.Index(c) if count > ccs[i].count { ccs[i].color = c ccs[i].count = count } } s := make(color.Palette, len(ccs)) for i, cc := range ccs { if cc.count == 0 { s[i] = p.Convert(base[i]) } else { s[i] = cc.color } } return s }
// Dithering algorithms // Dithering is the process of reducing the colorspace of an image to a more // restricted palette. Since the Game Boy Printer only has a 2bit colorspace // available, it's important that some dithering algorithms are implemented to // deal with the fact. Depending on the properties of the dithering algorithm // detail may or may not be preserved as well. Using simple techniques like // average dithering will yield results with lots of color banding, while employing // error diffusion techniques such as Floyd Steinberg will produce smoother // results (color banding is replaced by the introduction of noise) // The wikipedia article (http://en.wikipedia.org/wiki/Dither) is quite interesting // and talks about some dithering algorithms, some of which are implemented here. // Floyd Steinberg is an error diffusion dithering algorithm that adds the error // of each color conversion to the neighbours of each pixel. This way it's possible // to achieve a finer graded dithering func ditheringFloydSteinberg(img *image.Gray, p *color.Palette) { size := img.Bounds() for y := size.Min.Y; y < size.Max.Y; y++ { for x := size.Min.X; x < size.Max.X; x++ { c1 := img.GrayAt(x, y) c2 := p.Convert(c1).(color.Gray) delta := int(c1.Y) - int(c2.Y) switch { case x+1 < size.Max.X && y < size.Max.Y: img.SetGray(x+1, y, color.Gray{uint8(int(img.GrayAt(x+1, y).Y) + delta*7/16)}) fallthrough case x < size.Max.X && y+1 < size.Max.Y: img.SetGray(x, y+1, color.Gray{uint8(int(img.GrayAt(x, y+1).Y) + delta*5/16)}) fallthrough case x-1 >= size.Min.X && y+1 < size.Max.Y: img.SetGray(x-1, y+1, color.Gray{uint8(int(img.GrayAt(x-1, y+1).Y) + delta*3/16)}) fallthrough case x+1 < size.Max.X && y+1 < size.Max.Y: img.SetGray(x+1, y+1, color.Gray{uint8(int(img.GrayAt(x+1, y+1).Y) + delta*1/16)}) } img.Set(x, y, c2) } } }
func genTwitterGif(tweets []anaconda.Tweet, username string, tid int64) (string, error) { wid := 440 height := 220 colList := color.Palette{ color.RGBA{0x00, 0x00, 0x00, 0xFF}, color.RGBA{0xFF, 0x33, 0x33, 0xFF}, color.RGBA{0x33, 0xFF, 0x33, 0xFF}, color.RGBA{0x33, 0x33, 0xFF, 0xFF}, color.RGBA{0xFF, 0xFF, 0x33, 0xFF}, color.RGBA{0xFF, 0x33, 0xFF, 0xFF}, color.RGBA{0x33, 0xFF, 0xFF, 0xFF}, } newList := []*image.Paletted{} delayList := []int{} fireworkList := []FireWork{} disposalList := []byte{} draw2d.SetFontFolder("static") for i := range tweets { f := genFireworkFromTweet(tweets, i, float64(wid), float64(height)) fireworkList = append(fireworkList, f) } boundRect := image.Rect(0, 0, wid, height) for len(fireworkList) > 0 { rawImg := image.NewRGBA(boundRect) // TODO :: Create Custom Painter // which does blend up painter := raster.NewRGBAPainter(rawImg) gc := draw2dimg.NewGraphicContextWithPainter(rawImg, painter) gc.SetFontData(draw2d.FontData{ Name: "Roboto", }) gc.SetFontSize(8) gc.Clear() gc.SetFillColor(colList[0]) gc.MoveTo(0, 0) gc.LineTo(0, float64(height)) gc.LineTo(float64(wid), float64(height)) gc.LineTo(float64(wid), 0) gc.Close() gc.Fill() newFList := []FireWork{} for _, f := range fireworkList { if f.d > 0 { f.d -= 1.0 } else { gc.SetFillColor(colList[f.colID]) gc.SetStrokeColor(colList[f.colID]) gc.MoveTo(f.x, f.y) gc.FillStringAt(f.text, f.x-4, f.y+4) gc.MoveTo(f.x, f.y) gc.SetLineWidth(f.sz) gc.LineTo(f.x-f.dx, f.y-f.dy) for ns := 1.0; ns < f.sz; ns += 1.0 { gc.SetLineWidth(f.sz - ns) gc.LineTo(f.x-f.dx*ns*0.2, f.y-f.dy*ns*0.2) } gc.Stroke() f.x += f.dx f.y += f.dy f.t -= 1.0 f.dy += 0.3 } if f.t > 0 { newFList = append(newFList, f) } else if len(f.bundle) > 0 { for _, subF := range f.bundle { subF.x += f.x subF.y += f.y newFList = append(newFList, subF) } } } fireworkList = newFList // Make Pallette Image newImg := image.NewPaletted(boundRect, colList) for x := 0; x < wid; x++ { for y := 0; y < height; y++ { newImg.SetColorIndex(x, y, uint8(colList.Index(rawImg.At(x, y)))) } } // Add Lists if len(newList) == 0 { disposalList = append(disposalList, gif.DisposalNone) } else { disposalList = append(disposalList, gif.DisposalPrevious) } newList = append(newList, newImg) delayList = append(delayList, 10) } log.Println("Saving gif with ", len(newList), " frames") gifData := gif.GIF{ Image: newList, Delay: delayList, Disposal: disposalList, LoopCount: -1, BackgroundIndex: 0, Config: image.Config{ ColorModel: colList, Width: wid, Height: height, }, } fn := MakeGifFilename(username, tid) f, e := os.Create(fn) if e != nil { log.Println(e) return "", e } e = gif.EncodeAll(f, &gifData) if e != nil { log.Println(e) return "", e } return fn, nil }