GithubHelp home page GithubHelp logo

libvips / lua-vips Goto Github PK

View Code? Open in Web Editor NEW
124.0 15.0 10.0 15.36 MB

Lua binding for the libvips image processing library

License: MIT License

Lua 100.00%
lua libvips vips image-processing-library luajit

lua-vips's Introduction

libvips: an image processing library

CI Fuzzing Status Coverity Status Gitter

Introduction

libvips is a demand-driven, horizontally threaded image processing library. Compared to similar libraries, libvips runs quickly and uses little memory. libvips is licensed under the LGPL 2.1+.

It has around 300 operations covering arithmetic, histograms, convolution, morphological operations, frequency filtering, colour, resampling, statistics and others. It supports a large range of numeric types, from 8-bit int to 128-bit complex. Images can have any number of bands. It supports a good range of image formats, including JPEG, JPEG2000, JPEG-XL, TIFF, PNG, WebP, HEIC, AVIF, FITS, Matlab, OpenEXR, PDF, SVG, HDR, PPM / PGM / PFM, CSV, GIF, Analyze, NIfTI, DeepZoom, and OpenSlide. It can also load images via ImageMagick or GraphicsMagick, letting it work with formats like DICOM.

It comes with bindings for C, C++, and the command-line. Full bindings are available for :

Language Binding
Ruby ruby-vips
Python pyvips
PHP php-vips
C# / .NET NetVips
Go govips
Lua lua-vips
Crystal crystal-vips
Elixir vix

libvips is used as an image processing engine by:

sharp (on node.js)
imgproxy
bimg
sharp for Go
Ruby on Rails
carrierwave-vips
mediawiki
PhotoFlow

and others. The official libvips GUI is nip2, a strange combination of a spreadsheet and a photo editor.

Install

There are packages for most Unix-like operating systems, including macOS. Check your package manager.

There are binaries for Windows in releases.

The libvips website has detailed install notes.

Building from source

libvips uses the Meson build system, version 0.56 or later. Meson can use ninja, Visual Studio or XCode as a backend, so you'll also need one of them.

libvips must have build-essential, pkg-config, libglib2.0-dev, libexpat1-dev. See the Dependencies section below for a full list of the libvips optional dependencies.

There are basic bash completions in completions/, see the README in there.

Cheatsheet

cd libvips-x.y.x
meson setup build --prefix /my/install/prefix
cd build
meson compile
meson test
meson install

Check the output of meson setup carefully and make sure it found everything you wanted it to find. Add arguments to meson setup to change the build configuration.

  • Add flags like -Dnsgif=false to turn libvips options on and off, see meson_options.txt for a list of all the build options libvips supports.

  • Add flags like -Dmagick=disabled to turn libvips dependencies on and off, see meson_options.txt and the list below for a summary of all the libvips dependencies.

  • You might need to add --libdir lib on Debian if you don't want the arch name in the library path.

  • Add --default-library static for a static build.

  • Use eg. CC=clang CXX=clang++ meson setup ... to change compiler.

  • You can have many build-dir, pick whatever names you like, for example one for release and one for debug.

There's a more comprehensive test suite you can run once libvips has been installed. Use pytest in the libvips base directory.

Optional dependencies

If suitable versions are found, libvips will add support for the following libraries automatically. Packages are generally found with pkg-config, so make sure that is working.

libjpeg

Anything that is compatible with the IJG JPEG library. Use mozjpeg if you can. Another option is libjpeg-turbo.

libexif

If available, libvips adds support for EXIF metadata in JPEG files.

librsvg

The usual SVG loader. If this is not present, vips will try to load SVGs via imagemagick instead.

PDFium

If present, libvips will attempt to load PDFs with PDFium. Download the prebuilt pdfium binary from:

https://github.com/bblanchon/pdfium-binaries

Untar to the libvips install prefix, for example:

cd ~/vips
tar xf ~/pdfium-linux.tgz

Create a pdfium.pc like this (update the version number):

VIPSHOME=/home/john/vips
cat > $VIPSHOME/lib/pkgconfig/pdfium.pc << EOF
     prefix=$VIPSHOME
     exec_prefix=\${prefix}
     libdir=\${exec_prefix}/lib
     includedir=\${prefix}/include
     Name: pdfium
     Description: pdfium
     Version: 4290
     Requires:
     Libs: -L\${libdir} -lpdfium
     Cflags: -I\${includedir}
EOF

If PDFium is not detected, libvips will look for poppler-glib instead.

poppler-glib

The Poppler PDF renderer, with a glib API. If this is not present, vips will try to load PDFs via imagemagick.

cgif

If available, libvips will save GIFs with cgif. If this is not present, vips will try to save gifs via imagemagick instead.

libarchive

If available, libvips adds support for creating image pyramids with dzsave.

libtiff

The TIFF library. It needs to be built with support for JPEG and ZIP compression. 3.4b037 and later are known to be OK.

fftw3

If libvips finds this library, it uses it for fourier transforms.

lcms2

If present, vips_icc_import(), vips_icc_export() and vips_icc_transform() can be used to manipulate images with ICC profiles.

libspng

If present, libvips will load and save PNG files using libspng. If not, it will look for the standard libpng package.

libimagequant, quantizr

If one of these quantisation packages is present, libvips can write 8-bit palette-ised PNGs and GIFs.

ImageMagick, or optionally GraphicsMagick

If available, libvips adds support for loading and saving all libMagick-supported image file types. You can enable and disable load and save separately.

Imagemagick 6.9+ needs to have been built with --with-modules. Most packaged IMs are, I think.

If you are going to be using libvips with untrusted images, perhaps in a web server, for example, you should consider the security implications of enabling a package with such a large attack surface.

pangocairo

If available, libvips adds support for text rendering. You need the package pangocairo in pkg-config --list-all.

highway

If present, libvips will accelerate some operations with SIMD. If not, it will look for the orc-0.4 package.

matio

If available, vips can load images from Matlab save files.

cfitsio

If available, vips can load FITS images.

libwebp

If available, vips can load and save WebP images.

libniftiio

If available, vips can load and save NIfTI images.

OpenEXR

If available, libvips will directly read (but not write, sadly) OpenEXR images.

OpenJPEG

If available, libvips will read and write JPEG2000 images.

libjxl

If available, libvips will read and write JPEG-XL images.

OpenSlide

