disintegration / gift Goto Github PK
View Code? Open in Web Editor NEWGo Image Filtering Toolkit
License: MIT License
Go Image Filtering Toolkit
License: MIT License
See the 'Trim' example in https://images.weserv.nl/#adjustments. It trims "boring" pixels from all edges that contain values within a similarity of the top-left pixel. So the excess of (for example) edged white space is removed. Useful to 'intelligently' crop an image of something against a even coloured background. The resulting image will be smaller but the informational part of the image will not change in any way.
Is there any problem with making this public/exported? It's a handy utility function to use when implementing custom filters.
I'd love to see something along the lines of php's imagerotate which allows arbitrary angles for rotation along with a parameter for the color of the padding. I haven't seen it in any go inserted manip libraries and it would be great!
In readme and docs:
gift.Resize(800, 0, gift.LanczosResampling),
It's probably a typo because resizing to height 0 isn't very useful.
Hey there, nice project!
Having benchmarks to compare to other solutions (like bindings to ImageMagick et al) would be nice.
I'm idly looking for this sort of libraries and waiting to find one that performs well enough, having numbers would be great. It's also helpful when profiling.
If you'd like, I might be able to contribute some of them.
Hi, I wasn't sure where the best place to post this was since I'm not sure if it's a bug or if I'm just doing something silly. If this is the wrong forum I apologise.
I've been working on a little HTTP API that builds on gift (https://github.com/paddycarey/ims) and it's working great for PNG and JPEG images, but I've run into an issue when applying filters to animated GIF images. It seems that transparency is not preserved in the filtered frames and it results in large black areas that should really be transparent since they haven't changed since the previous frame.
This is maybe easier to explain with an example.
package main
import (
"fmt"
"image"
"image/gif"
"os"
"runtime"
"github.com/disintegration/gift"
)
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
f, err := os.Open("test.gif")
if err != nil {
panic(err)
}
defer f.Close()
g, err := gif.DecodeAll(f)
if err != nil {
panic(err)
}
filter := gift.New(
gift.FlipHorizontal(),
)
newImages := []*image.Paletted{}
for _, i := range g.Image {
dst := image.NewPaletted(filter.Bounds(i.Bounds()), i.Palette)
filter.Draw(dst, i)
newImages = append(newImages, dst)
}
g.Image = newImages
of, err := os.Create("out.gif")
if err != nil {
panic(err)
}
defer of.Close()
err = gif.EncodeAll(of, g)
if err != nil {
panic(err)
}
fmt.Println("Successfully encoded gif: out.gif")
}
Used with the following test image:
Produces the following output:
I looked around and found some similar issues, I thought it may be the same as this issue, it's certainly got the same symptoms, but I'm not sure. I'm able to run DecodeAll
and EncodeAll
and the result will be fine, provided I don't use gift. For what it's worth I also tested with imaging and it has the same issue.
go version
returns go1.4.1 linux/amd64
if that helps.
Thanks again for the great library, any help you could provide would be greatly appreciated.
I stumble on gift yesterday and I was wondering if it is already at a point where I could use it to replace this one liner
#!/bin/bash
convert "$1" -morphology Convolve DoG:15,100,0 -negate -normalize -blur 0x1 -channel RBG -level 60%,91%,0.1 "$2"
If this is not the right place to ask question about this lib please let me know what is the best venue.
Thanks
First off, this is a great library. I have been using gift with great results. Props to the author(s).
This issue is in regards to a white border rendered around images with a transparent background when using DrawAt with the OverOperator to write the image onto another image. My intent is to have transparent pngs render with no white border on top of other images.
Is this result the intended functionality of the OverOperator functionality? Is there any strategy I can take to get around this?
Example code below:
package main
import (
"image"
"image/color"
"image/draw"
"image/png"
"os"
"github.com/disintegration/gift"
)
func main() {
f, err := os.Open("test.png")
if err != nil {
panic(err)
}
defer f.Close()
srcImg, _, err := image.Decode(f)
if err != nil {
panic(err)
}
finalImg := image.NewRGBA(image.Rect(0, 0, 300, 300))
//draw background color (dk blue) on final image
bgColor := color.RGBA{0, 0, 100, 255}
draw.Draw(finalImg, finalImg.Bounds(), &image.Uniform{bgColor}, image.ZP, draw.Src)
gift.New().DrawAt(finalImg, srcImg, image.Point{0, 0}, gift.OverOperator)
fOut, err := os.Create("output.png")
if err != nil {
panic(err)
}
png.Encode(fOut, finalImg)
}
Source transparent background png:
Output image:
Golang 1.12.6 on aarch64, ppc64le, s390x:
Testing in: /builddir/build/BUILD/gift-1.2.0/_build/src
PATH: /builddir/build/BUILD/gift-1.2.0/_build/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/sbin
GOPATH: /builddir/build/BUILD/gift-1.2.0/_build:/usr/share/gocode
GO111MODULE: off
command: go test -buildmode pie -compiler gc -ldflags "-X github.com/disintegration/gift/version=1.2.0 -extldflags '-Wl,-z,relro -Wl,--as-needed -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld '"
testing: github.com/disintegration/gift
github.com/disintegration/gift
--- FAIL: TestBrightness (0.00s)
colors_test.go:434: test [brightness (-30)] failed: image.Rectangle{Min:image.Point{X:0, Y:0}, Max:image.Point{X:5, Y:3}}, []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x64, 0x54, 0x64, 0x14, 0x0, 0x34, 0x0, 0x34, 0x0}
--- FAIL: TestGolden (0.61s)
gift_test.go:593: resulting image differs from golden: contrast_increase
gift_test.go:593: resulting image differs from golden: saturation_decrease
gift_test.go:593: resulting image differs from golden: saturation_increase
gift_test.go:593: resulting image differs from golden: hue_rotate
FAIL
I implemented gift.Filter
interface with method Draw
below. But the result plain is white image only. Is there something wrong with my code? Or How to implement gift.Filter
in the right way?
func (f ditherFilter) Draw(dst draw.Image, src image.Image, options *gift.Options) {
dst = image.NewPaletted(src.Bounds(), color.Palette{color.Black, color.White})
draw.FloydSteinberg.Draw(dst, src.Bounds(), src, image.ZP)
}
reference: https://golang.org/pkg/image/draw/
Thanks.
It would be awesome to have this feature. Even simple average hash would be cool for the beginning.
Just need int64 that represents visual hash of the image.
Thank you!
Hi,
How to add watermark?And how to read a svg image?
Hi,
I want to create a CropMargin filter. This filter will look in the img, and remove the white line all around the image.
For this I need the source image to look for the pixel I want to remove.
If the Bounds method receive the src instead the src.Bounds, that would make a lot for filter possible.
For now I have to calculate the bound before I can create the filter Crop and apply it.
May be I can return the srcBound, and in the Draw I can draw the return the src.sub image. That may work, but the g.Bounds will return the wrong value.
Do you think it could be a possible evolution?
Note that benchmarks of the command line interface to gift are in https://github.com/ajstarks/gift/blob/master/README.md
Hello, is there a Posterize filter? If not, would you be interested in a contribution?
My Diffusion-Reaction simulation attempt. 18 seconds for 900 filters ( 512x512 image). Also I experienced freezes while playing with UnsharpMask/GaussianBlur parameters.
iteration := 300
filter_set := []gift.Filter{
gift.GaussianBlur(9),
gift.UnsharpMask(9, 9, 0),
gift.Threshold(50),
}
filters := []gift.Filter{}
for i := 0; i < iteration; i++ {
filters = append(filters, filter_set...)
}
g := gift.New(filters...)
package main
import (
"fmt"
"image"
"image/color"
"image/draw"
"image/png"
"log"
"os"
"time"
"github.com/disintegration/gift"
"github.com/fogleman/gg"
)
func main() {
start := time.Now()
circleimage := image.NewRGBA(image.Rect(0, 0, 512, 512))
draw.Draw(circleimage, circleimage.Bounds(), &image.Uniform{color.Black}, image.ZP, draw.Src)
dc := gg.NewContextForImage(circleimage)
dc.DrawCircle(128, 128, 32)
dc.SetRGB(1, 1, 1)
dc.Fill()
input := dc.Image()
// src := loadImage("input.png")
iteration := 300
filter_set := []gift.Filter{
gift.GaussianBlur(9),
gift.UnsharpMask(9, 9, 0),
gift.Threshold(50),
}
filters := []gift.Filter{}
for i := 0; i < iteration; i++ {
filters = append(filters, filter_set...)
}
g := gift.New(filters...)
dst := image.NewRGBA(g.Bounds(input.Bounds()))
g.Draw(dst, input)
saveImage("input.png", input)
saveImage("output.png", dst)
duration := time.Since(start)
// Formatted string, such as "2h3m0.5s" or "4.503μs"
fmt.Println(duration)
}
func loadImage(filename string) image.Image {
f, err := os.Open(filename)
if err != nil {
log.Fatalf("os.Open failed: %v", err)
}
defer f.Close()
img, _, err := image.Decode(f)
if err != nil {
log.Fatalf("image.Decode failed: %v", err)
}
return img
}
func saveImage(filename string, img image.Image) {
f, err := os.Create(filename)
if err != nil {
log.Fatalf("os.Create failed: %v", err)
}
defer f.Close()
err = png.Encode(f, img)
if err != nil {
log.Fatalf("png.Encode failed: %v", err)
}
}
How to save an image to a progressive image?
I am using below methods to blur a face in an image.
Am I using it properly or misusing?
package main
import (
"image"
"image/jpeg"
"log"
"os"
"github.com/disintegration/gift"
)
func main() {
faceX := 1713
faceY := 1752
faceWidth := 130
faceHeight := 130
src := loadImage("1.jpg")
//Copy original image
gCopyImage := gift.New()
fullImage := image.NewRGBA(gCopyImage.Bounds(src.Bounds()))
gCopyImage.Draw(fullImage, src)
//Crop some part
gCrop := gift.New(gift.Crop(image.Rect(faceX, faceY, faceX+faceWidth, faceY+faceHeight)))
croppedImage := image.NewRGBA(gCrop.Bounds(src.Bounds()))
gCrop.Draw(croppedImage, src)
//Pixelate the cropped image and draw on original image
gPixelate := gift.New(gift.Pixelate(20))
gPixelate.DrawAt(fullImage, croppedImage, image.Point{X: faceX, Y: faceY}, gift.OverOperator)
saveImage("out.jpg", fullImage)
}
func loadImage(filename string) image.Image {
f, err := os.Open(filename)
if err != nil {
log.Fatalf("os.Open failed: %v", err)
}
defer f.Close()
img, _, err := image.Decode(f)
if err != nil {
log.Fatalf("image.Decode failed: %v", err)
}
return img
}
func saveImage(filename string, img image.Image) {
f, err := os.Create(filename)
if err != nil {
log.Fatalf("os.Create failed: %v", err)
}
defer f.Close()
//err = png.Encode(f, img)
err = jpeg.Encode(f, img, &jpeg.Options{Quality: 99})
if err != nil {
log.Fatalf("png.Encode failed: %v", err)
}
}
Are there any plans to add thresholding to this library?
I'm completely new to this field, but would be interested in helping out if we can discuss what the API would look like. Any thoughts?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.