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.

Comments
  • 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
  • Whether to make GetImageBlob() report error

    Whether to make GetImageBlob() report error

    • version of imageMagick:
      Version: ImageMagick 7.0.9-13 Q16 x86_64 2020-01-01 https://imagemagick.org
      Copyright: © 1999-2020 ImageMagick Studio LLC
      License: https://imagemagick.org/script/license.php
      Features: Cipher DPC HDRI
      Delegates (built-in): bzlib fontconfig freetype jng jpeg lzma pangocairo png tiff webp wmf x xml zlib
      
    • imagick version: gopkg.in/gographics/imagick.v3 v3.3.0

    i find some question when debugging.

    q1, as shown in the figure, ImageMagick report error when GetImageBlob(). i think GetImageBlob() should report it.

    image

    q2, i got error convert: partition 0 overflow (> 512K) from convert and got nothing with GetImageBlob(). image

    opened by Zstro 4
  • ImageMagick panics when running (C binding issue?)

    ImageMagick panics when running (C binding issue?)

    Machine

    MacBook Pro 16 (2019) - Core Intel Core i7
    Version macOS Monterey 12.5 (21G72)
    

    Versions:

    - gopkg.in/gographics/imagick.v3 v3.4.1
    - imagemagick: stable 7.1.0-45 (bottled)
    

    go env

    GO111MODULE="auto"
    GOARCH="amd64"
    GOBIN=""
    GOCACHE="/Users/mitchell/Library/Caches/go-build"
    GOENV="/Users/mitchell/Library/Application Support/go/env"
    GOEXE=""
    GOEXPERIMENT=""
    GOFLAGS=""
    GOHOSTARCH="amd64"
    GOHOSTOS="darwin"
    GOINSECURE=""
    GOMODCACHE="/Users/mitchell/go/pkg/mod"
    GOOS="darwin"
    GOPATH="/Users/mitchell/go"
    GOPROXY="https://proxy.golang.org,direct"
    GOROOT="/usr/local/opt/go/libexec"
    GOSUMDB="sum.golang.org"
    GOTMPDIR=""
    GOTOOLDIR="/usr/local/opt/go/libexec/pkg/tool/darwin_amd64"
    GOVCS=""
    GOVERSION="go1.19"
    GCCGO="gccgo"
    GOAMD64="v1"
    AR="ar"
    CC="clang"
    CXX="clang++"
    CGO_ENABLED="1"
    GOMOD="/Users/mitchell/go/src/foo/bar/go.mod"
    GOWORK=""
    CGO_CFLAGS="-g -O2"
    CGO_CPPFLAGS=""
    CGO_CXXFLAGS="-g -O2"
    CGO_FFLAGS="-g -O2"
    CGO_LDFLAGS="-g -O2"
    PKG_CONFIG="pkg-config"
    GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/c6/4l4ylj_530z56dccw0b7_pq00000gn/T/go-build3480031562=/tmp/go-build -gno-record-gcc-switches -fno-common"
    

    .zshrc

    export CGO_CFLAGS_ALLOW='-Xpreprocessor'
    

    Example file:

    package main
    
    import (
    	"gopkg.in/gographics/imagick.v3/imagick"
    )
    
    func main() {
    	imagick.NewMagickWand()
    }
    

    Resulting panic:

    ➜ go run main.go
    fatal error: unexpected signal during runtime execution
    [signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0x44073f4]
    
    runtime stack:
    runtime.throw({0x409c9b0?, 0x43d3373?})
            /usr/local/opt/go/libexec/src/runtime/panic.go:1047 +0x5d fp=0x7ff7bfeff390 sp=0x7ff7bfeff360 pc=0x4032bfd
    runtime.sigpanic()
            /usr/local/opt/go/libexec/src/runtime/signal_unix.go:819 +0x369 fp=0x7ff7bfeff3e0 sp=0x7ff7bfeff390 pc=0x4046a29
    
    goroutine 1 [syscall]:
    runtime.cgocall(0x4076540, 0xc00005ff58)
            /usr/local/opt/go/libexec/src/runtime/cgocall.go:158 +0x5c fp=0xc00005ff30 sp=0xc00005fef8 pc=0x40052dc
    gopkg.in/gographics/imagick.v3/imagick._Cfunc_NewMagickWand()
            _cgo_gotypes.go:8518 +0x49 fp=0xc00005ff58 sp=0xc00005ff30 pc=0x4073e69
    gopkg.in/gographics/imagick.v3/imagick.NewMagickWand()
            /Users/mitchell/go/src/foo/bar/vendor/gopkg.in/gographics/imagick.v3/imagick/magick_wand.go:36 +0x19 fp=0xc00005ff70 sp=0xc00005ff58 pc=0x4073f39
    main.main()
            /Users/mitchell/go/src/foo/bar/cmd/main.go:8 +0x17 fp=0xc00005ff80 sp=0xc00005ff70 pc=0x40743f7
    runtime.main()
            /usr/local/opt/go/libexec/src/runtime/proc.go:250 +0x212 fp=0xc00005ffe0 sp=0xc00005ff80 pc=0x4035412
    runtime.goexit()
            /usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc00005ffe8 sp=0xc00005ffe0 pc=0x405d4e1
    
    goroutine 2 [force gc (idle)]:
    runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
            /usr/local/opt/go/libexec/src/runtime/proc.go:363 +0xd6 fp=0xc00004cfb0 sp=0xc00004cf90 pc=0x40357d6
    runtime.goparkunlock(...)
            /usr/local/opt/go/libexec/src/runtime/proc.go:369
    runtime.forcegchelper()
            /usr/local/opt/go/libexec/src/runtime/proc.go:302 +0xad fp=0xc00004cfe0 sp=0xc00004cfb0 pc=0x403566d
    runtime.goexit()
            /usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc00004cfe8 sp=0xc00004cfe0 pc=0x405d4e1
    created by runtime.init.6
            /usr/local/opt/go/libexec/src/runtime/proc.go:290 +0x25
    
    goroutine 3 [GC sweep wait]:
    runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
            /usr/local/opt/go/libexec/src/runtime/proc.go:363 +0xd6 fp=0xc00004d790 sp=0xc00004d770 pc=0x40357d6
    runtime.goparkunlock(...)
            /usr/local/opt/go/libexec/src/runtime/proc.go:369
    runtime.bgsweep(0x0?)
            /usr/local/opt/go/libexec/src/runtime/mgcsweep.go:278 +0x8e fp=0xc00004d7c8 sp=0xc00004d790 pc=0x402346e
    runtime.gcenable.func1()
            /usr/local/opt/go/libexec/src/runtime/mgc.go:178 +0x26 fp=0xc00004d7e0 sp=0xc00004d7c8 pc=0x4018326
    runtime.goexit()
            /usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc00004d7e8 sp=0xc00004d7e0 pc=0x405d4e1
    created by runtime.gcenable
            /usr/local/opt/go/libexec/src/runtime/mgc.go:178 +0x6b
    
    goroutine 4 [GC scavenge wait]:
    runtime.gopark(0xc000074000?, 0x40b2780?, 0x1?, 0x0?, 0x0?)
            /usr/local/opt/go/libexec/src/runtime/proc.go:363 +0xd6 fp=0xc00004df70 sp=0xc00004df50 pc=0x40357d6
    runtime.goparkunlock(...)
            /usr/local/opt/go/libexec/src/runtime/proc.go:369
    runtime.(*scavengerState).park(0x4119780)
            /usr/local/opt/go/libexec/src/runtime/mgcscavenge.go:389 +0x53 fp=0xc00004dfa0 sp=0xc00004df70 pc=0x4021513
    runtime.bgscavenge(0x0?)
            /usr/local/opt/go/libexec/src/runtime/mgcscavenge.go:617 +0x45 fp=0xc00004dfc8 sp=0xc00004dfa0 pc=0x4021ae5
    runtime.gcenable.func2()
            /usr/local/opt/go/libexec/src/runtime/mgc.go:179 +0x26 fp=0xc00004dfe0 sp=0xc00004dfc8 pc=0x40182c6
    runtime.goexit()
            /usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc00004dfe8 sp=0xc00004dfe0 pc=0x405d4e1
    created by runtime.gcenable
            /usr/local/opt/go/libexec/src/runtime/mgc.go:179 +0xaa
    
    goroutine 5 [finalizer wait]:
    runtime.gopark(0x4119b80?, 0xc000007860?, 0x0?, 0x0?, 0xc00004c770?)
            /usr/local/opt/go/libexec/src/runtime/proc.go:363 +0xd6 fp=0xc00004c628 sp=0xc00004c608 pc=0x40357d6
    runtime.goparkunlock(...)
            /usr/local/opt/go/libexec/src/runtime/proc.go:369
    runtime.runfinq()
            /usr/local/opt/go/libexec/src/runtime/mfinal.go:180 +0x10f fp=0xc00004c7e0 sp=0xc00004c628 pc=0x401742f
    runtime.goexit()
            /usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc00004c7e8 sp=0xc00004c7e0 pc=0x405d4e1
    created by runtime.createfing
            /usr/local/opt/go/libexec/src/runtime/mfinal.go:157 +0x45
    exit status 2
    
    opened by ping-localhost 10
  • 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 16
  • 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
