libVIPS

a demand-driven, horizontally threaded image processing library. Compared to similar libraries, libvips runs quickly and uses little memory. - libVIPS / blog / wikipedia

Compiling

It straitghforward through meson. But it requires additional libraries to support features:

  • libspng (recommended) - faster png operation
    • otherwise use libpng
  • mozjpeg (recommended) - compatible with the libjpeg API and ABI. It is intended to be a drop-in replacement for libjpeg. MozJPEG is a patch for libjpeg-turbo.
    • libjpeg-turbo - a JPEG image codec that uses SIMD instructions to accelerate baseline JPEG compression and decompression
    • libjpeg - fallback
  • libjxl - for jpegxl
  • libwebp

  • highway - SIMD support
  • orc - Optimized Inner Loops Runtime Compiler

nip2

A user interface for libvips.

Doc / c++ / SO

Image arithmetic

Perform an arithmetic operation, such as addition, on every pixel in an image or a pair of images.

  • vips_project - the sum of every row of pixels, and the sum of every column of pixels.

Defining Matrix

int akernel[] = { -1, -1, -1,
                -1, 16, -1,
                -1, -1, -1 };

VImage kernel = VImage::new_from_memory( akernel, sizeof(akernel), 
                                        3, 3, 1, VIPS_FORMAT_INT);

VImage conv = in.colourspace(VIPS_INTERPRETATION_sRGB, 
                                VImage::option()
                                ->set ("source_space", VIPS_INTERPRETATION_B_W)
                                )
                    .conv( kernel );

Internals

pyvips

import pyvips

image = pyvips.Image.new_from_file('some-image.jpg', access='sequential')
image *= [1, 2, 1]
mask = pyvips.Image.new_from_array([[-1, -1, -1],
                                    [-1, 16, -1],
                                    [-1, -1, -1]
                                   ], scale=8)
image = image.conv(mask, precision='integer')
image.write_to_file('x.jpg')

Ruby

Full bindings are available for

C++

  • The API overloads () to be vips_getpoint()

  • The API overloads [] to be vips_extract_band()

VIPS images / c++

VIPS images are three-dimensional arrays, the dimensions being width, height and bands

  • crop synonym for extract_area - Extract an area from an image.
  • data - Arrange for the underlying object to be entirely in memory, then return a pointer to the first pixel.

Iterate over pixel

You can’t really iterate over pixels in libvips, since images don’t really exist. Everything is a delayed computation and pixels only exist on demand. You can either implement a new vips operation, or render the whole image to an area of memory and then treat it like any other array. Have a look at vips_image_write_to_memory().

For eg:

From version 8.4

uint64_t dhash( VImage hash ) {
    VImage cache = VImage::new_memory();
    hash[0].write( cache);
    auto* p = (uint8_t*) cache.data();

	uint64_t hash_value = 0;

    for (int j = 0; j < h; j++) {
        for (int i = 0; i < w; i++) {
            hash_value <<= 1;
            hash_value |= *p++ > 0 ? 1 : 0; 
        }
    }

    return hash_value;
}

before

uint64_t dhash( VImage hash ) {
    auto w = hash.width();
    auto h = hash.height();
    cout << "w: " << w << " h: " << h << "band: " << hash.bands() << "\n";

    size_t size;
    auto* p = (uint8_t*) hash[0].write_to_memory( &size);
    uint64_t hash_value = 0;
      for (int j = 0; j < h; j++) {
        for (int i = 0; i < w; i++) {
            hash_value <<= 1;
            //hash_value |= hash(i, j)[0] > 0 ? 1 : 0;    // 1001101100111001101011010110000010011000011000110000111
            hash_value |= *p++ > 0 ? 1 : 0;               // 1001101100111001101011010110000010011000011000110000111
        }
    }
    return hash_value;
}

Note: it is much faster to do that than accessing pixels through vips_getpoint()

VIPS History

background on its 30 years of development

Written on January 14, 2022, Last update on December 10, 2023
image jpeg jxl lib ruby c++