If available, libvips can load OpenSlide-supported virtual slide files: Aperio, Hamamatsu, Leica, MIRAX, Sakura, Trestle, and Ventana.

libheif

If available, libvips can load and save HEIC and AVIF images. Your libheif (in turn) needs to be built with the correct decoders and encoders. You can check with eg.:

$ heif-convert --list-decoders
HEIC decoders:
- libde265 = libde265 HEVC decoder, version 1.0.9
AVIF decoders:
- dav1d = dav1d v6.6.0
- aom = AOMedia Project AV1 Decoder v3.5.0
$ heif-enc --list-encoders
HEIC encoders:
- x265 = x265 HEVC encoder (3.5+1-f0c1022b6) [default]
AVIF encoders:
- aom = AOMedia Project AV1 Encoder v3.5.0 [default]
- svt = SVT-AV1 encoder v1.1.0
- rav1e = Rav1e encoder

Contributors

Code Contributors

This project exists thanks to all the people who contribute.

Organizations

We've had generous financial support from our sponsors. Thank you very much!

lua-vips's People

Contributors

imagicthecat avatar jcupitt avatar kapouer avatar kleisauke avatar lexusburn avatar oktoze avatar riskozoslovenska avatar rolandlo avatar uasan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lua-vips's Issues

VipsOperation: class "new_from_memory" not found

I'm using twain to read raw data from scanner but vips.Image.new_from_memory() prints:
error: 'no such operation
VipsOperation: class "new_from_memory" not found
'

local depth = twain.TWAIN_DibDepth(hdib) --  Depth of DIB, in bits i.e. bits per pixel.
local width = twain.TWAIN_DibWidth(hdib) -- Width of DIB, in pixels (columns)
local height = twain.TWAIN_DibHeight(hdib) -- Height of DIB, in lines (rows)
local rowBytes = twain.DIB_RowBytes(hdib) -- Number of bytes needed to store one row of the DIB.
local size = height * rowBytes
local data = ffi.new("unsigned char[?]", size) -- unsigned char[?]== BYTE[?]
local dst
for nRow = 0, height - 1 do
 dst = data + (nRow * rowBytes)
 twain.DIB_ReadRow(hdib, nRow, dst) -- Read row n of the given DIB into buffer at dst
end
local image = vips.Image.new_from_memory(data, size, width, height, depth, C.VIPS_FORMAT_UCHAR) -- C.VIPS_FORMAT_UCHAR == 0

Lua debugger crash

I'm using ZeroBraneStudio (latest git version). When I create image and put cursor on top of image variable or put image variable to variable watch then debugger will crash. I think image needs __tostring() metamethod.

local image = vips.Image.new_from_file(path)

Possible memory leak

Hi John,

We are currently investigating a memory leak, it can be caused by lua-vips (or libvips 8.7 RC1), another dependency, a leak in OpenResty or a combination of these factors.

To exclude things, I started checking lua-vips for possible memory leaks. I've found a number of things:

  1. While checking for possible memory leaks, I used valgrind on our test environment from the openresty-valgrind RPM package provided by OpenResty. With this lua-script:

    local vips = require "vips"

    and this command:

    valgrind --leak-check=full /usr/local/openresty-valgrind/luajit/bin/luajit-2.1.0-beta3 vips-init.lua &> output.txt

    it generates this log: https://gist.github.com/kleisauke/57558977a2e31be0c809424078885196
    Note: this is without any GLib / libvips suppression file. So it may be a false-positive.

  2. In addition to valgrind we've made some stacktraces to potential memory leaks with memleax on the production server. See the memleax.txt attachment. We used memleax -e 400 to report all memory allocations that haven't been freed after 400 seconds.

  3. While attempting to fix this (see: kleisauke@bb4971f), I found something odd:
    Test image: https://images2.alphacoders.com/651/651450.jpg

    pyvips:

    python3.6 soak-test.py /home/651450.jpg
    memory: high-water mark 80.83 MB
    

    lua-vips master:

    luajit-2.1.0-beta3 soak-test.lua -- /home/651450.jpg
    memory: high-water mark 1.02 GB
    

    This may be the cause of the GC collector of LuaJIT, but it seems odd that the high-water mark is much higher than that of pyvips / python. I thought this was due to caching, but the soak test from Python is also disabling that: https://github.com/jcupitt/pyvips/blob/master/examples/soak-test.py#L9

I will further debug this (in combination with OpenResty) in the next few days, but I thought I'd let you know in advance. Any help would be greatly appreciated.

memleax.txt

Working with vips_region_fetch

I'm using OpenResty and trying to split an image to NN tiles
I'm trying to use vips_region_fetch like pyvips https://github.com/libvips/pyvips/blob/master/pyvips/vregion.py

local image = vips.Image.new_from_file(image_file, {access = "sequential"})
                
                local region = vobject.new(vips_lib.vips_region_new(image.vimage))

                local psize = ffi.new('size_t *')
                local pointer = vips_lib.vips_region_fetch(region, 0, 0, 100, 100, psize)

                if (pointer == ffi.NULL) then
                    ngx.say('unable to fetch from region')
                end  

                pointer = ffi.gc(pointer, glib_lib.g_free)
                -- local image = ffi.buffer(pointer, psize[0])

but this line local image = ffi.buffer(pointer, psize[0]) causes nginx crash

40354#40354: worker process 40357 exited on signal 11 (core dumped)

Could you give me some suggestions how i can get it working ?

Btw, i can use image:crop to split image to tiles. with your watermark example, i can merge the tiles like this

image_out = image_out:composite(
                            image_parts[i], 
                            "over", 
                            { x = x * tile_width, y = y * tile_height }
                        )

i think this way slower than vips_arrayjoin. I already tried to work with vips_arrayjoin but not success.
Could you tell me how to use vips_arrayjoin in lua ?

Bad performance when iterating over individual pixels

I am running into some issues when iterating over the pixels of an image. The image I'm dealing with is 1920x1080px, and iterating over a single row takes 8s -- without doing any real work. Iterating over all 1080 rows by extension would take much longer than an hour.

local img = Image.new_from_file("image.jpg")
local start = os.clock()
for x = 0, (img:width() - 1) do
  local _ = img(x, 0)