Releases(v3.4.2)
  • v3.4.2(Sep 11, 2022)

  • v2.6.2(Sep 4, 2022)

  • 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
C# bindings for Sokol using Sokol's binding generator

C# bindings for Sokol using Sokol's binding generator

Michal Strehovský 29 Jan 4, 2023
CRC32 slice-by-16 implementation in JS with an optional native binding to speed it up even futher

CRC32 slice-by-16 implementation in JS with an optional native binding to speed it up even futher. When used with Webpack/Browserify etc, it bundles the JS version.

Mathias Buus 8 Aug 4, 2021
C++ binding to Lua

bLua C++与Lua的胶水层,b代表着bridge 特性 依赖C++17 只有一个头文件 接口简单轻量 userdata的方式管理c++指针生命周期 用法 lua调用c++ 首先注册类及需要的成员函数 // 注册全局函数 bLua::reg_global_func(L, "newA", newA

null 3 Sep 30, 2022
libmagic binding for lua.

lua-libmagic libmagic binding for lua. see man libmagic for more details. Dependencies libmagic: https://github.com/file/file Installation luarocks in

Masatoshi Fukunaga 2 Jan 14, 2022
A binding between C++11 and Lua language

lua-intf lua-intf is a binding between C++11 and Lua language, it provides three different set of API in one package: LuaBinding, Export C++ class or

