Go binding to ImageMagick's MagickWand C API

Overview

Go Imagick

GoDoc Travis Build Status

Go Imagick is a Go bind to ImageMagick's MagickWand C API.

We support two compatibility branches:

master (tag v2.x.x): 6.9.1-7 <= ImageMagick <= 6.9.9-35
im-7   (tag v3.x.x): 7.x     <= ImageMagick <= 7.x
legacy (tag v1.x.x): 6.7.x   <= ImageMagick <= 6.8.9-10

They map, respectively, through gopkg.in:

gopkg.in/gographics/imagick.v2/imagick
gopkg.in/gographics/imagick.v3/imagick
gopkg.in/gographics/imagick.v1/imagick

Install

Docker

See examples/docker

Mac OS X

MacPorts

sudo port install ImageMagick

Ubuntu / Debian

sudo apt-get install libmagickwand-dev

Windows

Thanks @vprus

pacman -Syuu
pacman -S mingw-w64-x86_64-gcc
pacman -S mingw-w64-x86_64-pkg-config
pacman -S mingw-w64-x86_64-zlib
pacman -S mingw-w64-x86_64-imagemagick
  • Switch to cmd.exe shell, and do:
set PATH=<msys64>\mingw64\bin;%PATH%
set PKG_CONFIG_PATH=<msys64>\mingw64\lib\pkgconfig
set MAGICK_CODER_MODULE_PATH=<msys64>\mingw64\lib\ImageMagick-7.0.6\modules-Q16HDRI\coders
go build gopkg.in/gographics/imagick.v3/imagick

The default installation path of msys2 is C:\msys64 and you must change <msys64> to your installation path of msys2.

The MAGICK_CODER_MODULE_PATH environment variable tells ImageMagick where to find the decoders. If you still get the NoDecodeDelegateForThisImageFormat error, then make sure the version number and folders are correct.

Common

Check if pkg-config is able to find the right ImageMagick include and libs:

pkg-config --cflags --libs MagickWand

Then go get it:

go get gopkg.in/gographics/imagick.v2/imagick

Per the security update https://groups.google.com/forum/#!topic/golang-announce/X7N1mvntnoU you may need whitelist the -Xpreprocessor flag in your environment.

export CGO_CFLAGS_ALLOW='-Xpreprocessor'

Build tags

If you want to specify CGO_CFLAGS/CGO_LDFLAGS manually at build time, such as for building statically or without pkg-config, you can use the "no_pkgconfig" build tag:

go build -tags no_pkgconfig gopkg.in/gographics/imagick.v2/imagick

Examples

The examples folder is full with usage examples ported from C ones found in here: http://www.imagemagick.org/MagickWand/

Quick and partial example

package main

import "gopkg.in/gographics/imagick.v2/imagick"

func main() {
    imagick.Initialize()
    defer imagick.Terminate()

    mw := imagick.NewMagickWand()

    ...
}

Initialize() and Terminate

As per the ImageMagick C API, Initialize() should be called only once to set up the resources for using ImageMagick. This is typically done in your main() or init() for the entire application or library. Applications can defer a call to Terminate() to tear down the ImageMagick resources.

It is an error to Initialize and Terminate multiple times in specific functions and leads to common problems such as crashes or missing delegates. Do not use Terminate anywhere other than the absolute end of your need for ImageMagick within the program.

Managing memory

Since this is a CGO binding, and the Go GC does not manage memory allocated by the C API, it is then necessary to use the Terminate() and Destroy() methods.

Types which are created via New* constructors (MagickWand, DrawingWand, PixelIterator, PixelWand,...), or created and returned by methods like Clone() are managed by Go GC through the use of finalizers. They are not guaranteed to be cleaned up immediately after the object is not longer in use, but rather at some point later when GC actually executes its finalizers.

If you use struct literals, you should free resources manually:

package main

import "github.com/gographics/imagick/imagick"

func main() {
    imagick.Initialize()
    defer imagick.Terminate()

    mw := imagick.MagickWand{...}
    defer mw.Destroy()

    ...
}

Both methods are compatible if constructor methods used:

package main

import "github.com/gographics/imagick/imagick"

func main() {
    imagick.Initialize()
    defer imagick.Terminate()

    mw := imagick.NewMagickWand()
    defer mw.Destroy()

    ...
}

But you should NOT mix two ways of object creation:

package main

import "github.com/gographics/imagick/imagick"

func main() {
    imagick.Initialize()
    defer imagick.Terminate()

    mw1 := imagick.MagickWand{...}
    defer mw1.Destroy()

    mw2 := imagick.NewMagickWand()

    ...
}

Calling Destroy() on types that are either created via New* or returned from other functions calls forces the cleanup of the item immediately as opposed to later after garbage collection triggers the finalizer for the object. It would be good practice to explicitely call Destroy() to ensure C memory is freed sooner rather than later, depending on how often the GC is triggered.

License