end
print(string.format("Elapsed time: %.02f ms", (1000 * (os.clock() - start))) # Elapsed time: 7646.47 ms

I am trying to work with the image pixels directly to experiment with different clustering algorithms in Lua. Is this something that I can improve or sidestep somehow? I was assuming the approach in https://github.com/libvips/lua-vips/blob/a050f50c/example/array.lua might be faster, but running this fails:

# lua -v
LuaJIT 2.1.1693350652 -- Copyright (C) 2005-2023 Mike Pall. https://luajit.org/

# lua array.lua
lua: array.lua:14: bad storage class near 'typedef'
stack traceback:
	[C]: in function 'typeof'
	array.lua:14: in main chunk
	[C]: at 0x004062d0

Threshold to mask

Heya! Thanks for working on vips and for being so helpful to people like me that come around with questions on how to use it. I appreciate that a lot!

I'd like to accomplish the following thing:

  1. Load an image (jpeg most likely)
  2. Create an image masking out the brightest 1% and the lowest 30% of the image.
  3. Get the resulting non-masked images in a color space of my choice

nips2 has this really handy Image_select_item.Threshold_percent_item.action, but I don't know how to translate that to lua code. I also didn't find a lot of documentation about working with color spaces. For example, which color space are the pixels in after I loaded the jpeg? I'd like to work in a color space that has a good mapping of chroma / hue values to human perception (OKLab / CIELab / HSLuv would be great), how is the support for that in vips / lua-vips? Are there any examples, documentation or tutorials to take a look at to answer these questions?

Thanks again for any help!

addalpha() support

The VIPS docs mention an addalpha() function, but attempting to call image:addalpha() results in a VipsOperation: class "addalpha" not found error. I'm not sure why exactly this is. It's mentioned here that addalpha is just a convenience function for bandjoin_const, but I don't see what makes it different from any other operation that the binding supports.

I'd open a PR, but thing is, I'm not sure how to implement it. Typically, I'd just make a call to vips_lib.vips_addalpha(), but pyvips defines the function manually, so there might be something I'm missing.

NYI messages from LuaJIT

Hi John,

Running the soak.lua or the units tests with -jv outputs a few NYI messages. NYI messages indicate that this has not yet been implemented in the in LuaJIT's JIT compiler. See: http://wiki.luajit.org/NYI.

I think it will be good to solve these problems (where possible), especially in performance-critical code (such as voperation and gvalue and vobject).

NYI messages:

  1. [NYI: bytecode 50 at voperation.lua:102] Fixed with: kleisauke@f898808.
  2. [NYI: bytecode 51 at voperation.lua:118] Fixed with: #28
  3. [NYI: bytecode 51 at voperation.lua:188] Fixed with: kleisauke@8c46fac.
  4. [NYI: bytecode 72 at voperation.lua:214] Not fixable, we must iterate with pairs here.
  5. [NYI: bytecode 50 at voperation.lua:265] Fixed with: kleisauke@c4d87b5.
  6. [NYI: unsupported C type conversion at vobject.lua:89] Fixed with: kleisauke@f898808
  7. [NYI: bytecode 51 at Image_methods.lua:771] Not fixable, we can't circumvent the vargargs closure.
  8. [NYI: unsupported C type conversion at Image_methods.lua:448] Fixed with: kleisauke@f898808.
  9. [NYI: unsupported C type conversion at gvalue.lua:134], see footnote 1.
  10. [NYI: bytecode 51 at voperation.lua:91] Fixed with: kleisauke@6dd0e10

Footnotes:

  1. I think there might be ints in the array (because I don't see these messages for the array_int_type gtype).

I'll make a PR in the course of next week.

Some functions aren't found

A web app.
I want to take a requested an image file, put watermark on it on the fly via LuaJit and return an output image without creating an image file with a watermark. All via nginx.

I've faced with several "not found this functions" errors.

a part of my code:

  local vips = require("vips")
  local img = vips.Image.new_from_file("/path/to/image123.png", {access = "sequential"})
  local text = vips.Image.text("watermark123", {width = 200, dpi = 200, align = "centre", font = "sans bold"})


  -- NOTE 1
  text = text:rotate(-45)

  -- make the text transparent
  text = (text * 0.3):cast("uchar")



  -- NOTE 2
  text = text:gravity("centre", 200, 200)



  -- this block of pixels will be reused many times ... make a copy
  --text = text:copy_memory()

  text = text:replicate(1 + img:width() / text:width(), 1 + img:height() / text:height())
  text = text:crop(0, 0, img:width(), img:height())

  -- we make a constant colour image and attach the text mask as the alpha
  local overlay = text:new_from_image({255, 128, 128}):copy({interpretation = "srgb"})
  overlay = overlay:bandjoin(text)

  -- overlay the text
  img = img:composite(overlay, "over")


  --  buff = img:write_to_buffer(".jpg")
  buff = img:write_to_buffer(".png")

  ngx.print(buff)
  ngx.flush(true)

Errors:

    * VipsOperation: class "rotate" not found

    stack traceback:
    coroutine 0:
      [C]: in function 'error'
      /usr/local/share/lua/5.1/vips/voperation.lua:155: in function 'rotate'



    * VipsOperation: class "gravity" not found

    stack traceback:
    coroutine 0:
      [C]: in function 'error'
      /usr/local/share/lua/5.1/vips/voperation.lua:155: in function 'gravity'

      * lua entry thread aborted: runtime error: /usr/local/share/lua/5.1/vips/gvalue.lua:76: no such enum over
      lua-vips: no such enum type

      stack traceback:
      coroutine 0:
        [C]: in function 'error'
        /usr/local/share/lua/5.1/vips/gvalue.lua:76: in function 'to_enum'
        /usr/local/share/lua/5.1/vips/Image_methods.lua:555: in function 'composite'

What can cause them?


lua -v
Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio

luajit -v
LuaJIT 2.0.4 -- Copyright (C) 2005-2015 Mike Pall. http://luajit.org/

# or, obtained via nginx itself

LuaJIT 2.1.0-beta3


Ubuntu 18


I commented out the code with "rotate", then got "gravity" error. Then I commented out "gravity" and got the 3rd error.

Unable to call VipsForeignLoadPngFile

I'm tampering with lua-vips on a Raspberry Pi with a custom-built libvips, and I can't seem to get the module to work.

Here's the simple code I used:

local vips = require "vips"
local base = vips.Image.new_from_file("base.png")

and here's the traceback (run with luvit):

$ luvit test.lua
Uncaught exception:
./vips/voperation.lua:216: unable to call VipsForeignLoadPngFile

stack traceback:
	[C]: in function 'error'
	./vips/voperation.lua:216: in function 'new_from_file'
	/home/sjkim04/Desktop/test.lua:2: in function 'fn'
	[string "bundle:deps/require.lua"]:310: in function 'require'
	[string "bundle:/main.lua"]:128: in function <[string "bundle:/main.lua"]:20>
stack traceback:
	[C]: in function 'error'
	[string "bundle:/deps/utils.lua"]:41: in function 'assertResume'
	[string "bundle:/init.lua"]:52: in function <[string "bundle:/init.lua"]:47>
	[C]: in function 'xpcall'
	[string "bundle:/init.lua"]:47: in function 'fn'
	[string "bundle:deps/require.lua"]:310: in function <[string "bundle:deps/require.lua"]:266>

What's the problem with this? I installed most of the optional dependencies, including libspng, and the code still fails. I would appreciate some help.

Which version of ffi? And where?

I installed it via luarocks first. In LuaJit it works. In Lua - no, due to absense of ffi.

Lua 5.3 and LuaJit 2.0.5

Lua REPL:


$ lua
Lua 5.3.5  Copyright (C) 1994-2018 Lua.org, PUC-Rio
> local vips = require "vips"
/usr/share/lua/5.3/vips.lua:3: module 'ffi' not found:
[...............]

ffi for Lua 5.3 doesn't exist in luarocks:


$ sudo luarocks install  luaffifb
luaffifb not found for Lua 5.3.
Checking if available for other Lua versions...
Checking for Lua 5.1...
Checking for Lua 5.2...
Checking for Lua 5.4...

Error: No results matching query were found for Lua 5.3.

Gif not saving properly

Hello, i'm having an issue with gif saving
i load a gif using local base = vips.Image.new_from_file("base.gif", {n=-1}) , then i save it again using base:write_to_file("base2.gif") (just for testing)
And it seems that the base2 gif (the 2nd save) tries to "stack" the frames to save in file size, since nothing moves, but instead of actually stacking.. It just glitches out and become a transparent mess, any idea how i could fix that?

base
base2

Optional named arguments, not implemented?

Hello.

I try sent {Q = 60, strip = true} to write_to_file(), but does not work

image = vips.Image.thumbnail("somefile.jpg", 128)
image:write_to_file("tiny.jpg", {Q = 60, strip = true, optimize_coding = true})

Then i defined the function vips_jpegsave()

ffi.cdef[[
int vips_jpegsave (VipsImage *in, const char *filename, ...);
]]

Use

vips.vips_jpegsave(image, file_out, "Q", ffi.new('int', 60), "strip", true, nil)

I liked FFI vips = ffi.load("vips"), without helpers vips = require './vips' but how much it is correct and safe?

Thank.

vips_text() execution time regression if autofit and fontfile

Platform

W10 Vips 8.9.2

Bug Description

If vips_text() is called with width and height (autofit), plus fontfile is specified, it executes progressively slower if looped.

There are no memory leaks, crashes or any other abnormalities except the gradually increasing wall time. It does not matter if the fontfile is installed system wide or not, if it is in ttf or otf format.

Bug Reproduction

In any language just set w, h, fontfile (minimal reproducing combination), and measure the cycles in milliseconds.
This bug is easy to miss during testing if short loops and measured in seconds. The ms amount is unimportant, it's the progression that measuring in ms makes apparent.

Bug Reproduction Code

local vips = require 'vips'
vips.cache_set_max(5) -- to not just load cache.
local socket = require'socket' -- for milliseconds gettime()

for i = 1, 10000 do
   local time_mark = socket.gettime()
   local text = tostring(i):sub(-1) -- last digit only - to be unique, but w/o progressing autofit calculations.
   vips.Image.text(text, {width = 100, height = 100, fontfile = 'your_fontfile.ttf', font = 'Your_Font'})
   print(math.floor((socket.gettime() - time_mark) * 100) / 100, i) -- .nn precision
end

Notes

My results (timing is of course system and font dependent) are:

Sec   Loop
-----------
0.1   Start
0.2   1200
0.3   2400
0.4   3900
0.5   5300
...   etc

The same exact code and font, but without the fontfile param is 0.1 sec at any point — for any loop length.

While this ms difference might seem small — it's the ratio and progression that's important. In actual application with more complex and possibly multiple text manipulations — it becomes most apparent. This constant time increase is cruel.

Temp Workaround

Install all used fonts system wide. DON'T use fontfile, just font.

P.S.

Took quite some time to hunt the bug down — as there was absolutely no logical sense to suspect fontfile at all. I literally checked everything else including under the bed before realizing the butler did it. Hopefully you can guess where he is.

combine.lua example error

Hello.

When I try to run combine.lua example, I got such error

(lua-vips:15837): GLib-GObject-WARNING **: 00:11:40.698: cannot retrieve class for invalid (unclassed) type '<invalid>'
luajit: /usr/local/share/lua/5.1/vips/gvalue.lua:76: no such enum over
lua-vips: no such enum type

stack traceback:
        [C]: in function 'error'
        /usr/local/share/lua/5.1/vips/gvalue.lua:76: in function 'to_enum'
        /usr/local/share/lua/5.1/vips/Image_methods.lua:555: in function 'composite'
        combine.lua:17: in main chunk
        [C]: at 0x559cac02e1d0

What's wrong? Can I fix it myself without editing library itself?

Interpolation and Rotate

Greetings!
I'm trying to rotate an image 45° without any interpolation (Well, GIMP calls it "None" so i suppose its without interpolation)
But i can't figure out how to change it, anything i type returns unsupported gtype for set VipsInterpolate

This is my code:

local vips = require("lua-vips")

local base = vips.Image.new_from_file("thumbnail_base.png")
print("Enter Path of Sprite:")
local sprite = io.read()

local sprite_img = vips.Image.new_from_file(sprite)

local sprite_height = sprite_img:height()
local sprite_width = sprite_img:width()

local biggest_size = ((sprite_height>sprite_width) and sprite_height) or ((sprite_width>sprite_height) and sprite_width) --Gives me the biggest size (if image is 20x10, gives me 20)
if sprite_height == sprite_width then --If both sizes are the same (like 10x10) it just gives me 10
    biggest_size = sprite_height
end
print(biggest_size)

sprite_img = sprite_img:gravity("centre", biggest_size*1, biggest_size*1) --Adds empty space around the sprite
sprite_img:pngsave("sprite_step1_cropped.png")

sprite_img = sprite_img:resize(2, {kernel="VIPS_KERNEL_NEAREST"}) --Scales the sprite up A LOT
sprite_img:pngsave("sprite_step2_resized.png")

if (sprite_img:height() % 2) == 0 then
    sprite_img = sprite_img:gravity("centre", sprite_img:height()+1, sprite_img:height()+1) --If the sprite is not odd, adds 1 to the height and width
    sprite_img:pngsave("sprite_step3_resized2.png")
end
 
sprite_img = sprite_img:rotate(45, {interpolate="No idea what to put here"}) --Rotates the sprite 45° <<<<<< THIS IS WHERE I'M CONFUSED
sprite_img:pngsave("sprite_step4_rotated.png")

local sprite_width2 = sprite_img:width() --Gets the sprite's width again

sprite_img = sprite_img:resize(256/sprite_width2) --Returns the sprite to 256x256 resolution
sprite_img:pngsave("sprite_step5_resized3.png")

base = base:add(sprite_img) --Adds the sprite on top of the thumbnail_base

base:pngsave("x.png") --Exports the final result

Any idea how i can change/disable interpolation? Or if its even possible?

The specified module couldn't be found

The ffi.load("libvips-42.dll") call reports on Windows 10, LuaJIT 2.1.0-beta3. I've been following the instructions in the README of installing this, after installing libvips (By unzipping, and putting its bin directory in the user PATH).

As a confirmation, trying to manually do ffi.load "libglib-2.0-0.dll" (which is indeed in the same bin directory as libvips) works just fine, returning the expected userdata.

The pre-built binaries I have tried where:

  • vips-dev-w64-all-8.12.1
  • vips-dev-w64-web-8.12.1
  • vips-dev-w64-web-8.12.1-static
  • vips-dev-w64-all-8.11.4
  • vips-dev-w64-all-8.11.0
  • vips-dev-w64-all-8.8.0

All of those resulted in the reported error on require "vips". In addition to that, I have tested manually loading libvips in the following ways:

  • ffi.load [[C:\path\to\vips\bin\libvips-42.dll]]
  • ffi.load [[libvips-42.dll]]
    And trying to load libglib with similar methods for each of the tested subjects, which always loads just fine (I've tested other dlls some of them load just fine similar to libglib some don't similar to libvips)

Lastly, I am not quite sure if it is my setup problem (although I am sure I am following the steps right) or somehow with the libvips binary itself. lua-vips works just fine under Linux with LuaJIT 2.1.0-beta3.
I got my lua-vips directly through git cloning it on both Linux and Windows.

add something like `mutable`

The ruby-vips binding has a nice feature for encapsulating destructive operations, like metadata change or the draw operations:

https://www.libvips.org/2021/03/08/ruby-vips-mutate.html

tldr: you can write eg.:

z = x.mutate do |y|
  1000.times do 
    y.draw_circle! Array.new(3) {rand(255)},
      rand(y.width), rand(y.height), rand(100), fill: true
  end
end
  1. mutate takes an image (x in this case) and makes an instance of a class called MutableImage
  2. This constructor runs copy() to make a private copy of the underlying vips image, and subclasses Image, adding a few new methods such as draw_circle! (ruby uses the ! suffix on method names to indicate destructive operations)
  3. mutate executes the block after, passing in the mutable image (y in this case)
  4. draw_circle! modifies the image you give it by erm drawing a circle ... the first time this happens, libvips will force the iamge into memory, ie. allocate a huge ram buffer and render the image into that
  5. Now the 1000 circles are drawn directly into memory with no copying and no chance of side effects
  6. Finally, the mutable block ends, and mutate uses the modified vips image to build a new instance of the Image class
  7. And this new Image instance is returned (and assigned to z in this code)

So this scheme automates the copying that lua-vips requires right now before you can use destructive operations like metadata changes, or line or circle draw. It has locks to prevent things like set or remove being used on a non-mutable image, so it's always safe.

You see a nice speedup too: that code is more than 10x faster and needs less than 1/10th the memory compared to ruby-vips without mutate.

This would be a nice thing to add to lua-vips. You could perhaps use anonymous functions, so the code above might be:

z = x:mutate(function (y)
  for i = 1, 1000 do
    y:draw_circle(... stuff)
  end
end)

You'd need to add a new mutable image class and some locks to gate access to set, remove, draw_circle, etc.

TODO

Here's a TODO list of obvious problems that need fixing before we can declare 1.0. Please add more below.

  • check packaging: need to declare deps properly
  • need some docs
  • should we use error() for exceptions? what's the best way to do this?
  • need a test suite --- what's the best Lua unit test system?
  • need to use logging rather than print() --- what's the best logging framework?
  • need more gvalue types
  • need new_from_buffer()/write_to_buffer()
  • need image:remove() to remove metadata items
  • copy to memory, new memory etc.
  • not all binary operators know about arg reversal
  • need new_from_array() for matrix constants
  • look at setting and getting enums: can we use nicknames?
  • the rest of the operator overloads need implementing (we just have +)
  • add __tostring methods for image etc.
  • add more things to get standard fields from images, like format
  • add support for options in filenames
  • we assume that the input image is always the first required param, is this OK?
  • can we spot common errors like a.add(b) (ie. . instead of :) ?
  • need object.get_typeof() to test for fields
  • need hand-written wrappers for bandjoin etc.
  • use .., [], # for band join, split and number
  • use () for get pixel
  • add enum expansions, like sin / cos / tan
  • add convenience functions like bandsplit etc
  • need auto-expanding constants
  • support MODIFY args
  • remove a lot of logging
  • leakcheck with a debug vips
  • add to vips benchmark
  • make a benchmark against other Lua image processing libraries
  • upload the rockspec on 1.0!

Luaffi callback causes the process to crash

GDB bt

#0  0x00007f7f1bc96ae1 in lj_alloc_free (msp=0x40ebc010, ptr=0x410fff88)
    at lj_alloc.c:1376
#1  0x00007f7f1bc4ec6d in gc_sweep (g=g@entry=0x40ebc3b8, p=0x4020bcdc,
    lim=4294967294, lim@entry=4294967295) at lj_gc.c:406
#2  0x00007f7f1bc4f8a0 in gc_onestep (L=L@entry=0x41e64600) at lj_gc.c:628
#3  0x00007f7f1bc4fd4c in lj_gc_step (L=L@entry=0x41e64600) at lj_gc.c:689
#4  0x00007f7f1bc8ed85 in callback_conv_args (L=0x41e64600, cts=0x40eceec0)
    at lj_ccallback.c:619
#5  lj_ccallback_enter (cts=0x40eceec0, cf=<optimized out>)
    at lj_ccallback.c:687
#6  0x00007f7f1bc4eaf6 in lj_vm_ffi_callback ()
   from /usr/local/openresty/luajit/lib/libluajit-5.1.so.2
#7  0x00007f7e5acea42a in vips_argument_map (object=0x7f7db0001a00,
    fn=0x7f7f1c731008, a=0x0, b=0x0) at object.c:581
