core/image

image

Types

63

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, }Source

BMP_Error

BMP_Error :: enum int { None = 0, Invalid_File_Size = 1, Unsupported_BMP_Version = 2, Unsupported_OS2_File = 3, Unsupported_Compression = 4, Unsupported_BPP = 5, Invalid_Stride = 6, Invalid_Color_Count = 7, Implausible_File_Size = 8, Bitfield_Version_Unhandled = 9, // We don't (yet) handle bit fields for this BMP version. Bitfield_Sum_Exceeds_BPP = 10, // Total mask bit count > bpp Bitfield_Overlapped = 11, // Channel masks overlap }Source

BMP-specific

BMP_Header

BMP_Header :: struct #packed { // File header magic: BMP_Magic, size: u32le, _res1: u16le, _res2: u16le, 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, colorspace: BMP_Logical_Color_Space, endpoints: BMP_CIEXYZTRIPLE, gamma: [3]BMP_GAMMA16_16, // V5 intent: BMP_Gamut_Mapping_Intent, profile_data: u32le, profile_size: u32le, reserved: u32le, }Source

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' }Source

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, // .. }Source

See: http://justsolve.archiveteam.org/wiki/BMP#Well-known_versions

General_Image_Error

General_Image_Error :: enum int { None = 0, Unsupported_Option = 1, // File I/O Unable_To_Read_File = 2, Unable_To_Write_File = 3, // Invalid Unsupported_Format = 4, Invalid_Signature = 5, Invalid_Input_Image = 6, Image_Dimensions_Too_Large = 7, Invalid_Image_Dimensions = 8, Invalid_Number_Of_Channels = 9, Image_Does_Not_Adhere_to_Spec = 10, Invalid_Image_Depth = 11, Invalid_Bit_Depth = 12, Invalid_Color_Space = 13, // More data than pixels to decode into, for example. Corrupt = 14, // Output buffer is the wrong size Invalid_Output = 15, // Allocation Unable_To_Allocate_Or_Resize = 16, }Source

Image

Image :: struct { width: int, height: int, channels: int, depth: int, pixels: bytes.Buffer, // 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: Maybe(RGB_Pixel_16), metadata: Image_Metadata, which: Which_File_Type, }Source

JPEG_Error

JPEG_Error :: enum int { None = 0, Duplicate_SOI_Marker = 1, Invalid_JFXX_Extension_Code = 2, Encountered_SOS_Before_SOF = 3, Invalid_Quantization_Table_Precision = 4, Invalid_Quantization_Table_Index = 5, Invalid_Huffman_Coefficient_Type = 6, Invalid_Huffman_Table_Index = 7, Unsupported_Frame_Type = 8, Invalid_Frame_Bit_Depth_Combo = 9, Invalid_Sampling_Factor = 10, Unsupported_12_Bit_Depth = 11, Multiple_SOS_Markers = 12, Encountered_RST_Marker_Outside_ECS = 13, Extra_Data_After_SOS = 14, // Image seemed to have decoded okay, but there's more data after SOS Invalid_Thumbnail_Size = 15, Huffman_Symbols_Exceeds_Max = 16, }Source

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, }Source

Netpbm_Error

Netpbm_Error :: enum int { None = 0, // reading Invalid_Header_Token_Character = 1, Incomplete_Header = 2, Invalid_Header_Value = 3, Duplicate_Header_Field = 4, Buffer_Too_Small = 5, Invalid_Buffer_ASCII_Token = 6, Invalid_Buffer_Value = 7, // writing Invalid_Format = 8, }Source

Option

Option :: enum int { // LOAD OPTIONS info = 0, do_not_decompress_image = 1, return_header = 2, return_metadata = 3, alpha_add_if_missing = 4, // Ignored for QOI. Always returns RGBA8. alpha_drop_if_present = 5, // Unimplemented for QOI. Returns error. alpha_premultiply = 6, // Unimplemented for QOI. Returns error. blend_background = 7, // Ignored for non-PNG formats // Unimplemented do_not_expand_grayscale = 8, do_not_expand_indexed = 9, do_not_expand_channels = 10, // SAVE OPTIONS qoi_all_channels_linear = 11, // QOI, informative only. If not set, defaults to sRGB with linear alpha. }Source

IMPORTANT: .do_not_expand_* options currently skip handling of the alpha_* options,

	therefore Gray+Alpha will be returned as such even if you add `.alpha_drop_if_present`,
		and `.alpha_add_if_missing` and keyed transparency will likewise be ignored.

		The same goes for indexed images. This will be remedied in a near future update.
Image_Option:
	`.info`
		This option behaves as `.return_metadata` and `.do_not_decompress_image` and can be used
		to gather an image's dimensions and color information.

	`.return_header`
		Fill out img.metadata.header with the image's format-specific header struct.
		If we only care about the image specs, we can set `.return_header` +
		`.do_not_decompress_image`, or `.info`.

	`.return_metadata`
		Returns all chunks not needed to decode the data.
		It also returns the header as if `.return_header` was set.

	`.do_not_decompress_image`
		Skip decompressing IDAT chunk, defiltering and the rest.

	`.do_not_expand_grayscale`
		Do not turn grayscale (+ Alpha) images into RGB(A).
		Returns just the 1 or 2 channels present, although 1, 2 and 4 bit are still scaled to 8-bit.

	`.do_not_expand_indexed`
		Do not turn indexed (+ Alpha) images into RGB(A).
		Returns just the 1 or 2 (with `tRNS`) channels present.
		Make sure to use `return_metadata` to also return the palette chunk so you can recolor it yourself.

	`.do_not_expand_channels`
		Applies both `.do_not_expand_grayscale` and `.do_not_expand_indexed`.

	`.alpha_add_if_missing`
		If the image has no alpha channel, it'll add one set to max(type).
		Turns RGB into RGBA and Gray into Gray+Alpha

	`.alpha_drop_if_present`
		If the image has an alpha channel, drop it.
		You may want to use `.alpha_premultiply` in this case.

		NOTE: For PNG, this also skips handling of the tRNS chunk, if present,
		unless you select `alpha_premultiply`.
		In this case it'll premultiply the specified pixels in question only,
		as the others are implicitly fully opaque.	

	`.alpha_premultiply`
		If the image has an alpha channel, returns image data as follows:
			RGB *= A, Gray = Gray *= A

	`.blend_background`
		If a bKGD chunk is present in a PNG, we normally just set `img.background`
		with its value and leave it up to the application to decide how to display the image,
		as per the PNG specification.

		With `.blend_background` selected, we blend the image against the background
		color. As this negates the use for an alpha channel, we'll drop it _unless_
		you also specify `.alpha_add_if_missing`.

	Options that don't apply to an image format will be ignored by their loader.

PNG_Chunk_Type

PNG_Chunk_Type :: enum u32be { // IHDR must come first in a file IHDR = 'I' << 24 | 'H' << 16 | 'D' << 8 | 'R', // PLTE must precede the first IDAT chunk PLTE = 'P' << 24 | 'L' << 16 | 'T' << 8 | 'E', bKGD = 'b' << 24 | 'K' << 16 | 'G' << 8 | 'D', tRNS = 't' << 24 | 'R' << 16 | 'N' << 8 | 'S', IDAT = 'I' << 24 | 'D' << 16 | 'A' << 8 | 'T', iTXt = 'i' << 24 | 'T' << 16 | 'X' << 8 | 't', tEXt = 't' << 24 | 'E' << 16 | 'X' << 8 | 't', zTXt = 'z' << 24 | 'T' << 16 | 'X' << 8 | 't', iCCP = 'i' << 24 | 'C' << 16 | 'C' << 8 | 'P', pHYs = 'p' << 24 | 'H' << 16 | 'Y' << 8 | 's', gAMA = 'g' << 24 | 'A' << 16 | 'M' << 8 | 'A', tIME = 't' << 24 | 'I' << 16 | 'M' << 8 | 'E', sPLT = 's' << 24 | 'P' << 16 | 'L' << 8 | 'T', sRGB = 's' << 24 | 'R' << 16 | 'G' << 8 | 'B', hIST = 'h' << 24 | 'I' << 16 | 'S' << 8 | 'T', cHRM = 'c' << 24 | 'H' << 16 | 'R' << 8 | 'M', sBIT = 's' << 24 | 'B' << 16 | 'I' << 8 | 'T', // 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 = 'e' << 24 | 'X' << 16 | 'I' << 8 | 'f', // PNG files must end with IEND IEND = 'I' << 24 | 'E' << 16 | 'N' << 8 | 'D', // 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 = 'i' << 24 | 'D' << 16 | 'O' << 8 | 'T', CgBI = 'C' << 24 | 'g' << 16 | 'B' << 8 | 'I', }Source

PNG_Error

PNG_Error :: enum int { None = 0, IHDR_Not_First_Chunk = 1, IHDR_Corrupt = 2, IDAT_Missing = 3, IDAT_Must_Be_Contiguous = 4, IDAT_Corrupt = 5, IDAT_Size_Too_Large = 6, PLTE_Encountered_Unexpectedly = 7, PLTE_Invalid_Length = 8, PLTE_Missing = 9, TRNS_Encountered_Unexpectedly = 10, TNRS_Invalid_Length = 11, BKGD_Invalid_Length = 12, Unknown_Color_Type = 13, Invalid_Color_Bit_Depth_Combo = 14, Unknown_Filter_Method = 15, Unknown_Interlace_Method = 16, Requested_Channel_Not_Present = 17, Post_Processing_Error = 18, Invalid_Chunk_Length = 19, }Source

PNG-specific definitions

QOI_Error

QOI_Error :: enum int { None = 0, Missing_Or_Corrupt_Trailer = 1, // Image seemed to have decoded okay, but trailer is missing or corrupt. }Source

QOI-specific definitions

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, }Source

TGA_Extension

TGA_Extension :: struct #packed { extension_size: u16le, author_name: [41]u8, author_comments: [324]u8, datetime: struct { month: u16le, day: u16le, year: u16le, hour: u16le, minute: u16le, second: u16le, }, job_name: [41]u8, job_time: struct { hour: u16le, minute: u16le, second: u16le, }, software_id: [41]u8, software_version: struct #packed { number: u16le, letter: u8, }, key_color: [4]u8, aspect_ratio: [2]u16le, gamma: [2]u16le, color_correction_offset: u32le, postage_stamp_offset: u32le, scanline_offset: u32le, attributes: TGA_Alpha_Kind, }Source

Which_File_Type

Which_File_Type :: enum int { Unknown = 0, BMP = 1, DjVu = 2, // AT&T DjVu file format EXR = 3, FLIF = 4, GIF = 5, HDR = 6, // Radiance RGBE HDR ICNS = 7, // Apple Icon Image JPEG = 8, JPEG_2000 = 9, JPEG_XL = 10, NetPBM = 11, // NetPBM family PIC = 12, // Softimage PIC PNG = 13, // Portable Network Graphics PSD = 14, // Photoshop PSD QOI = 15, // Quite Okay Image SGI_RGB = 16, // Silicon Graphics Image RGB file format Sun_Rast = 17, // Sun Raster Graphic TGA = 18, // Targa Truevision TIFF = 19, // Tagged Image File Format WebP = 20, XBM = 21, // X BitMap }Source

Constants

4

MAX_DIMENSIONS

MAX_DIMENSIONS :: min(#config(MAX_DIMENSIONS, 8192 * 8192), 65535 * 65535)Source

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.

Variables

4

Procedures

24

alpha_add_if_missing

alpha_add_if_missing :: proc(img: ^Image, alpha_key: Alpha_Key = Alpha_Key{}, allocator: mem.Allocator = context.allocator) -> (ok: bool)Source

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: mem.Allocator = context.allocator) -> (ok: bool)Source

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]RGB_Pixel, allocator: mem.Allocator = context.allocator) -> (ok: bool)Source

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]RGBA_Pixel, allocator: mem.Allocator = context.allocator) -> (ok: bool)Source

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.

expand_grayscale

expand_grayscale :: proc(img: ^Image, allocator: mem.Allocator = context.allocator) -> (ok: bool)Source

Replicates grayscale values into RGB(A) 8- or 16-bit images as appropriate. Returns early with false if already an RGB(A) image.

premultiply_alpha

premultiply_alpha :: proc(img: ^Image) -> (ok: bool)Source

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.

Procedure Groups

4

Reference search

Find anything

Documentation preferences

Settings

System theme variants

Used only while Theme is set to System.