需先在本机安装 libvips 8.14+ 并配置 pkg-config,否则无法编译;MacOS 上需先 export CGO_CFLAGS_ALLOW="-Xpreprocessor";Windows 原生支持未测试,推荐通过 WSL 使用。
govips
davidbyttowMIT活跃维护Go 语言的高性能图像处理与缩放库,基于 libvips,支持 JPEG、PNG、WebP、HEIC、GIF、SVG、PDF 等格式,适合需要快速批量处理图片的服务端场景。
A lightning fast image processing and resizing library for Go
brew install vips pkg-config
go get -u github.com/davidbyttow/govips/v2/vipsREADME 未说明显存或 GPU 要求;需 libvips 8.14+、C 兼容编译器(gcc 4.6+ 或 clang 3.0+)及 Go 1.23+。
Go 语言封装 libvips 的高性能图像处理与缩放库,适合并发请求场景
Go 语言的高性能图像处理与缩放库,基于 libvips,支持 JPEG、PNG、WebP、HEIC、GIF、SVG、PDF 等格式,适合需要快速批量处理图片的服务端场景。
核心能力
- 封装 libvips 全部图像操作到 Go 原生类型
- 内置 vipsgen 代码生成器覆盖 193+ 操作
- 用 NewThumbnailFromFile 只解码所需像素生成缩略图
- 支持 JPEG/PNG/WebP/AVIF/TIFF 等格式互转
- 提供 io.Reader/Writer 流式加载与保存
容易踩的坑
- v2.20.0最新正式版2026-10-16 · 2026-10-16 15:51 UTC
Highlights
Keepexport option: every format-specific*ExportParamsstruct gains aKeep ForeignKeepfield wired to libvips'skeepsave option (libvips 8.15+). WhereStripMetadatais all-or-nothing,Keepis a bitmask:ForeignKeepExif | ForeignKeepIccretains just those,ForeignKeepNonestrips everything,ForeignKeepAllkeeps whatever the running libvips supports. Unset means no change; set, it takes precedence overStripMetadata. On libvips older than 8.15 a setKeepreturns a clear error (#551)
Behavior changes
- WebP exports now keep the source ICC profile when
StripMetadatais false, matching JPEG, PNG and TIFF. Previouslywebpsavewas always givenprofile="none", so WebP output silently lost the profile. Files from sources with an embedded profile grow by roughly the profile's size (about 3 KB for sRGB). To get the old output back, setStripMetadata: trueor aKeepwithoutForeignKeepIcc(#552, #556)
Fixes
Animated and multi-page images had several transforms that treated the stacked frames as one tall image:
Rotate(Angle90/Angle270)failed with "bad grid geometry" unless every page was loaded.Pages()is the page count of the file, not the loaded count (#553, #555)Rotate(Angle180)andFlip(DirectionVertical)reversed the frame order. Both now operate per frame (#554, #558)Zoomleft the page height stale, so a 2× zoom read as twice as many half-height frames (#554, #558)Resizecollapsed frames into one tall image wheneverpageHeight × scalewasn't a whole number, the #350 "toilet roll" again. The vertical scale is now chosen so the strip is exactlyframes × newPageHeight, asvips_thumbnaildoes. Output is unchanged when the rounding already agreed (#554, #558)
Housekeeping
- CI actions bumped to
actions/checkout@v7andactions/setup-go@v7(#550)
Thanks to @diego-choi for
Keepand the WebP fix, and to @ailintom for the Rotate fix and the thorough #554 report. - v2.19.02026-09-20 · 2026-09-20 17:41 UTC
查看更新说明
Highlights
- Streaming I/O: new
LoadImageFromReader,SaveToWriter, andTranscodeStreamfor working withio.Reader/io.Writerinstead of whole buffers (#539). Stream loads sniff the file signature, so sub-formats like AVIF vs HEIF are still reported correctly (#540) NewImageFromMemory: build anImageReffrom a raw pixel buffer (#528)- WebP
TargetSize: new option onWebpExportParams, requires libvips 8.17.4+ (#535) - Kill flag:
SetKillexposes libvips' image evaluation kill flag, for cancelling long-running work (#537) - BigTIFF image type detection (#527)
Fixes
Several of these are memory-safety bugs that could crash a process. Upgrading is recommended.
- Fix SIGSEGV after a failed
DrawRect: the error path unref'd the caller's image, so the laterClose()or GC finalizer was a double-unref. Reachable from truncated JPEGs (#547, #549) - Fix input double-unref in
Join, which caused intermittent use-after-free crashes at unrelated call sites (#531) - Fix
SetBlob: it passed the slice header to C instead of the backing array and panicked under cgocheck on any non-empty input (#545, #549) - Fix a C string leak on every
ExportMagickcall (#546, #549) - Keep
ImageRefarguments alive across cgo calls in two-image ops (Composite,Insert,Join,ArrayJoin,BandJoin,Mapim,Maplut,Add,Subtract,Multiply,Divide), closing a GC finalization hazard (#543) - Fix background colors on 1 and 2-band greyscale images for
Embedand friends (#534, #538)
Housekeeping
- Add
AGENTS.mdwith contributor and agent guidance: cgo/memory rules, testing conventions, known local quirks (#541, #542) - CI installs the libheif HEVC plugin so HEIC fixtures run (#529)
- Bump
golang.org/x/imageto 0.41.0 andgolang.org/x/netto 0.55.0 (#533, #532) - Bump
sharpinexamples/tiff(#536, #548)
Thanks to @antst, @alon-ne, @goodmartian, and @joecorall for patches, and to @svkoskin and @OvOhao for detailed bug reports.
- Streaming I/O: new
- v2.18.02026-04-01 · 2026-04-01 16:53 UTC
查看更新说明
Highlights
- Leak detector: new
OpenImageRefs()andAssertNoLeaks(t)API for tracking unclosedImageRefinstances (#525) - Split
ImageRef: decomposed the 2607-line god object into 8 focused files by concern — zero API changes, same public surface (#525) - WebP shrink-on-load support via scale parameter (#516)
- Animated AVIF (avis) detection support (#513)
- Fix memory leaks in
vipsGetPointandvipsImageGetAsString(#510) - Fix segfault during animated WebP export in test suite
- Replace panics with errors in
startupIfNeededand test helpers (#522, #523) - Update minimum libvips from 8.10 to 8.14 (#518)
- Fix C code bugs in
set_image_delayandlabel(#512) - Remove incorrect defers that would free internal vips pointers (#511)
- Update dependencies to fix known vulnerabilities
- Simplify CI workflow, align Go version with go.mod (#519)
Breaking
- Removed
vips/pipelinepackage — it was a thin wrapper overImageRefmethods covering ~40 of 139 methods, creating a dual-surface problem. UseImageRefmethods directly. - Minimum libvips version bumped from 8.10 to 8.14
- Leak detector: new
- v2.17.02026-03-01 · 2026-03-01 23:52 UTC
查看更新说明
What's Changed
New Features
- Add built-in vipsgen code generator for auto-generating C bridge wrappers
- Add
NewTransparentCanvashelper for creating transparent RGBA images - Add
Grey()constructor for creating gradient images - Add fast Go
image.Imageinterop:ToGoImageandNewImageFromGoImage - Add
LoopAPI and preserve loop/delay metadata inRemoveMetadata - Add gravity function
- Add PSD support
- Add Magick Save, support ICO load
- Add access options while loading image
- Add additional image operation functions
Bug Fixes
- Fix memory leak, panics, and race condition
- Fix memory leak when using multi pages
- Fix animated resize producing toilet-roll images
- Fix CMYK ICC profile ignored when embedded profile exists
- Fix TIFF tile dimensions zero-value crash
- Fix JXL type detection for ISOBMFF containers with varying box sizes
- Add
runtime.KeepAliveto prevent GC finalization during CGo calls - Stop implicitly converting BMP files to PNG
Internal Improvements
- Consolidate generated C bridge files into
generated.{c,h,go} - Consolidate hand-written C bridge files into
operations.{c,h,go} - Reduce hand-written C bridge code by using generated wrappers
- Remove dead code (
INT_TO_GBOOLEAN, unusedmax_alpha()) - Split golden tests by format for better organization
Security
- Update gopkg.in/yaml.v3 v3.0.0 to v3.0.1 (security fix)
- Bump golang.org/x/net from 0.25.0 to 0.38.0
Other
- Add new HEIC magic numbers
- Document GIF quality param limitation with native gifsave
- Add side effects import for golang.org/x/image/webp
- v2.16.02025-01-16 · 2025-01-16 06:41 UTC
查看更新说明
What's Changed
- Add support for JXL ISOBMFF-format by @jhdrn in https://github.com/davidbyttow/govips/pull/434
- Bump golang.org/x/image from 0.10.0 to 0.18.0 by @dependabot in https://github.com/davidbyttow/govips/pull/440
- Support PDF files with magic byte in the header by @karthik-bashetty in https://github.com/davidbyttow/govips/pull/451
- add side effects import for image/jpeg png and gif to avoid image: unknown format by @BennyThink in https://github.com/davidbyttow/govips/pull/452
- Expose more Parameters for TIFF export by @je4 in https://github.com/davidbyttow/govips/pull/454
- Support vips 8.16.0 by @cdimitroulas in https://github.com/davidbyttow/govips/pull/455
- write icc files to tmp only when necessary (with tests) by @rhafer in https://github.com/davidbyttow/govips/pull/456
- Jemalloc option in README.md by @alxarno in https://github.com/davidbyttow/govips/pull/461
New Contributors
- @jhdrn made their first contribution in https://github.com/davidbyttow/govips/pull/434
- @karthik-bashetty made their first contribution in https://github.com/davidbyttow/govips/pull/451
- @BennyThink made their first contribution in https://github.com/davidbyttow/govips/pull/452
- @je4 made their first contribution in https://github.com/davidbyttow/govips/pull/454
- @cdimitroulas made their first contribution in https://github.com/davidbyttow/govips/pull/455
- @rhafer made their first contribution in https://github.com/davidbyttow/govips/pull/456
- @alxarno made their first contribution in https://github.com/davidbyttow/govips/pull/461
Full Changelog: https://github.com/davidbyttow/govips/compare/v2.15.0...v2.16.0
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
govips
A lightning fast image processing and resizing library for Go
This package wraps the core functionality of libvips image processing library by exposing all image operations on first-class types in Go.
Libvips is generally 4-8x faster than other graphics processors such as GraphicsMagick and ImageMagick. Check the benchmark: Speed and Memory Use
The intent for this is to enable developers to build extremely fast image processors in Go, which is suited well for concurrent requests.
Project Status
govips now includes a built-in code generator (cmd/vipsgen/) that uses libvips GObject introspection to auto-generate type-safe Go bindings. This covers 193+ operations across 9 categories (arithmetic, colour, conversion, convolution, create, freqfilt, histogram, morphology, resample), while complex operations like image I/O remain as hand-written bindings for full control.
Requirements
- libvips 8.14+
- C compatible compiler such as gcc 4.6+ or clang 3.0+
- Go 1.23+
Dependencies
MacOS
Use homebrew to install vips and pkg-config:
brew install vips pkg-config
Windows
The recommended approach on Windows is to use Govips via WSL and Ubuntu.
If you need to run Govips natively on Windows, it's not difficult but will require some effort. We don't have a recommended environment or setup at the moment. Windows is also not in our list of CI/CD targets so Govips is not regularly tested for compatibility. If you would be willing to setup and maintain a robust CI/CD Windows environment, please open a PR, we would be pleased to accept your contribution and support Windows as a platform.
Installation
go get -u github.com/davidbyttow/govips/v2/vips
MacOS note
On MacOS, govips may not compile without first setting an environment variable:
export CGO_CFLAGS_ALLOW="-Xpreprocessor"
Examples
Every example below assumes this setup:
package main
import (
"fmt"
"os"
"github.com/davidbyttow/govips/v2/vips"
)
func main() {
vips.Startup(nil)
defer vips.Shutdown()
// ... example code goes here
}
1. Load an image and export as JPEG
The basics: load from a file, auto-rotate based on EXIF data, and write it back out.
image, err := vips.NewImageFromFile("input.jpg")
if err != nil {
log.Fatal(err)
}
// Fix orientation from EXIF metadata
if err := image.AutoRotate(); err != nil {
log.Fatal(err)
}
buf, _, err := image.ExportJpeg(vips.NewJpegExportParams())
if err != nil {
log.Fatal(err)
}
os.WriteFile("output.jpg", buf, 0644)
2. Resize an image
Scale an image down by 50% using the Lanczos3 kernel (the sharpest option).
image, err := vips.NewImageFromFile("photo.jpg")
if err != nil {
log.Fatal(err)
}
// Scale to 50%
if err := image.Resize(0.5, vips.KernelLanczos3); err != nil {
log.Fatal(err)
}
buf, _, err := image.ExportJpeg(&vips.JpegExportParams{Quality: 85})
if err != nil {
log.Fatal(err)
}
os.WriteFile("resized.jpg", buf, 0644)
3. Create a thumbnail with smart crop
NewThumbnailFromFile is the fastest way to generate thumbnails. It decodes only the pixels it needs.
// Load and shrink to fit within 200x200, cropping to the most interesting region
image, err := vips.NewThumbnailFromFile("photo.jpg", 200, 200, vips.InterestingAttention)
if err != nil {
log.Fatal(err)
}
buf, _, err := image.ExportJpeg(&vips.JpegExportParams{Quality: 80})
if err != nil {
log.Fatal(err)
}
os.WriteFile("thumb.jpg", buf, 0644)
4. Convert between formats
Load a JPEG and export it as WebP and PNG.
image, err := vips.NewImageFromFile("photo.jpg")
if err != nil {
log.Fatal(err)
}
// Export as WebP (lossy)
webpBuf, _, err := image.ExportWebp(&vips.WebpExportParams{Quality: 75})
if err != nil {
log.Fatal(err)
}
os.WriteFile("photo.webp", webpBuf, 0644)
// Export as PNG
pngBuf, _, err := image.ExportPng(&vips.PngExportParams{Compression: 6})
if err != nil {
log.Fatal(err)
}
os.WriteFile("photo.png", pngBuf, 0644)
5. Crop and extract a region
Pull out a specific rectangle from an image.
image, err := vips.NewImageFromFile("photo.jpg")
if err != nil {
log.Fatal(err)
}
// Extract a 300x300 region starting at (50, 100)
if err := image.ExtractArea(50, 100, 300, 300); err != nil {
log.Fatal(err)
}
buf, _, err := image.ExportPng(vips.NewPngExportParams())
if err != nil {
log.Fatal(err)
}
os.WriteFile("cropped.png", buf, 0644)
6. Blur and sharpen
Apply a Gaussian blur or sharpen an image.
image, err := vips.NewImageFromFile("photo.jpg")
if err != nil {
log.Fatal(err)
}
// Gaussian blur with sigma=3.0
if err := image.GaussianBlur(3.0); err != nil {
log.Fatal(err)
}
buf, _, err := image.ExportJpeg(vips.NewJpegExportParams())
if err != nil {
log.Fatal(err)
}
os.WriteFile("blurred.jpg", buf, 0644)
// Or sharpen instead: sigma=1.0, x1=2.0, m2=3.0
image2, _ := vips.NewImageFromFile("photo.jpg")
if err := image2.Sharpen(1.0, 2.0, 3.0); err != nil {
log.Fatal(err)
}
buf2, _, _ := image2.ExportJpeg(vips.NewJpegExportParams())
os.WriteFile("sharpened.jpg", buf2, 0644)
7. Rotate and flip
Rotate by fixed angles and flip along an axis.
image, err := vips.NewImageFromFile("photo.jpg")
if err != nil {
log.Fatal(err)
}
// Rotate 90 degrees clockwise
if err := image.Rotate(vips.Angle90); err != nil {
log.Fatal(err)
}
// Flip horizontally
if err := image.Flip(vips.DirectionHorizontal); err != nil {
log.Fatal(err)
}
buf, _, err := image.ExportJpeg(vips.NewJpegExportParams())
if err != nil {
log.Fatal(err)
}
os.WriteFile("rotated.jpg", buf, 0644)
8. Adjust brightness, saturation, and hue
Modulate works in the LCH color space. Brightness and saturation are multipliers (1.0 = no change), hue is an angle shift in degrees.
image, err := vips.NewImageFromFile("photo.jpg")
if err != nil {
log.Fatal(err)
}
// Bump brightness by 20%, desaturate by 30%, shift hue by 45 degrees
if err := image.Modulate(1.2, 0.7, 45); err != nil {
log.Fatal(err)
}
buf, _, err := image.ExportJpeg(&vips.JpegExportParams{Quality: 90})
if err != nil {
log.Fatal(err)
}
os.WriteFile("adjusted.jpg", buf, 0644)
9. Composite two images (watermark overlay)
Layer one image on top of another using Porter-Duff blending.
base, err := vips.NewImageFromFile("photo.jpg")
if err != nil {
log.Fatal(err)
}
overlay, err := vips.NewImageFromFile("watermark.png")
if err != nil {
log.Fatal(err)
}
// Place the watermark at position (20, 20) using "over" blending
if err := base.Composite(overlay, vips.BlendModeOver, 20, 20); err != nil {
log.Fatal(err)
}
buf, _, err := base.ExportJpeg(&vips.JpegExportParams{Quality: 90})
if err != nil {
log.Fatal(err)
}
os.WriteFile("watermarked.jpg", buf, 0644)
10. Add a text label
Overlay text directly onto an image.
image, err := vips.NewImageFromFile("photo.jpg")
if err != nil {
log.Fatal(err)
}
err = image.Label(&vips.LabelParams{
Text: "govips",
Font: "sans bold 16",
OffsetX: vips.ValueOf(20),
OffsetY: vips.ValueOf(20),
Opacity: 0.8,
Color: vips.Color{R: 255, G: 255, B: 255},
Alignment: vips.AlignLow,
Width: vips.ValueOf(200),
Height: vips.ValueOf(40),
})
if err != nil {
log.Fatal(err)
}
buf, _, err := image.ExportPng(vips.NewPngExportParams())
if err != nil {
log.Fatal(err)
}
os.WriteFile("labeled.png", buf, 0644)
11. Flatten transparency onto a background color
Remove the alpha channel by compositing onto a solid color.
image, err := vips.NewImageFromFile("logo.png")
if err != nil {
log.Fatal(err)
}
// Flatten alpha onto white
if err := image.Flatten(&vips.Color{R: 255, G: 255, B: 255}); err != nil {
log.Fatal(err)
}
buf, _, err := image.ExportJpeg(&vips.JpegExportParams{Quality: 90})
if err != nil {
log.Fatal(err)
}
os.WriteFile("flattened.jpg", buf, 0644)
12. Embed an image in a larger canvas
Center an image inside a larger canvas with a colored background.
image, err := vips.NewImageFromFile("icon.png")
if err != nil {
log.Fatal(err)
}
w, h := image.Width(), image.Height()
// Center the image inside a 800x600 canvas with a dark background
if err := image.EmbedBackgroundRGBA(
(800-w)/2, (600-h)/2, 800, 600,
&vips.ColorRGBA{R: 30, G: 30, B: 30, A: 255},
); err != nil {
log.Fatal(err)
}
buf, _, err := image.ExportPng(vips.NewPngExportParams())
if err != nil {
log.Fatal(err)
}
os.WriteFile("embedded.png", buf, 0644)
13. Load from a byte buffer and strip metadata
Useful when you're reading images from HTTP requests or databases.
inputBytes, err := os.ReadFile("photo.jpg")
if err != nil {
log.Fatal(err)
}
image, err := vips.NewImageFromBuffer(inputBytes)
if err != nil {
log.Fatal(err)
}
// Strip all EXIF/metadata for privacy
if err := image.RemoveMetadata(); err != nil {
log.Fatal(err)
}
buf, _, err := image.ExportJpeg(&vips.JpegExportParams{
Quality: 80,
StripMetadata: true,
})
if err != nil {
log.Fatal(err)
}
os.WriteFile("clean.jpg", buf, 0644)
14. Build a pipeline: thumbnail, sharpen, and export as AVIF
Chain multiple operations together. Each method mutates the image in place, so you can pipeline them naturally.
image, err := vips.NewThumbnailFromFile("photo.jpg", 800, 600, vips.InterestingCentre)
if err != nil {
log.Fatal(err)
}
if err := image.Sharpen(0.7, 1.0, 2.0); err != nil {
log.Fatal(err)
}
buf, _, err := image.ExportAvif(&vips.AvifExportParams{
Quality: 50,
Effort: 4,
})
if err != nil {
log.Fatal(err)
}
os.WriteFile("output.avif", buf, 0644)
15. Stream images with io.Reader and io.Writer
Load directly from any io.Reader (HTTP body, S3 stream, file handle) and save directly to any io.Writer — without buffering the full compressed input or output in Go memory. If the reader also implements io.Seeker (like os.File), libvips uses random access for efficient loading of formats like HEIF. One exception on the save side: TIFF requires seekable output, so it is encoded in memory and written to w in a single chunk (bytes identical to ExportTiff).
// Stream-load: no full-file buffer in Go memory
f, err := os.Open("input.heic")
if err != nil {
log.Fatal(err)
}
defer f.Close()
image, err := vips.LoadImageFromReader(f, nil)
if err != nil {
log.Fatal(err)
}
defer image.Close()
// Process as usual
if err := image.AutoRotate(); err != nil {
log.Fatal(err)
}
// Stream-save: encoded chunks written directly to the output
out, err := os.Create("output.jpg")
if err != nil {
log.Fatal(err)
}
defer out.Close()
err = image.SaveToWriter(out, vips.ImageTypeJPEG, &vips.ExportParams{
Quality: 85,
})
if err != nil {
log.Fatal(err)
}
For the full set of format-specific export options (PNG palette, WebP near-lossless/target size, TIFF compression, HEIF bit depth, ...), use the typed variants: SaveToWriterJpeg, SaveToWriterPng, SaveToWriterWebp, SaveToWriterTiff, SaveToWriterHeif, SaveToWriterGif.
For non-seekable readers (e.g. http.Request.Body), libvips buffers header data up to ~1 GB by default. Lower the limit to bound memory usage:
vips.Startup(nil)
vips.SetPipeReadLimit(100 * 1024 * 1024) // 100 MB
16. End-to-end streaming transcode
TranscodeStream runs reader → decode → transform → encode → writer as one pipeline, picking the cheapest decode strategy automatically:
// Upload handler: stream the request body through a JPEG transcode into
// content-addressed storage, hashing the output while writing.
hasher := sha256.New()
err := vips.TranscodeStream(req.Body, io.MultiWriter(hasher, storage), &vips.TranscodeOptions{
Format: vips.ImageTypeJPEG,
AutoRotate: true,
ExportParams: &vips.ExportParams{Quality: 85, Interlaced: false},
})
Two decode strategies:
- Sequential fast path — when no random-access transform is needed, pixels flow from reader to writer in one pass. Peak RAM is bounded by libvips line caches, independent of file size and pixel count. Available directly via
LoadImageFromReaderwithparams.Access.Set(vips.AccessSequential); the source then stays connected (keep the reader open) untilClose. - Materialized path — when random access is required (e.g. EXIF rotation), the decoded frame is rendered in one streaming pass to memory or, above a threshold, to an unlinked scratch file on disc. RAM stays bounded either way; the source is released as soon as materialization finishes.
vips.SetStreamDiscThreshold(64 << 20) // decoded frames >64 MB go to scratch disc (default 100 MB, or VIPS_DISC_THRESHOLD)
vips.SetStreamScratchDir("/var/scratch") // default os.TempDir()
Which operations keep the sequential fast path? Sequential images may only be read top-to-bottom, once. Safe: resize/thumbnail (shrink), crop, flatten, colorspace conversion, sharpen/blur (line kernels), horizontal flip, format conversion. Forcing materialization: rotation (90°/180°/270°), vertical flip, AutoRotate for EXIF orientations 3–8 (TranscodeStream detects this from the header automatically), FindTrim, SmartCrop, and anything else that reads pixels out of order. Attempting a random-access operation on a sequential image fails with an "out of order read" error from libvips.
Codec caveats. True end-to-end streaming also depends on the codec: progressive (interlaced) JPEG and interlaced PNG cannot stream — on decode the codec buffers all input before emitting rows, and on encode (govips' default JPEG params set Interlace: true) it buffers the whole image before writing the first byte. Pass Interlaced: false for streaming output. HEIF/HEIC decodes whole-frame inside libheif regardless of access mode, and TIFF output is encoded in memory (seekable-output requirement). Non-seekable inputs additionally accumulate compressed bytes read so far (bounded by SetPipeReadLimit).
Where errors surface. On the default (materialized) load, truncated or erroring streams fail inside LoadImageFromReader/TranscodeStream during materialization. On the sequential path the load only reads the header, so the same failures surface from the operation that first consumes pixels — typically SaveToWriter — wrapped with the original reader error (errors.Is works).
See the examples/ folder for more.
Running tests
$ make test
Code Generation
The built-in generator lives in cmd/vipsgen/ and uses libvips GObject introspection to discover operations and their arguments at build time. To regenerate the bindings:
go generate ./vips/
This produces the generated files in vips/gen_*.{c,h,go}. You should not need to regenerate unless you are adding support for new libvips operations.
Memory usage note
MALLOC_ARENA_MAX
libvips uses GLib for memory management, and it brings GLib memory fragmentation
issues to heavily multi-threaded programs. First thing you can try if you noticed
constantly growing RSS usage without Go's sys memory growth is set MALLOC_ARENA_MAX:
MALLOC_ARENA_MAX=2 application
This will reduce GLib memory appetites by reducing the number of malloc arenas that it can create. By default GLib creates one are per thread, and this would follow to memory fragmentation.
Jemalloc
If the arena option doesn't help, you can try replacing the standard allocator with jemalloc,
which emphasizes fragmentation avoidance and scalable concurrency support.
To do this, you need to install the libjemalloc-dev package.
And pass the following flags for build command:
CGO_CFLAGS="-fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free" CGO_LDFLAGS="-ljemalloc" go build
Contributing
Feel free to file issues or create pull requests. See this guide on contributing for more information.
Credits
Thanks to:
- John Cupitt for creating and maintaining libvips
- Toni Melisma for pushing to a 2.x release
- wix.com for the govips logo and lots of great functionality
- All of our fantastic contributors
License
MIT