#8  0x00007f7f1bc4ebd4 in lj_vm_ffi_call ()
   from /usr/local/openresty/luajit/lib/libluajit-5.1.so.2
#9  0x00007f7f1bc8e3d4 in lj_ccall_func (L=L@entry=0x41e64600,
    cd=<optimized out>) at lj_ccall.c:1161
#10 0x00007f7f1bca24a6 in lj_cf_ffi_meta___call (L=0x41e64600) at lib_ffi.c:230
#11 0x00007f7f1bc4cae3 in lj_BC_FUNCC ()
   from /usr/local/openresty/luajit/lib/libluajit-5.1.so.2
#12 0x00000000004e9279 in ngx_http_lua_run_thread (L=L@entry=0x40ebc378,
    r=r@entry=0x162df90, ctx=ctx@entry=0x1651470, nrets=nrets@entry=0)

When the process runs for more than 2 hours, it may be crash.

Using VIPs library and Lua to process pictures

To get an original picture from the file, what I want to do is to select a position, cut a rectangle, and make a concave or convex semicircle on the edge of the rectangle, and make this area transparent. Is there an appropriate API or solution?

Windows 64 bit problem

Hello. I was able to get win32 version to work wirh these libs:
http://www.vips.ecs.soton.ac.uk/supported/8.1/win32/.

