package core:image
Overview
package image implements a general 2D image library to be used with other image related packages
Index
Types (55)
- Alpha_Key
- BMP_CIEXYZ
- BMP_CIEXYZTRIPLE
- BMP_Compression
- BMP_Error
- BMP_FXPT2DOT30
- BMP_GAMMA16_16
- BMP_Gamut_Mapping_Intent
- BMP_Header
- BMP_Info
- BMP_Logical_Color_Space
- BMP_Magic
- BMP_Version
- Channel
- Destroy_Proc
- Error
- GA_Pixel
- GA_Pixel_16
- G_Pixel
- G_Pixel_16
- General_Image_Error
- Image
- Image_Metadata
- Loader_Proc
- Netpbm_Error
- Netpbm_Format
- Netpbm_Header
- Netpbm_Info
- OS2_Header
- Option
- Options
- PNG_Chunk
- PNG_Chunk_Header
- PNG_Chunk_Type
- PNG_Color_Type
- PNG_Color_Value
- PNG_Error
- PNG_IHDR
- PNG_Info
- PNG_Interlace_Method
- QOI_Color_Space
- QOI_Error
- QOI_Header
- QOI_Info
- RGBA_Pixel
- RGBA_Pixel_16
- RGB_Pixel
- RGB_Pixel_16
- TGA_Alpha_Kind
- TGA_Data_Type
- TGA_Extension
- TGA_Footer
- TGA_Header
- TGA_Info
- Which_File_Type
Constants (4)
Variables (0)
This section is empty.
Procedures (24)
- alpha_add_if_missing
- alpha_apply_keyed_alpha
- alpha_drop_if_present
- apply_palette_rgb
- apply_palette_rgba
- blend_pixel
- blend_single_channel
- compute_buffer_size
- destroy
- expand_grayscale
- is_valid_color_image
- is_valid_grayscale_image
- is_valid_image
- load_from_bytes
- load_from_file
- pixels_to_image
- premultiply_alpha
- read_data
- read_u8
- register
- return_single_channel
- which_bytes
- which_file
- write_bytes
Procedure Groups (4)
Types
Alpha_Key ¶
Related Procedures With Parameters
BMP_CIEXYZ ¶
BMP_CIEXYZ :: [3]u32le
BMP_CIEXYZTRIPLE ¶
BMP_CIEXYZTRIPLE :: [3][3]u32le
BMP_Compression ¶
BMP_Compression :: enum u32le { RGB = 0, RLE8 = 1, RLE4 = 2, Bit_Fields = 3, // If Windows Huffman1D = 3, // If OS2v2 JPEG = 4, // If Windows RLE24 = 4, // If OS2v2 PNG = 5, Alpha_Bit_Fields = 6, CMYK = 11, CMYK_RLE8 = 12, CMYK_RLE4 = 13, }
BMP_Error ¶
BMP_Error :: enum int { None = 0, Invalid_File_Size, Unsupported_BMP_Version, Unsupported_OS2_File, Unsupported_Compression, Unsupported_BPP, Invalid_Stride, Invalid_Color_Count, Implausible_File_Size, Bitfield_Version_Unhandled, // We don't (yet) handle bit fields for this BMP version. Bitfield_Sum_Exceeds_BPP, // Total mask bit count > bpp Bitfield_Overlapped, // Channel masks overlap }
BMP-specific
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
Error ¶
Error :: union { General_Image_Error, Netpbm_Error, PNG_Error, QOI_Error, BMP_Error, compress.Error, compress.General_Error, compress.Deflate_Error, compress.ZLIB_Error, io.Error, runtime.Allocator_Error, }
Related Procedures With Returns
- load_from_bytes
- load_from_file
- load (procedure groups)
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
- alpha_add_if_missing
- alpha_drop_if_present
- apply_palette_rgb
- apply_palette_rgba
- destroy
- expand_grayscale
- is_valid_color_image
- is_valid_grayscale_image
- is_valid_image
- premultiply_alpha
- return_single_channel
- apply_palette (procedure groups)
Related Procedures With Returns
- load_from_bytes
- load_from_file
- pixels_to_image
- load (procedure groups)
Image_Metadata ¶
Image_Metadata :: union { ^Netpbm_Info, ^PNG_Info, ^QOI_Info, ^TGA_Info, ^BMP_Info, }
Loader_Proc ¶
Loader_Proc :: proc(data: []u8, options: Options = Options{}, allocator := context.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, }
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 :: distinct bit_set[Option]
Related Procedures With Parameters
- alpha_drop_if_present
- load_from_bytes
- load_from_file
- load (procedure groups)
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_Chunk_Type ¶
PNG_Chunk_Type :: enum u32be { // IHDR must come first in a file IHDR = 1229472850, // PLTE must precede the first IDAT chunk PLTE = 1347179589, bKGD = 1649100612, tRNS = 1951551059, IDAT = 1229209940, iTXt = 1767135348, tEXt = 1950701684, zTXt = 2052348020, iCCP = 1766015824, pHYs = 1883789683, gAMA = 1732332865, tIME = 1950960965, sPLT = 1934642260, sRGB = 1934772034, hIST = 1749635924, cHRM = 1665684045, sBIT = 1933723988, // eXIf tags are not part of the core spec, but have been ratified // in v1.5.0 of the PNG Ext register. // // We will provide unprocessed chunks to the caller if `.return_metadata` is set. // Applications are free to implement an Exif decoder. eXIf = 1700284774, // PNG files must end with IEND IEND = 1229278788, // XCode sometimes produces "PNG" files that don't adhere to the PNG spec. // We recognize them only in order to avoid doing further work on them. // // Some tools like PNG Defry may be able to repair them, but we're not // going to reward Apple for producing proprietary broken files purporting // to be PNGs by supporting them. iDOT = 1766084436, CgBI = 1130840649, }
PNG_Color_Type ¶
PNG_Color_Type :: distinct bit_set[PNG_Color_Value; u8]
PNG_Color_Value ¶
PNG_Color_Value :: enum u8 { Paletted = 0, // 1 << 0 = 1 Color = 1, // 1 << 1 = 2 Alpha = 2, // 1 << 2 = 4 }
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_IHDR ¶
PNG_IHDR :: struct #packed { width: u32be, height: u32be, bit_depth: u8, color_type: PNG_Color_Type, compression_method: u8, filter_method: u8, interlace_method: PNG_Interlace_Method, }
PNG_Interlace_Method ¶
PNG_Interlace_Method :: enum u8 { None = 0, Adam7 = 1, }
QOI_Color_Space ¶
QOI_Color_Space :: enum u8 { sRGB = 0, Linear = 1, }
QOI_Error ¶
QOI_Error :: enum int { None = 0, Missing_Or_Corrupt_Trailer, // Image seemed to have decoded okay, but trailer is missing or corrupt. }
QOI-specific definitions
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, }
RGBA_Pixel ¶
RGBA_Pixel :: [4]u8
RGBA_Pixel_16 ¶
RGBA_Pixel_16 :: [4]u16
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, }
TGA_Info ¶
TGA_Info :: struct { header: TGA_Header, image_id: string, footer: runtime.Maybe($T=TGA_Footer), extension: runtime.Maybe($T=TGA_Extension), }
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)
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.
New_TGA_Signature ¶
New_TGA_Signature :: "TRUEVISION-XFILE.\x00"
PNG_IHDR_SIZE ¶
PNG_IHDR_SIZE :: size_of(PNG_IHDR)
Variables
This section is empty.
Procedures
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_apply_keyed_alpha ¶
alpha_apply_keyed_alpha :: 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.
alpha_drop_if_present ¶
alpha_drop_if_present :: proc(img: ^Image, options: Options = Options{}, alpha_key: Alpha_Key = Alpha_Key{}, allocator := context.allocator) -> (ok: bool) {…}
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.
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.
apply_palette_rgba ¶
apply_palette_rgba :: proc(img: ^Image, palette: [256][4]u8, allocator := context.allocator) -> (ok: bool) {…}
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.
blend_pixel ¶
blend_pixel :: proc(fg: [0]$T, alpha: $T, bg: [0]$T) -> (res: [0]$T) {…}
blend_single_channel ¶
blend_single_channel :: proc(fg, alpha, bg: $T) -> (res: $T) {…}
compute_buffer_size ¶
compute_buffer_size :: proc(width, height, channels, depth: int, extra_row_bytes: int = int(0)) -> (size: int) {…}
Function to help with image buffer calculations
destroy ¶
destroy :: proc(img: ^Image, allocator := context.allocator) {…}
expand_grayscale ¶
expand_grayscale :: proc(img: ^Image, allocator := context.allocator) -> (ok: bool) {…}
Replicates grayscale values into RGB(A) 8- or 16-bit images as appropriate.
Returns early with false
if already an RGB(A) image.
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?
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?
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?
load_from_bytes ¶
load_from_bytes :: proc(data: []u8, options: Options = Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) {…}
load_from_file ¶
load_from_file :: proc(filename: string, options: Options = Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) {…}
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.
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: $T, $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: $T) -> (res: u8, err: compress.General_Error) {…}
register ¶
register :: proc(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.
which_bytes ¶
which_bytes :: proc(data: []u8) -> Which_File_Type {…}
which_file ¶
which_file :: proc(path: string) -> Which_File_Type {…}
write_bytes ¶
write_bytes :: proc(buf: ^bytes.Buffer, data: []u8) -> (err: compress.General_Error) {…}
Procedure Groups
apply_palette ¶
apply_palette :: proc{ apply_palette_rgb, apply_palette_rgba, }
blend ¶
blend :: proc{ blend_single_channel, blend_pixel, }
load ¶
load :: proc{ load_from_bytes, load_from_file, }
which ¶
which :: proc{ which_bytes, which_file, }
Source Files
Generation Information
Generated with odin version dev-2024-12 (vendor "odin") Windows_amd64 @ 2024-12-17 21:11:00.990321300 +0000 UTC