v7.1.2-34 Latest Stable Release

Architecture

Discover the architecture of ImageMagick, including its pixel cache, image properties, profiles, threading, distributed processing, and custom coders/filters. Learn how ImageMagick efficiently manages pixels, metadata, and large images across heterogeneous platforms for powerful image conversion, editing, and composition.

quickstart.sh
# Install via your favorite Package Manager
$ brew install imagemagick
# Convert PNG to WebP with compression
$ magick input.png -quality 85 output.webp
# Resize image maintaining aspect ratio
$ magick input.jpg -resize 800x600^ output.jpg
Under the Hood

Architecture of ImageMagick

The citizens of Oz were quite content with their benefactor, the all-powerful Wizard. They accepted his wisdom and benevolence without ever questioning the who, why, and where of his power. Like the citizens of Oz, if you feel comfortable that ImageMagick can help you convert, edit, or compose your images without knowing what goes on behind the curtain, feel free to skip this section. However, if you want to know more about the software and algorithms behind ImageMagick, read on. To fully benefit from this discussion, you should be comfortable with image nomenclature and be familiar with computer programming.

Architecture Overview

An image typically consists of a rectangular region of pixels and metadata. To convert, edit, or compose an image in an efficient manner, we need convenient access to any pixel anywhere within the region (and sometimes outside the region). And in the case of an image sequence, we need access to any pixel of any region of any image in the sequence. However, there are hundreds of image formats such JPEG, TIFF, PNG, GIF, etc., that makes it difficult to access pixels on demand. Within these formats we find differences in:

  • Colorspace: sRGB, linear RGB, linear GRAY, CMYK, YUV, Lab, etc.
  • Bit depth: 1, 4, 8, 12, 16, etc.
  • Storage format: unsigned, signed, float, double, etc.
  • Compression: uncompressed, RLE, Zip, BZip, etc.
  • Orientation: top-to-bottom, right-to-left, etc.
  • Layout: raw, interspersed with opcodes, etc.

In addition, some image pixels may require attenuation, some formats permit more than one frame, and some formats contain vector graphics that must first be rasterized (converted from vector to pixels).

Processing Requirements

An efficient implementation of an image processing algorithm may require we get or set:

  • One pixel a time (e.g. pixel at location 10,3)
  • A single scanline (e.g. all pixels from row 4)
  • A few scanlines at once (e.g. pixel rows 4-7)
  • A single column or columns of pixels
  • An arbitrary region of pixels from the image
  • A pixel in random order (e.g. 14,15 and 640,480)
  • Pixels from two different images
  • Pixels outside image boundaries (e.g. -1,-3)
  • High-dynamic range or floating-point components
  • Multi-threaded execution & heterogeneous platforms

The Pixel Cache

The ImageMagick pixel cache is a repository for image pixels with up to 64 channels. The channels are stored contiguously at the depth specified when ImageMagick was built. The channel depths are 8 bits-per-pixel component for the Q8 version of ImageMagick, 16 bits-per-pixel component for the Q16 version, and 32 bits-per-pixel component for the Q32 version. By default pixel components are 32-bit floating-bit high dynamic-range quantities. The channels can hold any value but typically contain red, green, blue, and alpha intensities or cyan, magenta, yellow, black and alpha intensities.

Create the Pixel Cache

The pixel cache is associated with an image when it is created and it is initialized when you try to get or put pixels. Here are three common methods to associate a pixel cache with an image:

Canvas Initialized

Create canvas to background color:

image=AllocateImage(image_info);
SetImageExtent(image,640,480);
QueryMagickColor("red",...);
SetImageBackgroundColor(image);
From Disk Image

Create from a JPEG on disk:

strcpy(image_info->filename,"image.jpg");
image=ReadImage(image_info,exception);
From Memory Blob

Create from a memory blob:

image=BlobToImage(blob_info,blob,extent,exception);

When the pixel cache is initialized, pixels are scaled from whatever bit depth they originated from to that required by the pixel cache. You can determine which version you have with the -version option:

identify-version.sh
$ identify -version
Version: ImageMagick 7.1.2-34 2026-10-14 Q16-HDRI https://imagemagick.org

Access the Pixel Cache

Once associated, use these methods to access pixels in the cache:

  • GetVirtualPixels(): gets pixels you do not intend to modify or outside region (virtual pixels).
  • GetAuthenticPixels(): gets pixels you intend to modify (authentic pixels).
  • QueueAuthenticPixels(): queue pixels you intend to set.
  • SyncAuthenticPixels(): update the pixel cache with modified pixels.

Here is a typical MagickCore code snippet copying pixels and decreasing intensity by 10%:

