package core:image
Overview
General 2D image types and procedures to be used with other image related packages.
Index
Types (63)
- BMP_CIEXYZTRIPLE
- BMP_FXPT2DOT30
- BMP_GAMMA16_16
- BMP_Gamut_Mapping_Intent
- BMP_Header
- BMP_Info
- BMP_Logical_Color_Space
- BMP_Magic
- BMP_Version
- Channel
- Exif
- GA_Pixel
- GA_Pixel_16
- G_Pixel
- G_Pixel_16
- General_Image_Error
- Image
- Image_Metadata
- JFIF_APP0
- JFXX_APP0
- JFXX_Extension_Code
- JPEG_Info
- JPEG_Marker
- Loader_Proc
- Netpbm_Error
- Netpbm_Format
- Netpbm_Header
- Netpbm_Header
- Netpbm_Info
- OS2_Header
- OS2_Header
- Option
- Options
- PNG_Chunk
- PNG_Chunk_Header
- PNG_Color_Type
- PNG_Error
- PNG_Error
- PNG_Info
- PNG_Info
- PNG_Interlace_Method
- QOI_Header
- QOI_Info
- QOI_Info
- QOI_Magic
- RGBA_Pixel
- RGBA_Pixel_16
- RGB_Pixel
- RGB_Pixel_16
- RGB_Pixel_16
- TGA_Alpha_Kind
- TGA_Data_Type
- TGA_Extension
- TGA_Footer
- Which_File_Type
- alpha_drop_if_present
- apply_palette
- destroy
- expand_grayscale
- which
- which_file
- write_bytes
- write_bytes
Constants (4)
Variables (3)
Procedures (24)
- BMP_Compression
- BMP_FXPT2DOT30
- GA_Pixel
- GA_Pixel
- JFXX_Extension_Code
- QOI_Error
- alpha_add_if_missing
- alpha_add_if_missing
- alpha_apply_keyed_alpha
- alpha_drop_if_present
- apply_palette
- apply_palette_rgb
- blend_single_channel
- destroy
- expand_grayscale
- load_from_bytes
- load_from_file
- premultiply_alpha
- read_data
- read_u8
- register
- return_single_channel
- which_bytes
- which_file
Procedure Groups (4)
Types
BMP_CIEXYZTRIPLE ¶
BMP_CIEXYZTRIPLE :: [3][3]u32le
BMP_FXPT2DOT30 ¶
BMP_FXPT2DOT30 :: u32le
BMP_GAMMA16_16 ¶
BMP_GAMMA16_16 :: [2]u16le
BMP_Gamut_Mapping_Intent ¶
BMP_Gamut_Mapping_Intent :: enum u32le { INVALID = 0, // If not V5, this field will just be zero-initialized and not valid. ABS_COLORIMETRIC = 8, BUSINESS = 1, GRAPHICS = 2, IMAGES = 4, }
BMP_Header ¶
BMP_Header :: struct #packed { // File header magic: BMP_Magic, size: u32le, _res1: u16le, // Reserved; must be zero _res2: u16le, // Reserved; must be zero pixel_offset: u32le, // V3 info_size: BMP_Version, width: i32le, height: i32le, planes: u16le, bpp: u16le, compression: BMP_Compression, image_size: u32le, pels_per_meter: [2]u32le, colors_used: u32le, colors_important: u32le, // V4 masks: [4]u32le `fmt:"32b"`, colorspace: BMP_Logical_Color_Space, endpoints: [3][3]u32le, gamma: [3][2]u16le, // V5 intent: BMP_Gamut_Mapping_Intent, profile_data: u32le, profile_size: u32le, reserved: u32le, }
BMP_Info ¶
BMP_Info :: struct { info: BMP_Header, }
img.metadata is wrapped in a struct in case we need to add to it later without putting it in BMP_Header
BMP_Logical_Color_Space ¶
BMP_Logical_Color_Space :: enum u32le { CALIBRATED_RGB = 0, sRGB = 1934772034, // 'sRGB' WINDOWS_COLOR_SPACE = 1466527264, // 'Win ' }
BMP_Magic ¶
BMP_Magic :: enum u16le { Bitmap = 19778, // 'BM' OS2_Bitmap_Array = 16706, // 'BA' OS2_Icon = 17225, // 'IC', OS2_Color_Icon = 18755, // 'CI' OS2_Pointer = 21584, // 'PT' OS2_Color_Pointer = 20547, // 'CP' }
BMP_Version ¶
BMP_Version :: enum u32le { OS2_v1 = 12, // BITMAPCOREHEADER (Windows V2 / OS/2 version 1.0) OS2_v2 = 64, // BITMAPCOREHEADER2 (OS/2 version 2.x) V3 = 40, // BITMAPINFOHEADER V4 = 108, // BITMAPV4HEADER V5 = 124, // BITMAPV5HEADER ABBR_16 = 16, // Abbreviated ABBR_24 = 24, // .. ABBR_48 = 48, // .. ABBR_52 = 52, // .. ABBR_56 = 56, // .. }
See: http://justsolve.archiveteam.org/wiki/BMP#Well-known_versions
GA_Pixel ¶
GA_Pixel :: [2]u8
GA_Pixel_16 ¶
GA_Pixel_16 :: [2]u16
G_Pixel_16 ¶
G_Pixel_16 :: [1]u16
General_Image_Error ¶
General_Image_Error :: enum int { None = 0, Unsupported_Option, // File I/O Unable_To_Read_File, Unable_To_Write_File, // Invalid Unsupported_Format, Invalid_Signature, Invalid_Input_Image, Image_Dimensions_Too_Large, Invalid_Image_Dimensions, Invalid_Number_Of_Channels, Image_Does_Not_Adhere_to_Spec, Invalid_Image_Depth, Invalid_Bit_Depth, Invalid_Color_Space, // More data than pixels to decode into, for example. Corrupt, // Output buffer is the wrong size Invalid_Output, // Allocation Unable_To_Allocate_Or_Resize, }
Image ¶
Image :: struct { width: int, height: int, channels: int, depth: int, // Channel depth in bits, typically 8 or 16 pixels: bytes.Buffer `fmt:"-"`, // Some image loaders/writers can return/take an optional background color. // For convenience, we return them as u16 so we don't need to switch on the type // in our viewer, and can just test against nil. background: runtime.Maybe($T=[3]u16), metadata: Image_Metadata, which: Which_File_Type, }
Related Procedures With Parameters
Related Procedures With Returns
- load_from_bytes
- load_from_file
- pixels_to_image
- load (procedure groups)
JFXX_APP0 ¶
JFXX_APP0 :: struct { extension_code: JFXX_Extension_Code, x_thumbnail: u8, y_thumbnail: u8, thumbnail: []u8 `fmt:"-"`, }
JFXX_Extension_Code ¶
JFXX_Extension_Code :: PNG_IHDR
JPEG_Info ¶
JPEG_Info :: struct { jfif_app0: runtime.Maybe($T=JFIF_APP0), jfxx_app0: runtime.Maybe($T=JFXX_APP0), comments: [dynamic]string, exif: [dynamic]Exif, frame_type: JPEG_Marker, }
JPEG_Marker ¶
JPEG_Marker :: enum u8 { SOF0 = 192, // Baseline sequential DCT SOF1 = 193, // Extended sequential DCT SOF2 = 194, // Progressive DCT SOF3 = 195, // Lossless (sequential) SOF5 = 197, // Differential sequential DCT SOF6 = 198, // Differential progressive DCT SOF7 = 199, // Differential lossless (sequential) SOF9 = 201, // Extended sequential DCT, Arithmetic coding SOF10 = 202, // Progressive DCT, Arithmetic coding SOF11 = 203, // Lossless (sequential), Arithmetic coding SOF13 = 205, // Differential sequential DCT, Arithmetic coding SOF14 = 206, // Differential progressive DCT, Arithmetic coding SOF15 = 207, // Differential lossless (sequential), Arithmetic coding DHT = 196, JPG = 200, DAC = 204, RST0 = 208, RST1 = 209, RST2 = 210, RST3 = 211, RST4 = 212, RST5 = 213, RST6 = 214, RST7 = 215, SOI = 216, EOI = 217, SOS = 218, DQT = 219, DNL = 220, DRI = 221, DHP = 222, EXP = 223, APP0 = 224, APP1 = 225, APP2 = 226, APP3 = 227, APP4 = 228, APP5 = 229, APP6 = 230, APP7 = 231, APP8 = 232, APP9 = 233, APP10 = 234, APP11 = 235, APP12 = 236, APP13 = 237, APP14 = 238, APP15 = 239, JPG0 = 240, JPG1 = 241, JPG2 = 242, JPG3 = 243, JPG4 = 244, JPG5 = 245, JPG6 = 246, JPG7 = 247, JPG8 = 248, JPG9 = 249, JPG10 = 250, JPG11 = 251, JPG12 = 252, JPG13 = 253, COM = 254, TEM = 1, }
Loader_Proc ¶
Loader_Proc :: proc(data: []u8, options: Options, allocator: runtime.Allocator) -> (img: ^Image, err: Error)
Related Procedures With Parameters
Netpbm_Error ¶
Netpbm_Error :: enum int { None = 0, // reading Invalid_Header_Token_Character, Incomplete_Header, Invalid_Header_Value, Duplicate_Header_Field, Buffer_Too_Small, Invalid_Buffer_ASCII_Token, Invalid_Buffer_Value, // writing Invalid_Format, }
Netpbm_Format ¶
Netpbm_Format :: enum int { P1, P2, P3, P4, P5, P6, P7, Pf, PF, }
Netpbm-specific definitions
Netpbm_Info ¶
Netpbm_Info :: struct { header: Netpbm_Header, }
OS2_Header ¶
OS2_Header :: BMP_Compression
Option ¶
Option :: enum int { // LOAD OPTIONS info = 0, do_not_decompress_image, return_header, return_metadata, alpha_add_if_missing, // Ignored for QOI. Always returns RGBA8. alpha_drop_if_present, // Unimplemented for QOI. Returns error. alpha_premultiply, // Unimplemented for QOI. Returns error. blend_background, // Ignored for non-PNG formats // Unimplemented do_not_expand_grayscale, do_not_expand_indexed, do_not_expand_channels, // SAVE OPTIONS qoi_all_channels_linear, // QOI, informative only. If not set, defaults to sRGB with linear alpha. }
Options ¶
Options :: PNG_Color_Value
PNG_Chunk ¶
PNG_Chunk :: struct #packed { header: PNG_Chunk_Header, data: []u8, crc: u32be, }
PNG_Chunk_Header ¶
PNG_Chunk_Header :: struct #packed { length: u32be, type: PNG_Chunk_Type, }
PNG_Color_Type ¶
PNG_Color_Type :: distinct bit_set[PNG_Color_Value; u8]
PNG_Error ¶
PNG_Error :: enum int { None = 0, IHDR_Not_First_Chunk, IHDR_Corrupt, IDAT_Missing, IDAT_Must_Be_Contiguous, IDAT_Corrupt, IDAT_Size_Too_Large, PLTE_Encountered_Unexpectedly, PLTE_Invalid_Length, PLTE_Missing, TRNS_Encountered_Unexpectedly, TNRS_Invalid_Length, BKGD_Invalid_Length, Unknown_Color_Type, Invalid_Color_Bit_Depth_Combo, Unknown_Filter_Method, Unknown_Interlace_Method, Requested_Channel_Not_Present, Post_Processing_Error, Invalid_Chunk_Length, }
PNG-specific definitions
PNG_Error ¶
PNG_Error :: TGA_Header
PNG_Info ¶
PNG_Info :: JFXX_Extension_Code
PNG_Interlace_Method ¶
PNG_Interlace_Method :: enum u8 { None = 0, Adam7 = 1, }
QOI_Header ¶
QOI_Header :: struct #packed { magic: u32be, width: u32be, height: u32be, channels: u8, color_space: QOI_Color_Space, }
QOI_Info ¶
QOI_Info :: struct { header: QOI_Header, }
QOI_Info ¶
QOI_Info :: JFIF_Unit
QOI_Magic ¶
QOI_Magic :: TGA_Info
RGBA_Pixel ¶
RGBA_Pixel :: [4]u8
RGBA_Pixel_16 ¶
RGBA_Pixel_16 :: [4]u16
RGB_Pixel_16 ¶
RGB_Pixel_16 :: PNG_Chunk_Type
RGB_Pixel_16 ¶
RGB_Pixel_16 :: [3]u16
TGA_Alpha_Kind ¶
TGA_Alpha_Kind :: enum u8 { None, Undefined_Ignore, Undefined_Retain, Useful, Premultiplied, }
TGA_Data_Type ¶
TGA_Data_Type :: enum u8 { No_Image_Data = 0, Uncompressed_Color_Mapped = 1, Uncompressed_RGB = 2, Uncompressed_Black_White = 3, Compressed_Color_Mapped = 9, Compressed_RGB = 10, Compressed_Black_White = 11, }
TGA_Extension ¶
TGA_Extension :: struct #packed { extension_size: u16le, // Size of this struct. If not 495 bytes it means it's an unsupported version. author_name: [41]u8 `fmt:"s,0"`, // Author name, ASCII. Zero-terminated author_comments: [324]u8 `fmt:"s,0"`, // Author comments, formatted as 4 lines of 80 character lines, each zero terminated. datetime: struct { month: u16le, day: u16le, year: u16le, hour: u16le, minute: u16le, second: u16le, }, job_name: [41]u8 `fmt:"s,0"`, // Author name, ASCII. Zero-terminated job_time: struct { hour: u16le, minute: u16le, second: u16le, }, software_id: [41]u8 `fmt:"s,0"`, // Software ID name, ASCII. Zero-terminated software_version: struct #packed { number: u16le, // Version number * 100 letter: u8 `fmt:"r"`, }, key_color: [4]u8, // ARGB key color used at time of production aspect_ratio: [2]u16le, // Numerator / Denominator gamma: [2]u16le, // Numerator / Denominator, range should be 0.0..10.0 color_correction_offset: u32le, // 0 if no color correction information postage_stamp_offset: u32le, // 0 if no thumbnail scanline_offset: u32le, // 0 if no scanline table attributes: TGA_Alpha_Kind, }
Which_File_Type ¶
Which_File_Type :: enum int { Unknown, BMP, DjVu, // AT&T DjVu file format EXR, FLIF, GIF, HDR, // Radiance RGBE HDR ICNS, // Apple Icon Image JPEG, JPEG_2000, JPEG_XL, NetPBM, // NetPBM family PIC, // Softimage PIC PNG, // Portable Network Graphics PSD, // Photoshop PSD QOI, // Quite Okay Image SGI_RGB, // Silicon Graphics Image RGB file format Sun_Rast, // Sun Raster Graphic TGA, // Targa Truevision TIFF, // Tagged Image File Format WebP, XBM, // X BitMap }
Related Procedures With Parameters
Related Procedures With Returns
- which_bytes
- which_file
- which (procedure groups)
apply_palette ¶
apply_palette :: QOI_Color_Space
destroy ¶
destroy :: Options
Related Procedures With Parameters
- alpha_drop_if_present
- load_from_bytes
- load_from_file
- load (procedure groups)
expand_grayscale ¶
expand_grayscale :: BMP_CIEXYZ
which ¶
which :: JPEG_Error
write_bytes ¶
write_bytes :: Error
Related Procedures With Returns
- load_from_bytes
- load_from_file
- load (procedure groups)
Constants
MAX_DIMENSIONS ¶
MAX_DIMENSIONS :: min(#config(MAX_DIMENSIONS, 8192 * 8192), 65535 * 65535)
67_108_864 pixels max by default.
For QOI, the Worst case scenario means all pixels will be encoded as RGBA literals, costing 5 bytes each. This caps memory usage at 320 MiB.
The tunable is limited to 4_294_836_225 pixels maximum, or 4 GiB per 8-bit channel. It is not advised to tune it this large.
The 64 Megapixel default is considered to be a decent upper bound you won't run into in practice, except in very specific circumstances.
MAX_DIMENSIONS ¶
MAX_DIMENSIONS :: New_TGA_Signature
PNG_IHDR_SIZE ¶
PNG_IHDR_SIZE :: size_of(PNG_IHDR)
Variables
Procedures
BMP_Compression ¶
BMP_Compression :: alpha_add_if_missing
Add alpha channel if missing, in-place.
Expects 1..4 channels (Gray, Gray + Alpha, RGB, RGBA).
Any other number of channels will be considered an error, returning false without modifying the image.
If the input image already has an alpha channel, it'll return true early (without considering optional keyed alpha).
If an image doesn't already have an alpha channel:
If the optional alpha_key is provided, it will be resolved as follows:
- For RGB, if pix = key.rgb -> pix = {0, 0, 0, key.a}
- For Gray, if pix = key.r -> pix = {0, key.g}
Otherwise, an opaque alpha channel will be added.
BMP_FXPT2DOT30 ¶
BMP_FXPT2DOT30 :: alpha_drop_if_present
Drop alpha channel if present, in-place.
Expects 1..4 channels (Gray, Gray + Alpha, RGB, RGBA).
Any other number of channels will be considered an error, returning false without modifying the image.
Of the options, the following are considered:
.alpha_premultiply
If the image has an alpha channel, returns image data as follows: RGB *= A, Gray = Gray *= A
.blend_background
If `img.background` is set, it'll be blended in like this: RGB = (1 - A) * Background + A * RGB
If an image has 1 (Gray) or 3 (RGB) channels, it'll return early without modifying the image,
with one exception: alpha_key and img.background are present, and .blend_background is set.
In this case a keyed alpha pixel will be replaced with the background color.
GA_Pixel ¶
GA_Pixel :: is_valid_grayscale_image
Does the image have 1 or 2 channels, a valid bit depth (8 or 16), Is the pointer valid, are the dimensions valid?
GA_Pixel ¶
GA_Pixel :: pixels_to_image
Take a slice of pixels ([]RGBA_Pixel, etc), and return an Image
Don't call destroy on the resulting Image. Instead, delete the original pixels slice.
JFXX_Extension_Code ¶
JFXX_Extension_Code :: is_valid_color_image
Does the image have 3 or 4 channels, a valid bit depth (8 or 16), Is the pointer valid, are the dimensions valid?
QOI_Error ¶
QOI_Error :: apply_palette_rgba
Apply palette to 8-bit single-channel image and return an 8-bit RGBA image, in-place.
If the image given is not a valid 8-bit single channel image, the procedure will return false early.
Related Procedure Groups
alpha_add_if_missing ¶
alpha_add_if_missing :: proc(img: ^Image, alpha_key: Alpha_Key = Alpha_Key{}, allocator := context.allocator) -> (ok: bool) {…}
Add alpha channel if missing, in-place.
Expects 1..4 channels (Gray, Gray + Alpha, RGB, RGBA).
Any other number of channels will be considered an error, returning false without modifying the image.
If the input image already has an alpha channel, it'll return true early (without considering optional keyed alpha).
If an image doesn't already have an alpha channel:
If the optional alpha_key is provided, it will be resolved as follows:
- For RGB, if pix = key.rgb -> pix = {0, 0, 0, key.a}
- For Gray, if pix = key.r -> pix = {0, key.g}
Otherwise, an opaque alpha channel will be added.
alpha_add_if_missing ¶
alpha_add_if_missing :: write_bytes
alpha_drop_if_present ¶
alpha_drop_if_present :: is_valid_image
Does the image have 1..4 channels, a valid bit depth (8 or 16), Is the pointer valid, are the dimensions valid?
apply_palette ¶
apply_palette :: expand_grayscale
Replicates grayscale values into RGB(A) 8- or 16-bit images as appropriate.
Returns early with false if already an RGB(A) image.
apply_palette_rgb ¶
apply_palette_rgb :: proc(img: ^Image, palette: [256][3]u8, allocator := context.allocator) -> (ok: bool) {…}
Apply palette to 8-bit single-channel image and return an 8-bit RGB image, in-place.
If the image given is not a valid 8-bit single channel image, the procedure will return false early.
Related Procedure Groups
blend_single_channel ¶
blend_single_channel :: proc(fg, alpha, bg: $T) -> (res: $$deferred_return) {…}
Related Procedure Groups
destroy ¶
destroy :: proc(img: ^Image, allocator := context.allocator) {…}
expand_grayscale ¶
expand_grayscale :: compute_buffer_size
Function to help with image buffer calculations
load_from_bytes ¶
load_from_bytes :: proc(data: []u8, options: Options = Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) {…}
Related Procedure Groups
load_from_file ¶
load_from_file :: proc(filename: string, options: Options = Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) {…}
Related Procedure Groups
premultiply_alpha ¶
For all pixels of the image, multiplies R, G and B by Alpha. This is useful mainly for games rendering anti-aliased transparent sprites. Grayscale with alpha images are supported as well. Note that some image formats like QOI explicitly do NOT support premultiplied alpha, so you will end up with a non-standard file.
read_data ¶
read_data :: proc(z: $C, $T: typeid) -> (res: typeid, err: compress.General_Error) {…}
Helper functions to read and write data from/to a Context, etc.
read_u8 ¶
read_u8 :: proc(z: $C) -> (res: u8, err: compress.General_Error) {…}
register ¶
register :: proc "contextless" (kind: Which_File_Type, loader: Loader_Proc, destroyer: Destroy_Proc) {…}
return_single_channel ¶
When you have an RGB(A) image, but want a particular channel.
Procedure Groups
blend ¶
blend :: proc{ blend_single_channel, blend_pixel, }
load ¶
load :: proc{ load_from_bytes, load_from_file, }
pixels_to_image ¶
pixels_to_image :: apply_palette
which ¶
which :: proc{ which_bytes, which_file, }
Source Files
Generation Information
Generated with odin version dev-2026-03 (vendor "odin") Windows_amd64 @ 2026-03-16 21:30:53.962440200 +0000 UTC