Browse Source

png + compress: Rearrange error unions.

Jeroen van Rijn 3 years ago
parent
commit
9b5ae95677

+ 3 - 9
core/compress/common.odin

@@ -9,9 +9,8 @@ package compress
 */
 */
 
 
 import "core:io"
 import "core:io"
-import "core:image"
 import "core:bytes"
 import "core:bytes"
-import "core:mem"
+import "core:runtime"
 
 
 /*
 /*
 	These settings bound how much compression algorithms will allocate for their output buffer.
 	These settings bound how much compression algorithms will allocate for their output buffer.
@@ -48,16 +47,12 @@ when size_of(uintptr) == 8 {
 
 
 Error :: union {
 Error :: union {
 	General_Error,
 	General_Error,
-	mem.Allocator_Error,
 	Deflate_Error,
 	Deflate_Error,
 	ZLIB_Error,
 	ZLIB_Error,
 	GZIP_Error,
 	GZIP_Error,
 	ZIP_Error,
 	ZIP_Error,
-	/*
-		This is here because png.load will return a this type of error union,
-		as it may involve an I/O error, a Deflate error, etc.
-	*/
-	image.Error,
+
+	runtime.Allocator_Error,
 }
 }
 
 
 General_Error :: enum {
 General_Error :: enum {
@@ -71,7 +66,6 @@ General_Error :: enum {
 	Incompatible_Options,
 	Incompatible_Options,
 	Unimplemented,
 	Unimplemented,
 
 
-
 	/*
 	/*
 		Memory errors
 		Memory errors
 	*/
 	*/

+ 20 - 3
core/image/common.odin

@@ -11,6 +11,8 @@ package image
 
 
 import "core:bytes"
 import "core:bytes"
 import "core:mem"
 import "core:mem"
+import "core:compress"
+import "core:runtime"
 
 
 Image :: struct {
 Image :: struct {
 	width:         int,
 	width:         int,
@@ -112,19 +114,34 @@ Option :: enum {
 }
 }
 Options :: distinct bit_set[Option]
 Options :: distinct bit_set[Option]
 
 
-Error :: enum {
+Error :: union {
+	General_Image_Error,
+	PNG_Error,
+
+	compress.Error,
+	compress.General_Error,
+	compress.Deflate_Error,
+	compress.ZLIB_Error,
+	runtime.Allocator_Error,
+}
+
+General_Image_Error :: enum {
+	None = 0,
+	Invalid_Image_Dimensions,
+	Image_Does_Not_Adhere_to_Spec,
+}
+
+PNG_Error :: enum {
 	Invalid_PNG_Signature,
 	Invalid_PNG_Signature,
 	IHDR_Not_First_Chunk,
 	IHDR_Not_First_Chunk,
 	IHDR_Corrupt,
 	IHDR_Corrupt,
 	IDAT_Missing,
 	IDAT_Missing,
 	IDAT_Must_Be_Contiguous,
 	IDAT_Must_Be_Contiguous,
 	IDAT_Corrupt,
 	IDAT_Corrupt,
-	PNG_Does_Not_Adhere_to_Spec,
 	PLTE_Encountered_Unexpectedly,
 	PLTE_Encountered_Unexpectedly,
 	PLTE_Invalid_Length,
 	PLTE_Invalid_Length,
 	TRNS_Encountered_Unexpectedly,
 	TRNS_Encountered_Unexpectedly,
 	BKGD_Invalid_Length,
 	BKGD_Invalid_Length,
-	Invalid_Image_Dimensions,
 	Unknown_Color_Type,
 	Unknown_Color_Type,
 	Invalid_Color_Bit_Depth_Combo,
 	Invalid_Color_Bit_Depth_Combo,
 	Unknown_Filter_Method,
 	Unknown_Filter_Method,

+ 1 - 2
core/image/png/example.odin

@@ -12,7 +12,6 @@ package png
 	An example of how to use `load`.
 	An example of how to use `load`.
 */
 */
 
 
-import "core:compress"
 import "core:image"
 import "core:image"
 // import "core:image/png"
 // import "core:image/png"
 import "core:bytes"
 import "core:bytes"
@@ -42,7 +41,7 @@ demo :: proc() {
 	file: string
 	file: string
 
 
 	options := image.Options{.return_metadata}
 	options := image.Options{.return_metadata}
-	err:       compress.Error
+	err:       image.Error
 	img:      ^image.Image
 	img:      ^image.Image
 
 
 	file = "../../../misc/logo-slim.png"
 	file = "../../../misc/logo-slim.png"

+ 37 - 41
core/image/png/png.odin

@@ -21,11 +21,7 @@ import "core:io"
 import "core:mem"
 import "core:mem"
 import "core:intrinsics"
 import "core:intrinsics"
 
 
-Error     :: compress.Error
-E_General :: compress.General_Error
-E_PNG     :: image.Error
-E_Deflate :: compress.Deflate_Error
-
+Error     :: image.Error
 Image     :: image.Image
 Image     :: image.Image
 Options   :: image.Options
 Options   :: image.Options
 
 
@@ -248,13 +244,13 @@ ADAM7_Y_SPACING := []int{ 8,8,8,4,4,2,2 }
 read_chunk :: proc(ctx: ^$C) -> (chunk: Chunk, err: Error) {
 read_chunk :: proc(ctx: ^$C) -> (chunk: Chunk, err: Error) {
 	ch, e := compress.read_data(ctx, Chunk_Header)
 	ch, e := compress.read_data(ctx, Chunk_Header)
 	if e != .None {
 	if e != .None {
-		return {}, E_General.Stream_Too_Short
+		return {}, compress.General_Error.Stream_Too_Short
 	}
 	}
 	chunk.header = ch
 	chunk.header = ch
 
 
 	chunk.data, e = compress.read_slice(ctx, int(ch.length))
 	chunk.data, e = compress.read_slice(ctx, int(ch.length))
 	if e != .None {
 	if e != .None {
-		return {}, E_General.Stream_Too_Short
+		return {}, compress.General_Error.Stream_Too_Short
 	}
 	}
 
 
 	// Compute CRC over chunk type + data
 	// Compute CRC over chunk type + data
@@ -264,12 +260,12 @@ read_chunk :: proc(ctx: ^$C) -> (chunk: Chunk, err: Error) {
 
 
 	crc, e3 := compress.read_data(ctx, u32be)
 	crc, e3 := compress.read_data(ctx, u32be)
 	if e3 != .None {
 	if e3 != .None {
-		return {}, E_General.Stream_Too_Short
+		return {}, compress.General_Error.Stream_Too_Short
 	}
 	}
 	chunk.crc = crc
 	chunk.crc = crc
 
 
 	if chunk.crc != u32be(computed_crc) {
 	if chunk.crc != u32be(computed_crc) {
-		return {}, E_General.Checksum_Failed
+		return {}, compress.General_Error.Checksum_Failed
 	}
 	}
 	return chunk, nil
 	return chunk, nil
 }
 }
@@ -297,7 +293,7 @@ append_chunk :: proc(list: ^[dynamic]Chunk, src: Chunk, allocator := context.all
 	append(list, c)
 	append(list, c)
 	if len(list) != length + 1 {
 	if len(list) != length + 1 {
 		// Resize during append failed.
 		// Resize during append failed.
-		return .Out_Of_Memory
+		return mem.Allocator_Error.Out_Of_Memory
 	}
 	}
 
 
 	return
 	return
@@ -313,19 +309,19 @@ read_header :: proc(ctx: ^$C) -> (IHDR, Error) {
 	// Validate IHDR
 	// Validate IHDR
 	using header
 	using header
 	if width == 0 || height == 0 {
 	if width == 0 || height == 0 {
-		return {}, E_PNG.Invalid_Image_Dimensions
+		return {}, .Invalid_Image_Dimensions
 	}
 	}
 
 
 	if compression_method != 0 {
 	if compression_method != 0 {
-		return {}, E_General.Unknown_Compression_Method
+		return {}, compress.General_Error.Unknown_Compression_Method
 	}
 	}
 
 
 	if filter_method != 0 {
 	if filter_method != 0 {
-		return {}, E_PNG.Unknown_Filter_Method
+		return {}, .Unknown_Filter_Method
 	}
 	}
 
 
 	if interlace_method != .None && interlace_method != .Adam7 {
 	if interlace_method != .None && interlace_method != .Adam7 {
-		return {}, E_PNG.Unknown_Interlace_Method
+		return {}, .Unknown_Interlace_Method
 
 
 	}
 	}
 
 
@@ -343,7 +339,7 @@ read_header :: proc(ctx: ^$C) -> (IHDR, Error) {
 			}
 			}
 		}
 		}
 		if !allowed {
 		if !allowed {
-			return {}, E_PNG.Invalid_Color_Bit_Depth_Combo
+			return {}, .Invalid_Color_Bit_Depth_Combo
 		}
 		}
 	case 2, 4, 6:
 	case 2, 4, 6:
 		/*
 		/*
@@ -351,7 +347,7 @@ read_header :: proc(ctx: ^$C) -> (IHDR, Error) {
 			Allowed bit depths: 8 and 16
 			Allowed bit depths: 8 and 16
 		*/
 		*/
 		if bit_depth != 8 && bit_depth != 16 {
 		if bit_depth != 8 && bit_depth != 16 {
-			return {}, E_PNG.Invalid_Color_Bit_Depth_Combo
+			return {}, .Invalid_Color_Bit_Depth_Combo
 		}
 		}
 	case 3:
 	case 3:
 		/*
 		/*
@@ -366,11 +362,11 @@ read_header :: proc(ctx: ^$C) -> (IHDR, Error) {
 			}
 			}
 		}
 		}
 		if !allowed {
 		if !allowed {
-			return {}, E_PNG.Invalid_Color_Bit_Depth_Combo
+			return {}, .Invalid_Color_Bit_Depth_Combo
 		}
 		}
 
 
 	case:
 	case:
-		return {}, E_PNG.Unknown_Color_Type
+		return {}, .Unknown_Color_Type
 	}
 	}
 
 
 	return header, nil
 	return header, nil
@@ -406,7 +402,7 @@ load_from_file :: proc(filename: string, options := Options{}, allocator := cont
 		return load_from_slice(data, options)
 		return load_from_slice(data, options)
 	} else {
 	} else {
 		img = new(Image)
 		img = new(Image)
-		return img, E_General.File_Not_Found
+		return img, compress.General_Error.File_Not_Found
 	}
 	}
 }
 }
 
 
@@ -420,7 +416,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
 	}
 	}
 
 
 	if .alpha_drop_if_present in options && .alpha_add_if_missing in options {
 	if .alpha_drop_if_present in options && .alpha_add_if_missing in options {
-		return {}, E_General.Incompatible_Options
+		return {}, compress.General_Error.Incompatible_Options
 	}
 	}
 
 
 	if .do_not_expand_channels in options {
 	if .do_not_expand_channels in options {
@@ -437,7 +433,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
 
 
 	signature, io_error := compress.read_data(ctx, Signature)
 	signature, io_error := compress.read_data(ctx, Signature)
 	if io_error != .None || signature != .PNG {
 	if io_error != .None || signature != .PNG {
-		return img, E_PNG.Invalid_PNG_Signature
+		return img, .Invalid_PNG_Signature
 	}
 	}
 
 
 	idat: []u8
 	idat: []u8
@@ -472,14 +468,14 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
 
 
 		ch, e = compress.peek_data(ctx, Chunk_Header)
 		ch, e = compress.peek_data(ctx, Chunk_Header)
 		if e != .None {
 		if e != .None {
-			return img, E_General.Stream_Too_Short
+			return img, compress.General_Error.Stream_Too_Short
 		}
 		}
 		// name := chunk_type_to_name(&ch.type); // Only used for debug prints during development.
 		// name := chunk_type_to_name(&ch.type); // Only used for debug prints during development.
 
 
 		#partial switch ch.type {
 		#partial switch ch.type {
 		case .IHDR:
 		case .IHDR:
 			if seen_ihdr || !first {
 			if seen_ihdr || !first {
-				return {}, E_PNG.IHDR_Not_First_Chunk
+				return {}, .IHDR_Not_First_Chunk
 			}
 			}
 			seen_ihdr = true
 			seen_ihdr = true
 
 
@@ -508,7 +504,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
 			}
 			}
 
 
 			if img.channels == 0 || img.depth == 0 {
 			if img.channels == 0 || img.depth == 0 {
-				return {}, E_PNG.IHDR_Corrupt
+				return {}, .IHDR_Corrupt
 			}
 			}
 
 
 			img.width  = int(header.width)
 			img.width  = int(header.width)
@@ -530,18 +526,18 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
 			// PLTE must appear before IDAT and can't appear for color types 0, 4.
 			// PLTE must appear before IDAT and can't appear for color types 0, 4.
 			ct := transmute(u8)info.header.color_type
 			ct := transmute(u8)info.header.color_type
 			if seen_idat || ct == 0 || ct == 4 {
 			if seen_idat || ct == 0 || ct == 4 {
-				return img, E_PNG.PLTE_Encountered_Unexpectedly
+				return img, .PLTE_Encountered_Unexpectedly
 			}
 			}
 
 
 			c = read_chunk(ctx) or_return
 			c = read_chunk(ctx) or_return
 
 
 			if c.header.length % 3 != 0 || c.header.length > 768 {
 			if c.header.length % 3 != 0 || c.header.length > 768 {
-				return img, E_PNG.PLTE_Invalid_Length
+				return img, .PLTE_Invalid_Length
 			}
 			}
 			plte_ok: bool
 			plte_ok: bool
 			_plte, plte_ok = plte(c)
 			_plte, plte_ok = plte(c)
 			if !plte_ok {
 			if !plte_ok {
-				return img, E_PNG.PLTE_Invalid_Length
+				return img, .PLTE_Invalid_Length
 			}
 			}
 
 
 			if .return_metadata in options {
 			if .return_metadata in options {
@@ -555,11 +551,11 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
 			}
 			}
 			// There must be at least 1 IDAT, contiguous if more.
 			// There must be at least 1 IDAT, contiguous if more.
 			if seen_idat {
 			if seen_idat {
-				return img, E_PNG.IDAT_Must_Be_Contiguous
+				return img, .IDAT_Must_Be_Contiguous
 			}
 			}
 
 
 			if idat_length > 0 {
 			if idat_length > 0 {
-				return img, E_PNG.IDAT_Must_Be_Contiguous
+				return img, .IDAT_Must_Be_Contiguous
 			}
 			}
 
 
 			next := ch.type
 			next := ch.type
@@ -571,13 +567,13 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
 
 
 				ch, e = compress.peek_data(ctx, Chunk_Header)
 				ch, e = compress.peek_data(ctx, Chunk_Header)
 				if e != .None {
 				if e != .None {
-					return img, E_General.Stream_Too_Short
+					return img, compress.General_Error.Stream_Too_Short
 				}
 				}
 				next = ch.type
 				next = ch.type
 			}
 			}
 			idat = bytes.buffer_to_bytes(&idat_b)
 			idat = bytes.buffer_to_bytes(&idat_b)
 			if int(idat_length) != len(idat) {
 			if int(idat_length) != len(idat) {
-				return {}, E_PNG.IDAT_Corrupt
+				return {}, .IDAT_Corrupt
 			}
 			}
 			seen_idat = true
 			seen_idat = true
 		case .IEND:
 		case .IEND:
@@ -597,7 +593,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
 			switch ct {
 			switch ct {
 				case 3: // Indexed color
 				case 3: // Indexed color
 					if c.header.length != 1 {
 					if c.header.length != 1 {
-						return {}, E_PNG.BKGD_Invalid_Length
+						return {}, .BKGD_Invalid_Length
 					}
 					}
 					col := _plte.entries[c.data[0]]
 					col := _plte.entries[c.data[0]]
 					img.background = [3]u16{
 					img.background = [3]u16{
@@ -607,13 +603,13 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
 					}
 					}
 				case 0, 4: // Grayscale, with and without Alpha
 				case 0, 4: // Grayscale, with and without Alpha
 					if c.header.length != 2 {
 					if c.header.length != 2 {
-						return {}, E_PNG.BKGD_Invalid_Length
+						return {}, .BKGD_Invalid_Length
 					}
 					}
 					col := u16(mem.slice_data_cast([]u16be, c.data[:])[0])
 					col := u16(mem.slice_data_cast([]u16be, c.data[:])[0])
 					img.background = [3]u16{col, col, col}
 					img.background = [3]u16{col, col, col}
 				case 2, 6: // Color, with and without Alpha
 				case 2, 6: // Color, with and without Alpha
 					if c.header.length != 6 {
 					if c.header.length != 6 {
-						return {}, E_PNG.BKGD_Invalid_Length
+						return {}, .BKGD_Invalid_Length
 					}
 					}
 					col := mem.slice_data_cast([]u16be, c.data[:])
 					col := mem.slice_data_cast([]u16be, c.data[:])
 					img.background = [3]u16{u16(col[0]), u16(col[1]), u16(col[2])}
 					img.background = [3]u16{u16(col[0]), u16(col[1]), u16(col[2])}
@@ -622,7 +618,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
 			c = read_chunk(ctx) or_return
 			c = read_chunk(ctx) or_return
 
 
 			if .Alpha in info.header.color_type {
 			if .Alpha in info.header.color_type {
-				return img, E_PNG.TRNS_Encountered_Unexpectedly
+				return img, .TRNS_Encountered_Unexpectedly
 			}
 			}
 
 
 			if .return_metadata in options {
 			if .return_metadata in options {
@@ -655,7 +651,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
 				We're not going to add support for it. If you have the misfortunte of coming
 				We're not going to add support for it. If you have the misfortunte of coming
 				across one of these files, use a utility to defry it.
 				across one of these files, use a utility to defry it.
 			*/
 			*/
-			return img, E_PNG.PNG_Does_Not_Adhere_to_Spec
+			return img, .Image_Does_Not_Adhere_to_Spec
 		case:
 		case:
 			// Unhandled type
 			// Unhandled type
 			c = read_chunk(ctx) or_return
 			c = read_chunk(ctx) or_return
@@ -673,7 +669,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
 	}
 	}
 
 
 	if !seen_idat {
 	if !seen_idat {
-		return img, E_PNG.IDAT_Missing
+		return img, .IDAT_Missing
 	}
 	}
 
 
 	/*
 	/*
@@ -710,7 +706,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
 
 
 	buf_len := len(buf.buf)
 	buf_len := len(buf.buf)
 	if expected_size != buf_len {
 	if expected_size != buf_len {
-		return {}, E_PNG.IDAT_Corrupt
+		return {}, .IDAT_Corrupt
 	}
 	}
 
 
 	/*
 	/*
@@ -1549,7 +1545,7 @@ defilter_16 :: proc(params: ^Filter_Params) -> (ok: bool) {
 	return
 	return
 }
 }
 
 
-defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^IHDR, options: Options) -> (err: compress.Error) {
+defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^IHDR, options: Options) -> (err: Error) {
 	input    := bytes.buffer_to_bytes(filter_bytes)
 	input    := bytes.buffer_to_bytes(filter_bytes)
 	width    := int(header.width)
 	width    := int(header.width)
 	height   := int(header.height)
 	height   := int(header.height)
@@ -1585,7 +1581,7 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^IHDR, option
 		}
 		}
 		if !filter_ok {
 		if !filter_ok {
 			// Caller will destroy buffer for us.
 			// Caller will destroy buffer for us.
-			return E_PNG.Unknown_Filter_Method
+			return .Unknown_Filter_Method
 		}
 		}
 	} else {
 	} else {
 		/*
 		/*
@@ -1623,7 +1619,7 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^IHDR, option
 
 
 				if !filter_ok {
 				if !filter_ok {
 					// Caller will destroy buffer for us.
 					// Caller will destroy buffer for us.
-					return E_PNG.Unknown_Filter_Method
+					return .Unknown_Filter_Method
 				}
 				}
 
 
 				t := temp.buf[:]
 				t := temp.buf[:]

+ 4 - 0
tests/core/image/build.bat

@@ -0,0 +1,4 @@
+@echo off
+pushd ..
+odin run image
+popd

+ 13 - 13
tests/core/image/test_core_image.odin

@@ -64,7 +64,7 @@ PNG_Test :: struct {
 	file:   string,
 	file:   string,
 	tests:  []struct {
 	tests:  []struct {
 		options:        image.Options,
 		options:        image.Options,
-		expected_error: compress.Error,
+		expected_error: image.Error,
 		dims:           PNG_Dims,
 		dims:           PNG_Dims,
 		hash:           u32,
 		hash:           u32,
 	},
 	},
@@ -1198,37 +1198,37 @@ Corrupt_PNG_Tests   := []PNG_Test{
 	{
 	{
 		"xs1n0g01", // signature byte 1 MSBit reset to zero
 		"xs1n0g01", // signature byte 1 MSBit reset to zero
 		{
 		{
-			{Default, I_Error.Invalid_PNG_Signature, {}, 0x_0000_0000},
+			{Default, .Invalid_PNG_Signature, {}, 0x_0000_0000},
 		},
 		},
 	},
 	},
 	{
 	{
 		"xs2n0g01", // signature byte 2 is a 'Q'
 		"xs2n0g01", // signature byte 2 is a 'Q'
 		{
 		{
-			{Default, I_Error.Invalid_PNG_Signature, {}, 0x_0000_0000},
+			{Default, .Invalid_PNG_Signature, {}, 0x_0000_0000},
 		},
 		},
 	},
 	},
 	{
 	{
 		"xs4n0g01", // signature byte 4 lowercase
 		"xs4n0g01", // signature byte 4 lowercase
 		{
 		{
-			{Default, I_Error.Invalid_PNG_Signature, {}, 0x_0000_0000},
+			{Default, .Invalid_PNG_Signature, {}, 0x_0000_0000},
 		},
 		},
 	},
 	},
 	{
 	{
 		"xs7n0g01", // 7th byte a space instead of control-Z
 		"xs7n0g01", // 7th byte a space instead of control-Z
 		{
 		{
-			{Default, I_Error.Invalid_PNG_Signature, {}, 0x_0000_0000},
+			{Default, .Invalid_PNG_Signature, {}, 0x_0000_0000},
 		},
 		},
 	},
 	},
 	{
 	{
 		"xcrn0g04", // added cr bytes
 		"xcrn0g04", // added cr bytes
 		{
 		{
-			{Default, I_Error.Invalid_PNG_Signature, {}, 0x_0000_0000},
+			{Default, .Invalid_PNG_Signature, {}, 0x_0000_0000},
 		},
 		},
 	},
 	},
 	{
 	{
 		"xlfn0g04", // added lf bytes
 		"xlfn0g04", // added lf bytes
 		{
 		{
-			{Default, I_Error.Invalid_PNG_Signature, {}, 0x_0000_0000},
+			{Default, .Invalid_PNG_Signature, {}, 0x_0000_0000},
 		},
 		},
 	},
 	},
 	{
 	{
@@ -1240,37 +1240,37 @@ Corrupt_PNG_Tests   := []PNG_Test{
 	{
 	{
 		"xc1n0g08", // color type 1
 		"xc1n0g08", // color type 1
 		{
 		{
-			{Default, I_Error.Unknown_Color_Type, {}, 0x_0000_0000},
+			{Default, .Unknown_Color_Type, {}, 0x_0000_0000},
 		},
 		},
 	},
 	},
 	{
 	{
 		"xc9n2c08", // color type 9
 		"xc9n2c08", // color type 9
 		{
 		{
-			{Default, I_Error.Unknown_Color_Type, {}, 0x_0000_0000},
+			{Default, .Unknown_Color_Type, {}, 0x_0000_0000},
 		},
 		},
 	},
 	},
 	{
 	{
 		"xd0n2c08", // bit-depth 0
 		"xd0n2c08", // bit-depth 0
 		{
 		{
-			{Default, I_Error.Invalid_Color_Bit_Depth_Combo, {}, 0x_0000_0000},
+			{Default, .Invalid_Color_Bit_Depth_Combo, {}, 0x_0000_0000},
 		},
 		},
 	},
 	},
 	{
 	{
 		"xd3n2c08", // bit-depth 3
 		"xd3n2c08", // bit-depth 3
 		{
 		{
-			{Default, I_Error.Invalid_Color_Bit_Depth_Combo, {}, 0x_0000_0000},
+			{Default, .Invalid_Color_Bit_Depth_Combo, {}, 0x_0000_0000},
 		},
 		},
 	},
 	},
 	{
 	{
 		"xd9n2c08", // bit-depth 99
 		"xd9n2c08", // bit-depth 99
 		{
 		{
-			{Default, I_Error.Invalid_Color_Bit_Depth_Combo, {}, 0x_0000_0000},
+			{Default, .Invalid_Color_Bit_Depth_Combo, {}, 0x_0000_0000},
 		},
 		},
 	},
 	},
 	{
 	{
 		"xdtn0g01", // missing IDAT chunk
 		"xdtn0g01", // missing IDAT chunk
 		{
 		{
-			{Default, I_Error.IDAT_Missing, {}, 0x_0000_0000},
+			{Default, .IDAT_Missing, {}, 0x_0000_0000},
 		},
 		},
 	},
 	},
 	{
 	{