pixel-manipulation.c
const Quantum *p;
Quantum *q;
ssize_t x, y;
destination=CloneImage(source,source->columns,source->rows,MagickTrue,exception); for (y=0; y < (ssize_t) source->rows; y++) { p=GetVirtualPixels(source,0,y,source->columns,1,exception); q=GetAuthenticPixels(destination,0,y,destination->columns,1,exception); if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) break; for (x=0; x < (ssize_t) source->columns; x++) { SetPixelRed(image,90*p->red/100,q); SetPixelGreen(image,90*p->green/100,q); SetPixelBlue(image,90*p->blue/100,q); SetPixelAlpha(image,90*p->opacity/100,q); p+=GetPixelChannels(source); q+=GetPixelChannels(destination); } if (SyncAuthenticPixels(destination,exception) == MagickFalse) break; } if (y < (ssize_t) source->rows) { /* an exception was thrown */ }

Use GetVirtualMetacontent() to retrieve any meta-content associated with each pixel, for example, an infrared channel.

Virtual Pixels

A virtual pixel defines what value should be returned when an operation needs a pixel that lies outside the actual image boundaries, such as during blurs, distortions, resizes, or neighborhood-based filters. Access to virtual pixels is controlled by the SetImageVirtualPixelMethod() method or -virtual-pixel option. Recognized methods include:

Method Description
backgroundsurrounding area is background color
blacksurrounding area is black
checker-tilealternate squares with image and background color
dithernon-random 32x32 dithered pattern
edgeextend edge pixel toward infinity (default)
graysurrounding area is gray
horizontal-tilehorizontally tile image, background color above/below
horizontal-tile-edgehorizontally tile image and replicate side edge pixels
mirrormirror tile image
randomchoose random pixel from image
tiletile image
transparentsurrounding area is transparent blackness
vertical-tilevertically tile image, sides are background color
vertical-tile-edgevertically tile image and replicate side edge pixels
whitesurrounding area is white

Cache Storage and Resource Requirements

Pixel cache storage scales with image area and component bit depth. Large images automatically spill from heap memory to disk, and are optionally memory-mapped. Resource limits can be tuned via policies (security policy, policy.xml), environment variables, or -limit.

Resource Limit Description
widthmaximum width of an image
heightmaximum height of an image
areamaximum area in bytes in cache memory before spilling to disk
memorymaximum heap memory allocated for pixel cache
mapmaximum memory map allocation for pixel cache
diskmaximum disk space permitted for pixel cache
filesmaximum number of open pixel cache files
threadmaximum parallel threads permitted
timemaximum seconds execution time permitted

To check current resource settings, run:

$ identify -list resource

Image Properties and Profiles

Images have metadata associated with them in the form of properties (width, height, description) and profiles (EXIF, IPTC, color management). Get, set, or update properties using GetImageProperty() and SetImageProperty():

SetImageProperty(image,"comment","This space for rent");
comment=GetImageProperty(image,"comment");

Profiles are handled via GetImageProfile(), SetImageProfile(), and ProfileImage().

Multispectral Imagery

ImageMagick supports multispectral imagery where all channels have the same dimensions and number of pixels. PSD, TIFF, MIFF, MPC, and FTXT fully support multispectral images up to 31 bands (21 meta channels), or up to 62 bands (52 meta channels) if built with --enable-64bit-channel-masks.

Streaming Pixels

Pixel streaming allows consuming pixels as they are read/written, scaling resource usage with image width rather than area. Use ReadStream() or WriteStream(), or the lightweight stream tool.

Large Image Support

ImageMagick supports mega- to tera-pixel image sizes. When memory is exhausted, temporary disk caches are utilized. You can monitor large image processing or offload tasks to a distributed pixel cache across remote servers.

$ magick logo: -resize 250000x250000 logo.miff

Threads of Execution

Many internal algorithms use OpenMP multi-threading. When writing custom multithreaded code using MagickCore, use cache views (e.g., AcquireVirtualCacheView()) rather than direct pixel cache accessors to ensure thread safety.

Enable Dynamic Throttling for Optimized Performance

Enable dynamic throttling to automatically introduce slight delays between processing scanlines based on system load average, preventing resource exhaustion under heavy workloads:

<policy domain="resource" name="dynamic-throttle" value="true"/>

Heterogeneous Distributed Processing

ImageMagick supports heterogeneous distributed processing using the OpenCL framework across CPUs, GPUs, and accelerators. Verify OpenCL availability with:

$ magick identify -version

Custom Image Coders

An image coder (encoder/decoder) registers, classifies, reads, writes, and unregisters image formats. Custom coders can be implemented and loaded as modules using the Magick Coder Kit.

Custom Image Filters

Add custom image processing algorithms invoked via the -process option or ExecuteModuleProcess(). Get started quickly with the Magick Filter Kit.