func varianceF(img image.Image, disk int) (imageF, imageF) { m := meanF(img, disk) // gets a grayscale copy of local mean // create a grayscale version of the original //g := gift.New( gift.Grayscale() ) //v := image.NewRGBA(g.Bounds(img.Bounds())) //g.Draw(v, img) g := gift.New(gift.Grayscale()) dst := image.NewRGBA(g.Bounds(img.Bounds())) g.Draw(dst, img) bounds := img.Bounds() floatData := make([][]float32, bounds.Max.Y-bounds.Min.Y) for i := range floatData { floatData[i] = make([]float32, bounds.Max.X-bounds.Min.X) } for y := bounds.Min.X; y < bounds.Max.X; y++ { for x := bounds.Min.Y; x < bounds.Max.Y; x++ { p1r, p1g, p1b, _ := dst.At(x, y).RGBA() g1 := 0.2125*float64(p1r) + 0.7154*float64(p1g) + 0.0721*float64(p1b) g2 := float64(m[x][y]) floatData[x][y] = float32((g1 - g2) * (g1 - g2)) } } return m, floatData }
func makeThumb(source, destination string) error { // {{{ file, err := os.Open(source) if err != nil { return err } defer file.Close() // decode jpeg into image.Image img, err := jpeg.Decode(file) if err != nil { return err } g := gift.New( gift.ResizeToFill(200, 200, gift.LanczosResampling, gift.CenterAnchor), ) out, err := os.Create(destination) if err != nil { return err } defer out.Close() // write new image to file dst := image.NewRGBA(g.Bounds(img.Bounds())) g.Draw(dst, img) return jpeg.Encode(out, dst, &jpeg.Options{100}) } // }}}
// Render draws rune r front the specified font at the specified dpi and scale. It returns a // grayscale image that is just large enough to contain the rune. func Render(font *truetype.Font, r rune, dpi, scale float64) (*image.Gray, error) { glyph := truetype.NewGlyphBuf() index := font.Index(r) glyph.Load(font, font.FUnitsPerEm(), index, truetype.FullHinting) ctx := freetype.NewContext() boxer := makeBoundingBoxer() ctx.SetSrc(image.NewUniform(color.White)) ctx.SetDst(boxer) ctx.SetClip(boxer.largeBounds) ctx.SetFontSize(250) ctx.SetDPI(dpi) ctx.SetFont(font) if err := glyph.Load(font, font.FUnitsPerEm(), font.Index(r), truetype.FullHinting); err != nil { return nil, fmt.Errorf("Unable to load glyph: %v\n", err) } var rp raster.Point rp.X = ctx.PointToFix32(0) rp.Y = ctx.PointToFix32(100) ctx.DrawString(string(r), rp) boxer.complete() g := gift.New( gift.Resize(int(float64(boxer.Bounds().Dx())*scale+0.5), int(float64(boxer.Bounds().Dy())*scale+0.5), gift.CubicResampling), ) dst := image.NewGray(g.Bounds(boxer.Bounds())) g.Draw(dst, boxer) return dst, nil }
// TODO Too min images should not resized func resizeImage(src image.Image, n int) image.Image { srcBounds := src.Bounds() gi := gift.New(gift.Resize(srcBounds.Max.Y/n, srcBounds.Max.Y/n, gift.LanczosResampling)) dst := image.NewRGBA(gi.Bounds(srcBounds)) gi.Draw(dst, src) return dst }
func blur(img image.Image, howmuch float32) image.Image { g := gift.New(gift.Grayscale()) g.Add(gift.GaussianBlur(howmuch)) dst := image.NewRGBA(g.Bounds(img.Bounds())) g.Draw(dst, img) return (dst) }
func (fi *FileInfo) createThumb(buffer *bytes.Buffer, c context.Context) { if imageTypes.MatchString(fi.Type) { src, _, err := image.Decode(bytes.NewReader(buffer.Bytes())) check(err) filter := gift.New(gift.ResizeToFit( THUMB_MAX_WIDTH, THUMB_MAX_HEIGHT, gift.LanczosResampling, )) dst := image.NewNRGBA(filter.Bounds(src.Bounds())) filter.Draw(dst, src) buffer.Reset() bWriter := bufio.NewWriter(buffer) switch fi.Type { case "image/jpeg", "image/pjpeg": err = jpeg.Encode(bWriter, dst, nil) case "image/gif": err = gif.Encode(bWriter, dst, nil) default: err = png.Encode(bWriter, dst) } check(err) bWriter.Flush() thumbnailKey := fi.Key + thumbSuffix + filepath.Ext(fi.Name) item := &memcache.Item{ Key: thumbnailKey, Value: buffer.Bytes(), } err = memcache.Set(c, item) check(err) fi.ThumbnailKey = thumbnailKey } }
func mean(img image.Image, disk int) image.Image { g := gift.New(gift.Grayscale()) g.Add(gift.Mean(disk, false)) // use square neighborhood dst := image.NewRGBA(g.Bounds(img.Bounds())) g.Draw(dst, img) return (dst) }
// DrawPicture . func DrawPicture(src image.Image, width int, height int) *image.Gray { rect := image.Rect(0, 0, width, height) img := image.NewGray(rect) rander := rander() for x := 0; x < width; x++ { for y := 0; y < height; y++ { var c color.Gray if IsBlack(src, x, y) { if y > 1 && IsNotBlack(src, x, y-1) { c = borderColor(rander) } else { c = insideColor(rander) } } else { c = outsideColor(rander) } x1, y1 := transformCurve(x, y, width, height) //c = color.Gray{c.Y + ScaledLuminanceAt(90, src, x, y)} img.Set(x1, y1, c) } } g := gift.New( //gift.GaussianBlur(2), ) img2 := image.NewGray(rect) g.Draw(img2, img) return img2 }
func analyzeFile(filename string, resize bool) (*Cover, error) { file, err := os.Open(filename) if err != nil { return nil, err } defer file.Close() img, _, err := image.Decode(file) if err != nil { return nil, err } if resize { start := time.Now() g := gift.New(gift.Resize(500, 0, gift.LanczosResampling)) dst := image.NewRGBA(g.Bounds(img.Bounds())) g.Draw(dst, img) img = dst fmt.Printf("- RESIZE %s took %s\n", path.Base(filename), time.Since(start)) } start := time.Now() bg, c1, c2, c3 := colorart.Analyze(img) fmt.Printf("- ANALYZE %s took %s\n", path.Base(filename), time.Since(start)) return &Cover{filename, bg.String(), c1.String(), c2.String(), c3.String()}, nil }
func procImage(fileName string) (string, error) { reader, err := os.Open(fileName) if err != nil { fmt.Errorf("Failed to open image with error: %s\n", err) return "", err } defer reader.Close() src, _, err := image.Decode(reader) if err != nil { fmt.Errorf("Failed to decode image with error: %s\n", err) return "", err } g := gift.New( gift.Invert(), ) dst := image.NewRGBA(g.Bounds(src.Bounds())) g.Draw(dst, src) var opt jpeg.Options opt.Quality = 100 fileName = fileName + "_processed.jpg" out, _ := os.Create(fileName) err = jpeg.Encode(out, dst, &opt) if err != nil { fmt.Errorf("Failed to encode image with error: %s\n", err) return "", err } return fileName, nil }
// Sets skin.Processed to an isometric render of the head from a top-left angle (showing 3 sides). func (skin *mcSkin) GetCube(width int) error { // Crop out the top of the head topFlat := imaging.Crop(skin.Image, image.Rect(8, 0, 16, 8)) // Resize appropriately, so that it fills the `width` when rotated 45 def. topFlat = imaging.Resize(topFlat, int(float64(width)*math.Sqrt(2)/3+1), 0, imaging.NearestNeighbor) // Create the Gift filter filter := gift.New( gift.Rotate(45, color.Transparent, gift.LinearInterpolation), ) bounds := filter.Bounds(topFlat.Bounds()) top := image.NewNRGBA(bounds) // Draw it on the filter, then smush it! filter.Draw(top, topFlat) top = imaging.Resize(top, width+2, width/3, imaging.NearestNeighbor) // Skew the front and sides at 15 degree angles to match up with the // head that has been smushed front := skin.cropHead(skin.Image).(*image.NRGBA) side := imaging.Crop(skin.Image, image.Rect(0, 8, 8, 16)) front = imaging.Resize(front, width/2, int(float64(width)/1.75), imaging.NearestNeighbor) side = imaging.Resize(side, width/2, int(float64(width)/1.75), imaging.NearestNeighbor) front = skewVertical(front, math.Pi/12) side = skewVertical(imaging.FlipH(side), math.Pi/-12) // Create a new image to assemble upon skin.Processed = image.NewNRGBA(image.Rect(0, 0, width, width)) // Draw each side draw.Draw(skin.Processed.(draw.Image), image.Rect(0, width/6, width/2, width), side, image.Pt(0, 0), draw.Src) draw.Draw(skin.Processed.(draw.Image), image.Rect(width/2, width/6, width, width), front, image.Pt(0, 0), draw.Src) // Draw the top we created draw.Draw(skin.Processed.(draw.Image), image.Rect(-1, 0, width+1, width/3), top, image.Pt(0, 0), draw.Over) return nil }
func main() { if len(os.Args) != 2 { fmt.Println("Usage:\tgoimger <file>") os.Exit(1) } srcFileName := os.Args[1] srcFile, _ := os.Open(srcFileName) src, _, _ := image.Decode(srcFile) // let's make a new gift g := gift.New( gift.Grayscale(), gift.UnsharpMask(1.0, 0.5, 0.0), ) // dest - output image dest := image.NewRGBA(g.Bounds(src.Bounds())) // draw result g.Draw(dest, src) outFileName := srcFileName + "_goimger.jpg" toimg, _ := os.Create(outFileName) defer toimg.Close() jpeg.Encode(toimg, dest, &jpeg.Options{jpeg.DefaultQuality}) }
func main() { if len(os.Args) != 2 { fmt.Println("Usage:\tspiffy <file>") os.Exit(1) } srcFileName := os.Args[1] srcFile, _ := os.Open(srcFileName) src, _, _ := image.Decode(srcFile) // 1. Create a new GIFT and add some filters: g := gift.New( gift.Grayscale(), gift.UnsharpMask(1.0, 1.0, 0.0), ) // 2. Create a new image of the corresponding size. // dst is a new target image, src is the original image dst := image.NewRGBA(g.Bounds(src.Bounds())) // 3. Use Draw func to apply the filters to src and store the result in dst: g.Draw(dst, src) outFileName := srcFileName + ".spiffy.jpg" toimg, _ := os.Create(outFileName) defer toimg.Close() jpeg.Encode(toimg, dst, &jpeg.Options{jpeg.DefaultQuality}) }
func CropImage(img image.Image, rect image.Rectangle) (croped image.Image) { g := gift.New( gift.Crop(rect), ) croped_image := image.NewRGBA(g.Bounds(rect)) g.Draw(croped_image, img) return croped_image }
func newResizeFuncGift(resampling gift.Resampling) resizeFunc { return func(im image.Image) image.Image { g := gift.New(gift.Resize(width, height, resampling)) newIm := newImageFunc(g.Bounds(im.Bounds())) g.Draw(newIm, im) return newIm } }
// take an image and revert its rgb channels (255-channel) func invert(img image.Image) image.Image { g := gift.New(gift.Grayscale(), gift.Invert()) dst := image.NewRGBA(g.Bounds(img.Bounds())) g.Draw(dst, img) return dst }
// loadimage loads all the images of the deck into a map for later display func loadimage(d deck.Deck, m map[string]image.Image) { firstrun++ w, h := d.Canvas.Width, d.Canvas.Height cw := openvg.VGfloat(w) ch := openvg.VGfloat(h) msize := int(cw * .01) mx := cw / 2 my := ch * 0.05 mbg := "white" mfg := "black" for ns, s := range d.Slide { for ni, i := range s.Image { if !modfile(i.Name, StartTime) { continue } openvg.Start(w, h) if i.Link != "" { fmt.Fprintf(os.Stderr, "Found altimg %s\n", i.Link) } f, err := os.Open(i.Name) if err != nil { fmt.Fprintf(os.Stderr, "%v\n", err) continue } img, _, err := image.Decode(f) if err != nil { fmt.Fprintf(os.Stderr, "%v\n", err) continue } openvg.FillColor(mbg) openvg.Rect(0, 0, cw, ch) openvg.FillColor(mfg) openvg.TextMid(mx, my, fmt.Sprintf("Loading image %s %d from slide %d", i.Name, ni, ns), "sans", msize) bounds := img.Bounds() iw := i.Width ih := i.Height if i.Scale > 0 { iw = int(float64(iw) * (i.Scale / 100)) ih = int(float64(ih) * (i.Scale / 100)) } // if the specified dimensions are native use those, otherwise resize if iw == (bounds.Max.X-bounds.Min.X) && ih == (bounds.Max.Y-bounds.Min.Y) { m[i.Name] = img } else { g := gift.New(gift.Resize(iw, ih, gift.BoxResampling)) resized := image.NewRGBA(g.Bounds(img.Bounds())) g.Draw(resized, img) m[i.Name] = resized } f.Close() openvg.End() } } }
func doit(fn string) (string, error) { file, err := os.Open(fn) if err != nil { return "", err } defer file.Close() img, _, err := image.Decode(file) if err != nil { return "", err } b := img.Bounds() var g *gift.GIFT if b.Max.X-b.Min.X >= resizeThreshold || b.Max.Y-b.Min.Y >= resizeThreshold { g = gift.New( gift.Resize(resizeSize, resizeSize, gift.LanczosResampling), gift.GaussianBlur(sigma)) } else { g = gift.New(gift.GaussianBlur(sigma)) } dst := image.NewRGBA(g.Bounds(img.Bounds())) g.Draw(dst, img) img = dst fn = path.Base(fn) ext := path.Ext(fn) fn = fmt.Sprintf("./%s.blur%s", fn[:len(fn)-len(ext)], ext) w, _ := os.Create(fn) defer w.Close() if err = jpeg.Encode(w, dst, nil); err != nil { return "", err } return fn, nil }
func (this *AvatarController) Post() { w := this.ResponseWriter r := this.Request data := e.Data{Status: 1, Msg: "上传成功"} log.Println("头像上传post") r.ParseMultipartForm(32 << 20) log.Println("表单解析") file, handler, err := r.FormFile("realPicFile") if err != nil { log.Println("上传错误") return } fileext := filepath.Ext(handler.Filename) log.Println("文件后缀名字" + fileext) if u.Check(fileext) == false { data.Status = 0 data.Msg = "不允许的上传类型" u.OutputJson(w, &data) return } cookie := u.Cookie{HTTP: this.HTTP} filename := cookie.GetCookie().UserId.Value + ".png" log.Println("文件名称" + filename) imgfile, _ := os.OpenFile(Upload_Dir+filename, os.O_CREATE|os.O_WRONLY, 0660) defer imgfile.Close() //把图片变成400X400尺寸的 m1, err := jpeg.Decode(file) if err != nil { panic(err) } bounds := m1.Bounds() //如果第二参数为0则保持横纵比 g := gift.New( gift.Resize(400, 400, gift.LanczosResampling), ) dst := image.NewRGBA(g.Bounds(bounds)) g.Draw(dst, m1) err = png.Encode(imgfile, dst) if err != nil { log.Println("上传失败") return } filedir := Show_Dir + filename data.Data = filedir log.Println(data) u.OutputJson(w, &data) }
func resizeImage(img image.Image, size image.Point) image.Image { g := gift.New(gift.Resize(size.X, size.Y, gift.LanczosResampling)) rect := image.Rectangle{Max: size} switch img.(type) { case *image.Gray: dst := image.NewGray(rect) g.Draw(dst, img) return dst default: dst := image.NewRGBA(rect) g.Draw(dst, img) return dst } }
func (prc *RotateProcessor) process(nim image.Image, params imageserver.Params) (image.Image, error) { rot, err := prc.getRotation(params) if err != nil { return nil, err } if rot == 0 { return nim, nil } f, err := prc.getFilter(rot, params) if err != nil { return nil, err } g := gift.New(f) out := imageserver_image_internal.NewDrawableSize(nim, g.Bounds(nim.Bounds())) g.Draw(out, nim) return out, nil }
// try to focus on a specific scale by using a mexican hat filter func focus(img image.Image, s float32) image.Image { onethird := s / 3.0 small := blur(img, s-onethird) large := blur(img, s+onethird) bounds := img.Bounds() floatData := make([][]float32, bounds.Max.X-bounds.Min.X) for i := range floatData { floatData[i] = make([]float32, bounds.Max.Y-bounds.Min.Y) } for y := bounds.Min.Y; y < bounds.Max.Y; y++ { for x := bounds.Min.X; x < bounds.Max.X; x++ { p1r, p1g, p1b, _ := small.At(x, y).RGBA() p2r, p2g, p2b, _ := large.At(x, y).RGBA() g1 := 0.2125*float64(p1r) + 0.7154*float64(p1g) + 0.0721*float64(p1b) g2 := 0.2125*float64(p2r) + 0.7154*float64(p2g) + 0.0721*float64(p2b) floatData[x][y] = float32(g1 - g2) } } min := floatData[0][0] max := floatData[0][0] for y := bounds.Min.Y; y < bounds.Max.Y; y++ { for x := bounds.Min.X; x < bounds.Max.X; x++ { if min > floatData[x][y] { min = floatData[x][y] } if max < floatData[x][y] { max = floatData[x][y] } } } g := gift.New(gift.Grayscale()) dst := image.NewRGBA(g.Bounds(img.Bounds())) g.Draw(dst, img) for y := bounds.Min.Y; y < bounds.Max.Y; y++ { for x := bounds.Min.X; x < bounds.Max.X; x++ { dst.Set(x, y, color.Gray16{uint16((floatData[x][y] - min) / (max - min) * 65535)}) } } return dst }
func (prc *ResizeProcessor) process(nim image.Image, params imageserver.Params) (image.Image, error) { width, height, err := prc.getSize(params) if err != nil { return nil, err } if width == 0 && height == 0 { return nim, err } f, err := prc.getFilter(width, height, params) if err != nil { return nil, err } g := gift.New(f) out := imageserver_image_internal.NewDrawableSize(nim, g.Bounds(nim.Bounds())) g.Draw(out, nim) return out, nil }
func getimage(image_path string, w, h int, resized bool) (image.Image, error) { f, err := os.Open(image_path) if err != nil { fmt.Fprintf(os.Stderr, "%v\n", err) return nil, err } defer f.Close() img, _, err := image.Decode(f) if err != nil { fmt.Fprintf(os.Stderr, "%v\n", err) return nil, err } if resized { g := gift.New(gift.ResizeToFit(w, h, gift.BoxResampling)) res := image.NewRGBA(g.Bounds(img.Bounds())) g.Draw(res, img) return res, nil } return img, nil }
func (this *AvatarController) Cut() { r := this.Request data := e.Data{Status: 1, Msg: "上传成功"} r.ParseForm() x, err := strconv.Atoi(r.FormValue("x")) y, err := strconv.Atoi(r.FormValue("y")) x2, err := strconv.Atoi(r.FormValue("x2")) y2, err := strconv.Atoi(r.FormValue("y2")) fileName := r.FormValue("fileName") log.Println(x, y, x2, y2, fileName) g := gift.New( gift.Crop(image.Rect(x, y, x2, y2)), gift.Resize(220, 220, gift.LanczosResampling), ) log.Println("图片名称" + fileName) //打开待处理的图片 file, err := os.Open(fileName) if err != nil { panic(err) } defer file.Close() m1, err := png.Decode(file) if err != nil { panic(err) } bounds := m1.Bounds() dst := image.NewRGBA(g.Bounds(bounds)) g.Draw(dst, m1) cookie := u.Cookie{HTTP: this.HTTP} filename := cookie.GetCookie().UserId.Value + ".png" imgfile, err := os.Create(Avatar_ReDir + filename) os.Remove(Upload_Dir + filename) defer imgfile.Close() err = png.Encode(imgfile, dst) u.OutputJson(this.ResponseWriter, &data) }
// nytheadlines retrieves data from the New York Times API, decodes and displays it. func (d *display) nytheadlines(section string, thumb bool) { hdim := dimen{x: 0, y: 0, width: d.width, height: d.height / 2} r, err := netread(fmt.Sprintf(NYTfmt, section, NYTAPIkey)) if err != nil { fmt.Fprintf(os.Stderr, "headline read error: %v\n", err) hdim.gerror(d.bgcolor, d.textcolor, "no headlines") return } defer r.Close() var data NYTHeadlines err = json.NewDecoder(r).Decode(&data) if err != nil { fmt.Fprintf(os.Stderr, "decode: %v\n", err) hdim.gerror(d.bgcolor, d.textcolor, "no headlines") return } x := d.width * 0.10 y := d.height * 0.10 thumbsize := int(d.height * 0.05) hdim.regionFill(d.bgcolor, d.textcolor) headsize := d.width / 80 spacing := openvg.VGfloat(thumbsize) for i := len(data.Results) - 1; i >= 0; i-- { openvg.Text(x, y, fromHTML.Replace(data.Results[i].Title), "serif", int(headsize)) if len(data.Results[i].Thumbnail) > 0 { img, imerr := netimage(data.Results[i].Thumbnail) if imerr != nil { continue } g := gift.New() g.Add(gift.Resize(0, thumbsize, gift.LanczosResampling)) gift.Resize(thumbsize, thumbsize, gift.BoxResampling) resized := image.NewRGBA(g.Bounds(img.Bounds())) g.Draw(resized, img) openvg.Img(x-100, y-(spacing*0.25), resized) } y = y + spacing } openvg.Image(d.width*0.05, 15, 30, 30, "poweredby_nytimes_30a.png") openvg.End() }
func meanF(img image.Image, disk int) imageF { g := gift.New(gift.Grayscale()) g.Add(gift.Mean(disk, false)) // use square neighborhood dst := image.NewRGBA(g.Bounds(img.Bounds())) g.Draw(dst, img) // now convert this to float array of arrays floatData := make([][]float32, dst.Bounds().Max.Y-dst.Bounds().Min.Y) for i := range floatData { floatData[i] = make([]float32, dst.Bounds().Max.X-dst.Bounds().Min.X) } bounds := dst.Bounds() for y := bounds.Min.X; y < bounds.Max.X; y++ { for x := bounds.Min.Y; x < bounds.Max.Y; x++ { pr, _, _, _ := dst.At(x, y).RGBA() floatData[x][y] = float32(pr) // 0.2125*float32(pr) + 0.7154*float32(pg) + 0.0721*float32(pb) } } return floatData }
func analyzeFile(filename string) (bg, c1, c2, c3 colorart.Color) { file, err := os.Open(filename) defer file.Close() if err != nil { log.Fatal(err) } img, _, err := image.Decode(file) if err != nil { log.Fatal(err) } b := img.Bounds() if b.Max.X-b.Min.X > resizeThreshold || b.Max.Y-b.Min.Y > resizeThreshold { g := gift.New(gift.Resize(resizeSize, 0, gift.LanczosResampling)) dst := image.NewRGBA(image.Rect(0, 0, resizeSize, resizeSize)) g.Draw(dst, img) img = dst } return colorart.Analyze(img) }
func variance(img image.Image, disk int) (image.Image, image.Image) { m := mean(img, disk) // gets a grayscale copy // create a grayscale version of the original g := gift.New(gift.Grayscale()) v := image.NewRGBA(g.Bounds(img.Bounds())) g.Draw(v, img) bounds := img.Bounds() dst := image.NewGray(bounds) for y := bounds.Min.X; y < bounds.Max.X; y++ { for x := bounds.Min.Y; x < bounds.Max.Y; x++ { p1r, p1g, p1b, _ := v.At(x, y).RGBA() p2r, p2g, p2b, _ := m.At(x, y).RGBA() g1 := 0.2125*float64(p1r) + 0.7154*float64(p1g) + 0.0721*float64(p1b) g2 := 0.2125*float64(p2r) + 0.7154*float64(p2g) + 0.0721*float64(p2b) dst.Set(x, y, color.Gray16{uint16(math.Sqrt((g1 - g2) * (g1 - g2)))}) //fmt.Println("value: ", math.Sqrt((g1-g2) * (g1-g2))) } } return m, dst }
// GreyscaleDctMatrix Computes the Dct of a greyscale image using matrixes func GreyscaleDctMatrix(im image.Image) uint64 { greyFilter := gift.Grayscale() convFilter := gift.Convolution([]float32{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }, true, false, false, 0) resizeFilter := gift.Resize(32, 32, gift.LinearResampling) g := gift.New(greyFilter, convFilter, resizeFilter) dst := image.NewRGBA(g.Bounds(im.Bounds())) g.Draw(dst, im) /* out, _ := os.Create("/Users/danielriley/desktop/output.jpg") var opt jpeg.Options opt.Quality = 80 _ = jpeg.Encode(out, dst, &opt) // put quality to 80% out1, _ := os.Create("/Users/danielriley/desktop/output1.jpg") opt.Quality = 80 _ = jpeg.Encode(out1, im, &opt) // put quality to 80% return 0 */ //width := im.Bounds().Max.X //height := im.Bounds().Max.Y m := make([][]float64, 32) for i := 0; i < 32; i++ { m[i] = make([]float64, 32) for j := 0; j < 32; j++ { _, _, b, _ := dst.At(i, j).RGBA() m[i][j] = float64(b) } } /* out, _ := os.Create("/Users/danielriley/desktop/output.jpg") var opt jpeg.Options opt.Quality = 80 _ = jpeg.Encode(out, dst, &opt) // put quality to 80% out1, _ := os.Create("/Users/danielriley/desktop/output1.jpg") opt.Quality = 80 _ = jpeg.Encode(out1, im, &opt) // put quality to 80% */ imMatrix := FloatMatrix(m) dctMatrix := NewDCTMatrix(32) // We can safely ignore errors here, since the sizes // always match. dct, _ := dctMatrix.Multiply(imMatrix) dct, _ = dct.Multiply(dctMatrix.Transposed()) sub, _ := dct.SubMatrix(1, 1, 8, 8) values := sub.UnrollX() // We need the original values, so we must sort a copy cpy := make([]float64, len(values)) copy(cpy, values) sort.Float64s(cpy) median := (cpy[64/2-1] + cpy[64/2]) / 2 fmt.Println("got median ", median) bit := uint64(1) hash := uint64(0) for _, v := range values { if v > median { hash |= bit } bit <<= 1 } fmt.Println("calculated hash ", hash) return hash /* imgMtx, err := manipulator.GrayImageToMatrix(img) if err != nil { panic(err) } dctMtx, err := createDctMatrix(img.Bounds().Max.X, img.Bounds().Max.Y) if err != nil { panic(err) } dctMtxTransp := dctMtx.T() // Transpose dctMtx.Mul(dctMtx, imgMtx) dctMtx.Mul(dctMtx, dctMtxTransp) dctImage, err := manipulator.CropMatrix(dctMtx, 0, 0, 7, 7) if err != nil { panic(err) } subsec := dctImage.RawMatrix().Data median := median(subsec) var one, hash uint64 = 1, 0 for i := 0; i < len(subsec); i++ { current := subsec[i] if current > median { hash |= one } one = one << 1 } return hash */ }