From 01e8e682c0a6021c117553c53f181487be1c841c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 14 May 2022 14:38:26 +0100 Subject: [PATCH 01/12] Generalized `core:image` loader ```odin import "core:image" import "core:image/png" ... img, err := image.load_from_file("path.png") ``` --- core/image/common.odin | 1 + core/image/general_loader.odin | 39 ++++++++++++++++++++++++++++++++++ core/image/netpbm/netpbm.odin | 12 +++++++++++ core/image/png/png.odin | 6 ++++++ core/image/qoi/qoi.odin | 5 +++++ 5 files changed, 63 insertions(+) create mode 100644 core/image/general_loader.odin diff --git a/core/image/common.odin b/core/image/common.odin index 4085a0a05..75a649e52 100644 --- a/core/image/common.odin +++ b/core/image/common.odin @@ -172,6 +172,7 @@ General_Image_Error :: enum { Unable_To_Write_File, // Invalid + Unsupported_Format, Invalid_Signature, Invalid_Input_Image, Image_Dimensions_Too_Large, diff --git a/core/image/general_loader.odin b/core/image/general_loader.odin new file mode 100644 index 000000000..73f50f055 --- /dev/null +++ b/core/image/general_loader.odin @@ -0,0 +1,39 @@ +package image + +import "core:mem" +import "core:os" + +Loader_Proc :: #type proc(data: []byte, options: Options, allocator: mem.Allocator) -> (img: ^Image, err: Error) + +@(private) +_internal_loaders: [Which_File_Type]Loader_Proc + +register_loader :: proc(kind: Which_File_Type, loader: Loader_Proc) { + assert(_internal_loaders[kind] == nil) + _internal_loaders[kind] = loader +} + +load :: proc{ + load_from_slice, + load_from_file, +} + +load_from_slice :: proc(data: []u8, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { + loader := _internal_loaders[which(data)] + if loader == nil { + return nil, .Unsupported_Format + } + return loader(data, options, allocator) +} + + +load_from_file :: proc(filename: string, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { + data, ok := os.read_entire_file(filename, allocator) + defer delete(data, allocator) + if ok { + return load_from_slice(data, options, allocator) + } else { + img = new(Image, allocator) + return img, .Unable_To_Read_File + } +} diff --git a/core/image/netpbm/netpbm.odin b/core/image/netpbm/netpbm.odin index 9574faa26..bcc78c402 100644 --- a/core/image/netpbm/netpbm.odin +++ b/core/image/netpbm/netpbm.odin @@ -748,4 +748,16 @@ autoselect_pbm_format_from_image :: proc(img: ^Image, prefer_binary := true, for // We couldn't find a suitable format return {}, false +} + +@(init, private) +_register :: proc() { + loader :: proc(data: []byte, options: Options, allocator: mem.Allocator) -> (img: ^Image, err: Error) { + return load_from_buffer(data, allocator) + } + register_loader(.PBM, loader) + register_loader(.PGM, loader) + register_loader(.PPM, loader) + register_loader(.PAM, loader) + register_loader(.PFM, loader) } \ No newline at end of file diff --git a/core/image/png/png.odin b/core/image/png/png.odin index d526dfb27..3dcd0df38 100644 --- a/core/image/png/png.odin +++ b/core/image/png/png.odin @@ -1640,3 +1640,9 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IH } load :: proc{load_from_file, load_from_slice, load_from_context} + + +@(init, private) +_register :: proc() { + image.register_loader(.PNG, load_from_slice) +} \ No newline at end of file diff --git a/core/image/qoi/qoi.odin b/core/image/qoi/qoi.odin index 83b212be8..346356094 100644 --- a/core/image/qoi/qoi.odin +++ b/core/image/qoi/qoi.odin @@ -403,4 +403,9 @@ qoi_hash :: #force_inline proc(pixel: RGBA_Pixel) -> (index: u8) { i4 := u16(pixel.a) * 11 return u8((i1 + i2 + i3 + i4) & 63) +} + +@(init, private) +_register :: proc() { + image.register_loader(.QOI, load_from_slice) } \ No newline at end of file From 5af7004f442c9790b176b46053185c42f9d65704 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 14 May 2022 14:43:50 +0100 Subject: [PATCH 02/12] Add image packages to examples/all --- core/image/netpbm/netpbm.odin | 10 +++++----- examples/all/all_main.odin | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/core/image/netpbm/netpbm.odin b/core/image/netpbm/netpbm.odin index bcc78c402..fb88cdc8c 100644 --- a/core/image/netpbm/netpbm.odin +++ b/core/image/netpbm/netpbm.odin @@ -755,9 +755,9 @@ _register :: proc() { loader :: proc(data: []byte, options: Options, allocator: mem.Allocator) -> (img: ^Image, err: Error) { return load_from_buffer(data, allocator) } - register_loader(.PBM, loader) - register_loader(.PGM, loader) - register_loader(.PPM, loader) - register_loader(.PAM, loader) - register_loader(.PFM, loader) + image.register_loader(.PBM, loader) + image.register_loader(.PGM, loader) + image.register_loader(.PPM, loader) + image.register_loader(.PAM, loader) + image.register_loader(.PFM, loader) } \ No newline at end of file diff --git a/examples/all/all_main.odin b/examples/all/all_main.odin index 36acf7714..5a0bc4d3e 100644 --- a/examples/all/all_main.odin +++ b/examples/all/all_main.odin @@ -62,8 +62,10 @@ import fmt "core:fmt" import hash "core:hash" import image "core:image" +import netpbm "core:image/netpbm" import png "core:image/png" import qoi "core:image/qoi" +import tga "core:image/tga" import io "core:io" import log "core:log" From 5bc866e420d8eb9e909db71e230d1283c6116d7e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 14 May 2022 14:44:24 +0100 Subject: [PATCH 03/12] Allow for `import _ "foo"` to allow for `@(init)` procedures; Remove `using import` code --- src/checker.cpp | 48 ++++++++++-------------------------------------- src/parser.cpp | 14 ++++---------- src/parser.hpp | 1 - 3 files changed, 14 insertions(+), 49 deletions(-) diff --git a/src/checker.cpp b/src/checker.cpp index d186163e4..da9a97622 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -4356,6 +4356,9 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { } String import_name = path_to_entity_name(id->import_name.string, id->fullpath, false); + if (is_blank_ident(import_name)) { + force_use = true; + } // NOTE(bill, 2019-05-19): If the directory path is not a valid entity name, force the user to assign a custom one // if (import_name.len == 0 || import_name == "_") { @@ -4363,17 +4366,13 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { // } if (import_name.len == 0 || is_blank_ident(import_name)) { - if (id->is_using) { - // TODO(bill): Should this be a warning? - } else { - if (id->import_name.string == "") { - String invalid_name = id->fullpath; - invalid_name = get_invalid_import_name(invalid_name); + if (id->import_name.string == "") { + String invalid_name = id->fullpath; + invalid_name = get_invalid_import_name(invalid_name); - error(id->token, "Import name %.*s, is not a valid identifier. Perhaps you want to reference the package by a different name like this: import \"%.*s\" ", LIT(invalid_name), LIT(invalid_name)); - } else { - error(token, "Import name, %.*s, cannot be use as an import name as it is not a valid identifier", LIT(id->import_name.string)); - } + error(id->token, "Import name %.*s, is not a valid identifier. Perhaps you want to reference the package by a different name like this: import \"%.*s\" ", LIT(invalid_name), LIT(invalid_name)); + } else { + error(token, "Import name, %.*s, cannot be use as an import name as it is not a valid identifier", LIT(id->import_name.string)); } } else { GB_ASSERT(id->import_name.pos.line != 0); @@ -4383,38 +4382,11 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { scope); add_entity(ctx, parent_scope, nullptr, e); - if (force_use || id->is_using) { + if (force_use) { add_entity_use(ctx, nullptr, e); } } - if (id->is_using) { - if (parent_scope->flags & ScopeFlag_Global) { - error(id->import_name, "built-in package imports cannot use using"); - return; - } - - // NOTE(bill): Add imported entities to this file's scope - for_array(elem_index, scope->elements.entries) { - String name = scope->elements.entries[elem_index].key.string; - Entity *e = scope->elements.entries[elem_index].value; - if (e->scope == parent_scope) continue; - - if (is_entity_exported(e, true)) { - Entity *found = scope_lookup_current(parent_scope, name); - if (found != nullptr) { - // NOTE(bill): - // Date: 2019-03-17 - // The order has to be the other way around as `using` adds the entity into the that - // file scope otherwise the error would be the wrong way around - redeclaration_error(name, found, e); - } else { - add_entity_with_name(ctx, parent_scope, e->identifier, e, name); - } - } - } - } - scope->flags |= ScopeFlag_HasBeenImported; } diff --git a/src/parser.cpp b/src/parser.cpp index df7f908a6..1f4093e5f 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1160,11 +1160,10 @@ Ast *ast_package_decl(AstFile *f, Token token, Token name, CommentGroup *docs, C return result; } -Ast *ast_import_decl(AstFile *f, Token token, bool is_using, Token relpath, Token import_name, +Ast *ast_import_decl(AstFile *f, Token token, Token relpath, Token import_name, CommentGroup *docs, CommentGroup *comment) { Ast *result = alloc_ast_node(f, Ast_ImportDecl); result->ImportDecl.token = token; - result->ImportDecl.is_using = is_using; result->ImportDecl.relpath = relpath; result->ImportDecl.import_name = import_name; result->ImportDecl.docs = docs; @@ -4382,7 +4381,6 @@ Ast *parse_import_decl(AstFile *f, ImportDeclKind kind) { CommentGroup *docs = f->lead_comment; Token token = expect_token(f, Token_import); Token import_name = {}; - bool is_using = kind != ImportDecl_Standard; switch (f->curr_token.kind) { case Token_Ident: @@ -4393,22 +4391,18 @@ Ast *parse_import_decl(AstFile *f, ImportDeclKind kind) { break; } - if (!is_using && is_blank_ident(import_name)) { - syntax_error(import_name, "Illegal import name: '_'"); - } - Token file_path = expect_token_after(f, Token_String, "import"); Ast *s = nullptr; if (f->curr_proc != nullptr) { - syntax_error(import_name, "You cannot use 'import' within a procedure. This must be done at the file scope"); + syntax_error(import_name, "Cannot use 'import' within a procedure. This must be done at the file scope"); s = ast_bad_decl(f, import_name, file_path); } else { - s = ast_import_decl(f, token, is_using, file_path, import_name, docs, f->line_comment); + s = ast_import_decl(f, token, file_path, import_name, docs, f->line_comment); array_add(&f->imports, s); } - if (is_using) { + if (kind != ImportDecl_Standard) { syntax_error(import_name, "'using import' is not allowed, please use the import name explicitly"); } diff --git a/src/parser.hpp b/src/parser.hpp index c7b4fd0d8..698ed7623 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -585,7 +585,6 @@ AST_KIND(_DeclBegin, "", bool) \ Token import_name; \ CommentGroup *docs; \ CommentGroup *comment; \ - bool is_using; \ }) \ AST_KIND(ForeignImportDecl, "foreign import declaration", struct { \ Token token; \ From e46d87b2210a1e2f0aa95827808f3b69b11f17dc Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 14 May 2022 14:47:58 +0100 Subject: [PATCH 04/12] Fix type and keep -vet happy --- core/image/netpbm/netpbm.odin | 2 +- core/image/tga/tga.odin | 1 - examples/all/all_main.odin | 2 ++ 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core/image/netpbm/netpbm.odin b/core/image/netpbm/netpbm.odin index fb88cdc8c..83c8a2f59 100644 --- a/core/image/netpbm/netpbm.odin +++ b/core/image/netpbm/netpbm.odin @@ -752,7 +752,7 @@ autoselect_pbm_format_from_image :: proc(img: ^Image, prefer_binary := true, for @(init, private) _register :: proc() { - loader :: proc(data: []byte, options: Options, allocator: mem.Allocator) -> (img: ^Image, err: Error) { + loader :: proc(data: []byte, options: image.Options, allocator: mem.Allocator) -> (img: ^Image, err: Error) { return load_from_buffer(data, allocator) } image.register_loader(.PBM, loader) diff --git a/core/image/tga/tga.odin b/core/image/tga/tga.odin index 0539706b3..67a088eb5 100644 --- a/core/image/tga/tga.odin +++ b/core/image/tga/tga.odin @@ -12,7 +12,6 @@ package tga import "core:mem" import "core:image" -import "core:compress" import "core:bytes" import "core:os" diff --git a/examples/all/all_main.odin b/examples/all/all_main.odin index 5a0bc4d3e..36326b48e 100644 --- a/examples/all/all_main.odin +++ b/examples/all/all_main.odin @@ -166,8 +166,10 @@ _ :: xml _ :: fmt _ :: hash _ :: image +_ :: netpbm _ :: png _ :: qoi +_ :: tga _ :: io _ :: log _ :: math From 9c1f270bd56e367a34691517daa11194d2ef14e9 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 14 May 2022 14:55:15 +0100 Subject: [PATCH 05/12] Rename `load_from_slice` to `load_from_bytes` across `core` --- core/compress/gzip/example.odin | 2 +- core/compress/gzip/gzip.odin | 8 ++++---- core/image/general_loader.odin | 6 +++--- core/image/png/png.odin | 14 ++++++-------- core/image/qoi/qoi.odin | 10 +++++----- 5 files changed, 19 insertions(+), 21 deletions(-) diff --git a/core/compress/gzip/example.odin b/core/compress/gzip/example.odin index 0e2c2b9f6..c010d5979 100644 --- a/core/compress/gzip/example.odin +++ b/core/compress/gzip/example.odin @@ -45,7 +45,7 @@ main :: proc() { if len(args) < 2 { stderr("No input file specified.\n") - err := load(slice=TEST, buf=&buf, known_gzip_size=len(TEST)) + err := load(data=TEST, buf=&buf, known_gzip_size=len(TEST)) if err == nil { stdout("Displaying test vector: ") stdout(bytes.buffer_to_string(&buf)) diff --git a/core/compress/gzip/gzip.odin b/core/compress/gzip/gzip.odin index 4482d4a7e..4de4d1b63 100644 --- a/core/compress/gzip/gzip.odin +++ b/core/compress/gzip/gzip.odin @@ -102,7 +102,7 @@ E_Deflate :: compress.Deflate_Error GZIP_MAX_PAYLOAD_SIZE :: i64(max(u32le)) -load :: proc{load_from_slice, load_from_file, load_from_context} +load :: proc{load_from_bytes, load_from_file, load_from_context} load_from_file :: proc(filename: string, buf: ^bytes.Buffer, expected_output_size := -1, allocator := context.allocator) -> (err: Error) { context.allocator = allocator @@ -112,16 +112,16 @@ load_from_file :: proc(filename: string, buf: ^bytes.Buffer, expected_output_siz err = E_General.File_Not_Found if ok { - err = load_from_slice(data, buf, len(data), expected_output_size) + err = load_from_bytes(data, buf, len(data), expected_output_size) } return } -load_from_slice :: proc(slice: []u8, buf: ^bytes.Buffer, known_gzip_size := -1, expected_output_size := -1, allocator := context.allocator) -> (err: Error) { +load_from_bytes :: proc(data: []byte, buf: ^bytes.Buffer, known_gzip_size := -1, expected_output_size := -1, allocator := context.allocator) -> (err: Error) { buf := buf z := &compress.Context_Memory_Input{ - input_data = slice, + input_data = data, output = buf, } return load_from_context(z, buf, known_gzip_size, expected_output_size, allocator) diff --git a/core/image/general_loader.odin b/core/image/general_loader.odin index 73f50f055..4cc8569ab 100644 --- a/core/image/general_loader.odin +++ b/core/image/general_loader.odin @@ -14,11 +14,11 @@ register_loader :: proc(kind: Which_File_Type, loader: Loader_Proc) { } load :: proc{ - load_from_slice, + load_from_bytes, load_from_file, } -load_from_slice :: proc(data: []u8, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { +load_from_bytes :: proc(data: []byte, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { loader := _internal_loaders[which(data)] if loader == nil { return nil, .Unsupported_Format @@ -31,7 +31,7 @@ load_from_file :: proc(filename: string, options := Options{}, allocator := cont data, ok := os.read_entire_file(filename, allocator) defer delete(data, allocator) if ok { - return load_from_slice(data, options, allocator) + return load_from_bytes(data, options, allocator) } else { img = new(Image, allocator) return img, .Unable_To_Read_File diff --git a/core/image/png/png.odin b/core/image/png/png.odin index 3dcd0df38..f91ad2b66 100644 --- a/core/image/png/png.odin +++ b/core/image/png/png.odin @@ -18,7 +18,6 @@ import "core:compress/zlib" import "core:image" import "core:os" -import "core:strings" import "core:hash" import "core:bytes" import "core:io" @@ -318,13 +317,12 @@ read_header :: proc(ctx: ^$C) -> (image.PNG_IHDR, Error) { } chunk_type_to_name :: proc(type: ^image.PNG_Chunk_Type) -> string { - t := transmute(^u8)type - return strings.string_from_ptr(t, 4) + return string(([^]u8)(type)[:4]) } -load_from_slice :: proc(slice: []u8, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { +load_from_bytes :: proc(data: []byte, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { ctx := &compress.Context_Memory_Input{ - input_data = slice, + input_data = data, } /* @@ -344,7 +342,7 @@ load_from_file :: proc(filename: string, options := Options{}, allocator := cont defer delete(data) if ok { - return load_from_slice(data, options) + return load_from_bytes(data, options) } else { img = new(Image) return img, .Unable_To_Read_File @@ -1639,10 +1637,10 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IH return nil } -load :: proc{load_from_file, load_from_slice, load_from_context} +load :: proc{load_from_file, load_from_bytes, load_from_context} @(init, private) _register :: proc() { - image.register_loader(.PNG, load_from_slice) + image.register_loader(.PNG, load_from_bytes) } \ No newline at end of file diff --git a/core/image/qoi/qoi.odin b/core/image/qoi/qoi.odin index 346356094..884f4963b 100644 --- a/core/image/qoi/qoi.odin +++ b/core/image/qoi/qoi.odin @@ -180,9 +180,9 @@ save_to_file :: proc(output: string, img: ^Image, options := Options{}, allocato save :: proc{save_to_memory, save_to_file} -load_from_slice :: proc(slice: []u8, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { +load_from_bytes :: proc(data: []byte, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { ctx := &compress.Context_Memory_Input{ - input_data = slice, + input_data = data, } img, err = load_from_context(ctx, options, allocator) @@ -196,7 +196,7 @@ load_from_file :: proc(filename: string, options := Options{}, allocator := cont defer delete(data) if ok { - return load_from_slice(data, options) + return load_from_bytes(data, options) } else { img = new(Image) return img, .Unable_To_Read_File @@ -359,7 +359,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a return } -load :: proc{load_from_file, load_from_slice, load_from_context} +load :: proc{load_from_file, load_from_bytes, load_from_context} /* Cleanup of image-specific data. @@ -407,5 +407,5 @@ qoi_hash :: #force_inline proc(pixel: RGBA_Pixel) -> (index: u8) { @(init, private) _register :: proc() { - image.register_loader(.QOI, load_from_slice) + image.register_loader(.QOI, load_from_bytes) } \ No newline at end of file From 4e080057fb0f24e66bb6ad4eccb931f1f325da9b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 14 May 2022 15:01:17 +0100 Subject: [PATCH 06/12] Rename `load_from_buffer` to `load_from_bytes` --- core/image/netpbm/netpbm.odin | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/image/netpbm/netpbm.odin b/core/image/netpbm/netpbm.odin index 83c8a2f59..bfaf49fc6 100644 --- a/core/image/netpbm/netpbm.odin +++ b/core/image/netpbm/netpbm.odin @@ -28,7 +28,7 @@ BINARY :: Formats{.P4, .P5, .P6} + PAM + PFM load :: proc { load_from_file, - load_from_buffer, + load_from_bytes, } load_from_file :: proc(filename: string, allocator := context.allocator) -> (img: ^Image, err: Error) { @@ -40,10 +40,10 @@ load_from_file :: proc(filename: string, allocator := context.allocator) -> (img return } - return load_from_buffer(data) + return load_from_bytes(data) } -load_from_buffer :: proc(data: []byte, allocator := context.allocator) -> (img: ^Image, err: Error) { +load_from_bytes :: proc(data: []byte, allocator := context.allocator) -> (img: ^Image, err: Error) { context.allocator = allocator img = new(Image) @@ -753,7 +753,7 @@ autoselect_pbm_format_from_image :: proc(img: ^Image, prefer_binary := true, for @(init, private) _register :: proc() { loader :: proc(data: []byte, options: image.Options, allocator: mem.Allocator) -> (img: ^Image, err: Error) { - return load_from_buffer(data, allocator) + return load_from_bytes(data, allocator) } image.register_loader(.PBM, loader) image.register_loader(.PGM, loader) From 3aa0a733f3b59388ae320f07cfabb1f4e7f0cec2 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 14 May 2022 15:06:55 +0100 Subject: [PATCH 07/12] Add `destroy` with loader --- core/image/general_loader.odin | 12 +++++++++--- core/image/netpbm/netpbm.odin | 13 ++++++++----- core/image/png/png.odin | 5 ++--- core/image/qoi/qoi.odin | 5 ++--- 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/core/image/general_loader.odin b/core/image/general_loader.odin index 4cc8569ab..3acffb452 100644 --- a/core/image/general_loader.odin +++ b/core/image/general_loader.odin @@ -4,13 +4,20 @@ import "core:mem" import "core:os" Loader_Proc :: #type proc(data: []byte, options: Options, allocator: mem.Allocator) -> (img: ^Image, err: Error) +Destroy_Proc :: #type proc(img: ^Image) @(private) _internal_loaders: [Which_File_Type]Loader_Proc +_internal_destroyers: [Which_File_Type]Destroy_Proc -register_loader :: proc(kind: Which_File_Type, loader: Loader_Proc) { +register :: proc(kind: Which_File_Type, loader: Loader_Proc, destroyer: Destroy_Proc) { + assert(loader != nil) + assert(destroyer != nil) assert(_internal_loaders[kind] == nil) _internal_loaders[kind] = loader + + assert(_internal_destroyers[kind] == nil) + _internal_destroyers[kind] = destroyer } load :: proc{ @@ -33,7 +40,6 @@ load_from_file :: proc(filename: string, options := Options{}, allocator := cont if ok { return load_from_bytes(data, options, allocator) } else { - img = new(Image, allocator) - return img, .Unable_To_Read_File + return nil, .Unable_To_Read_File } } diff --git a/core/image/netpbm/netpbm.odin b/core/image/netpbm/netpbm.odin index bfaf49fc6..778ec2c5e 100644 --- a/core/image/netpbm/netpbm.odin +++ b/core/image/netpbm/netpbm.odin @@ -755,9 +755,12 @@ _register :: proc() { loader :: proc(data: []byte, options: image.Options, allocator: mem.Allocator) -> (img: ^Image, err: Error) { return load_from_bytes(data, allocator) } - image.register_loader(.PBM, loader) - image.register_loader(.PGM, loader) - image.register_loader(.PPM, loader) - image.register_loader(.PAM, loader) - image.register_loader(.PFM, loader) + destroyer :: proc(img: ^Image) { + _ = destroy(img) + } + image.register(.PBM, loader, destroyer) + image.register(.PGM, loader, destroyer) + image.register(.PPM, loader, destroyer) + image.register(.PAM, loader, destroyer) + image.register(.PFM, loader, destroyer) } \ No newline at end of file diff --git a/core/image/png/png.odin b/core/image/png/png.odin index f91ad2b66..ea888d0ad 100644 --- a/core/image/png/png.odin +++ b/core/image/png/png.odin @@ -344,8 +344,7 @@ load_from_file :: proc(filename: string, options := Options{}, allocator := cont if ok { return load_from_bytes(data, options) } else { - img = new(Image) - return img, .Unable_To_Read_File + return nil, .Unable_To_Read_File } } @@ -1642,5 +1641,5 @@ load :: proc{load_from_file, load_from_bytes, load_from_context} @(init, private) _register :: proc() { - image.register_loader(.PNG, load_from_bytes) + image.register(.PNG, load_from_bytes, destroy) } \ No newline at end of file diff --git a/core/image/qoi/qoi.odin b/core/image/qoi/qoi.odin index 884f4963b..f10f2ff56 100644 --- a/core/image/qoi/qoi.odin +++ b/core/image/qoi/qoi.odin @@ -198,8 +198,7 @@ load_from_file :: proc(filename: string, options := Options{}, allocator := cont if ok { return load_from_bytes(data, options) } else { - img = new(Image) - return img, .Unable_To_Read_File + return nil, .Unable_To_Read_File } } @@ -407,5 +406,5 @@ qoi_hash :: #force_inline proc(pixel: RGBA_Pixel) -> (index: u8) { @(init, private) _register :: proc() { - image.register_loader(.QOI, load_from_bytes) + image.register(.QOI, load_from_bytes, destroy) } \ No newline at end of file From c516fb947f7aafd00363dfcdaefa79f96e4f4ee5 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 14 May 2022 15:11:23 +0100 Subject: [PATCH 08/12] Add `image.destroy` --- core/image/common.odin | 1 + core/image/general_loader.odin | 13 +++++++++++++ core/image/netpbm/netpbm.odin | 7 ++----- core/image/png/png.odin | 1 + core/image/qoi/qoi.odin | 1 + core/image/which.odin | 22 +++++++++++----------- 6 files changed, 29 insertions(+), 16 deletions(-) diff --git a/core/image/common.odin b/core/image/common.odin index 75a649e52..28129a6e1 100644 --- a/core/image/common.odin +++ b/core/image/common.odin @@ -54,6 +54,7 @@ Image :: struct { */ background: Maybe(RGB_Pixel_16), metadata: Image_Metadata, + which: Which_File_Type, } Image_Metadata :: union { diff --git a/core/image/general_loader.odin b/core/image/general_loader.odin index 3acffb452..79f5fb737 100644 --- a/core/image/general_loader.odin +++ b/core/image/general_loader.odin @@ -43,3 +43,16 @@ load_from_file :: proc(filename: string, options := Options{}, allocator := cont return nil, .Unable_To_Read_File } } + +destroy :: proc(img: ^Image, allocator := context.allocator) -> bool { + if img == nil { + return true + } + context.allocator = allocator + destroyer := _internal_destroyers[img.which] + if destroyer != nil { + destroyer(img) + } + free(img) + return true +} \ No newline at end of file diff --git a/core/image/netpbm/netpbm.odin b/core/image/netpbm/netpbm.odin index 778ec2c5e..5a504cd7c 100644 --- a/core/image/netpbm/netpbm.odin +++ b/core/image/netpbm/netpbm.odin @@ -47,6 +47,7 @@ load_from_bytes :: proc(data: []byte, allocator := context.allocator) -> (img: ^ context.allocator = allocator img = new(Image) + img.which = .NetPBM header: Header; defer header_destroy(&header) header_size: int @@ -758,9 +759,5 @@ _register :: proc() { destroyer :: proc(img: ^Image) { _ = destroy(img) } - image.register(.PBM, loader, destroyer) - image.register(.PGM, loader, destroyer) - image.register(.PPM, loader, destroyer) - image.register(.PAM, loader, destroyer) - image.register(.PFM, loader, destroyer) + image.register(.NetPBM, loader, destroyer) } \ No newline at end of file diff --git a/core/image/png/png.odin b/core/image/png/png.odin index ea888d0ad..35fdb58d8 100644 --- a/core/image/png/png.odin +++ b/core/image/png/png.odin @@ -372,6 +372,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a if img == nil { img = new(Image) } + img.which = .PNG info := new(image.PNG_Info) img.metadata = info diff --git a/core/image/qoi/qoi.odin b/core/image/qoi/qoi.odin index f10f2ff56..29a17d4f4 100644 --- a/core/image/qoi/qoi.odin +++ b/core/image/qoi/qoi.odin @@ -224,6 +224,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a if img == nil { img = new(Image) } + img.which = .QOI if .return_metadata in options { info := new(image.QOI_Info) diff --git a/core/image/which.odin b/core/image/which.odin index 30cb78405..82cb03ce6 100644 --- a/core/image/which.odin +++ b/core/image/which.odin @@ -14,7 +14,7 @@ Which_File_Type :: enum { JPEG, JPEG_2000, JPEG_XL, - PBM, PGM, PPM, PAM, PFM, // NetPBM family + NetPBM, // NetPBM family PIC, // Softimage PIC PNG, // Portable Network Graphics PSD, // Photoshop PSD @@ -111,16 +111,16 @@ which_bytes :: proc(data: []byte) -> Which_File_Type { switch s[2] { case '\t', '\n', '\r': switch s[1] { - case '1', '4': - return .PBM - case '2', '5': - return .PGM - case '3', '6': - return .PPM - case '7': - return .PAM - case 'F', 'f': - return .PFM + case '1', '4': // PBM + return .NetPBM + case '2', '5': // PGM + return .NetPBM + case '3', '6': // PPM + return .NetPBM + case '7': // PAM + return .NetPBM + case 'F', 'f': // PFM + return .NetPBM } } case s[:8] == "\x89PNG\r\n\x1a\n": From e8485ee7e7b5487bad1e195235a93543c82b630a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 14 May 2022 15:15:04 +0100 Subject: [PATCH 09/12] Correction to `image.destroy` --- core/image/common.odin | 2 +- core/image/general_loader.odin | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/image/common.odin b/core/image/common.odin index 28129a6e1..baacd64d9 100644 --- a/core/image/common.odin +++ b/core/image/common.odin @@ -57,7 +57,7 @@ Image :: struct { which: Which_File_Type, } -Image_Metadata :: union { +Image_Metadata :: union #shared_nil { ^Netpbm_Info, ^PNG_Info, ^QOI_Info, diff --git a/core/image/general_loader.odin b/core/image/general_loader.odin index 79f5fb737..bf0061311 100644 --- a/core/image/general_loader.odin +++ b/core/image/general_loader.odin @@ -52,7 +52,9 @@ destroy :: proc(img: ^Image, allocator := context.allocator) -> bool { destroyer := _internal_destroyers[img.which] if destroyer != nil { destroyer(img) + } else { + assert(img.metadata == nil) + free(img) } - free(img) return true } \ No newline at end of file From 22dc02064795a72d5ea4704195638e6f10d7b434 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 14 May 2022 15:16:14 +0100 Subject: [PATCH 10/12] Destroy pixel buffer --- core/image/general_loader.odin | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/image/general_loader.odin b/core/image/general_loader.odin index bf0061311..21a662967 100644 --- a/core/image/general_loader.odin +++ b/core/image/general_loader.odin @@ -2,6 +2,7 @@ package image import "core:mem" import "core:os" +import "core:bytes" Loader_Proc :: #type proc(data: []byte, options: Options, allocator: mem.Allocator) -> (img: ^Image, err: Error) Destroy_Proc :: #type proc(img: ^Image) @@ -54,6 +55,7 @@ destroy :: proc(img: ^Image, allocator := context.allocator) -> bool { destroyer(img) } else { assert(img.metadata == nil) + bytes.buffer_destroy(&img.pixels) free(img) } return true From d74e4b427d873b56bf6069c674107197fc44774b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 14 May 2022 15:16:56 +0100 Subject: [PATCH 11/12] Remove `bool` return on `image.destroy` --- core/image/general_loader.odin | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/image/general_loader.odin b/core/image/general_loader.odin index 21a662967..36629c39e 100644 --- a/core/image/general_loader.odin +++ b/core/image/general_loader.odin @@ -45,9 +45,9 @@ load_from_file :: proc(filename: string, options := Options{}, allocator := cont } } -destroy :: proc(img: ^Image, allocator := context.allocator) -> bool { +destroy :: proc(img: ^Image, allocator := context.allocator) { if img == nil { - return true + return } context.allocator = allocator destroyer := _internal_destroyers[img.which] @@ -58,5 +58,4 @@ destroy :: proc(img: ^Image, allocator := context.allocator) -> bool { bytes.buffer_destroy(&img.pixels) free(img) } - return true } \ No newline at end of file From f7b18cd86ebce34f4b62ba313a998bc45c513d04 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 14 May 2022 15:32:28 +0100 Subject: [PATCH 12/12] Add DjVu --- core/image/which.odin | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/image/which.odin b/core/image/which.odin index 82cb03ce6..ab608174f 100644 --- a/core/image/which.odin +++ b/core/image/which.odin @@ -6,6 +6,7 @@ Which_File_Type :: enum { Unknown, BMP, + DjVu, // AT&T DjVu file format EXR, FLIF, GIF, @@ -88,6 +89,11 @@ which_bytes :: proc(data: []byte) -> Which_File_Type { switch { case s[:2] == "BM": return .BMP + case s[:8] == "AT&TFORM": + switch s[12:16] { + case "DJVU", "DJVM": + return .DjVu + } case s[:4] == "\x76\x2f\x31\x01": return .EXR case s[:6] == "GIF87a", s[:6] == "GIF89a":