fix: clean up all memory leaks. use tracking allocator in example
This commit is contained in:
@@ -2,5 +2,3 @@
|
|||||||
|
|
||||||
BlurHash Implementation in Odin
|
BlurHash Implementation in Odin
|
||||||
|
|
||||||
### TODO
|
|
||||||
- [ ] Clean up memory leaks
|
|
||||||
|
|||||||
+9
-11
@@ -61,9 +61,7 @@ base83_decode_str :: proc(str: string) -> int {
|
|||||||
base83_decode :: proc{base83_decode_str, base83_decode_byte}
|
base83_decode :: proc{base83_decode_str, base83_decode_byte}
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
base83_encode :: proc(value, length: int, allocator := context.allocator) -> string {
|
base83_encode :: proc(b: ^strings.Builder, value, length: int, allocator := context.allocator) {
|
||||||
b := strings.builder_make_none(allocator)
|
|
||||||
|
|
||||||
pow :: proc(base, exp: int) -> int {
|
pow :: proc(base, exp: int) -> int {
|
||||||
base := base
|
base := base
|
||||||
exp := exp
|
exp := exp
|
||||||
@@ -80,10 +78,8 @@ base83_encode :: proc(value, length: int, allocator := context.allocator) -> str
|
|||||||
|
|
||||||
for i in 1..=length {
|
for i in 1..=length {
|
||||||
digit := (value / pow(83, length - i)) % 83
|
digit := (value / pow(83, length - i)) % 83
|
||||||
strings.write_byte(&b, ENC_TABLE[digit])
|
strings.write_byte(b, ENC_TABLE[digit])
|
||||||
}
|
}
|
||||||
|
|
||||||
return strings.to_string(b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
@@ -168,6 +164,7 @@ decode :: proc(blurhash: string, width, height: int, punch := 1.0, allocator :=
|
|||||||
|
|
||||||
colors_size := num_x * num_y
|
colors_size := num_x * num_y
|
||||||
colors := make([][3]f32, colors_size)
|
colors := make([][3]f32, colors_size)
|
||||||
|
defer delete(colors)
|
||||||
|
|
||||||
for iter in 0..<colors_size {
|
for iter in 0..<colors_size {
|
||||||
if iter == 0 {
|
if iter == 0 {
|
||||||
@@ -266,6 +263,7 @@ encode :: proc(pixels: []byte, x_components, y_components, width, height, bytes_
|
|||||||
|
|
||||||
builder := strings.builder_make_len_cap(0, 2 + 4 + (9 * 9 - 1) * 2)
|
builder := strings.builder_make_len_cap(0, 2 + 4 + (9 * 9 - 1) * 2)
|
||||||
factors := make([dynamic][3]f32, 0, x_components * y_components)
|
factors := make([dynamic][3]f32, 0, x_components * y_components)
|
||||||
|
defer delete(factors)
|
||||||
|
|
||||||
for y in 0..<y_components {
|
for y in 0..<y_components {
|
||||||
for x in 0..<x_components {
|
for x in 0..<x_components {
|
||||||
@@ -278,7 +276,7 @@ encode :: proc(pixels: []byte, x_components, y_components, width, height, bytes_
|
|||||||
ac := factors[1:]
|
ac := factors[1:]
|
||||||
|
|
||||||
size_flag := (x_components - 1) + (y_components - 1) * 9
|
size_flag := (x_components - 1) + (y_components - 1) * 9
|
||||||
strings.write_string(&builder, base83_encode(size_flag, 1))
|
base83_encode(&builder, size_flag, 1)
|
||||||
|
|
||||||
max_value: f32
|
max_value: f32
|
||||||
|
|
||||||
@@ -290,16 +288,16 @@ encode :: proc(pixels: []byte, x_components, y_components, width, height, bytes_
|
|||||||
|
|
||||||
quantized_max_value := int(max(0, min(82, math.floor(actual_max_value * 166 - 0.5))))
|
quantized_max_value := int(max(0, min(82, math.floor(actual_max_value * 166 - 0.5))))
|
||||||
max_value = f32(quantized_max_value + 1) / 166.0
|
max_value = f32(quantized_max_value + 1) / 166.0
|
||||||
strings.write_string(&builder, base83_encode(quantized_max_value, 1))
|
base83_encode(&builder, quantized_max_value, 1)
|
||||||
} else {
|
} else {
|
||||||
max_value = 1
|
max_value = 1
|
||||||
strings.write_string(&builder, base83_encode(0, 1))
|
base83_encode(&builder, 0, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
strings.write_string(&builder, base83_encode(encode_dc(dc), 4))
|
base83_encode(&builder, encode_dc(dc), 4)
|
||||||
|
|
||||||
for factor in ac {
|
for factor in ac {
|
||||||
strings.write_string(&builder, base83_encode(encode_ac(factor, max_value), 2))
|
base83_encode(&builder, encode_ac(factor, max_value), 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
return strings.to_string(builder), nil
|
return strings.to_string(builder), nil
|
||||||
|
|||||||
+39
-4
@@ -5,20 +5,24 @@ import "core:image"
|
|||||||
import "core:image/qoi"
|
import "core:image/qoi"
|
||||||
import "core:image/png"
|
import "core:image/png"
|
||||||
import "core:slice"
|
import "core:slice"
|
||||||
|
import "core:mem"
|
||||||
import "core:os/os2"
|
import "core:os/os2"
|
||||||
|
|
||||||
import blurhash "../"
|
import blurhash "../"
|
||||||
|
|
||||||
decode_example :: proc() {
|
decode_example :: proc() {
|
||||||
if len(os2.args) < 3 {
|
if len(os2.args) < 3 {
|
||||||
fmt.eprintln("Please the blurhash as an arg")
|
fmt.eprintln("Please input the blurhash as an arg")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
track: mem.Tracking_Allocator
|
||||||
|
mem.tracking_allocator_init(&track, context.allocator)
|
||||||
|
alloc := mem.tracking_allocator(&track)
|
||||||
|
|
||||||
width := 400
|
width := 400
|
||||||
height := 240
|
height := 240
|
||||||
pixels, err := blurhash.decode(os2.args[2], width, height, 1.2)
|
pixels, err := blurhash.decode(os2.args[2], width, height, 1.2, alloc)
|
||||||
defer delete(pixels)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.eprintln(err)
|
fmt.eprintln(err)
|
||||||
return
|
return
|
||||||
@@ -35,6 +39,20 @@ decode_example :: proc() {
|
|||||||
fmt.eprintln(save_err)
|
fmt.eprintln(save_err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete(pixels, alloc)
|
||||||
|
|
||||||
|
for _, leak in track.allocation_map {
|
||||||
|
fmt.printfln("%v leaked %m", leak.location, leak.size)
|
||||||
|
}
|
||||||
|
for bad_free in track.bad_free_array {
|
||||||
|
fmt.printfln("%v allocation %p was freed badly", bad_free.location, bad_free.memory)
|
||||||
|
}
|
||||||
|
fmt.printfln("Peak Mem: %m", track.peak_memory_allocated)
|
||||||
|
fmt.printfln("Total Mem: %m", track.total_memory_allocated)
|
||||||
|
fmt.printfln("Current Mem: %m", track.current_memory_allocated)
|
||||||
|
fmt.printfln("Total Allocs: %v, Total Frees: %v:", track.total_allocation_count, track.total_free_count)
|
||||||
|
fmt.printfln("Total Mem Free'd: %m", track.total_memory_freed)
|
||||||
}
|
}
|
||||||
|
|
||||||
encode_example :: proc() {
|
encode_example :: proc() {
|
||||||
@@ -49,13 +67,30 @@ encode_example :: proc() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
bhash, hash_err := blurhash.encode(img.pixels.buf[:], 5, 4, img.width, img.height, img.width*img.channels)
|
track: mem.Tracking_Allocator
|
||||||
|
mem.tracking_allocator_init(&track, context.allocator)
|
||||||
|
alloc := mem.tracking_allocator(&track)
|
||||||
|
|
||||||
|
bhash, hash_err := blurhash.encode(img.pixels.buf[:], 5, 4, img.width, img.height, img.width*img.channels, alloc)
|
||||||
if hash_err != nil {
|
if hash_err != nil {
|
||||||
fmt.eprintln(hash_err)
|
fmt.eprintln(hash_err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.println(bhash)
|
fmt.println(bhash)
|
||||||
|
delete(bhash, alloc)
|
||||||
|
|
||||||
|
for _, leak in track.allocation_map {
|
||||||
|
fmt.printfln("%v leaked %m", leak.location, leak.size)
|
||||||
|
}
|
||||||
|
for bad_free in track.bad_free_array {
|
||||||
|
fmt.printfln("%v allocation %p was freed badly", bad_free.location, bad_free.memory)
|
||||||
|
}
|
||||||
|
fmt.printfln("Peak Mem: %m", track.peak_memory_allocated)
|
||||||
|
fmt.printfln("Total Mem: %m", track.total_memory_allocated)
|
||||||
|
fmt.printfln("Current Mem: %m", track.current_memory_allocated)
|
||||||
|
fmt.printfln("Total Allocs: %v, Total Frees: %v:", track.total_allocation_count, track.total_free_count)
|
||||||
|
fmt.printfln("Total Mem Free'd: %m", track.total_memory_freed)
|
||||||
}
|
}
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
|
|||||||
Reference in New Issue
Block a user