aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2021-10-06 22:43:33 +0200
committerJeroen van Rijn <Kelimion@users.noreply.github.com>2021-10-06 22:43:33 +0200
commitc4b4a841d68f4bde69f4e1472b7d8fa24f96a376 (patch)
tree5fb212b07e4941e164d2ea66b201158bee798ddc /core
parent263d63aa5678276532776c129829b6a77f56bcad (diff)
png: Move metadata.
Diffstat (limited to 'core')
-rw-r--r--core/image/common.odin105
-rw-r--r--core/image/png/example.odin164
-rw-r--r--core/image/png/helpers.odin41
-rw-r--r--core/image/png/png.odin124
4 files changed, 216 insertions, 218 deletions
diff --git a/core/image/common.odin b/core/image/common.odin
index 2826a65ca..919670a61 100644
--- a/core/image/common.odin
+++ b/core/image/common.odin
@@ -26,8 +26,11 @@ Image :: struct {
*/
background: Maybe([3]u16),
- metadata_ptr: rawptr,
- metadata_type: typeid,
+ metadata: Image_Metadata,
+}
+
+Image_Metadata :: union {
+ ^PNG_Info,
}
/*
@@ -153,9 +156,100 @@ PNG_Error :: enum {
}
/*
- Functions to help with image buffer calculations
+ PNG-specific structs
*/
+PNG_Info :: struct {
+ header: PNG_IHDR,
+ chunks: [dynamic]PNG_Chunk,
+}
+
+PNG_Chunk_Header :: struct #packed {
+ length: u32be,
+ type: PNG_Chunk_Type,
+}
+
+PNG_Chunk :: struct #packed {
+ header: PNG_Chunk_Header,
+ data: []byte,
+ crc: u32be,
+}
+
+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',
+ CbGI = 'C' << 24 | 'b' << 16 | 'H' << 8 | 'I',
+}
+
+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_IHDR_SIZE :: size_of(PNG_IHDR)
+#assert (PNG_IHDR_SIZE == 13)
+PNG_Color_Value :: enum u8 {
+ Paletted = 0, // 1 << 0 = 1
+ Color = 1, // 1 << 1 = 2
+ Alpha = 2, // 1 << 2 = 4
+}
+PNG_Color_Type :: distinct bit_set[PNG_Color_Value; u8]
+
+PNG_Interlace_Method :: enum u8 {
+ None = 0,
+ Adam7 = 1,
+}
+
+/*
+ Functions to help with image buffer calculations
+*/
compute_buffer_size :: proc(width, height, channels, depth: int, extra_row_bytes := int(0)) -> (size: int) {
size = ((((channels * width * depth) + 7) >> 3) + extra_row_bytes) * height
return
@@ -164,7 +258,6 @@ compute_buffer_size :: proc(width, height, channels, depth: int, extra_row_bytes
/*
For when you have an RGB(A) image, but want a particular channel.
*/
-
Channel :: enum u8 {
R = 1,
G = 2,
@@ -226,8 +319,8 @@ return_single_channel :: proc(img: ^Image, channel: Channel) -> (res: ^Image, ok
res.depth = img.depth
res.pixels = t
res.background = img.background
- res.metadata_ptr = img.metadata_ptr
- res.metadata_type = img.metadata_type
+ // res.metadata_ptr = img.metadata_ptr
+ // res.metadata_type = img.metadata_type
return res, true
}
diff --git a/core/image/png/example.odin b/core/image/png/example.odin
index 5370b0bcf..5e7dca4c8 100644
--- a/core/image/png/example.odin
+++ b/core/image/png/example.odin
@@ -53,93 +53,91 @@ demo :: proc() {
} else {
fmt.printf("Image: %vx%vx%v, %v-bit.\n", img.width, img.height, img.channels, img.depth)
- assert(img.metadata_ptr != nil && img.metadata_type == Info)
-
- v := (^Info)(img.metadata_ptr)
-
- // Handle ancillary chunks as you wish.
- // We provide helper functions for a few types.
- for c in v.chunks {
- #partial switch c.header.type {
- case .tIME:
- if t, t_ok := core_time(c); t_ok {
- fmt.printf("[tIME]: %v\n", t)
- }
- case .gAMA:
- if gama, gama_ok := gamma(c); gama_ok {
- fmt.printf("[gAMA]: %v\n", gama)
- }
- case .pHYs:
- if phys, phys_ok := phys(c); phys_ok {
- if phys.unit == .Meter {
- xm := f32(img.width) / f32(phys.ppu_x)
- ym := f32(img.height) / f32(phys.ppu_y)
- dpi_x, dpi_y := phys_to_dpi(phys)
- fmt.printf("[pHYs] Image resolution is %v x %v pixels per meter.\n", phys.ppu_x, phys.ppu_y)
- fmt.printf("[pHYs] Image resolution is %v x %v DPI.\n", dpi_x, dpi_y)
- fmt.printf("[pHYs] Image dimensions are %v x %v meters.\n", xm, ym)
- } else {
- fmt.printf("[pHYs] x: %v, y: %v pixels per unknown unit.\n", phys.ppu_x, phys.ppu_y)
+ if v, ok := img.metadata.(^image.PNG_Info); ok {
+ // Handle ancillary chunks as you wish.
+ // We provide helper functions for a few types.
+ for c in v.chunks {
+ #partial switch c.header.type {
+ case .tIME:
+ if t, t_ok := core_time(c); t_ok {
+ fmt.printf("[tIME]: %v\n", t)
}
- }
- case .iTXt, .zTXt, .tEXt:
- res, ok_text := text(c)
- if ok_text {
- if c.header.type == .iTXt {
- fmt.printf("[iTXt] %v (%v:%v): %v\n", res.keyword, res.language, res.keyword_localized, res.text)
+ case .gAMA:
+ if gama, gama_ok := gamma(c); gama_ok {
+ fmt.printf("[gAMA]: %v\n", gama)
+ }
+ case .pHYs:
+ if phys, phys_ok := phys(c); phys_ok {
+ if phys.unit == .Meter {
+ xm := f32(img.width) / f32(phys.ppu_x)
+ ym := f32(img.height) / f32(phys.ppu_y)
+ dpi_x, dpi_y := phys_to_dpi(phys)
+ fmt.printf("[pHYs] Image resolution is %v x %v pixels per meter.\n", phys.ppu_x, phys.ppu_y)
+ fmt.printf("[pHYs] Image resolution is %v x %v DPI.\n", dpi_x, dpi_y)
+ fmt.printf("[pHYs] Image dimensions are %v x %v meters.\n", xm, ym)
+ } else {
+ fmt.printf("[pHYs] x: %v, y: %v pixels per unknown unit.\n", phys.ppu_x, phys.ppu_y)
+ }
+ }
+ case .iTXt, .zTXt, .tEXt:
+ res, ok_text := text(c)
+ if ok_text {
+ if c.header.type == .iTXt {
+ fmt.printf("[iTXt] %v (%v:%v): %v\n", res.keyword, res.language, res.keyword_localized, res.text)
+ } else {
+ fmt.printf("[tEXt/zTXt] %v: %v\n", res.keyword, res.text)
+ }
+ }
+ defer text_destroy(res)
+ case .bKGD:
+ fmt.printf("[bKGD] %v\n", img.background)
+ case .eXIf:
+ if res, ok_exif := exif(c); ok_exif {
+ /*
+ Other than checking the signature and byte order, we don't handle Exif data.
+ If you wish to interpret it, pass it to an Exif parser.
+ */
+ fmt.printf("[eXIf] %v\n", res)
+ }
+ case .PLTE:
+ if plte, plte_ok := plte(c); plte_ok {
+ fmt.printf("[PLTE] %v\n", plte)
} else {
- fmt.printf("[tEXt/zTXt] %v: %v\n", res.keyword, res.text)
+ fmt.printf("[PLTE] Error\n")
}
+ case .hIST:
+ if res, ok_hist := hist(c); ok_hist {
+ fmt.printf("[hIST] %v\n", res)
+ }
+ case .cHRM:
+ if res, ok_chrm := chrm(c); ok_chrm {
+ fmt.printf("[cHRM] %v\n", res)
+ }
+ case .sPLT:
+ res, ok_splt := splt(c)
+ if ok_splt {
+ fmt.printf("[sPLT] %v\n", res)
+ }
+ splt_destroy(res)
+ case .sBIT:
+ if res, ok_sbit := sbit(c); ok_sbit {
+ fmt.printf("[sBIT] %v\n", res)
+ }
+ case .iCCP:
+ res, ok_iccp := iccp(c)
+ if ok_iccp {
+ fmt.printf("[iCCP] %v\n", res)
+ }
+ iccp_destroy(res)
+ case .sRGB:
+ if res, ok_srgb := srgb(c); ok_srgb {
+ fmt.printf("[sRGB] Rendering intent: %v\n", res)
+ }
+ case:
+ type := c.header.type
+ name := chunk_type_to_name(&type)
+ fmt.printf("[%v]: %v\n", name, c.data)
}
- defer text_destroy(res)
- case .bKGD:
- fmt.printf("[bKGD] %v\n", img.background)
- case .eXIf:
- if res, ok_exif := exif(c); ok_exif {
- /*
- Other than checking the signature and byte order, we don't handle Exif data.
- If you wish to interpret it, pass it to an Exif parser.
- */
- fmt.printf("[eXIf] %v\n", res)
- }
- case .PLTE:
- if plte, plte_ok := plte(c); plte_ok {
- fmt.printf("[PLTE] %v\n", plte)
- } else {
- fmt.printf("[PLTE] Error\n")
- }
- case .hIST:
- if res, ok_hist := hist(c); ok_hist {
- fmt.printf("[hIST] %v\n", res)
- }
- case .cHRM:
- if res, ok_chrm := chrm(c); ok_chrm {
- fmt.printf("[cHRM] %v\n", res)
- }
- case .sPLT:
- res, ok_splt := splt(c)
- if ok_splt {
- fmt.printf("[sPLT] %v\n", res)
- }
- splt_destroy(res)
- case .sBIT:
- if res, ok_sbit := sbit(c); ok_sbit {
- fmt.printf("[sBIT] %v\n", res)
- }
- case .iCCP:
- res, ok_iccp := iccp(c)
- if ok_iccp {
- fmt.printf("[iCCP] %v\n", res)
- }
- iccp_destroy(res)
- case .sRGB:
- if res, ok_srgb := srgb(c); ok_srgb {
- fmt.printf("[sRGB] Rendering intent: %v\n", res)
- }
- case:
- type := c.header.type
- name := chunk_type_to_name(&type)
- fmt.printf("[%v]: %v\n", name, c.data)
}
}
}
diff --git a/core/image/png/helpers.odin b/core/image/png/helpers.odin
index 59d8fb70b..ecc0183bc 100644
--- a/core/image/png/helpers.odin
+++ b/core/image/png/helpers.odin
@@ -34,16 +34,13 @@ destroy :: proc(img: ^Image) {
bytes.buffer_destroy(&img.pixels)
- assert(img.metadata_ptr != nil && img.metadata_type == Info)
- v := (^Info)(img.metadata_ptr)
-
- for chunk in &v.chunks {
- delete(chunk.data)
+ if v, ok := img.metadata.(^image.PNG_Info); ok {
+ for chunk in &v.chunks {
+ delete(chunk.data)
+ }
+ delete(v.chunks)
+ free(v)
}
- delete(v.chunks)
-
- // Clean up Info.
- free(img.metadata_ptr)
free(img)
}
@@ -51,7 +48,7 @@ destroy :: proc(img: ^Image) {
Chunk helpers
*/
-gamma :: proc(c: Chunk) -> (res: f32, ok: bool) {
+gamma :: proc(c: image.PNG_Chunk) -> (res: f32, ok: bool) {
if c.header.type != .gAMA || len(c.data) != size_of(gAMA) {
return {}, false
}
@@ -61,7 +58,7 @@ gamma :: proc(c: Chunk) -> (res: f32, ok: bool) {
INCHES_PER_METER :: 1000.0 / 25.4
-phys :: proc(c: Chunk) -> (res: pHYs, ok: bool) {
+phys :: proc(c: image.PNG_Chunk) -> (res: pHYs, ok: bool) {
if c.header.type != .pHYs || len(c.data) != size_of(pHYs) {
return {}, false
}
@@ -73,7 +70,7 @@ phys_to_dpi :: proc(p: pHYs) -> (x_dpi, y_dpi: f32) {
return f32(p.ppu_x) / INCHES_PER_METER, f32(p.ppu_y) / INCHES_PER_METER
}
-time :: proc(c: Chunk) -> (res: tIME, ok: bool) {
+time :: proc(c: image.PNG_Chunk) -> (res: tIME, ok: bool) {
if c.header.type != .tIME || len(c.data) != size_of(tIME) {
return {}, false
}
@@ -81,7 +78,7 @@ time :: proc(c: Chunk) -> (res: tIME, ok: bool) {
return (^tIME)(raw_data(c.data))^, true
}
-core_time :: proc(c: Chunk) -> (t: coretime.Time, ok: bool) {
+core_time :: proc(c: image.PNG_Chunk) -> (t: coretime.Time, ok: bool) {
if png_time, png_ok := time(c); png_ok {
using png_time
return coretime.datetime_to_time(
@@ -93,7 +90,7 @@ core_time :: proc(c: Chunk) -> (t: coretime.Time, ok: bool) {
}
}
-text :: proc(c: Chunk) -> (res: Text, ok: bool) {
+text :: proc(c: image.PNG_Chunk) -> (res: Text, ok: bool) {
assert(len(c.data) == int(c.header.length))
#partial switch c.header.type {
case .tEXt:
@@ -196,7 +193,7 @@ text_destroy :: proc(text: Text) {
delete(text.text)
}
-iccp :: proc(c: Chunk) -> (res: iCCP, ok: bool) {
+iccp :: proc(c: image.PNG_Chunk) -> (res: iCCP, ok: bool) {
ok = true
fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator)
@@ -232,7 +229,7 @@ iccp_destroy :: proc(i: iCCP) {
}
-srgb :: proc(c: Chunk) -> (res: sRGB, ok: bool) {
+srgb :: proc(c: image.PNG_Chunk) -> (res: sRGB, ok: bool) {
if c.header.type != .sRGB || len(c.data) != size_of(sRGB_Rendering_Intent) {
return {}, false
}
@@ -244,7 +241,7 @@ srgb :: proc(c: Chunk) -> (res: sRGB, ok: bool) {
return res, true
}
-plte :: proc(c: Chunk) -> (res: PLTE, ok: bool) {
+plte :: proc(c: image.PNG_Chunk) -> (res: PLTE, ok: bool) {
if c.header.type != .PLTE {
return {}, false
}
@@ -258,7 +255,7 @@ plte :: proc(c: Chunk) -> (res: PLTE, ok: bool) {
return
}
-splt :: proc(c: Chunk) -> (res: sPLT, ok: bool) {
+splt :: proc(c: image.PNG_Chunk) -> (res: sPLT, ok: bool) {
if c.header.type != .sPLT {
return {}, false
}
@@ -309,7 +306,7 @@ splt_destroy :: proc(s: sPLT) {
delete(s.name)
}
-sbit :: proc(c: Chunk) -> (res: [4]u8, ok: bool) {
+sbit :: proc(c: image.PNG_Chunk) -> (res: [4]u8, ok: bool) {
/*
Returns [4]u8 with the significant bits in each channel.
A channel will contain zero if not applicable to the PNG color type.
@@ -327,7 +324,7 @@ sbit :: proc(c: Chunk) -> (res: [4]u8, ok: bool) {
}
-hist :: proc(c: Chunk) -> (res: hIST, ok: bool) {
+hist :: proc(c: image.PNG_Chunk) -> (res: hIST, ok: bool) {
if c.header.type != .hIST {
return {}, false
}
@@ -349,7 +346,7 @@ hist :: proc(c: Chunk) -> (res: hIST, ok: bool) {
return
}
-chrm :: proc(c: Chunk) -> (res: cHRM, ok: bool) {
+chrm :: proc(c: image.PNG_Chunk) -> (res: cHRM, ok: bool) {
ok = true
if c.header.length != size_of(cHRM_Raw) {
return {}, false
@@ -367,7 +364,7 @@ chrm :: proc(c: Chunk) -> (res: cHRM, ok: bool) {
return
}
-exif :: proc(c: Chunk) -> (res: Exif, ok: bool) {
+exif :: proc(c: image.PNG_Chunk) -> (res: Exif, ok: bool) {
ok = true
diff --git a/core/image/png/png.odin b/core/image/png/png.odin
index 536b82be2..f77bf7519 100644
--- a/core/image/png/png.odin
+++ b/core/image/png/png.odin
@@ -51,95 +51,6 @@ Signature :: enum u64be {
PNG = 0x89 << 56 | 'P' << 48 | 'N' << 40 | 'G' << 32 | '\r' << 24 | '\n' << 16 | 0x1a << 8 | '\n',
}
-Info :: struct {
- header: IHDR,
- chunks: [dynamic]Chunk,
-}
-
-Chunk_Header :: struct #packed {
- length: u32be,
- type: Chunk_Type,
-}
-
-Chunk :: struct #packed {
- header: Chunk_Header,
- data: []byte,
- crc: u32be,
-}
-
-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',
- CbGI = 'C' << 24 | 'b' << 16 | 'H' << 8 | 'I',
-}
-
-IHDR :: struct #packed {
- width: u32be,
- height: u32be,
- bit_depth: u8,
- color_type: Color_Type,
- compression_method: u8,
- filter_method: u8,
- interlace_method: Interlace_Method,
-}
-IHDR_SIZE :: size_of(IHDR)
-#assert (IHDR_SIZE == 13)
-
-Color_Value :: enum u8 {
- Paletted = 0, // 1 << 0 = 1
- Color = 1, // 1 << 1 = 2
- Alpha = 2, // 1 << 2 = 4
-}
-Color_Type :: distinct bit_set[Color_Value; u8]
-
-Interlace_Method :: enum u8 {
- None = 0,
- Adam7 = 1,
-}
-
Row_Filter :: enum u8 {
None = 0,
Sub = 1,
@@ -262,8 +173,8 @@ ADAM7_Y_SPACING := []int{ 8,8,8,4,4,2,2 }
// Implementation starts here
-read_chunk :: proc(ctx: ^$C) -> (chunk: Chunk, err: Error) {
- ch, e := compress.read_data(ctx, Chunk_Header)
+read_chunk :: proc(ctx: ^$C) -> (chunk: image.PNG_Chunk, err: Error) {
+ ch, e := compress.read_data(ctx, image.PNG_Chunk_Header)
if e != .None {
return {}, compress.General_Error.Stream_Too_Short
}
@@ -305,7 +216,7 @@ read_chunk :: proc(ctx: ^$C) -> (chunk: Chunk, err: Error) {
return chunk, nil
}
-copy_chunk :: proc(src: Chunk, allocator := context.allocator) -> (dest: Chunk, err: Error) {
+copy_chunk :: proc(src: image.PNG_Chunk, allocator := context.allocator) -> (dest: image.PNG_Chunk, err: Error) {
if int(src.header.length) != len(src.data) {
return {}, .Invalid_Chunk_Length
}
@@ -318,7 +229,7 @@ copy_chunk :: proc(src: Chunk, allocator := context.allocator) -> (dest: Chunk,
return
}
-append_chunk :: proc(list: ^[dynamic]Chunk, src: Chunk, allocator := context.allocator) -> (err: Error) {
+append_chunk :: proc(list: ^[dynamic]image.PNG_Chunk, src: image.PNG_Chunk, allocator := context.allocator) -> (err: Error) {
if int(src.header.length) != len(src.data) {
return .Invalid_Chunk_Length
}
@@ -334,13 +245,13 @@ append_chunk :: proc(list: ^[dynamic]Chunk, src: Chunk, allocator := context.all
return
}
-read_header :: proc(ctx: ^$C) -> (IHDR, Error) {
+read_header :: proc(ctx: ^$C) -> (image.PNG_IHDR, Error) {
c, e := read_chunk(ctx)
if e != nil {
return {}, e
}
- header := (^IHDR)(raw_data(c.data))^
+ header := (^image.PNG_IHDR)(raw_data(c.data))^
// Validate IHDR
using header
if width == 0 || height == 0 || u128(width) * u128(height) > MAX_DIMENSIONS {
@@ -407,7 +318,7 @@ read_header :: proc(ctx: ^$C) -> (IHDR, Error) {
return header, nil
}
-chunk_type_to_name :: proc(type: ^Chunk_Type) -> string {
+chunk_type_to_name :: proc(type: ^image.PNG_Chunk_Type) -> string {
t := transmute(^u8)type
return strings.string_from_ptr(t, 4)
}
@@ -462,9 +373,8 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
img = new(Image)
}
- info := new(Info)
- img.metadata_ptr = info
- img.metadata_type = typeid_of(Info)
+ info := new(image.PNG_Info)
+ img.metadata = info
signature, io_error := compress.read_data(ctx, Signature)
if io_error != .None || signature != .PNG {
@@ -477,11 +387,11 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
idat_length := u64(0)
- c: Chunk
- ch: Chunk_Header
+ c: image.PNG_Chunk
+ ch: image.PNG_Chunk_Header
e: io.Error
- header: IHDR
+ header: image.PNG_IHDR
// State to ensure correct chunk ordering.
seen_ihdr := false; first := true
@@ -492,7 +402,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
seen_iend := false
_plte := PLTE{}
- trns := Chunk{}
+ trns := image.PNG_Chunk{}
final_image_channels := 0
@@ -502,7 +412,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
// Peek at next chunk's length and type.
// TODO: Some streams may not provide seek/read_at
- ch, e = compress.peek_data(ctx, Chunk_Header)
+ ch, e = compress.peek_data(ctx, image.PNG_Chunk_Header)
if e != .None {
return img, compress.General_Error.Stream_Too_Short
}
@@ -547,7 +457,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
img.height = int(header.height)
using header
- h := IHDR{
+ h := image.PNG_IHDR{
width = width,
height = height,
bit_depth = bit_depth,
@@ -607,7 +517,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
return {}, image.PNG_Error.IDAT_Size_Too_Large
}
- ch, e = compress.peek_data(ctx, Chunk_Header)
+ ch, e = compress.peek_data(ctx, image.PNG_Chunk_Header)
if e != .None {
return img, compress.General_Error.Stream_Too_Short
}
@@ -1599,7 +1509,7 @@ defilter_16 :: proc(params: ^Filter_Params) -> (ok: bool) {
return
}
-defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^IHDR, options: Options) -> (err: Error) {
+defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IHDR, options: Options) -> (err: Error) {
input := bytes.buffer_to_bytes(filter_bytes)
width := int(header.width)
height := int(header.height)