Copyright (c) 2013-2016, The GoGraphics Team All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  • Neither the name of the organization nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL HERBERT G. FISCHER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Issues
  • memory leak

    memory leak

    Hi, sorry to bother you. I was doing some testing since one of my applications, the memory is never cleared after the wand is destroyed.

    Code used to test:

    func main(){

       // data image content ...
        mw, err := xcimagick.NewImagick(data)
    if err != nil {
    	logger.Error(err)
    	return
    }
    defer mw.Destory()
    
       // ...
    

    }

    func Init() (err error) { imagick.Initialize() return }

    func Destory() (err error) { imagick.Terminate() return }

    type MagicWand struct { mw *imagick.MagickWand }

    func NewImagick(data []byte) (m *MagicWand, err error) { mw := imagick.NewMagickWand() err = mw.ReadImageBlob(data) if err != nil { logger.Error(err) return }

    m = &MagicWand{mw: mw}
    return
    

    }

    func (m *MagicWand) GetImageFormat() string { return strings.ToLower(m.mw.GetImageFormat()) }

    func (m *MagicWand) GetImagesBlob() []byte { return m.mw.GetImagesBlob() }

    func (m *MagicWand) Destory() { m.mw.Destroy() }

    func (m *MagicWand) ConvertGifToJpeg() (ret *MagicWand, err error) { ret = NewMagickWand() bcolor := NewPixelWand()

    for i := 1; i < int(m.mw.GetNumberImages()); i++ {
    	m.mw.SetIteratorIndex(i)
    	w, h, x, y, err := m.mw.GetImagePage()
    	if err != nil {
    		logger.Error(err)
    		continue
    	}
    
    	tmp := m.mw.GetImage()
    	ret.mw.NewImage(w, h, bcolor)
    	ret.mw.SetImageColorspace(tmp.GetImageColorspace())
    	ret.mw.CompositeImage(tmp, tmp.GetImageCompose(), true, x, y)
    	tmp.Destroy()
    	break
    }
    
    m.mw.Destroy()
    if err != nil {
    	logger.Error(err)
    	return
    }
    return
    

    }

    func (m *MagicWand) CompressImageJpeg(quality uint) (err error) { err = m.mw.SetImageCompression(imagick.COMPRESSION_JPEG) if err != nil { logger.Error(err) return }

    if quality > 0 {
    	orgQ := m.mw.GetImageCompressionQuality()
    	if orgQ > quality {
    		err = m.mw.SetImageCompressionQuality(quality)
    		if err != nil {
    			logger.Error(err)
    			return
    		}
    	}
    }
    
    m.mw.SetImageFormat("jpeg")
    return
    

    }

    func (m *MagicWand) GetImageSize() (w, h uint, err error) { if m.GetImageFormat() == "gif" { w, h, _, _, err = m.mw.GetImagePage() } else { w = m.mw.GetImageWidth() h = m.mw.GetImageHeight() } return }

    func (m *MagicWand) ResizeImage(w, h uint) (err error) { return m.mw.ResizeImage(w, h, imagick.FILTER_CATROM) }

    func (m *MagicWand) CropImage(w, h uint, x, y int) (err error) { return m.mw.CropImage(w, h, x, y) }

    func (m *MagicWand) GetImageMime() string { return fmt.Sprintf("image/%s", strings.ToLower(m.mw.GetImageFormat())) }

    func (m *MagicWand) GetImageOrientation() int { return int(m.mw.GetImageOrientation()) }

    opened by zlm3110561045 57
  • Issues with ReadImageBlob hanging

    Issues with ReadImageBlob hanging

    I've posted here, so would rather not repost, but wondered if anyone had any advice? http://stackoverflow.com/questions/39644215/imagemagick-go-api-http-hangs-on-readimageblob

    Thanks

    opened by amlwwalker 36
  • EPS image resized, but it appears distortion

    EPS image resized, but it appears distortion

    I am using V2

    func TestImageResizeEPS() {
    	imagick.Initialize()
    	defer imagick.Terminate()
    	var err error
    	mw := imagick.NewMagickWand()
    	mw.SetResolution(200, 200)
    	mw.SetColorspace(imagick.COLORSPACE_SRGB)
    	err = mw.ReadImage("/tmp/abc.eps")
    	if err != nil {
    		panic(err)
    	}
    	mw = mw.CoalesceImages()
    	mw.SetImageAlphaChannel(imagick.ALPHA_CHANNEL_DEACTIVATE)
    	err = mw.SetImageCompressionQuality(DefaultImageQuality)
    	if err != nil {
    		panic(err)
    	}
    	mw.StripImage()
    	mw.TrimImage(0)
    
    	// For EPS vector image, If the width and height of the picture are too small, it will be enlarged
    	width, height := option.ScaleImageSize(mw.GetImageWidth(), mw.GetImageHeight())
    	if width != mw.GetImageWidth() || height != mw.GetImageHeight() {
    		err = mwm.ScaleImage(width, height)
    	}
    
    	err = mw.SetImageFormat("JPEG")
    	if err != nil {
    		panic(err)
    	}
    	originalHeight := mw.GetImageHeight()
    	originalWidth := mw.GetImageWidth()
    
    	// Calculated width and height of resize
    	w, h := option.GetResizeByWidthHeight(int64(originalWidth), int64(originalHeight), "keepratio", maxCompressEdge, maxCompressEdge)
    
    	if err = imw.ResizeImage(uint(w), uint(h), imagick.FILTER_LANCZOS, 0.85); err != nil {
    		return
    	}
    	if err = mw.WriteImage("/tmp/abc.jpg"); err != nil {
    		panic(err)
    	}
    }
    

    After resized, the picture will be distorted

    opened by taomin597715379 23
  • fatal error: unexpected signal during runtime execution

    fatal error: unexpected signal during runtime execution

    golang app that resizes images works fine with alone requests but if i try to make several resizes quickly - got this:

    fatal error: unexpected signal during runtime execution [signal 0xb code=0x1 addr=0x7f276656096e pc=0x7f276656096e]

    runtime stack: runtime.throw(0x9d3f80, 0x2a) /usr/local/go/src/runtime/panic.go:527 +0x90 runtime.sigpanic() /usr/local/go/src/runtime/sigpanic_unix.go:12 +0x5a

    goroutine 19 [syscall, locked to thread]: runtime.cgocall(0x7acee0, 0xc820044980, 0x0) /usr/local/go/src/runtime/cgocall.go:120 +0x11b fp=0xc820044950 sp=0xc820044920 github.com/gographics/imagick/imagick._Cfunc_MagickReadImage(0x7f2760025a40, 0x7f2760027a90, 0x7f2700000000) ??:0 +0x35 fp=0xc820044980 sp=0xc820044950 github.com/gographics/imagick/imagick.(_MagickWand).ReadImage(0xc82014e020, 0xc820136177, 0x59, 0x0, 0x0) /go/src/github.com/gographics/imagick/imagick/magick_wand_image.go:2165 +0x82 fp=0xc8200449b8 sp=0xc820044980 app/cropper.CropImage(0x7f2766e95bb0, 0xc8201442c0, 0xc82015a0e0) /go/src/app/cropper/cropper.go:78 +0x7f9 fp=0xc820044b78 sp=0xc8200449b8 net/http.HandlerFunc.ServeHTTP(0xa0f958, 0x7f2766e95bb0, 0xc8201442c0, 0xc82015a0e0) /usr/local/go/src/net/http/server.go:1422 +0x3a fp=0xc820044b98 sp=0xc820044b78 net/http.(_ServeMux).ServeHTTP(0xc82006f050, 0x7f2766e95bb0, 0xc8201442c0, 0xc82015a0e0) /usr/local/go/src/net/http/server.go:1699 +0x17d fp=0xc820044bf0 sp=0xc820044b98 net/http.serverHandler.ServeHTTP(0xc820012480, 0x7f2766e95bb0, 0xc8201442c0, 0xc82015a0e0) /usr/local/go/src/net/http/server.go:1862 +0x19e fp=0xc820044c50 sp=0xc820044bf0 net/http.(_conn).serve(0xc820144210) /usr/local/go/src/net/http/server.go:1361 +0xbee fp=0xc820044fa8 sp=0xc820044c50 runtime.goexit() /usr/local/go/src/runtime/asm_amd64.s:1721 +0x1 fp=0xc820044fb0 sp=0xc820044fa8 created by net/http.(_Server).Serve /usr/local/go/src/net/http/server.go:1910 +0x3f6

    goroutine 1 [IO wait]: net.runtime_pollWait(0x7f2766e95910, 0x72, 0xc82000a180) /usr/local/go/src/runtime/netpoll.go:157 +0x60 net.(_pollDesc).Wait(0xc82006ca70, 0x72, 0x0, 0x0) /usr/local/go/src/net/fd_poll_runtime.go:73 +0x3a net.(_pollDesc).WaitRead(0xc82006ca70, 0x0, 0x0) /usr/local/go/src/net/fd_poll_runtime.go:78 +0x36 net.(_netFD).accept(0xc82006ca10, 0x0, 0x7f2766e95a08, 0xc820142240) /usr/local/go/src/net/fd_unix.go:408 +0x27c net.(_TCPListener).AcceptTCP(0xc820038098, 0x465f30, 0x0, 0x0) /usr/local/go/src/net/tcpsock_posix.go:254 +0x4d net/http.tcpKeepAliveListener.Accept(0xc820038098, 0x0, 0x0, 0x0, 0x0) /usr/local/go/src/net/http/server.go:2135 +0x41 net/http.(_Server).Serve(0xc820012480, 0x7f2766e959d0, 0xc820038098, 0x0, 0x0) /usr/local/go/src/net/http/server.go:1887 +0xb3 net/http.(_Server).ListenAndServe(0xc820012480, 0x0, 0x0) /usr/local/go/src/net/http/server.go:1877 +0x136 net/http.ListenAndServe(0xc82000bb00, 0x5, 0x0, 0x0, 0x0, 0x0) /usr/local/go/src/net/http/server.go:1967 +0x8f main.main() /go/src/app/main.go:50 +0x62f

    goroutine 17 [syscall, locked to thread]: runtime.goexit() /usr/local/go/src/runtime/asm_amd64.s:1721 +0x1

    opened by Ivanezko 22
  • Memory issue with the imagick initialization

    Memory issue with the imagick initialization

    I have explained the code in the following link. Which uses the

        imagick.Initialize() 
        defer imagick.Terminate() 
    

    to initialize the library. If, I don't include these lines in the code my /tmp folder size keep on increasing. Where as on the other hand if i include them in code my RAM size increases monotonously and in the end my handler crashes. Kindly look into this matter. Why is it happening. Moreover, as such i don't have any memory leak in my code.

    func CreateMaster(keyName string, desiredAspectRatio float64, isMaster bool) bool {             
    
        s3Client := s3.New(session.New(), &aws.Config{Region: aws.String(region)})
            params := &s3.GetObjectInput{
            Bucket: aws.String(bucketName),
            Key: aws.String(keyName),
            }
    
        fmt.Println(" Master creation request for key : " + keyName)
        out, err := s3Client.GetObject(params)
    
        if err != nil { 
            return false                                       
        }
    
        defer out.Body.Close()  
        img, err := ioutil.ReadAll(out.Body)
    
        if err != nil { 
                return false      
        }                   
    
        mw := imagick.NewMagickWand()
        defer mw.Destroy()
    
        err = mw.ReadImageBlob(img)
        if err != nil {  
            return false                   
        }
    
    
        if isMaster == false {
            paramsPut := &s3.PutObjectInput{
                        Bucket:         aws.String(masterBucketName),
                        Key:            aws.String(keyName),
                        Body:         bytes.NewReader(mw.GetImageBlob()),
                }
    
            _, err = s3Client.PutObject(paramsPut)
            if err != nil {
                log.Printf("Couldn't put the image on s3 : " + keyName + "%s\n", err)       
            }
    
            return true
        }
    
    
            originalWidth := float64(mw.GetImageWidth())
            originalHeight := float64(mw.GetImageHeight())
    
        imageAspectRatio  := originalWidth / originalHeight
            masterWidth := cwMasterWidth
            masterHeight := cwMasterHeight
            masterAspectRatio := math.Trunc((cwMasterWidth / cwMasterHeight) * 100)/100
    
        if masterAspectRatio != desiredAspectRatio {           
                        masterAspectRatio = desiredAspectRatio
                    }
    
    
        pwm := imagick.NewPixelWand()
        defer pwm.Destroy()
    
        tx := imagick.NewMagickWand()
        defer tx.Destroy()  
    
        if isMaster == true {               
    
                var w, h uint = 0, 0
                size := fmt.Sprintf("%dx%d^+0+0", w, h) 
                        if imageAspectRatio <= masterAspectRatio {                
                            // trim the height
                w = uint(originalWidth)
                h = (uint(originalWidth / masterAspectRatio))
                   size = fmt.Sprintf("%dx%d^+0+0", w, h)
                         } else { 
                            // trim the width
                w = uint(originalHeight * masterAspectRatio)
                h = uint(originalHeight)
                size = fmt.Sprintf("%dx%d^+0+0", w, h)
                         }
    
                tx = mw.TransformImage("", size)        
                tx.SetImageGravity(imagick.GRAVITY_CENTER)
                offsetX := -(int(w) - int(tx.GetImageWidth())) / 2
                offsetY := -(int(h) - int(tx.GetImageHeight())) / 2
                err := tx.ExtentImage(w, h, offsetX, offsetY)
    
                        if float64(tx.GetImageWidth()) > masterWidth && float64(tx.GetImageHeight()) > masterHeight  {                                        
                            err = tx.ResizeImage(uint(masterWidth), uint(masterHeight), imagick.FILTER_BOX, 1)
                if err != nil {
                    log.Printf("Inside CreateMaster function Couldn't resize the image : " + keyName + "%s\n", err) 
                    return false                 
                }                                                           
                        }                                       
                    }       
    
         paramsPut := &s3.PutObjectInput{
                        Bucket:         aws.String(masterBucketName),
                        Key:            aws.String(keyName),
                        Body:         bytes.NewReader(tx.GetImageBlob()),
                }
    
        _, err = s3Client.PutObject(paramsPut)
        if err != nil {
            log.Printf("Inside CreateMaster function Couldn't put the image on s3 : " + keyName + "%s\n", err)  
            return false        
        }
    
        return true
    }
    

    http://stackoverflow.com/questions/35768266/memory-leak-in-go-lang-http-handler

    opened by palaiya 20
  • GIF image transcoding speed is too slow and quality is too large

    GIF image transcoding speed is too slow and quality is too large

    The gographics version is 6.9.1-7 The imageMagick version is 7.0.7.11

    When I use imagemagick transcoding, I found that the quality of the gif image after transcoding is very high and the speed is very slow. The transcoding of a 50-frame image takes 3s. After testing, it is found that the following function is relatively slow:
    retImg = imgWand.GetImagesBlob()

    I saw in the community that you can optimize in the following way, the command is as follows:

    convert xxx.gif $completeMiff -dither none -deconstruct \
        -layers optimize -matte -depth 7 -resize 100x73 xxx.gif
    

    The reference is:http://studio.imagemagick.org/discourse-server/viewtopic.php?f=1&t=13339&start=0 But I did not find an optimized method in the Go code. I combined it according to the API, and the code is as follows:

    imgWand = imgWand.MergeImageLayers(imagick.IMAGE_LAYER_OPTIMIZE)
    err := imgWand.PosterizeImage(uint(2), imagick.DITHER_METHOD_NO)
    if err != nil {
        return nil, false, NewError(exception.BadImageRequestBody, "Image PosterizeImage")
    }
    err = imgWand.SetImageMatte(true)
    if err != nil {
        return nil, false, NewError(exception.BadImageRequestBody, "Image SetImageMatte")
    }
    err = imgWand.SetImageDepth(uint(7))
    if err != nil {
        return nil, false, NewError(exception.BadImageRequestBody, "Image SetImageDepth")
    }                
    

    20191217-102931

    opened by jackDiscovery 19
  • ./main.go:26:2: undefined: imagick.Initialize |  ./main.go:27:8: undefined: imagick.Terminate  |  ./main.go:28:8: undefined: imagick.NewMagickWand

    ./main.go:26:2: undefined: imagick.Initialize | ./main.go:27:8: undefined: imagick.Terminate | ./main.go:28:8: undefined: imagick.NewMagickWand

    Hello am using Debian with docker to install the ImageMagick library in our project but still am getting an error

    "gopkg.in/gographics/imagick.v3/imagick"

    Docker file


    FROM golang:1.15 AS builder
    
    COPY ${PWD} /app
    WORKDIR /app
    
    COPY go.mod .
    COPY go.sum .
    RUN go mod download
    COPY . .
    
    # Toggle CGO based on your app requirement. CGO_ENABLED=1 for enabling CGO
    RUN CGO_ENABLED=0 go build -ldflags '-s -w' -o /app/appbin *.go
    # Use below if using vendor
    # RUN CGO_ENABLED=0 go build -mod=vendor -ldflags '-s -w -extldflags "-static"' -o /app/appbin *.go
    
    FROM debian:stable-slim
    
    # Following commands are for installing CA certs (for proper functioning of HTTPS and other TLS)
    RUN apt-get update && apt-get install -y --no-install-recommends \
    		ca-certificates  \
            netbase \
            && rm -rf /var/lib/apt/lists/ \
            && apt-get autoremove -y && apt-get autoclean -y
    
    # Add new user 'appuser'. App should be run without root privileges as a security measure
    RUN adduser --home "/appuser" --disabled-password appuser \
        --gecos "appuser,-,-,-"
    USER appuser
    
    COPY --from=builder /app /home/appuser/app
    
    WORKDIR /home/appuser/app
    
    # Since running as a non-root user, port bindings < 1024 are not possible
    # 8000 for HTTP; 8443 for HTTPS;
    EXPOSE 2053
    EXPOSE 2053
    
    CMD ["./appbin"]
    

    Error message

    image

    # command-line-arguments
    ./main.go:26:2: undefined: imagick.Initialize
    ./main.go:27:8: undefined: imagick.Terminate
    ./main.go:28:8: undefined: imagick.NewMagickWand
    

    kindly help

    opened by andysteve 18
  • Centos7 development environment configuration

    Centos7 development environment configuration

    I compiled and installed imagemagick-7.0.10-10 to /usr/local/ImageMagick, and export LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}/usr/local/ImageMagick/lib" export PKG_CONFIG_PATH=/usr/local/ImageMagick/lib/pkgconfig/

    go run main.go

    /usr/lib/golang/pkg/tool/linux_amd64/link: running gcc failed: exit status 1 /usr/bin/ld: not found -lMagickWand-7.Q16HDRI collect2: error:ld return 1

    err

    lib

    Why did this error occur? What else do I need to do

    opened by hailiangchen 18
  • How to create optimised and progressive Images (JPG, PNG)

    How to create optimised and progressive Images (JPG, PNG)

    I am using the following code in go lang to resize my images in JPEG and PNG format. Could you please tell how do I convert them to progressive and optimized using Imagick library.

    I am saying optimized reason being I used the following command to test whether image size gets reduced or not. But, it increases the output file size.

    convert -strip -interlace Plane input-file.jpg output-file.jpg

    size = fmt.Sprintf("%dx%d^+0+0", w, h)
    		tx := mw.TransformImage("", size)
    		tx.SetImageGravity(imagick.GRAVITY_CENTER)
    		offsetX := -(int(w) - int(tx.GetImageWidth())) / 2
    		offsetY := -(int(h) - int(tx.GetImageHeight())) / 2
    		err := tx.ExtentImage(w, h, offsetX, offsetY)
    
    opened by palaiya 18
  • Interlace changes don't appear to be making it to output file or blob.

    Interlace changes don't appear to be making it to output file or blob.

    Hi there,

    I tried everything I could think of to avoid creating an issue where none exists, but I'm currently at a loss as to whether, or not, this is, indeed, a bug. I apologize in advance for wasting your time in any way.

    I'm attempting to change a non-progressive JPEG to a progressive JPEG, but the change does not seem to make it to the output.

    Here's the code (image_resizing1.go):

    package main
    
    import (
        "github.com/bfitzsimmons/imagick/imagick"
    )
    
    func main() {
        const (
            original_filepath = "/Users/bfitzsimmons/Pictures/test/plant.jpg"
            output1           = "/Users/bfitzsimmons/Pictures/test/plant_1.jpg"
        )
    
        var (
            err       error
            new_width uint
        )
    
        // Set up imagick.
        imagick.Initialize()
        defer imagick.Terminate()
    
        mw := imagick.NewMagickWand()
        defer mw.Destroy()
    
        // Open and load the file.
        if err = mw.ReadImage(original_filepath); err != nil {
            panic(err)
        }
    
        // Get the width and height.
        width := mw.GetImageWidth()
        height := mw.GetImageHeight()
        ratio := float64(width) / float64(height)
    
        if width > 1000 {
            new_width = 1000
        } else {
            new_width = width
        }
    
        final_width := new_width
        final_height := int(float64(new_width) / ratio)
    
        // Set the quality.
        if err = mw.SetImageCompressionQuality(85); err != nil {
            panic(err)
        }
    
        if err = mw.SetImageInterlaceScheme(imagick.INTERLACE_LINE); err != nil {
            panic(err)
        }
    
        // Resize it.
        if err = mw.ResizeImage(uint(final_width), uint(final_height), imagick.FILTER_LANCZOS, 1); err != nil {
            panic(err)
        }
    
        // Write it out to a file.
        if err = mw.WriteImage(output1); err != nil {
            panic(err)
        }
    }
    

    Here's the output:

    $ go run image_resizing1.go && identify -verbose /Users/bfitzsimmons/Pictures/test/plant_1.jpg | grep Interlace
      Interlace: None
    

    Now, when I run the command line convert command I see the output I'm expecting:

    $ convert /Users/bfitzsimmons/Pictures/test/plant.jpg -interlace Line /Users/bfitzsimmons/Pictures/test/plant_1.jpg && identify -verbose /Users/bfitzsimmons/Pictures/test/plant_1.jpg | grep Interlace
      Interlace: JPEG
    

    Here's the version of ImageMagick installed on Mac OS X 10.9.2:

    $ brew info imagemagick
    imagemagick: stable 6.8.8-9 (bottled), HEAD
    http://www.imagemagick.org
    /usr/local/Cellar/imagemagick/6.8.8-9 (1429 files, 21M) *
      Poured from bottle
    From: https://github.com/Homebrew/homebrew/commits/master/Library/Formula/imagemagick.rb
    ==> Dependencies
    Build: pkg-config ✔
    Required: libtool ✔
    Recommended: jpeg ✔, libpng ✔, freetype ✔
    Optional: fontconfig ✘, libtiff ✘, little-cms ✘, little-cms2 ✘, jasper ✘, libwmf ✘, librsvg ✘, liblqr ✘, openexr ✘, ghostscript ✘, webp ✘
    

    Am I looking at a bug in imagick, or am I doing something wrong?

    Thanks, in advance, for any help on this (potential?) issue.

    opened by bfitzsimmons 16
  • Don't return error if action succeeded

    Don't return error if action succeeded

    I use IM primarily to convert tiffs. Libtiff (which imagemagick uses under the hood) will call its warning handler whenever it encounters a tag it doesn't recognize. Because tiff tags are just a free-for-all key-value store where every piece of software that's ever touched the file has dumped some info, that means it calls its warning handler pretty much every time.

    That isn't a problem because it just skips those tags, finishes reading the file, everything is a-ok. But right now that means when using this lib I get an error during ReadFile...

    So two issues.

    First, we need a way for end users to figure out what the ExceptionType of an error is. We can make the user do type assertion from error to MagickWandException to get it, but it needs to be accessible. That's as easy as changing MagickWandException#kind to be public and documenting.

    Second, anything that wraps a c api method that returns MagickBooleanType shouldn't return an error unless the api call returns false.

    opened by heyimalex 15
  • memory increasing to infinity

    memory increasing to infinity

    Hi, I have issues with memory going wild and using every bit of ram it can get. I have simple function to create smaller version of an image and save it beside the source one.

    This whole logic is inside GIN framework. The snippet that has memory leak is here and as you can see, I am getting desperate with the clearImagickWand() function which still doesn't work as it should.

    What can I do beside using cmd and imagick's convert like a peasant.

    The memory leak is not small. Every 15 or so images (jpg and png, bellow 1MB) my memory usage jumps by ~700MB which is absolutely insane

    func clearImagickWand(mw *imagick.MagickWand) {
    	mw.Clear()
    	mw.Destroy()
    	runtime.SetFinalizer(mw, nil)
    	mw = nil
    }
    
    func createCoverImage(pathNoExtension string, coverPathName string) bool {
    	sourceImagePath := getSourceImageForCover(filepath.Dir(pathNoExtension))
    	mw := imagick.NewMagickWand()
    
    	err := mw.ReadImage(sourceImagePath)
    	if err != nil {
    		clearImagickWand(mw)
    		return false
    	}
    
    	width, height, err := mw.GetSize()
    	if err != nil {
    		clearImagickWand(mw)
    		return false
    	}
    
    	// create thumb if we are requesting cover
    	if width > 320 {
    		scaleRatio := 320 / width
    		width = width * scaleRatio
    		height = height * scaleRatio
    
    		err = mw.ResizeImage(width, height, imagick.FILTER_LANCZOS, -0.1)
    		if err != nil {
    			clearImagickWand(mw)
    			return false
    		}
    	}
    
    	err = mw.WriteImage(coverPathName)
    	if err != nil {
    		clearImagickWand(mw)
    		return false
    	}
    
    	clearImagickWand(mw)
    
    	return true
    }
    

    Whole script is in the attachment fileserver.zip (it's in zip since github doesn't approve of .go files), the GIN server is running inside a docker image:

    FROM golang:1.17
    
    COPY . /app
    
    WORKDIR /app
    
    RUN apt update
    RUN apt install -y pkg-config libmagickwand-dev
    
    RUN mkdir -p data/content
    RUN mkdir -p data/cache
    
    RUN go mod tidy
    RUN go mod download
    RUN go build -tags="jsoniter nomsgpack" -o fileserver
    
    EXPOSE 9068
    
    CMD ["/app/fileserver", "-p", "9068", "-b", "/app/data/content", "-c", "/app/data/cache"]
    
    opened by FluffyDiscord 9
  • tiff convert leak memory

    tiff convert leak memory

    convert tiff to jpg use lots of memory, and not free. following is code:

    func (y *YImageMagic) GenReduceImage(outPath string, width, height, quality uint, resize bool) error {
    	if y.mw == nil {
    		return perrors.New("magic wand nil")
    	}
    
    	if err := y.mw.StripImage(); err != nil {
    		return perrors.WithStack(err)
    	}
    
    	if resize {
    		// FILTER_BOX fastest
    		if err := y.mw.ResizeImage(width, height, imagick.FILTER_BOX); err != nil {
    			return perrors.WithStack(err)
    		}
    	} else {
    		if err := y.mw.ResizeImage(y.mw.GetImageWidth(), y.mw.GetImageHeight(), imagick.FILTER_BOX); err != nil {
    			return perrors.WithStack(err)
    		}
    	}
    
    		if err := y.mw.AutoOrientImage(); err != nil {
    			return perrors.WithStack(err)
    		}
    
    		if err := y.mw.SetImageCompressionQuality(quality); err != nil {
    			return perrors.WithStack(err)
    		}
    
    		if err := y.mw.WriteImage(outPath); err != nil {
    			return perrors.WithStack(err)
    		}
    	return nil
    }
    
    opened by yfanswer 1
  • Is imagick support ReadStream or WriteStream?

    Is imagick support ReadStream or WriteStream?

    ReadStream() makes the image pixels available to a user supplied callback method immediately upon reading a scanline with the ReadImage() method.

    WriteStream() makes the image pixels available to a user supplied callback method immediately upon writing pixel data with the WriteImage() method.

    opened by linfangrong 1
  • Issue: MontageImage returning nil MagickWand obj

    Issue: MontageImage returning nil MagickWand obj

    Using 7.0.9-8 for ImageMagick 9.52 Gslib and 3.30 for golang imagegick

    `

       imagick.Initialize()
       defer imagick.Terminate()
    
    mwResult := imagick.NewMagickWand()
    defer mwResult.Destroy()
    
    mw := imagick.NewMagickWand()
    defer mw.Clear()
    
    err := mw.SetResolution(150, 150)
    if err != nil {
    	return nil, err
    }
    
    dw := imagick.NewDrawingWand()
    defer dw.Clear()
    
    mon := imagick.NewMagickWand()
    defer mon.Clear()
    
    err = mon.SetResourceLimit(imagick.RESOURCE_MEMORY, 8589934592)
    if err != nil {
    	return nil, err
    }
    err = mon.SetResourceLimit(imagick.RESOURCE_MAP, 8589934592)
    if err != nil {
    	return nil, err
    }
    
    data, err := ioutil.ReadFile(localPDFFilePath)
    if err != nil {
    	return nil, err
    }
    
    zerologger.Info().Msg("ReadImageBlob started")
    err = mw.ReadImageBlob(data)
    if err != nil {
    	return nil, err
    }
    zerologger.Info().Msg("ReadImageBlob completed")
    
    zerologger.Info().Msg("MontageImage started")
    mon = mw.MontageImage(dw, "4x4+0+0", "640x480+0+0", imagick.MONTAGE_MODE_UNFRAME, "0x0+0+0")
    zerologger.Info().Msg("MontageImage completed")
    
    dw.Clear()
    mw.Clear()
    //HERE: ERR: mon obj has nil 'mw' object, and causing issue
    err = mon.SharpenImage(2, 1)
    if err != nil {
    	return nil, err
    }
    
    err = mon.SetImageFormat("pdf")
    if err != nil {
    	return nil, err
    }
    
    err = mwResult.AddImage(mon)
    if err != nil {
    	return nil, err
    }
    
    zerologger.Info().Msg("GetImagesBlob started")
    result := mwResult.GetImagesBlob()
    zerologger.Info().Msg("GetImagesBlob completed")
    return result, nil`
    

    It returns Assertion Failed error after

    Assertion failed: wand != (MagickWand *) NULL,file ../ImageMagick-7.0.9-2/MagickWand/magick-image.c, line 11467

    This issue only comes if we pass large PDF file which contains more than 300+ pages depends on content of page.

    bug 
    opened by asaleem772 3
  • WIP: Fix fdopen causing error on Windows (refs #229)

    WIP: Fix fdopen causing error on Windows (refs #229)

    Refs #229

    This branch aims to fix Magick Wand ReadImageFile() returning error "The storage control block address is invalid." on Windows

    A test has been written, but the project needs to be set up with Appveyor CI for a windows test. Or someone needs to actually test this and fix it in windows.

    opened by justinfx 0
  • Magick Wand ReadImageFile()  return error

    Magick Wand ReadImageFile() return error "The storage control block address is invalid."

    The error message returned is "The storage control block address is invalid."

    Here is my code

    `package main import ( "fmt" "os"

    "gopkg.in/gographics/imagick.v3/imagick"
    

    ) func main() { imagick.Initialize() defer imagick.Terminate()

    mw := imagick.NewMagickWand()
    
    file, err := os.Open("4.jpg")
    if err != nil {
    	fmt.Println(err)
    }
    
    err = mw.ReadImageFile(file)
    if err != nil {
    	fmt.Println(err)
    }
    

    } ` Did I make a mistake

    opened by hailiangchen 7
Releases(v3.4.1)
  • v3.4.1(Jun 10, 2022)

  • v2.6.1(Jun 10, 2022)

    • Add check for cols/rows params to avoid divide-by-zero error (SIGFPE) in C (refs #278)
    • Clear finalizers when Destroy() is called (refs #213)
    Source code(tar.gz)
    Source code(zip)
  • v3.4.0(Apr 25, 2021)

    • Added gradient drawing support for ImageMagick 7 (#157)
    • Clear finalizers when Destroy() is called (#213)
    • Update ExceptionInfo to check if set, and if warn/error level (#229)
    • Expose MagickWand.CropImageToTiles (#165)
    • Expose the GetImageEntropy function
    • Exposed wand SetImageMask (#256)
    Source code(tar.gz)
    Source code(zip)
  • v2.6.0(Jan 4, 2020)

    • Add examples/docker (#175)
    • Fix examples and add test script (#171)
    • Expose MagickWand.CompositeImageGravity
    • Fix ExceptionInfo.Error() not properly printing entire error output
    • Expose ConvertImageCommand() (#220)
    • Expose GradientImage API (#162) - Thanks @gavbaa
    • Create testing docker images: https://hub.docker.com/orgs/gographics/repositories
    • Update travis CI to use docker builds for faster testing and better control of ImageMagick version
    • README updates
    Source code(tar.gz)
    Source code(zip)
  • v3.3.0(Jan 3, 2020)

    • Add examples/docker (#175)
    • Add ImageMagick.SetImageAlpha (#177)
    • Fix examples and add test script (#188)
    • Expose MagickWand.CompositeImageGravity
    • Fix ExceptionInfo.Error() not properly printing entire error output
    • Expose ConvertImageCommand() (#220)
    • Create testing docker images: https://hub.docker.com/orgs/gographics/repositories
    • Update travis CI to use docker builds for faster testing and better control of ImageMagick version
    • README updates
    Source code(tar.gz)
    Source code(zip)
  • v3.2.0(Jan 10, 2018)

    • #140: Fix bug in reflect example
    • #139: Add SetResourceLimit() function
    • #147: Fix memory crashes when using PixelWand instances in GetImageHistogram()
    • README updates
    • Contributor file updates
    • Travis CI support
    Source code(tar.gz)
    Source code(zip)
  • v2.5.0(Jan 10, 2018)

    • #140: Fix bug in reflect example
    • #139: Add SetResourceLimit() function
    • #147: Fix memory crashes when using PixelWand instances in GetImageHistogram()
    • README updates
    • Contributor file updates
    • Travis CI support
    Source code(tar.gz)
    Source code(zip)
  • v3.1.1(Aug 31, 2017)

  • v2.4.1(Aug 31, 2017)

  • v2.3.1(Mar 25, 2017)

  • v3.0.0(Nov 5, 2016)

    This is the first tag for ImageMagick 7.x support. It correlated with the following import path:

    import gopkg.in/gographics/imagick.v3/imagick
    

    While it may not include every new feature that was introduced in ImageMagick 7.x, it does compile and pass tests. Missing features can be added upon request.

    Source code(tar.gz)
    Source code(zip)
  • v2.3.0(Nov 5, 2016)

    New in v2.3.0

    • #89 - Support for KernelInfo (thanks @Danack)
    • #87 - Updated Windows build instructions (thanks @vprus)
    • #93 - README cleanups for syntax highlighting (thanks @brunoqc)
    Source code(tar.gz)
    Source code(zip)
Owner
Go Graphics community
Graphics community for gophers
Go Graphics community
Go OpenCL (GOCL) Binding

gocl Go OpenCL (GOCL) Binding (http://www.gocl.org) Library documentation: http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/ http://www.khron

Rain Liu 85 Jan 25, 2022
OpenGL binding generator for Go

GoGL GoGL is an OpenGL binding generator for Go. No external dependencies like GLEW are needed. Install the OpenGL bindings For example, OpenGL 2.1 bi

Christoph Schunk 139 Apr 26, 2022
A Go skia binding based on skia C library through cgo

go-skia is a Go skia binding based on skia C library through cgo. Note: the project is still in early stage, and it only supports Linux-amd64 now. The

Go101 19 Mar 9, 2022
Go bindings for OpenCV / 2.x API in gocv / 1.x API in opencv

Go OpenCV binding A Golang binding for OpenCV. OpenCV 1.x C API bindings through CGO, and OpenCV 2+ C++ API (GoCV) through SWIG. Disclaimer This is a

go-opencv 1.3k Jun 28, 2022
geoserver is a Go library for manipulating a GeoServer instance via the GeoServer REST API.

Geoserver geoserver Is a Go Package For Manipulating a GeoServer Instance via the GeoServer REST API. How to install: go get -v gopkg.in/hishamkaram/g

Hisham waleed karam 74 Jun 16, 2022
Cgo bindings to PulseAudio's Simple API, for easily playing or capturing raw audio.

pulse-simple Cgo bindings to PulseAudio's Simple API, for easily playing or capturing raw audio. The full Simple API is supported, including channel m

Tommy 20 Jun 17, 2022
Vulkan API bindings for Go programming language

Golang Bindings for Vulkan API Package vulkan provides Go bindings for Vulkan — a low-overhead, cross-platform 3D graphics and compute API. Updated Oc

null 632 Jun 28, 2022
Go Graphics - 2D rendering in Go with a simple API.

Go Graphics gg is a library for rendering 2D graphics in pure Go. Installation go get -u github.com/fogleman/gg Alternatively, you may use gopkg.in t

Michael Fogleman 3.5k Jul 1, 2022
Canvas is a Go drawing library based on OpenGL or using software rendering that is very similar to the HTML5 canvas API

Go canvas Canvas is a pure Go library that provides drawing functionality as similar as possible to the HTML5 canvas API. It has nothing to do with HT

Thomas Friedel 426 Jun 19, 2022
A simple API written in Go that creates badges in SVG format, based on the requested route.

A simple API written in Go that creates badges in SVG format, based on the requested route. Those graphics can be used to style README.md files, or to add tags to webpages.

Toby 3 Jul 2, 2021
Use Windows API to capture a image from a Webcam in GoLANG

Windows-API-Capture-Webcam Use Windows API to capture a image from a Webcam in GoLANG Other Go is a amazing and powerful programming language. If you

SaturnsVoid 9 Mar 10, 2022
API-first image file text search 🔍

API-first image file text search ??

John Forstmeier 2 Dec 11, 2021
HTML Canvas 2D Context API for mobile, desktop and web

canvas HTML Canvas 2D Context API for mobile, desktop and web Context2D API https://www.w3.org/TR/2dcontext/ native code implement https://github.com/

GoPlus 2 Apr 22, 2022
An API which allows you to upload an image and responds with the same image, stripped of EXIF data

strip-metadata This is an API which allows you to upload an image and responds with the same image, stripped of EXIF data. How to run You need to have

Cristina Simionescu 0 Nov 25, 2021
API for generate image to ASCII Art

ASCII API Generate ASCII art from image. You can try this API here: ascii.projec

Sh4yn 3 Mar 10, 2022
A utility library to make use of the X Go Binding easier. (Implements EWMH and ICCCM specs, key binding support, etc.)

xgbutil is a utility library designed to work with the X Go Binding. This project's main goal is to make various X related tasks easier. For example,

Andrew Gallant 179 May 26, 2022
A utility library to make use of the X Go Binding easier. (Implements EWMH and ICCCM specs, key binding support, etc.)

xgbutil is a utility library designed to work with the X Go Binding. This project's main goal is to make various X related tasks easier. For example,

Andrew Gallant 179 May 26, 2022
mass-binding-target is a command line tool for generating binding target list by search plot files from disk.

mass-binding-target mass-binding-target is a command line tool for generating binding target list by search plot files from disk. Build Go 1.13 or new

null 0 Nov 5, 2021
The X Go Binding is a low-level API to communicate with the X server. It is modeled on XCB and supports many X extensions.

Note that this project is largely unmaintained as I don't have the time to do or support more development. Please consider using this fork instead: ht

Andrew Gallant 444 Jun 18, 2022
A Go language binding for encodeing and decoding data in the bencode format that is used by the BitTorrent peer-to-peer file sharing protocol.

bencode-go A Go language binding for encoding and decoding data in the bencode format that is used by the BitTorrent peer-to-peer file sharing protoco

Jack Palevich 184 Jun 26, 2022
SDL2 binding for Go

SDL2 binding for Go go-sdl2 is SDL2 wrapped for Go users. It enables interoperability between Go and the SDL2 library which is written in C. That mean

Ve & Co. 1.8k Jul 3, 2022
Reflectionless data binding for Go's net/http (not actively maintained)

binding Reflectionless data binding for Go's net/http Features HTTP request data binding Data validation (custom and built-in) Error handling Benefits

Matt Holt 791 Jun 15, 2022
Go binding for the cairo graphics library

go-cairo Go binding for the cairo graphics library Based on Dethe Elza's version https://bitbucket.org/dethe/gocairo but significantly extended and up

Erik Unger 118 Apr 18, 2022
Go OpenCL (GOCL) Binding

gocl Go OpenCL (GOCL) Binding (http://www.gocl.org) Library documentation: http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/ http://www.khron

Rain Liu 85 Jan 25, 2022
OpenGL binding generator for Go

GoGL GoGL is an OpenGL binding generator for Go. No external dependencies like GLEW are needed. Install the OpenGL bindings For example, OpenGL 2.1 bi

Christoph Schunk 139 Apr 26, 2022
Go binding for GTK

go-gtk WHATS Go bindings for GTK SCREENSHOT INSTALL You can experiment with go-gtk by running the various example programs: git clone https://github.c

mattn 1.9k Jun 28, 2022
Qt binding for Go (Golang) with support for Windows / macOS / Linux / FreeBSD / Android / iOS / Sailfish OS / Raspberry Pi / AsteroidOS / Ubuntu Touch / JavaScript / WebAssembly

Introduction Qt is a free and open-source widget toolkit for creating graphical user interfaces as well as cross-platform applications that run on var

null 9.3k Jun 27, 2022
gin auto binding,grpc, and annotated route,gin 注解路由, grpc,自动参数绑定工具

中文文档 Automatic parameter binding base on go-gin doc Golang gin automatic parameter binding Support for RPC automatic mapping Support object registrati

xxj 226 Jun 30, 2022
Go binding for gammu

gogammu is binding for SMS related functions of libGammu (documentation). gogammu/smsd is simple, MySQL based, SMS daemon, written entirely in Go (it

Michał Derkacz 14 Dec 24, 2020