# ImageCache vs TextureSystem: Understanding the Distinction for Texture Access in OpenImageIO

> Understand the distinction between OpenImageIO's ImageCache and TextureSystem for texture access. Learn how TextureSystem builds on ImageCache with advanced features like UV coordinates and mip-mapping.

- Repository: [Academy Software Foundation/openimageio](https://github.com/academysoftwarefoundation/openimageio)
- Tags: deep-dive
- Published: 2026-02-23

---

**ImageCache provides low-level, raw pixel access to image files while TextureSystem adds high-level texture semantics including UV coordinates, filtering, and mip-mapping on top of an underlying ImageCache.**

OpenImageIO (OIIO) offers two distinct APIs in the AcademySoftwareFoundation/openimageio repository for accessing image data. Understanding the distinction between ImageCache and TextureSystem for accessing textures is critical for selecting the right approach for rendering pipelines versus raw image processing tools.

## What Is ImageCache?

**ImageCache** (`OIIO::ImageCache`) serves as the low-level caching layer that opens image files, reads individual tiles or scanlines, and stores decoded pixels in memory. According to the source code in [`src/include/OpenImageIO/imagecache.h`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/include/OpenImageIO/imagecache.h), this class provides a thread-safe API oriented around files and pixel regions, with no concept of texture coordinates, wrap modes, or filtering.

The cache manages file handles, memory limits, and deduplication automatically. Key methods include `get_pixels()` for reading arbitrary pixel regions and `get_tile()` for direct tile access, both implemented in [`src/libtexture/imagecache.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/libtexture/imagecache.cpp).

```cpp
#include <OpenImageIO/imagecache.h>
using namespace OIIO;

// Create a shared ImageCache instance
std::shared_ptr<ImageCache> ic = ImageCache::create();

// Read raw pixels from a specific region of interest
ROI roi = get_roi_full();  // selects the whole image
std::vector<float> pixels(roi.width() * roi.height() * roi.nchannels());

bool ok = ic->get_pixels("myimage.exr", 0, 0,  // filename, subimage, miplevel
                         roi, TypeFloat,
                         make_span(pixels));

```

This API is ideal for utilities like `maketx` or `oiiotool` that require direct pixel manipulation without texture sampling semantics.

## What Is TextureSystem?

**TextureSystem** (`OIIO::TextureSystem`) builds upon an ImageCache to provide high-level texture look-up capabilities. As defined in [`src/include/OpenImageIO/texture.h`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/include/OpenImageIO/texture.h) and implemented in [`src/libtexture/texturesys.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/libtexture/texturesys.cpp), it adds UV/UVW coordinate look-ups, wrap mode handling, automatic mip-level selection, anisotropic filtering, and derivative-based antialiasing.

Internally, `TextureSystemImpl` (declared in [`src/libtexture/texture_pvt.h`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/libtexture/texture_pvt.h)) maintains a shared pointer to an `ImageCache` instance (`m_imagecache_sp`) and delegates all file I/O to it while applying the texture sampling pipeline.

```cpp
#include <OpenImageIO/texture.h>
using namespace OIIO;

// Create a TextureSystem (internally creates a shared ImageCache)
std::shared_ptr<TextureSystem> ts = TextureSystem::create();

// Configure texture sampling options
TextureOpt opt;
opt.mipmap = TextureOpt::MipModeTrilinear;
opt.wrap = TextureOpt::WrapClamp;
opt.anisotropic = 16;

// Sample at normalized UV coordinates (0.33, 0.77)
float result[4];
bool ok = ts->texture("mytexture.tx", opt,
                      0.33f, 0.77f,   // s, t
                      0.0f, 0.0f,     // dsdx, dtdx (derivatives)
                      0.0f, 0.0f,     // dsdy, dtdy (derivatives)
                      4, result);     // nchannels, output

```

## Key Architectural Differences

**Coordinate System**
- **ImageCache**: Uses integer pixel indices and Regions of Interest (ROI) to access data.
- **TextureSystem**: Uses normalized floating-point UV/UVW coordinates (ranging from 0.0 to 1.0) with derivative vectors for filtering calculations.

**Feature Set**
- **ImageCache**: Provides autotiling, file-handle limits, memory management, and deduplication. It exposes methods like `get_tile()` and `get_image_info()` from [`src/include/OpenImageIO/imagecache.h`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/include/OpenImageIO/imagecache.h).
- **TextureSystem**: Adds wrap modes (clamp, periodic, mirror), trilinear and anisotropic filtering, environment map look-ups (`environment()` method), and 3D volume texture support (`texture3d()` in [`src/libtexture/texture3d.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/libtexture/texture3d.cpp)).

**Memory Management**
- **ImageCache**: Can be created as a standalone instance via `ImageCache::create(bool shared=true)` or shared globally.
- **TextureSystem**: Typically constructed via `TextureSystem::create(bool shared, std::shared_ptr<ImageCache> ic)`, allowing it to use either the global shared cache or a dedicated private cache for isolated memory management.

## When to Use Each API

**Use ImageCache directly** when building image processing utilities that need raw pixel data without filtering. This includes format conversion tools, metadata inspectors, or batch processors that operate on pixel arrays rather than texture samples.

**Use TextureSystem** when implementing renderers, shading engines, or any application requiring filtered texture sampling. The system handles complex filtering automatically based on screen-space derivatives, producing antialiased results that raw pixel access cannot provide.

You can mix both approaches by creating a private ImageCache and explicitly passing it to a TextureSystem:

```cpp
// Create a private ImageCache (shared=false)
auto ic = ImageCache::create(false);

// Create a TextureSystem using that specific cache
auto tex = TextureSystem::create(false, ic);

```

This pattern provides complete isolation of cache memory between different processing contexts.

## Summary

- **ImageCache** manages raw image file I/O, tile caching, and pixel buffers in [`src/libtexture/imagecache.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/libtexture/imagecache.cpp), exposing a file-centric API.
- **TextureSystem** in [`src/libtexture/texturesys.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/libtexture/texturesys.cpp) provides filtered texture look-ups using UV coordinates and sits atop an internal ImageCache instance (`m_imagecache_sp`).
- **ImageCache** understands pixels and ROIs; **TextureSystem** understands texture coordinates, mip-mapping, and filtering.
- Rendering code should typically use **TextureSystem** exclusively, while low-level image utilities should use **ImageCache** directly.

## Frequently Asked Questions

### Can TextureSystem function without an ImageCache?

No. According to the implementation in [`src/libtexture/texture_pvt.h`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/libtexture/texture_pvt.h), the `TextureSystemImpl` class contains a member `std::shared_ptr<ImageCache> m_imagecache_sp` that provides all underlying file I/O. When you call `TextureSystem::create()`, it either uses a shared global cache or creates a new one internally, but the architectural dependency is mandatory.

### Which API should I use for rendering applications?

Use **TextureSystem**. It provides the derivative-based filtering, mip-map selection, and wrap-mode handling required for high-quality texture sampling in renderers. The `texture()` method signature includes `dsdx`, `dtdx`, `dsdy`, and `dtdy` parameters specifically for antialiasing calculations based on screen-space derivatives.

### How do I control memory limits when using both systems?

Configure memory limits on the underlying **ImageCache** using methods like `attribute("max_memory_MB", value)` from [`src/include/OpenImageIO/imagecache.h`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/include/OpenImageIO/imagecache.h). If using a shared cache, these limits apply globally. If using a private cache passed to `TextureSystem::create(false, ic)`, the limits apply only to that isolated instance.

### Does ImageCache support all the file formats that TextureSystem supports?

Yes. Both APIs leverage the same image format plugins and I/O machinery. **TextureSystem** simply adds a processing layer on top of the raw data provided by **ImageCache**. Any file format readable by `ImageCache::get_pixels()` in [`src/libtexture/imagecache.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/libtexture/imagecache.cpp) is automatically available for texture sampling through `TextureSystem::texture()`.