Win64 version does not work with those binaries or binaries from http://www.vips.ecs.soton.ac.uk/supported/8.4/win32/.

local main = vips.Image.new_from_file(path.."Gugg_coloured.jpg")

error: 'field filename does not exist'
[stack traceback:
../lib/start.lua:250: in function 'error'
../lib/vips/vobject.lua:167: in function 'set'
../lib/vips/voperation.lua:218: in function 'new_from_file'
vips_test.lua:53: in main chunk
[C]: at 0x00402040]
(.:2896): GLib-GObject-WARNING **: gtype.c:4264: type id '0' is invalid
(.:2896): GLib-GObject-WARNING **: can't peek value table for type '' which is not currentl
y referenced
(.:2896): GLib-GObject-WARNING **: gvalue.c:188: cannot initialize GValue with type '(NULL)', this t
ype has no GTypeValueTable implementation

I can send my code to load dll's, it was not an easy task to get everything to load.
vips.Image.thumbnail does not work with any windows version, but other examples do work.

Cache control

Is it possible to use cache_set_max, cache_set_max_mem, etc in lua-vips?
I use lua-vips with openresty (nginx) and i see that source files (vips.Image.new_from_file) keep in memory.

Text only renders with font file that was loaded first

I have multiple .ttf fonts in different file paths, and in my application, if I try to create two text images with different font files, only the first one is properly rendered with the font.