Steve K. Chiu 406 Dec 5, 2022
Advanced version of lutok C++/Lua binding

Lutok2 C++/Lua binding helper for Lua 5.1 and LuaJIT 2.x+. Dependencies To use Lutok2 successfully you'll need: A standards-compliant C++11 complier L

Mário Kašuba 9 Jul 19, 2022
C++ binding to Lua

Kaguya C++ binding to Lua Licensed under Boost Software License Requirements Lua 5.1 to 5.3 (recommended: 5.3) C++03 compiler with boost library or C+

null 317 Jan 4, 2023
This is a simple version of Apex-Legends-SDK since so many people having struggles with python binding

This is a simple version of Apex-Legends-SDK since so many people having struggles with python binding

skidword64 43 Nov 30, 2022
A Sol-inspired minimalist Lua binding for Zig.

zoltan A Sol-inspired minimalist Lua binding for Zig. Features Supports Zig 0.9.0 Lua tables table creation from Zig get/set/create methods possible k

null 79 Dec 4, 2022
lua binding for Software implementation in C of the FIPS 198 Keyed-Hash Message Authentication Code HMAC

lua-hmac Compute the SHA-224, SHA-256, SHA-384, and SHA-512 message digests and the Hash-based Message Authentication Code (HMAC). this module is Lua

Masatoshi Fukunaga 3 Dec 3, 2022
Random for modern C++ with convenient API

Random for modern C++ with convenient API Design goals Supported compilers Integration Five-minute tutorial Number range Common type number range Char

Ilya Polishchuk 748 Jan 7, 2023
Arduino API for the Raspberry Pico

Raspberry PI Pico - Arduino API On Friday I was receiving my Raspberry PI Pico and I had the opportunity to play around with it. Actually most of the

Phil Schatzmann 59 Jan 2, 2023
A line follower simulation created in CoppeliaSim, with a C++ interface for CoppeliaSim's Remote API

Wall-E-Sim A line follower simulation created in CoppeliaSim, with a C++ interface for CoppeliaSim's Remote API This is a simuation of SRA's Wall-E bo

Anushree Sabnis 20 Dec 1, 2022
🍌 C++ Telegram Bot API library

?? banana - thin wrapper over Telegram Bot API written in C++17. Key Features Simple API Single interface for both blocking, non-blocking and even cor

Alexander 30 Nov 22, 2022
Arduino Sketch and a Web Bluetooth API for loading models and running inference on the Nano Sense 33 BLE device.

TF4Micro Motion Kit This repo contains the Arduino Sketch and a Web Bluetooth API for loading models and running inference on the device. Install and

Google Creative Lab 52 Nov 24, 2022
Common Sensor API for the BMA2 family of sensors

BMA2 Sensor API Sensor overview The BMA2 is a triaxial, low-g acceleration sensor with digital output. An ASIC in the sensor converts the output of a

Bosch Sensortec 9 Dec 5, 2022
A header-only version of Instagram Private API in C++

C++ Instagram API A header-only version of Instagram Private API in C++ Getting started. Writing your first bot General API Documentation Usage Error

Denis Beqiraj 36 Dec 1, 2022
Celeborn is a Userland API Unhooker that I developed for learning Windows APIs and Syscall implementations

Celeborn is a Userland API Unhooker that I developed for learning Windows APIs and Syscall implementations. It mainly detects and patches hooking instructions in NTDLL.dll file. All PRs are welcome!

Furkan Göksel 101 Nov 11, 2022
This is a library that can bypass the hidden api restriction on Android 9-12.

BypassHiddenApiRestriction This is a library that can bypass the restrictions on non-SDK interfaces on Android 9-12.

Wind 64 Dec 26, 2022