disintegration / imaging Goto Github PK
View Code? Open in Web Editor NEWImaging is a simple image processing package for Go
License: MIT License
Imaging is a simple image processing package for Go
License: MIT License
Encode
always compresses jpegs at 95%, it would be nice if this was configurable, or accessible from Save
https://github.com/disintegration/imaging/blob/master/helpers.go#L94
Hi,
is it possible to add a function for rotating an image and specify the offset ourself? I've checked the code and it seems the function for this is already there ... Just private ...
This would be a great help.
as converting a binary image in color? White and black?
Hi,
It would be neat to have a strip-alpha-functionality as an option for saving the image. Currently, PNG's that contains an alpha background and are saved to JPG are having a black background.
thanks,
pepijn
Hello, Grigory, do you know if I can save an image with a DPI (PPI) higher than the standard image library offers? They save at 72 PPI.
I've been using this package to rotate images as I migrate them from my laptop to a server, and I just went crazy trying to figure out why my EXIF data disappeared. It turns out that using this package caused that to happen. I am simply using imaging.Open
, imaging.Rotate180
, and imaging.Save
. It appears that the transformation to an image.NRGBA
makes that metadata disappear?
When automating simple tasks like rotation I think it makes sense that one would expect the image's metadata to remain. For example, ImageMagick's convert
command line utility does maintain EXIF data when doing a simple rotate. I think this package should include a warning that that's not the case here.
Hi,
How can i add a watermark to a image?
I am getting a bit confused with the 2 packages having a big overlap. Could you please elaborate a bit on wich one should be use ?
The usecase I am having is : resize and crop
Hello,
Is it possible to add EXIF information extractor ? And a bit greedy, I could not find any image library that supports saving original EXIF information after changing images (e.g. resize, rotate...). The encode function of go image library could not handle EXIF. So after you resize or rotate your photos, EXIF will lost in new saved copies.
I want to cut the Image(480×853) to (720 × 370).
so, I run
a := image.Rect(0,0,720,370)
src, _ := imaging.Open("FILE.jpg")
dst := imaging.Resize(src, 720, 0, imaging.Lanczos)
dst = imaging.Crop(src, a)
imaging.Save(dst, "dst.jpg")
but result is (480 × 370)
how can I cut the image to (720 × 370)
I use the following function to rotate images. The program keeps calling this function with a set of photos (each with 4-5MB, 3000x4000 size), each call will make the program's memory to increase about 100,000K (monitored from task manager), and after 10 or more times the program exits with "not enough memory" error.
Environment: go 1.3.1 windows 32-bit
I checked with go pprof, the top heap consumption ocurrs in helpers.go(line 27) and clone.go(line 13), transform.go(line 70). It seems "img" variables are not collected by GC in time. I checked with the code and could not find any problem. Is it the problem of go Garbage Collector or of other ?
func rotatePhoto(ip string, dir bool) error {
var rimg image.Image
img, err := imaging.Open(ip)
if err != nil {
return err
}
if dir {
rimg = imaging.Rotate270(img)
} else {
rimg = imaging.Rotate90(img)
}
// save the image to file
err = imaging.Save(rimg, ip)
rimg = nil
if err != nil {
fmt.Println(err)
return err
}
return nil
}
I cannot figure out how to paste an image with transparent areas into a background image. The code below produces an image where the transparent areas are colored (white if I save it as PNG, or black if I save it as JPEG). Please help.
package main
import (
"image"
"image/color"
"github.com/disintegration/imaging"
)
func main() {
background := imaging.New(200, 200, color.RGBA{0, 255, 0, 255})
line := imaging.New(100, 100, color.Transparent)
for x := 20; x < 80; x++ {
y := x/3 + 15
line.Set(x, y, color.RGBA{255, 0, 0, 255})
}
result := imaging.Paste(background, line, image.Point{0, 0})
imaging.Save(result, "test.png")
}
HIi,
I have a struct called SpriteImage which is defined like this:
type SpriteImage struct {
dimentions image.Point
lastImgPosition image.Point
sprite *image.NRGBA
}
In my flow, I first initiate a new such struct:
func NewSpriteImage(width, height int) SpriteImage {
c := color.RGBA{0xff, 0xff, 0xff, 0xff}
blankImage := imaging.New(width, height, c)
return SpriteImage{
dimentions: image.Point{X: width, Y: height},
lastImgPosition: image.Point{X: 0, Y: 0},
sprite: blankImage,
}
}
And then I add images to this SpriteImage like so:
func (s *SpriteImage) AddImage(img image.Image) error {
imgWidth := img.Bounds().Dx()
imgHeight := img.Bounds().Dy()
// Make sure new image will fit into the sprite.
if imgWidth != s.dimentions.X {
return fmt.Errorf("image width %d mismatch sprite width %d", imgWidth, s.dimentions.X)
}
spriteHeightLeft := s.dimentions.Y - s.lastImgPosition.Y
if imgHeight > spriteHeightLeft {
return fmt.Errorf("image height %d won't fit into sprite, sprite free space %d ", imgHeight, s.dimentions.Y)
}
// add image to sprite
s.sprite = imaging.Paste(s.sprite, img, s.lastImgPosition)
// update next image position within sprite
s.lastImgPosition = s.lastImgPosition.Add(image.Point{X: 0, Y: imgHeight})
return nil
}
Eventually, I want to take this SpriteImage and encode it as JPEG. But it doesn't seem to work. The native JPEG Encode function takes up an image, but I have an image.NRGBA. So I'm using github.com/disintegration/imaging lib like so:
func (s SpriteImage) GetBytes() ([]byte, error) {
var b bytes.Buffer
w := bufio.NewWriter(&b)
if s.sprite == nil {
return nil, fmt.Errorf("sprite is nil")
}
if err := imaging.Encode(w, s.sprite, imaging.JPEG); err != nil {
return nil, err
}
return b.Bytes(), nil
}
However is seems that the bytes returned are not in fact JPEG. The native Go JPEG lib will not decode those bytes to a Go image struct. If I try to decode those bytes to image like so:
m, _, err := image.Decode(reader)
if err != nil {
log.Fatal(err)
}
I'm getting err:
image: unknown format
Any ideas? Thanks!
This is not a problem with disintegration/imaging, but a Go problem: the image/jpeg
package can't seem to read JPEGs created for print media (other viewers and Imagemagick can).
https://code.google.com/p/go/issues/detail?id=4500
How would one go about building a custom decoder?
for example try to scale this image down by 50%:
this library will give incorrect result:
scaling performed by a correct software:
more info on the subject can be found in this article
there is also a nice video on youtube: https://youtu.be/LKnqECcg6Gw
Hi,
I wanted to contribute webp encoding/decoding to imaging (very nice library btw)!
However I think webp support was introduced around 1.2 and I seem to have read that you'd rather preserve compatibility with older go versions.
Should I rather write webp support in my own application?
I would like to say well done and keep up the good job. Have you considered the following :
If so what are the timelines like ?
Hi,
I'm wondering if this library supports animated gif or if it's a limitation of the Go image library itself.
Do you have information?
Dead simple example, with the source file giphy.gif
package main
import (
"runtime"
"github.com/disintegration/imaging"
)
func main() {
// use all CPU cores for maximum performance
runtime.GOMAXPROCS(runtime.NumCPU())
// input files
img, err := imaging.Open("giphy.gif")
if err != nil {
panic(err)
}
thumb := imaging.Thumbnail(img, 100, 100, imaging.Lanczos)
err = imaging.Save(thumb, "dst.gif")
if err != nil {
panic(err)
}
}
How to save progressive images?
Hi,
I'd love to see some new features in this library ;) For example:
Are they planned to be introduced? I could work on them :)
Hi
What's your UOM (mm, inch, px, pt ... ) used in CropCenter. I have a image 25.4X110mm, try to crop 20X110mm in center (both x, y) but can't get result as I wanted,
src, err := imaging.Open(filename)
if err != nil {
return rslt, err
}
fout := _tp1[0]
if ... {
//src = imaging.CropAnchor(src, int(PT_(realW)), int(PT_(realH)), imaging.Center) // Crop
src = imaging.CropCenter(src, int(PT_(realW)), int(PT_(realH)))
log.Println(int(PT_(realW)), int(PT_(realH)), realW, realH, "cima")
fout = strings.Replace(fout, fmt.Sprintf(".%s", ext), fmt.Sprintf("N.%s", ext), -1)
err = imaging.Save(src, fout)
if err != nil {
return rslt, err
}
}
func PT_(s string) float64 {
pos, uom := MeasureTuple(s)
var new_pos float64
switch strings.ToLower(uom) {
case "in":
new_pos = pos * 72.0
case "inch":
new_pos = pos * 72.0
case "cm":
new_pos = (pos * 10 / 25.4) * 72.0
case "mm":
new_pos = (pos / 25.4) * 72.0
case "pt":
new_pos = pos
default:
new_pos = pos
}
return new_pos
}
I started to play with imaging
and I very soon stumble on an interesting edge case. imaging.Resize
handle the case where width or heigth == 0 in a very intuitive way. There is a check in the code to do the right thing but in imaging.Thumbnail
this case is not supported. I can see argument either way so I am wondering if you this this has a bug or a feature.
Hi there,
Images (JPEG) get rotated by 90 degree if blured.
func blurImage(src io.Reader, imgType string) ([]byte, error) {
/*switch imgType {
case "jpeg":
img, err = jpeg.Decode(src)
case "png":
img, err = png.Decode(src)
case "gif":
img, err = gif.Decode(src)
default:
return nil, errors.New("No filetype")
}*/
img, imgType, err := image.Decode(src)
if err != nil {
return nil, err
}
var blurSigma float64
confBlurSigmaStr := os.Getenv("Blur_Sigma")
if confBlurSigmaStr == "" {
blurSigma = 25
} else {
blurSigma, err = strconv.ParseFloat(confBlurSigmaStr, 64)
}
if err != nil {
return nil, err
}
bluredImg := imaging.Blur(img, blurSigma)
return encodeImage(bluredImg, imgType)
}
Hey, using the following code:
package main
import (
"log"
"github.com/disintegration/imaging"
)
func main() {
src, err := imaging.Open("src.png")
if err != nil {
log.Fatal(err)
}
dst := imaging.Resize(src, 200, 200, imaging.Lanczos)
err = imaging.Save(dst, "dst.png")
if err != nil {
log.Fatal(err)
}
}
I'm seeing gray aliasing on the resized image:
Example:
Any ideas what I could do to reduce the gray edge?
Draw characters on image is an ordinary requirement, May be we should support it.
I have been using your code for image resizing mainly, and I would like to apply a unsharp mask. I feel like this may be possible with the tools you have created, but it is unclear to me. Can you explain how to do this, or add a function to do so?
Either way thanks for the code!
Trying to build our service with current git of imaging library and I have following error:
../../github.com/disintegration/imaging/effects.go:8: gaussianBlurKernel redeclared in this block
previous declaration at ../../github.com/disintegration/imaging/blur.go:8
../../github.com/disintegration/imaging/effects.go:19: Blur redeclared in this block
previous declaration at ../../github.com/disintegration/imaging/blur.go:26
../../github.com/disintegration/imaging/effects.go:40: blurHorizontal redeclared in this block
previous declaration at ../../github.com/disintegration/imaging/blur.go:47
../../github.com/disintegration/imaging/effects.go:94: blurVertical redeclared in this block
previous declaration at ../../github.com/disintegration/imaging/blur.go:101
../../github.com/disintegration/imaging/resize.go:65: Resize redeclared in this block
previous declaration at ../../github.com/disintegration/imaging/resample.go:19
../../github.com/disintegration/imaging/resize.go:116: resizeHorizontal redeclared in this block
previous declaration at ../../github.com/disintegration/imaging/resample.go:69
../../github.com/disintegration/imaging/resize.go:152: resizeVertical redeclared in this block
previous declaration at ../../github.com/disintegration/imaging/resample.go:137
../../github.com/disintegration/imaging/resize.go:191: resizeNearest redeclared in this block
previous declaration at ../../github.com/disintegration/imaging/resample.go:206
../../github.com/disintegration/imaging/resize.go:236: Fit redeclared in this block
previous declaration at ../../github.com/disintegration/imaging/resample.go:251
../../github.com/disintegration/imaging/resize.go:280: Thumbnail redeclared in this block
previous declaration at ../../github.com/disintegration/imaging/resample.go:295
../../github.com/disintegration/imaging/resize.go:280: too many errors
Checkout out 3ab6ec5 revision of this library and it works.
I have some pictures shot in portrait position coming from my digital camera (Panasonic Lumix) and phone (Samsung S7) which appear rotated after loading, fitting and saving them.
Here is the code:
package main
import (
"flag"
"fmt"
"github.com/disintegration/imaging"
)
func main() {
filename := flag.String("file", "", "input file")
flag.Parse()
if filename == nil {
panic("missing input file")
}
fmt.Println("opening " + *filename)
img, err := imaging.Open(*filename)
if err != nil {
panic(err)
}
dst := imaging.Fit(img, 800, 600, imaging.Lanczos)
if err := imaging.Save(dst, "converted.jpg"); err != nil {
panic(err)
}
}
The original is (when downloaded) shown in portrait mode.
The converted (probably has all EXIF info scrapped) is shown in neutral mode (guess that's landscape)
There is a premise that we must ensure the integrity of image, so I think there is some problem in Thumbnail function that the if condition is reverse.
if srcAspectRatio > thumbAspectRatio {
tmp = Resize(img, 0, thumbH, filter)
} else {
tmp = Resize(img, thumbW, 0, filter)
}
Hello is there something like: https://github.com/sksamuel/scrimage/blob/master/guide/fit.md
Where you fit the image to something like 100px x 100px and and add a background if it can't fit 100 x 100 correctly? (even transparent backgrounds are supported by that library)
Dear Grigory Dryapak,
This is completely awesome open source code project, But it does't support GIF file.
Can you please provide GIF support for this.
Thank you.
You use *image.NRGBA the default, but the standard library saves the image in *image.YCbCr. As a result, at least one extra converting image.
I plan to rewrite on the *image.YCbCr, but not anytime soon.
I noticed when working with jpeg, other formats are not looking.
I can't seem to find a way to specify a custom Anchor
based on coordinates when cropping an image. What am I missing?
after resizing, original animated gif has no animation, how to output an animated gif image
Seems this is the clearest package for image processing in The Great Go. How to add text on image by the way, has the author done with this?
Save Fail imaging: unsupported image format webp
Would it be possible to get support for TIF compression 4:
tiff: unsupported feature: compression value 4
Is there any way to set the jpeg quality from 0 to 100?
how to append text at the image?
For example, images for resize, fit and thumbnail. Also, for ResampleFilter
s.
For starters, I'm running Go 1.1.2 on OS X 10.8.
I'm not sure if this is a problem with me misusing the library, or something not working right in general. I'm trying to take a slice of images cropped images (the cropping works), resize them, and then overlay or paste them in 2 rows, and x columns, based on the size of the slice.
If I try and save the resized image to a file, it saves correctly. If I try and overlay the resized image on a new image, and save that new image, the new image does not save the resized images onto the one new image.
Here's some code to demonstrate what I'm doing.
func StitchImages(images []image.Image) image.Image {
imageCount := len(images)
imageWidth := stitchedImageWidth / imageCount * 2
imageHeight := stitchedImageHeight / 2
newImage := imaging.New(stitchedImageWidth, stitchedImageHeight, color.NRGBA{255, 0, 0, 255})
for i := 0; i < imageCount; i++ {
currImage := images[i]
x := ((i % (imageCount / 2)) * imageWidth)
y := 0
if i >= imageCount/2 {
y = imageHeight
}
croppedImage := CropCenter(currImage)
resizedImage := imaging.Resize(croppedImage, imageWidth, imageHeight, imaging.CatmullRom)
imaging.Overlay(newImage, resizedImage, image.Pt(x, y), 1.0)
}
return newImage
}
And being invoked from main.go as such:
sourceImage, _ := imaging.Open("NYAN.png")
croppedImage := Stitcher.CropFromBottom(sourceImage)
imagesToStitch := []image.Image{croppedImage, croppedImage, croppedImage, croppedImage, croppedImage, croppedImage, croppedImage, croppedImage}
stitchedImage := Stitcher.StitchImages(imagesToStitch)
imaging.Save(stitchedImage, "NYAN-collaged.png")
After updating to Go 1.5.1 the pkg no longer compiles with GOARCH=386. (Same issue whether GOOS is windows,linux or darwin)
[14:00:30][ruxton@cyclops:imaging] $ brew switch go 1.4.2
Cleaning /usr/local/Cellar/go/1.4.2
Cleaning /usr/local/Cellar/go/1.5.1
3 links created for /usr/local/Cellar/go/1.4.2
(master)
[14:00:31][ruxton@cyclops:imaging] $ go version
go version go1.4.2 darwin/amd64
(master)
[14:00:40][ruxton@cyclops:imaging] $ GOARCH=386 GOOS=windows go build -a
(master)
[14:00:49][ruxton@cyclops:imaging] $ brew switch go 1.5.1
Cleaning /usr/local/Cellar/go/1.4.2
Cleaning /usr/local/Cellar/go/1.5.1
3 links created for /usr/local/Cellar/go/1.5.1
(master)
[14:00:59][ruxton@cyclops:imaging] $ go version
go version go1.5.1 darwin/amd64
(master)
[14:01:03][ruxton@cyclops:imaging] $ GOARCH=386 GOOS=windows go build -a
# github.com/disintegration/imaging
run compiler with -v for register allocation sites
./helpers.go:229: internal compiler error: out of fixed registers
This may be too insignificant to even mention, but I noticed a little improvement in memory performance of Save()
when regexp
is not used in it.
I wrote a small benchmark func for it:
func BenchmarkSave(b *testing.B) {
img, err := Open("mickey.jpg")
catch(err)
b.ResetTimer()
for i := 0; i < b.N; i++ {
err = Save(img, "mickey.out.jpg")
catch(err)
}
}
When I ran it with the current Save()
method (with regexp
), this is what I got:
BenchmarkSave 50 52964825 ns/op 12308 B/op 80 allocs/op
When I ran it on a modified Save()
method (without regexp
), this is what I got:
BenchmarkSave 50 51917256 ns/op 4810 B/op 8 allocs/op
The time-wise performance is almost unchanged. But the memory allocations per invocation is 1/10th of the original number.
The regexp.MatchString()
is not really required here, since the switch
on format
is going to prevent any invalid file extension anyway.
I could send you a pull request making this change if that's okay.
I'm trying to use imaging
in an App Engine app, and after resizing about 6 images the application shuts down because of excessive memory usage. This usually happens because of goroutines that don't exit, so that might be the case. Is there a way to turn off parallel computation via a flag or option for environments like this? Or we can just make sure that all spawned goroutines always exit cleanly.
I would like to suggest an API that would merge all this filters since that have some basic similarities
dstImage = imaging.Blur(srcImage, 4.5)
dstImage = imaging.Sharpen(srcImage, 3.0)
filter = imaging.Filter(srcImage)
filter.Blur(4.5)
filter.Sharpen( 3.0)
Crop
, Paste
, Overlay
support interface InsteadBrightness
, Contrast
, Gamma
& Contrast
can be filters tooimg, err := imaging.Open("src.png") // Open Image and Return ImageSrc type
filter := imaging.Filter(img) // Start Filter
filter.Grayscale()
filter.Blur(4.5)
filter.Sharpen( 3.0)
filter.Brightness(+5)
filter.Contrast(+2)
img.Rotate(90) // Rotate Image 90 degree
img.PasteCenter(backgroundImage) // Paste Image a new Background
// Save a thumb copy of image
thumb , err := img.Thumbnail(100, 100, imaging.CatmullRom) // Return ImageSrc type
thumb.Save("dst_thumb.jpg") // Save Thumb
// Save Final Image
img.Save("dst.jpg")
toNRGBA(img)
would be called onceSharpen
uses Blur
and a simple cache can take place instead of trying to run the blur againimage.NewNRGBA
does not need to be called multiple timesimaging.Grayscale(srcImage)
etc can still be syntactic sugarsPerformance can easy be improved when working with multiple images with multiple filters and adjustment on the same images. Its open for improvement and discussion.
What do you think ?
Am hunting around for a way to convert svg to png, etc using pure g
There seems to be an overlap of functionalities provided by github.com/disintegration/imaging and github.com/disintegration/gift: rotate, flip, resize, crop, etc. What package should I use? What's the difference?
Hi,
I notice that is image brightness(or sort of ) lost when resize, any idea to fix it ?
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.