For instance, running the code:

vips.Image.text("TEST1", {font = "Stone Serif 10", fontfile = "stone-serif.ttf", dpi = 300}):write_to_file("test1.png")
vips.Image.text("TEST2", {font = "MatrixBoldSmallCaps 10", fontfile = "matrix.ttf", dpi = 300}):write_to_file("test2.png")

produces:

test1
test2

If I swap the lines, I get a different result:

test1
test2

What could be the reason behind this?

vips version: 8.12.1

Unable to change pixel interpretation

I want to calculate the magnitude and angle of the gradient of an image and display the magnitude as the value and the angle as the hue of HSV. But because set("interpretation", "multiband") and set("interpretation", "hsv") doesn't seem to do anything, when I load an srgb image I get an image back that is still incorrectly interpreted as srgb by write_to_file

local vips = require("vips")

local xkernel = vips.Image.new_from_array { { -3, 0, 3 }, { -10, 0, 10 }, { -3, 0, 3 } }
local ykernel = xkernel:rot90()

-- input 3band srgb image
function grad(image)
    image:set("interpretation", "multiband")
    -- image still srgb. why?

    image = image:bandmean()
    -- imgage 1band srgb

    local xgrad = image:conv(xkernel)
    local ygrad = image:conv(ykernel)

    local magnitude = (xgrad ^ 2 + ygrad ^ 2) ^ 0.5
    local angle = ygrad:math2(xgrad, "atan2")
    -- xgrad, ygrad, magnitude and angle are 1band srgb

    return magnitude .. angle
    --returns input 2 band srgb image instead of 2 band multiband what I want
end

-- input 2 band srgb instead of 2 band multiband
function ma2HSV(ma)
    local hsv = ma:extract_band(1)
    hsv = hsv .. 256
    hsv = hsv .. ma:extract_band(0)
    hsv:set("interpretation", "hsv")
    -- hsv is still 3 band srgb instead of hsv
    return hsv
end

local image = vips.Image.new_from_file("image.png")
-- image is 3 band srgb like it should be

ma2HSV(grad(image)):write_to_file("grad.png")
-- because of the incorrect interpretation, this is treated as an srgb image, not a hsv image

I really don't understand why set("interpretation", does't work. Trying to set using an invalid enum value gives this error message which indicates that this is the correct way of setting the interpretation attribute of an image object:
lua: /usr/local/share/lua/5.4/vips/gvalue.lua:76: no such enum invalid lua-vips: enum 'VipsInterpretation' has no member 'invalid', should be one of: error, multiband, b-w, histogram, xyz, lab, cmyk, labq, rgb, cmc, lch, labs, srgb, yxy, fourier, rgb16, grey16, matrix, scrgb, hsv

Here is my input and output:
image
grad

fix []

It'd be good to overload [] to mean extract band, but it didn't work on a quick try.

lua entry thread aborted: runtime error: /usr/local/share/lua/5.1/vips/voperation.lua:126: too many callbacks

