### Setup and display helper for sliding window decoding Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/sliding_window_tile_cache.html Sets up the environment for the sliding window example: imports os, numpy, matplotlib, and nvimgcodec, creates a Decoder instance, and defines a display helper for showing images. ```python import os import numpy as np from matplotlib import pyplot as plt resources_dir = os.getenv("PYNVIMGCODEC_EXAMPLES_RESOURCES_DIR", "../assets/images/") from nvidia import nvimgcodec decoder = nvimgcodec.Decoder() def display(images, titles=None, figsize=(10, 4)): num_images = len(images) fig, axes = plt.subplots(1, num_images, figsize=figsize) if num_images == 1: axes = [axes] for i, ax in enumerate(axes): ax.imshow(images[i]) if titles is not None and i < len(titles): ax.set_title(titles[i]) ax.axis('off') plt.tight_layout() plt.show() ``` -------------------------------- ### Import required libraries for multi-image example Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/multi-image.html Imports os, numpy, cupy, and matplotlib.pyplot for the multi-image decoding example. This is the initial setup for the script. ```python import os import numpy as np import cupy as cp from matplotlib import pyplot as plt ``` -------------------------------- ### Install nvImageCodec with all optional dependencies Source: https://docs.nvidia.com/cuda/nvimagecodec/installation.html Install nvImageCodec with all optional dependencies (nvjpeg, nvjpeg2k, nvtiff). Two variants cover CUDA 12.x/13.x on regular platforms and CUDA 12.x on Tegra platforms. ```bash pip install nvidia-nvimgcodec-cu{12, 13}[all] ``` ```bash pip install nvidia-nvimgcodec-tegra-cu{12}[all] ``` -------------------------------- ### Install nvImageCodec with select optional dependencies Source: https://docs.nvidia.com/cuda/nvimagecodec/installation.html Install nvImageCodec with a subset of optional dependencies. Use the first to enable only nvjpeg2k support, or the second to enable both nvjpeg2k and nvtiff support. Available for CUDA 12.x and 13.x. ```bash pip install nvidia-nvimgcodec-cu{12, 13}[nvjpeg2k] ``` ```bash pip install nvidia-nvimgcodec-cu{12, 13}[nvjpeg2k+nvtiff] ``` -------------------------------- ### Import required libraries for nvImageCodec and cuCIM example Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/cucim_sample.html Imports os, matplotlib.pyplot, and cupy for the example. These are needed for file paths, plotting, and GPU array operations. ```python import os from matplotlib import pyplot as plt import cupy as cp ``` -------------------------------- ### Set file names for ResNet50 classification example Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/cvcuda_sample.html Defines the input image file and the labels file for the classification example. ```python file_name = resources_dir + "tabby_tiger_cat.jpg" labelsfile = resources_dir + "../imagenet-classes.txt" ``` -------------------------------- ### Import nvImageCodec and necessary modules Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/reuse_resources.html Imports nvImageCodec and necessary modules for the examples. ```python from nvidia import nvimgcodec from matplotlib import pyplot as plt import os import numpy as np ``` -------------------------------- ### Install nvImageCodec for CUDA 12.x/13.x Source: https://docs.nvidia.com/cuda/nvimagecodec/installation.html Install the nvImageCodec Python package from PyPI for CUDA 12.x and 13.x on regular platforms, or for CUDA 12.x on Tegra platforms. The braces represent supported CUDA versions, e.g., cu12 or cu13. ```bash pip install nvidia-nvimgcodec-cu{12, 13} ``` ```bash pip install nvidia-nvimgcodec-tegra-cu{12} ``` -------------------------------- ### Import nvImageCodec and dependencies Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/advanced_multi_image.html Imports required libraries including nvimgcodec. This is the setup cell for the notebook. ```python import os import numpy as np from matplotlib import pyplot as plt from nvidia import nvimgcodec ``` -------------------------------- ### nvidia.nvimgcodec.Region.start Source: https://docs.nvidia.com/cuda/nvimagecodec/genindex.html Property of Region specifying the start coordinates. ```APIDOC ## nvidia.nvimgcodec.Region.start ### Description Property of Region that specifies the start coordinates of the region. ### Property `start` (tuple) ### Usage Access this property to get the start coordinates. ``` -------------------------------- ### Import required libraries Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/nvimgcodec.html Imports os, cv2, numpy, and matplotlib.pyplot for the examples. ```python import os import cv2 import numpy as np from matplotlib import pyplot as plt ``` -------------------------------- ### Region.start Source: https://docs.nvidia.com/cuda/nvimagecodec/py_api.html Property to get the start coordinates of the Region. ```APIDOC ## Region.start ### Description Property to get the start coordinates of the Region. ### Returns A list of starting coordinates. ``` -------------------------------- ### Setup: Import libraries and print environment info Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/torch_dataloader.html Imports required libraries and prints environment details including Python version, CPU, PyTorch, nvImageCodec, and CUDA availability. ```python import gc import os import platform import sys import time import shutil import urllib.request import zipfile import pathlib import threading import warnings from typing import List, Optional import numpy as np import torch from torch.utils.data import Dataset, DataLoader from PIL import Image import torchvision.transforms as T import matplotlib.pyplot as plt import matplotlib.ticker as mticker from nvidia import nvimgcodec def _cpu_model_name() -> str: """Best-effort CPU model name (Linux /proc/cpuinfo, fall back to ``platform``).""" if sys.platform.startswith("linux"): try: with open("/proc/cpuinfo") as f: for line in f: if line.startswith("model name"): return line.split(":", 1)[1].strip() except OSError: pass return platform.processor() or platform.machine() or "unknown" print(f"Python : {sys.version.split()[0]}") print(f"CPU : {_cpu_model_name()}") print(f"CPU cores : {os.cpu_count()} (logical)") print(f"PyTorch : {torch.__version__}") print(f"nvImageCodec: {nvimgcodec.__version__}") print(f"Start methods (multiprocessing): {torch.multiprocessing.get_all_start_methods()}") print(f"CUDA available: {torch.cuda.is_available()}") if torch.cuda.is_available(): print(f"GPU : {torch.cuda.get_device_name(0)}") print(f"GPU count : {torch.cuda.device_count()}") ``` ```text Python : 3.12.3 CPU : AMD EPYC 7413 24-Core Processor CPU cores : 48 (logical) PyTorch : 2.12.0+cu130 nvImageCodec: 0.9.0 Start methods (multiprocessing): ['fork', 'spawn', 'forkserver'] CUDA available: True GPU : NVIDIA H100 80GB HBM3 GPU count : 1 ``` -------------------------------- ### Initialize nvImageCodec library and create instance handle Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/c_samples.html Step 1 of the single image decode workflow. Creates the nvimgcodecInstance_t handle and fills nvimgcodecInstanceCreateInfo_t with built-in modules, extension modules, and a debug messenger enabled. All nvImageCodec APIs should return NVIMGCODEC_STATUS_SUCCESS; results may not be valid otherwise. ```cpp nvimgcodecInstance_t instance; nvimgcodecInstanceCreateInfo_t instance_create_info{NVIMGCODEC_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, sizeof(nvimgcodecInstanceCreateInfo_t), 0}; instance_create_info.load_builtin_modules = 1; instance_create_info.load_extension_modules = 1; instance_create_info.create_debug_messenger = 1; nvimgcodecInstanceCreate(&instance, &instance_create_info); ``` -------------------------------- ### Sample output: Running performance benchmarks Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/DICOM-pydicom.html This output shows the benchmark start message and the comparison description. ```text Running performance benchmarks... This compares CPU-based decoders (baseline) vs GPU-accelerated nvImageCodec plugin ``` -------------------------------- ### Manually install nvJPEG Python package Source: https://docs.nvidia.com/cuda/nvimagecodec/installation.html Manually install the nvJPEG library as a Python package for CUDA 12.x and 13.x. Use this if you do not have CUDA Toolkit installed or prefer to install nvJPEG independently. ```bash pip install nvidia-nvjpeg-cu{12, 13} ``` -------------------------------- ### Manually install nvJPEG2000 Python package Source: https://docs.nvidia.com/cuda/nvimagecodec/installation.html Manually install the nvJPEG2000 library as a Python package. Two variants cover CUDA 12.x/13.x on regular platforms and CUDA 12.x on Tegra platforms. For other options, see the nvJPEG2000 installation documentation. ```bash pip install nvidia-nvjpeg2k-cu{12, 13} ``` ```bash pip install nvidia-nvjpeg2k-tegra-cu{12} ``` -------------------------------- ### Initialize input image info for encoding Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/c_samples.html Sets up the input image buffer kind (strided host or device), assigns a pointer to the image data, and specifies the buffer size and CUDA stream. This is the first step before creating the image handle. ```c input_image_info.buffer_kind = NVIMGCODEC_IMAGE_BUFFER_KIND_STRIDED_HOST; //or NVIMGCODEC_IMAGE_BUFFER_KIND_STRIDED_DEVICE if image is already in GPU memory input_image_info.buffer = /* TODO assign pointer to host memory where the image data in planar format are stored */; input_image_info.buffer_size = buffer_size; input_image_info.cuda_stream = 0; // It is possible to assign cuda stream which will be used for synchronization. Here we assume it is default stream. ``` -------------------------------- ### Set up nvimgcodec decoder and display helper Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/code_stream.html Initializes the nvimgcodec Decoder and defines a display() helper that renders one or more images with matplotlib. The example resolves the sample image path from the PYNVIMGCODEC_EXAMPLES_RESOURCES_DIR environment variable, falling back to ../assets/images/, and loads cat-1046544_640.jp2. ```python import os import numpy as np from matplotlib import pyplot as plt resources_dir = os.getenv("PYNVIMGCODEC_EXAMPLES_RESOURCES_DIR", "../assets/images/") img_full_path = os.path.abspath(os.path.join(resources_dir, "cat-1046544_640.jp2")) from nvidia import nvimgcodec decoder = nvimgcodec.Decoder() def display(images, titles=None, figsize=(10, 4)): num_images = len(images) fig, axes = plt.subplots(1, num_images, figsize=figsize) if num_images == 1: axes = [axes] for i, ax in enumerate(axes): ax.imshow(images[i]) if titles is not None and i < len(titles): ax.set_title(titles[i]) ax.axis('off') plt.tight_layout() plt.show() ``` -------------------------------- ### Install required Python packages for DICOM processing Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/DICOM.html Install pydicom, pylibjpeg, and pylibjpeg-openjpeg with minimum versions. These are required for the notebook to work. ```bash pip install pydicom>=3.0.0 pip install pylibjpeg>=2.0.0 pip install pylibjpeg-openjpeg>=2.0.0 ``` -------------------------------- ### Display sample windows Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/sliding_window_tile_cache.html Selects four sample windows at quarter positions and displays them with their positions using the display function. ```python sample_indices = [0, len(windows) // 4, len(windows) // 2, 3 * len(windows) // 4] display( [windows[i] for i in sample_indices], [f"win @ {window_positions[i]}" for i in sample_indices], figsize=(14, 4), ) ``` -------------------------------- ### get_metadata Source: https://docs.nvidia.com/cuda/nvimagecodec/py_api.html Retrieves metadata from a code stream. Two overloads: one to get all metadata (optionally filtered by kind) and one to get a specific metadata by ID. ```APIDOC ## get_metadata ### Description Retrieves metadata from a code stream. Two overloads are available. ### Overload 1 #### Signature get_metadata(self: nvidia.nvimgcodec.nvimgcodec_impl.Decoder, code_stream: nvidia.nvimgcodec.nvimgcodec_impl.CodeStream, kind: Optional[nvidia.nvimgcodec.nvimgcodec_impl.MetadataKind] = None) -> list #### Parameters - **code_stream** (CodeStream) - Required - The code stream to get metadata from. - **kind** (Optional[MetadataKind]) - Optional - Optional metadata kind to filter by. If specified, only metadata of that kind will be returned. #### Returns A list of Metadata objects. If no metadata exists or no metadata matches the specified kind, returns an empty list. ### Overload 2 #### Signature get_metadata(self: nvidia.nvimgcodec.nvimgcodec_impl.Decoder, code_stream: nvidia.nvimgcodec.nvimgcodec_impl.CodeStream, id: int, kind: nvidia.nvimgcodec.nvimgcodec_impl.MetadataKind = ) -> nvidia.nvimgcodec.nvimgcodec_impl.Metadata #### Parameters - **code_stream** (CodeStream) - Required - The code stream to get metadata from. - **id** (int) - Required - The specific metadata ID to retrieve. - **kind** (MetadataKind) - Optional - Metadata kind. Defaults to TIFF tag kind if not specified. #### Returns A single Metadata object for the specified id. #### Raises - **RuntimeError** - If metadata with the specified ID is not found. ``` -------------------------------- ### Check pydicom version compatibility Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/DICOM.html This code checks if pydicom is installed and if its version is at least 3.0.0. It prints a warning if the version is too old, and an error message if pydicom is not installed. ```python try: import pydicom from packaging.version import parse v = pydicom. __version__ print(f"pydicom version: {v}") if parse(v) < parse("3.0.0"): print("⚠️ Please upgrade pydicom to >=3.0.0") else: print("✓ pydicom version is compatible") except ImportError: print("❌ pydicom is not installed.\nPlease install: pip install pydicom>=3.0.0") ``` -------------------------------- ### Access SubIFD offsets and get thumbnail CodeStream Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/advanced_multi_image.html Gets SubIFD offsets from the CodeStream and uses get_sub_code_stream to access the thumbnail. The output shows the SubIFD offset and thumbnail dimensions. ```python # Get SubIFD offsets directly from the CodeStream subifd_offsets = cs.subifd_offsets print(f"SubIFD offsets: {subifd_offsets}") # Access the thumbnail using its offset thumb_cs = cs.get_sub_code_stream(bitstream_offset=subifd_offsets[0]) print(f"Thumbnail: {thumb_cs.width}x{thumb_cs.height}, {thumb_cs.num_channels} channels") ``` ```text SubIFD offsets: [1555488] Thumbnail: 180x180, 3 channels ``` -------------------------------- ### Set resource folder and create decoder/encoder Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/nvimgcodec_transcode.html Sets the resource folder using the environment variable PYNVIMGCODEC_EXAMPLES_RESOURCES_DIR or a default path, then creates nvImageCodec decoder and encoder instances. ```python resources_dir = os.getenv("PYNVIMGCODEC_EXAMPLES_RESOURCES_DIR", "../assets/images/") decoder = nvimgcodec.Decoder() encoder = nvimgcodec.Encoder() ``` -------------------------------- ### Install nvImageCodec with pip Source: https://docs.nvidia.com/cuda/nvimagecodec/index.html Install the nvImageCodec Python package. Use the cu12 variant for Windows, Linux, and SBSA, and the tegra variant for Tegra. Optionally specify a subset of codec dependencies such as nvjpeg2k and nvtiff. ```bash # For windows, linux and sbsa pip install nvidia-nvimgcodec-cu12[all] # For tegra pip install nvidia-nvimgcodec-tegra-cu12[all] # You can specify a subset of the dependencies: nvjpeg, nvjpeg2k, nvtiff # depending what codecs would you like to use. For example: pip install nvidia-nvimgcodec-cu12[nvjpeg2k,nvtiff] ``` -------------------------------- ### Prepare Benchmark Dataset Script Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/torch_dataloader.html This script prepares a benchmark dataset by downloading sample JPEG images, replicating them to reach a target count, and pre-resizing them to a fixed size. It uses environment variables for configuration and handles download failures gracefully. ```python # ── Configuration ────────────────────────────────────────────────────────────── BENCHMARK_IMAGE_DIR = os.getenv("BENCHMARK_IMAGE_DIR", "./benchmark_images") N_IMAGES = 2000 # total images in benchmark set BATCH_SIZE = 32 NUM_WORKERS = 8 # I/O worker processes N_WARMUP_BATCHES = 3 # Must be large relative to NUM_WORKERS * prefetch_factor (= 16 with PyTorch defaults). # At t_start the iterator may already hold that many pre-decoded batches produced # during warmup, so a small n_measure inflates the reported throughput. See the note # above benchmark() for the full argument. N_BENCHMARK_BATCHES = 200 # All loaders use this H×W; the dataset prep step below resizes every image to # this size on disk, so the timed regions later don't pay per-image resize cost. # Spawn helper modules (%%writefile below) read NVIMGCODEC_NUM_WORKERS from the # environment to cap the Decoder's CPU thread pool. BENCHMARK_H, BENCHMARK_W = 256, 256 os.environ["NVIMGCODEC_NUM_WORKERS"] = str(NUM_WORKERS) # ─────────────────────────────────────────────────────────────────────────────── benchmark_dir = pathlib.Path(BENCHMARK_IMAGE_DIR) def _collect_jpegs(folder: pathlib.Path) -> List[pathlib.Path]: return sorted(p for ext in ("*.jpg", "*.jpeg", "*.JPEG", "*.JPG") for p in folder.rglob(ext)) existing = _collect_jpegs(benchmark_dir) if benchmark_dir.exists() else [] if len(existing) >= N_IMAGES: image_paths = [str(p) for p in existing[:N_IMAGES]] print(f"Using {len(image_paths)} existing images from {benchmark_dir}") else: # ── Download a small JPEG dataset (public PyTorch tutorial archive) ───────── # Alternatively: point BENCHMARK_IMAGE_DIR at any folder with ≥N_IMAGES JPEGs SEED_DIR = benchmark_dir / "_seed" SEED_DIR.mkdir(parents=True, exist_ok=True) seed_files = _collect_jpegs(SEED_DIR) if not seed_files: print("Downloading sample JPEG images (PyTorch tutorial faces archive) …") # Public JPEGs on download.pytorch.org. Hugging Face ILSVRC mirrors often return 401 (gated). _url = "https://download.pytorch.org/tutorial/faces.zip" _zip = SEED_DIR / "faces.zip" try: urllib.request.urlretrieve(_url, _zip) with zipfile.ZipFile(_zip) as zf: zf.extractall(SEED_DIR) _zip.unlink() except Exception as e: print(f" Download failed ({e}).") seed_files = _collect_jpegs(SEED_DIR) print(f" Seed images: {len(seed_files)}") if not seed_files: raise RuntimeError( f"No seed JPEGs found under {SEED_DIR}. " "The download from https://download.pytorch.org/tutorial/faces.zip failed " "or the archive contained no JPEGs. Set BENCHMARK_IMAGE_DIR to a folder " f"with at least one JPEG, or place images under {SEED_DIR}." ) # ── Replicate seed images to reach N_IMAGES ──────────────────────────────── OUT_DIR = benchmark_dir / "images" OUT_DIR.mkdir(parents=True, exist_ok=True) existing = _collect_jpegs(OUT_DIR) if len(existing) < N_IMAGES: print(f"Replicating seed images to {N_IMAGES} total …") for i in range(N_IMAGES): src = seed_files[i % len(seed_files)] dst = OUT_DIR / f"img_{i:05d}.jpg" if not dst.exists(): shutil.copy2(src, dst) existing = _collect_jpegs(OUT_DIR) image_paths = [str(p) for p in existing[:N_IMAGES]] print(f"Benchmark dataset ready: {len(image_paths)} images in {OUT_DIR}") # ── Pre-resize once, on disk, to BENCHMARK_H × BENCHMARK_W ───────────────────── # Every approach below stacks a batch into a single tensor (default_collate ≡ # torch.stack), which requires identical shapes. Doing the resize once here — # instead of inside each __getitem__ / collate_fn — keeps the timed regions # focused on decode and avoids charging the same preprocessing work to different # approaches in different places. Originals are left untouched in the source # directory; the resized cache lives next to them in `_prepared/`. PREPARED_DIR = benchmark_dir / "_prepared" PREPARED_DIR.mkdir(parents=True, exist_ok=True) prepared = _collect_jpegs(PREPARED_DIR) if len(prepared) < N_IMAGES: print(f"Pre-resizing images to {BENCHMARK_H}x{BENCHMARK_W} → {PREPARED_DIR} …") for i, src in enumerate(image_paths): dst = PREPARED_DIR / f"img_{i:05d}.jpg" if dst.exists(): continue with Image.open(src) as im: im.convert("RGB").resize( (BENCHMARK_W, BENCHMARK_H), Image.BILINEAR ).save(dst, "JPEG", quality=90) prepared = _collect_jpegs(PREPARED_DIR) image_paths = [str(p) for p in prepared[:N_IMAGES]] print(f"Using {len(image_paths)} pre-resized images from {PREPARED_DIR}") ``` -------------------------------- ### nvidia.nvimgcodec.Metadata.kind Source: https://docs.nvidia.com/cuda/nvimagecodec/py_api.html Gets the kind of metadata. ```APIDOC ## Metadata.kind ### Description Property to get the kind of metadata. ### Returns The metadata kind (e.g. EXIF, GEO, medical formats). ``` -------------------------------- ### Create nv_spawn_helpers.py with %%writefile Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/torch_dataloader.html Uses Jupyter's %%writefile magic to create the helper module containing the Dataset, worker_init_fn, and decoder setup. The module defines a per-worker Decoder and handles CUDA cleanup. Restart the kernel after editing this file to avoid stale class definitions. ```python %%writefile nv_spawn_helpers.py """Approach 1 helpers — single-image GPU decode inside ``__getitem__``. Each spawn worker imports this module afresh, so the module-level ``_worker_decoder`` ends up bound to that worker's own CUDA context. """ import atexit from typing import List, Optional import torch from torch.utils.data import Dataset from nvidia import nvimgcodec # Per-worker singleton — one Decoder per worker process. _worker_decoder: Optional[nvimgcodec.Decoder] = None def _release_worker_decoder() -> None: """Drop the per-worker Decoder while CUDA is still alive in this process.""" global _worker_decoder if _worker_decoder is not None: # Drain any in-flight decode work before releasing the Decoder so its # destructor doesn't synchronize against a half-torn-down stream. torch.cuda.synchronize() _worker_decoder = None # Flush the producer-side CUDA IPC limbo so already-acked tensors get # released NOW. Otherwise their CudaIPCSentData entries linger until # process exit and CudaIPCRefCountersFile::~ prints "Producer process # has been terminated before all shared CUDA tensors released". torch.cuda.ipc_collect() def init_nv_worker(worker_id: int) -> None: """``worker_init_fn`` — construct the per-worker Decoder AFTER spawn so it is bound to the worker's own CUDA context, not the parent's.""" global _worker_decoder # Force torch CUDA init NOW so torch's CUDA-shutdown atexit is registered # before ours; LIFO order then guarantees our handler runs first at exit. torch.cuda.init() # Single-image decode: one CPU helper thread is enough; the default # (= num cores per worker) would oversubscribe with NUM_WORKERS spawn procs. _worker_decoder = nvimgcodec.Decoder(max_num_cpu_threads=1) atexit.register(_release_worker_decoder) class NvSingleSpawnDataset(Dataset): """Decode one image per ``__getitem__`` call on the GPU.""" def __init__(self, paths: List[str]): self.paths = paths def __len__(self) -> int: return len(self.paths) def __getitem__(self, idx: int): global _worker_decoder if _worker_decoder is None: # num_workers=0 fallback _worker_decoder = nvimgcodec.Decoder(max_num_cpu_threads=1) img = _worker_decoder.decode(nvimgcodec.CodeStream(self.paths[idx])) if img is None: raise RuntimeError( f"nvImageCodec returned None for {self.paths[idx]!r}. " "Check that the file exists and contains a decodable image." ) # Images are pre-resized on disk; no F.interpolate here. t = torch.as_tensor(img.cuda(), device="cuda").float() / 255.0 t = t.permute(2, 0, 1) # HWC → CHW return t, 0 ``` -------------------------------- ### nvidia.nvimgcodec.Metadata.id Source: https://docs.nvidia.com/cuda/nvimagecodec/py_api.html Gets the ID of the metadata. ```APIDOC ## Metadata.id ### Description Property to get the ID of the metadata. ### Returns The metadata ID. For TIFF tag metadata kind, this is the tag ID. For other metadata kinds, it is reserved for future use. ``` -------------------------------- ### nvidia.nvimgcodec.Backend.__init__ Source: https://docs.nvidia.com/cuda/nvimagecodec/py_api.html Constructs a Backend object. The default constructor initializes with GPU_ONLY backend kind and default parameters. The parameterized constructor allows specifying backend kind, load hint, and load hint policy. ```APIDOC ## Backend.__init__ ### Description Constructs a Backend object. The default constructor initializes with GPU_ONLY backend kind and default parameters. The parameterized constructor allows specifying backend kind, load hint, and load hint policy. ### Method Constructor ### Signature `__init__(self: nvidia.nvimgcodec.nvimgcodec_impl.Backend) -> None` `__init__(self: nvidia.nvimgcodec.nvimgcodec_impl.Backend, backend_kind: nvidia.nvimgcodec.nvimgcodec_impl.BackendKind, load_hint: float = 1.0, load_hint_policy: nvidia.nvimgcodec.nvimgcodec_impl.LoadHintPolicy = ) -> None` ### Parameters - **backend_kind** (BackendKind) - Required - Specifies the type of backend (e.g., GPU_ONLY, CPU_ONLY). - **load_hint** (float) - Optional - Fraction of the batch samples that will be processed by this backend (default is 1.0). This is just a hint for performance balancing, so particular extension can ignore it and work on all images it recognizes. - **load_hint_policy** (LoadHintPolicy) - Optional - Policy for using the load hint, affecting how processing is distributed. ### Returns None ``` -------------------------------- ### nvidia.nvimgcodec.Metadata.format Source: https://docs.nvidia.com/cuda/nvimagecodec/py_api.html Gets the format of the metadata. ```APIDOC ## Metadata.format ### Description Property to get the format of the metadata. ### Returns The metadata format (e.g. RAW, JSON, XML). ``` -------------------------------- ### Prepare input image info for encoding Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/c_samples.html Initializes nvimgcodecImageInfo_t for a planar RGB image with unsigned 8-bit samples stored in host memory. Assumes 3 planes, 1 channel each, and computes pitch and buffer size. ```c nvimgcodecImageInfo_t input_image_info{NVIMGCODEC_STRUCTURE_TYPE_IMAGE_INFO, sizeof(nvimgcodecImageInfo_t), 0}; input_image_info.num_planes = 3; input_image_info.plane_info[0].height = /* TODO assign image height */; input_image_info.plane_info[0].width = /* TODO assign image width */; input_image_info.plane_info[0].num_channels = 1; input_image_info.color_spec = NVIMGCODEC_COLORSPEC_SRGB; input_image_info.sample_format = NVIMGCODEC_SAMPLEFORMAT_P_RGB; input_image_info.chroma_subsampling = NVIMGCODEC_SAMPLING_444; auto sample_type = NVIMGCODEC_SAMPLE_DATA_TYPE_UINT8; // For general case, having sample type, we can calculate bytes per element using formula static_cast(sample_type) >> (8 + 3); // so shift by 8 since 8..15 bits represents type bitdepth, then shift by 3 to convert to # bytes // here we can simple assign 1 as we assumed type is uint8 int bytes_per_element = 1; int pitch_in_bytes = input_image_info.plane_info[0].width * input_image_info.plane_info[0].num_channels * bytes_per_element; size_t buffer_size = 0; for (size_t p = 0; p < input_image_info.num_planes; p++) { input_image_info.plane_info[p].width = input_image_info.plane_info[0].width; input_image_info.plane_info[p].height = input_image_info.plane_info[0].height; input_image_info.plane_info[p].row_stride = pitch_in_bytes; input_image_info.plane_info[p].sample_type = sample_type; input_image_info.plane_info[p].num_channels = input_image_info.plane_info[0].num_channels; input_image_info.plane_info[p].precision = 8; buffer_size += input_image_info.plane_info[p].row_stride * input_image_info.plane_info[0].height; } ``` -------------------------------- ### Region.out_of_bounds_samples Source: https://docs.nvidia.com/cuda/nvimagecodec/py_api.html Property to get the out of bounds samples. ```APIDOC ## Region.out_of_bounds_samples ### Description Property to get the out of bounds samples. ### Returns A list of out of bounds samples. ``` -------------------------------- ### Create nvImageCodec DataLoader and benchmark Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/torch_dataloader.html Sets up a DataLoader using nvImageCodec's collate function and spawn-based workers, then benchmarks it. Output shows 6358 img/s and 5.0 ms/batch. ```python from nv_spawn_collate_helpers import ( CodeStreamDataset, init_nv_collate_worker, nvimgcodec_collate_fn, ) nv_batch_loader = DataLoader( CodeStreamDataset(image_paths), batch_size=BATCH_SIZE, num_workers=NUM_WORKERS, multiprocessing_context='spawn', persistent_workers=True, prefetch_factor=2, worker_init_fn=init_nv_collate_worker, collate_fn=nvimgcodec_collate_fn ) r = benchmark(nv_batch_loader, to_gpu=False) results["nvImageCodec batch decode"] = r print(f"nvImageCodec batch decode: {r['images_per_sec']:.0f} img/s | {r['ms_per_batch']:.1f} ms/batch") ``` ```text nvImageCodec batch decode: 6358 img/s | 5.0 ms/batch ``` -------------------------------- ### Import libraries and define display helper Source: https://docs.nvidia.com/cuda/nvimagecodec/samples/decode_source.html Sets up the environment: imports os, numpy, matplotlib, and nvimgcodec. Defines a display() function to show images in a row with optional titles. ```python import os import numpy as np from matplotlib import pyplot as plt resources_dir = os.getenv("PYNVIMGCODEC_EXAMPLES_RESOURCES_DIR", "../../resources/") img_full_path = os.path.abspath(os.path.join(resources_dir, "jpeg2k/cat-1046544_640.jp2")) from nvidia import nvimgcodec decoder = nvimgcodec.Decoder() def display(images, titles=None, figsize=(10, 4)): num_images = len(images) fig, axes = plt.subplots(1, num_images, figsize=figsize) if num_images == 1: axes = [axes] for i, ax in enumerate(axes): ax.imshow(images[i]) if titles is not None and i < len(titles): ax.set_title(titles[i]) ax.axis('off') plt.tight_layout() plt.show() ```