I use ab -n 1000 -c 100 "xxx.com/asdsad".
I get the original picture

Requests per second:    1457.55 [#/sec] (mean)
Time per request:       68.608 [ms] (mean)
Time per request:       0.686 [ms] (mean, across all concurrent requests)
Transfer rate:          101334.15 [Kbytes/sec] received

but,I use thumbnail_buffer, the rps decrease a lot.

Requests per second:    85.25 [#/sec] (mean)
Time per request:       1328.824 [ms] (mean)
Time per request:       13.288 [ms] (mean, across all concurrent requests)
Transfer rate:          1845.87 [Kbytes/sec] received

Usage with OpenResty?

Congrats on your work, lua-vips looks really nice. I'd like to use it with OpenResty, but I want to avoid blocking the main process. Have you done any tests in this area and/or have any ideas on how you would approach this?

failures on mips64el / s390x with openresty's version of luajit

Hi,

luajit in debian/trixie (which will come after bookworm, the current stable) has moved to openresty's version.
It supports several architectures: amd64 arm64 armel armhf i386 mips64el mipsel s390x powerpc

The lua-vips debian package, however, fails on two of those, when running the tests.

Build logs:
mips64el
s390x

which can be compared to a successful build:
armhf

This may very well be a luajit bug, but I'm starting it here now :)

vips.Image.text : no such operation

I recently installed vips-8.10.5, and tried rendering text, but I got an error:

> vips = require 'vips'
> image = vips.Image.text("Hello <i>World!</i>", {dpi = 300})
/usr/local/share/lua/5.1/vips/voperation.lua:155: no such operation
VipsOperation: class "text" not found

stack traceback:
	[C]: in function 'error'
	/usr/local/share/lua/5.1/vips/voperation.lua:155: in function 'text'
	stdin:1: in main chunk
	[C]: at 0x5649cc4771d0

(this is the example taken from README, run in luajit interactive mode)

I installed vips with just ./configure && make && sudo make install && sudo ldconfig. Did I miss something? Is there a proper way to uninstall and try again, maybe trying an older version?

lua: could not load library vips

i'm currently using lua5.1 on ubuntu 20.04 and installed libvips on ubuntu also installed lua-vip and luaffi... now there is vips directory on my lua path but when i run my lua script, it give me following error :
"" could not load library vips ""

how can i solve this problem ,
thank you in advance

"pngload: out of order"

Hello, good evening.
I was testing a system of "searching" an image within one, and I am sorry if this is easy to solve, however, I have a speculation although I do not know exactly how to carry it out.
My idea about this problem is that I'm cutting out an image before, but isn't Lua supposed to wait until the process is finished?

The code in question:

local function searchImg(img, tar, s)
    local cordX, cordY = search(img, tar, s) -- the "real" searcher, nothing to show

    local sizeX, sizeY = tar:size()
    local radX, radY = sizeX/2, sizeY/2

    -- s = s and s>1 and (s-1) or (s or 0)
    local left, top = cordX-radX, cordY-radY
    local image = img:crop(left, top, sizeX, sizeY)

    if image:equal(tar):min() == 255 then
        return {
            top = top,
            left = left,
            width = sizeX,
            height = sizeY
        }, image
    end

    return nil
end

Output:
image

Can't save image as a GIF?

Hello,
I've recently been playing around with libvips and all has gone smoothly save for one issue: I can't seem to be able to save a GIF image back to file after reading it; I get a VipsForeignSave: "test2.gif" is not a known file format error.

That error is being raised by this code:

local vips = require("vips")

local image = vips.Image.new_from_file("test.gif", {n = -1})
image:write_to_file("test2.gif")

Additionally, I also tried running a code sample provided in a different issue, only to get the same result.

Reading the GIF and saving it to other formats (PNG) works. I've also tried to use magicksave()

local vips = require("vips")

local image = vips.Image.new_from_file("test.gif", {n = -1})
image:magicksave("test2.gif")

but that gives me a no such operation error.

Is this a limitation of the Lua binding? Am I doing something wrong?

My libvips version is 8.10.2.

Thanks in advance!

new_from_buffer() VS new_from_file()

Hello.
The lua worker, read bytes from stream pipe, we know length buffer, but not know image type.

How best to do, create an image object, new_from_buffer(buff) or file.write(buff) and new_from_file(name)?

Thank.

Problem with using openresty nginx luajit

Hello, I'm trying to run hello world example in nginx configuration

location = /lua {
        content_by_lua '
            local vips = require "vips"
            local image1 = vips.Image.text("Hello <i>World!</i>", { dpi = 300 })
            print("writing to x.png ...")
            image1:write_to_file("x.png")
        ';
}

My Dockerfile

FROM openresty/openresty:alpine

RUN adduser -D -H -s /sbin/nologin nginx

RUN apk add --no-cache wget luarocks gd-dev vips-dev vips-tools make pango-dev

RUN curl -fSL https://luarocks.github.io/luarocks/releases/luarocks-3.9.2.tar.gz -o luarocks-3.9.2.tar.gz \
    && tar xzf luarocks-3.9.2.tar.gz \
    && cd luarocks-3.9.2 \
    && ./configure \
        --prefix=/usr/local/openresty/luajit \
        --with-lua=/usr/local/openresty/luajit \
        --lua-suffix=jit-2.1.0-beta3 \
        --with-lua-include=/usr/local/openresty/luajit/include/luajit-2.1 \
    && make build \
    && make install \
    && rm -rf luarocks-3.9.2 luarocks-3.9.2.tar.gz

RUN luarocks install lua-vips

COPY ./docker/nginx/nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
COPY ./docker/nginx/conf.d/ /usr/local/openresty/nginx/conf/conf.d
COPY ./docker/nginx/test-upload.jpeg /

When I run the code it gives an error:

2024/02/27 06:52:12 [error] 9#9: *4 lua entry thread aborted: runtime error: ...local/openresty/luajit/share/lua/5.1/vips/voperation.lua:230: unable to call text
stack traceback:
coroutine 0:
[C]: in function 'error'
...local/openresty/luajit/share/lua/5.1/vips/voperation.lua:230: in function 'text'
content_by_lua(nginx.conf:176):7: in main chunk, client: 172.21.0.1, server: , request: "GET /lua HTTP/1.1", host: "localhost:56442"

When i try to use jpeg file i'll get another error:

/ # luajit
LuaJIT 2.1.ROLLING -- Copyright (C) 2005-2023 Mike Pall. https://luajit.org/
JIT: ON fold cse dce fwd dse narrow loop abc sink fuse
> vips = require 'vips'
> base = vips.Image.new_from_file("test-upload.jpeg")
...local/openresty/luajit/share/lua/5.1/vips/voperation.lua:230: unable to call VipsForeignLoadJpegFile

stack traceback:
	[C]: in function 'error'
	...local/openresty/luajit/share/lua/5.1/vips/voperation.lua:230: in function 'new_from_file'
	stdin:1: in main chunk
	[C]: at 0xaaaae7978c04

Vips config

/ # vips --vips-config
enable debug: false
enable deprecated: true
enable modules: true
enable cplusplus: true
enable RAD load/save: true
enable Analyze7 load/save: true
enable PPM load/save: true
enable GIF load: true
use fftw for FFTs: true
SIMD support with highway: true
accelerate loops with ORC: false
ICC profile support with lcms: true
zlib: true
text rendering with pangocairo: true
font file support with fontconfig: true
EXIF metadata support with libexif: true
JPEG load/save with libjpeg: true
JXL load/save with libjxl: true (dynamic module: true)
JPEG2000 load/save with OpenJPEG: true
PNG load/save with libspng: true
PNG load/save with libpng: false
selected quantisation package: imagequant
TIFF load/save with libtiff: true
image pyramid save with libarchive: false
HEIC/AVIF load/save with libheif: true (dynamic module: true)
WebP load/save with libwebp: true
PDF load with PDFium: false
PDF load with poppler-glib: true (dynamic module: true)
SVG load with librsvg: true
EXR load with OpenEXR: true
OpenSlide load: false (dynamic module: false)
Matlab load with libmatio: false
NIfTI load/save with niftiio: false
FITS load/save with cfitsio: true
GIF save with cgif: true
selected Magick package: MagickCore (dynamic module: true)
Magick API version: magick7
Magick load: true
Magick save: true

Vips version

/ # vips -v
vips-8.15.0

I'll run it in docker on macbook m1.

Maybe I forgot to configure something?
The problem looks similar to the one described here #49
Any help would be appreciated, thanks.

Hello World fails

Hello. Great library!

All other examples work (osx x64), but vips.Image.text fails.

-- make a new image with some text rendered on it
image = vips.Image.text("Hello World!", {dpi = 300})

error: 'no such operation
VipsOperation: class "text" not found
'

./configure --prefix=/Users/pasi/installed/C/vips/build --disable-dependency-tracking --enable-shared --disable-static --without-python --without-pangoft2 --without-libwebp --without-radiance --without-matio --without-openslide --without-poppler --without-OpenEXR --without-magick --without-gsf
--with-giflib-includes=/usr/local/Cellar/giflib/5.1.4/include --with-giflib-libraries=/usr/local/Cellar/giflib/5.1.4/lib
--with-jpeg-includes=/usr/local/Cellar/jpeg/8d/include --with-jpeg-libraries=/usr/local/Cellar/jpeg/8d/lib

Error if get undefined EXIF tag

vips = require "vips"

image = vips.Image.thumbnail("/opt/no_exif.jpg", 1920, {height = 200})

print('EXIF: ' .. image:get('exif-ifd0-Model'))

Out error

luajit: ./vips/Image_methods.lua:367: unable to get exif-ifd0-Model
stack traceback:
        [C]: in function 'error'
        ./vips/Image_methods.lua:367: in function 'get'
        example.lua:5: in main chunk
        [C]: at 0x55fda1393580

Is this expected behavior, need use pcall?

local status, res = pcall(image.get, image, 'exif-ifd0-Model')

if(status) then print('EXIF: ' .. res) end

Slow operations on spcor result image?

While messing around, I stumbled upon a peculiar occurrence: calling an operation on an image obtained by :spcor() is very slow, but only the first time the operation is called. To illustrate:

local function bench(image, method)
	print(image)

	local start = os.clock()

	image[method](image)

	print(os.clock() - start, "\n")
end


local image1 = Image.new_from_file("test1.png")
local image2 = Image.new_from_file("test2.png")

local image3 = image1:spcor(image2)

bench(image1, "max") -- Fast
bench(image3, "max") -- Slow
bench(image3, "max") -- Fast
bench(image3, "avg") -- Slow
bench(image3, "avg") -- Fast

Output:

test1.png: 1920x1080 uchar, 3 bands, srgb, pngload
0.014

temp-8: 1920x1080 float, 3 bands, srgb, pngload
8.495

temp-8: 1920x1080 float, 3 bands, srgb, pngload
0.00099999999999945

temp-8: 1920x1080 float, 3 bands, srgb, pngload
8.349

temp-8: 1920x1080 float, 3 bands, srgb, pngload
0.001

I'm asking mostly just to satiate my own curiosity (I assume this phenomenon occurs due to some internal technical details), but I'm also wondering if it's possible to mitigate this slowness; the only workaround I've been able to find is to shrink the images before calling :spcor().
I've tried to save the image to file and then read it back into memory, only for the write operation to take ~8 seconds and the resulting :max() on the loaded image to be instant.
Casting the image to the uchar format gave me the same results.
Trying to load test1.png with sequential access throws an out of order read error, but I assume that's because :spcor() can't work with it.

I'm on version 8.12.1

Rapid memory leak in vips_text() - if autofit and not cached

Details

If text() is called with height and width params (i.e. box autofit), and the text is different for each call (i.e. the image is not cached) — it very rapidly leaks memory on every loop, until a crash.

This is likely not specific to Lua, but I only have access to it atm.

Reproduction

-- Shortest working example:
local vips = require('vips')
for i = 1, 1000 do -- unique text
    vips.Image.text(tostring(i) .. 'see mem usage', { width = 100, height = 100 })
end

or

local vips = require('vips')
vips.cache_set_max(0) -- emulate unique
for i = 1, 1000 do
    vips.Image.text('see mem usage', { width = 100, height = 100 })
end

Location

text.c → vips_text_autofit() → likely vips_text_get_extents() → likely pango_layout_get_pixel_extents() unreffing. Can't tell more due to being on a toaster :(

P.S.

As a new libvips adept I can't thank @jcupitt enough for the bindings, guides, examples and overall support <3.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.