aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/bytes/util.odin187
-rw-r--r--core/image/png/example.odin48
2 files changed, 24 insertions, 211 deletions
diff --git a/core/bytes/util.odin b/core/bytes/util.odin
deleted file mode 100644
index a93e3e479..000000000
--- a/core/bytes/util.odin
+++ /dev/null
@@ -1,187 +0,0 @@
-package bytes
-
-/*
- Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
- Made available under Odin's BSD-2 license.
-
- List of contributors:
- Jeroen van Rijn: Initial implementation.
-
- `bytes.Buffer` type conversion helpers.
-*/
-
-import "core:intrinsics"
-import "core:mem"
-
-need_endian_conversion :: proc($FT: typeid, $TT: typeid) -> (res: bool) {
-
- // true if platform endian
- f: bool;
- t: bool;
-
- when ODIN_ENDIAN == "little" {
- f = intrinsics.type_is_endian_platform(FT) || intrinsics.type_is_endian_little(FT);
- t = intrinsics.type_is_endian_platform(TT) || intrinsics.type_is_endian_little(TT);
-
- return f != t;
- } else {
- f = intrinsics.type_is_endian_platform(FT) || intrinsics.type_is_endian_big(FT);
- t = intrinsics.type_is_endian_platform(TT) || intrinsics.type_is_endian_big(TT);
-
- return f != t;
- }
-
- return;
-}
-
-/*
- Input:
- count: number of elements
- $TT: destination type
- $FT: source type
- from_buffer: buffer to convert
- force_convert: cast each element separately
-
- Output:
- res: Converted/created buffer of []TT.
- backing: ^bytes.Buffer{} backing the converted data.
- alloc: Buffer was freshly allocated because we couldn't convert in-place. Points to `from_buffer` if `false`.
- err: True if we passed too few elements or allocation failed, etc.
-
- If `from_buffer` is empty, the input type $FT is ignored and `create_buffer_of_type` is called to create a fresh buffer.
-
- This helper will try to do as little work as possible, so if you're converting between two equally sized types,
- and they have compatible endianness, the contents will simply be reinterpreted using `slice_data_cast`.
-
- If you want each element to be converted in this case, set `force_convert` to `true`.
-
- For example, converting `[]u8{0, 60}` from `[]f16` to `[]u16` will return `[15360]` when simply reinterpreted,
- and `[1]` if force converted.
-
- Should you for example want to promote `[]f16` to `[]f32` (or truncate `[]f32` to `[]f16`), the size of these elements
- being different will result in a conversion anyway, so this flag is unnecessary in cases like these.
-
- Example:
- fmt.println("Convert []f16le (x2) to []f32 (x2).");
- b := []u8{0, 60, 0, 60}; // == []f16{1.0, 1.0}
-
- res, backing, had_to_allocate, err := bytes.buffer_convert_to_type(2, f32, f16le, b);
- fmt.printf("res : %v\n", res); // [1.000, 1.000]
- fmt.printf("backing : %v\n", backing); // &Buffer{buf = [0, 0, 128, 63, 0, 0, 128, 63], off = 0, last_read = Invalid}
- fmt.printf("allocated: %v\n", had_to_allocate); // true
- fmt.printf("err : %v\n", err); // false
-
- if had_to_allocate { defer bytes.buffer_destroy(backing); }
-
- fmt.println("\nConvert []f16le (x2) to []u16 (x2).");
-
- res2: []u16;
- res2, backing, had_to_allocate, err = bytes.buffer_convert_to_type(2, u16, f16le, b);
- fmt.printf("res : %v\n", res2); // [15360, 15360]
- fmt.printf("backing : %v\n", backing); // Buffer.buf points to `b` because it could be converted in-place.
- fmt.printf("allocated: %v\n", had_to_allocate); // false
- fmt.printf("err : %v\n", err); // false
-
- if had_to_allocate { defer bytes.buffer_destroy(backing); }
-
- fmt.println("\nConvert []f16le (x2) to []u16 (x2), force_convert=true.");
-
- res2, backing, had_to_allocate, err = bytes.buffer_convert_to_type(2, u16, f16le, b, true);
- fmt.printf("res : %v\n", res2); // [1, 1]
- fmt.printf("backing : %v\n", backing); // Buffer.buf points to `b` because it could be converted in-place.
- fmt.printf("allocated: %v\n", had_to_allocate); // false
- fmt.printf("err : %v\n", err); // false
-
- if had_to_allocate { defer bytes.buffer_destroy(backing); }
-*/
-buffer_convert_to_type :: proc(count: int, $TT: typeid, $FT: typeid, from_buffer: []u8, force_convert := false) -> (
- res: []TT, backing: ^Buffer, alloc: bool, err: bool) {
-
- backing = new(Buffer);
-
- if len(from_buffer) > 0 {
- /*
- Check if we've been given enough input elements.
- */
- from := mem.slice_data_cast([]FT, from_buffer);
- if len(from) != count {
- err = true;
- return;
- }
-
- /*
- We can early out if the types are exactly identical.
- This needs to be `when`, or res = from will fail if the types are different.
- */
- when FT == TT {
- res = from;
- buffer_init(backing, from_buffer);
- return;
- }
-
- /*
- We can do a data cast if in-size == out-size and no endian conversion is needed.
- */
- convert := need_endian_conversion(FT, TT);
- convert |= (size_of(TT) * count != len(from_buffer));
- convert |= force_convert;
-
- if !convert {
- // It's just a data cast
- res = mem.slice_data_cast([]TT, from_buffer);
- buffer_init(backing, from_buffer);
-
- if len(res) != count {
- err = true;
- }
- return;
- } else {
- if size_of(TT) * count == len(from_buffer) {
- /*
- Same size, can do an in-place Endianness conversion.
- If `force_convert`, this also handles the per-element cast instead of slice_data_cast.
- */
- res = mem.slice_data_cast([]TT, from_buffer);
- buffer_init(backing, from_buffer);
- for v, i in from {
- res[i] = TT(v);
- }
- } else {
- /*
- Result is a different size, we need to allocate an output buffer.
- */
- size := size_of(TT) * count;
- buffer_init_allocator(backing, size, size, context.allocator);
- alloc = true;
- res = mem.slice_data_cast([]TT, backing.buf[:]);
- if len(res) != count {
- err = true;
- return;
- }
-
- for v, i in from {
- res[i] = TT(v);
- }
- }
- }
- } else {
- /*
- The input buffer is empty, so we'll have to create a new one for []TT of length count.
- */
- res, backing, err = buffer_create_of_type(count, TT);
- alloc = true;
- }
-
- return;
-}
-
-buffer_create_of_type :: proc(count: int, $TT: typeid) -> (res: []TT, backing: ^Buffer, err: bool) {
- backing = new(Buffer);
- size := size_of(TT) * count;
- buffer_init_allocator(backing, size, size, context.allocator);
- res = mem.slice_data_cast([]TT, backing.buf[:]);
- if len(res) != count {
- err = true;
- }
- return;
-} \ No newline at end of file
diff --git a/core/image/png/example.odin b/core/image/png/example.odin
index 3891a88e5..f96ef01b2 100644
--- a/core/image/png/example.odin
+++ b/core/image/png/example.odin
@@ -9,12 +9,12 @@ package png
Jeroen van Rijn: Initial implementation.
Ginger Bill: Cosmetic changes.
- An example of how to use `png.load`.
+ An example of how to use `load`.
*/
import "core:compress"
import "core:image"
-import "core:image/png"
+// import "core:image/png"
import "core:bytes"
import "core:fmt"
@@ -31,33 +31,33 @@ main :: proc() {
file = "../../../misc/logo-slim.png";
- img, err = png.load(file, options);
- defer png.destroy(img);
+ img, err = load(file, options);
+ defer destroy(img);
if err != nil {
fmt.printf("Trying to read PNG file %v returned %v\n", file, err);
} else {
- v: ^png.Info;
+ v: ^Info;
fmt.printf("Image: %vx%vx%v, %v-bit.\n", img.width, img.height, img.channels, img.depth);
- if img.metadata_ptr != nil && img.metadata_type == png.Info {
- v = (^png.Info)(img.metadata_ptr);
+ if 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:
- t, _ := png.core_time(c);
+ t, _ := core_time(c);
fmt.printf("[tIME]: %v\n", t);
case .gAMA:
- fmt.printf("[gAMA]: %v\n", png.gamma(c));
+ fmt.printf("[gAMA]: %v\n", gamma(c));
case .pHYs:
- phys := png.phys(c);
+ phys := phys(c);
if phys.unit == .Meter {
xm := f32(img.width) / f32(phys.ppu_x);
ym := f32(img.height) / f32(phys.ppu_y);
- dpi_x, dpi_y := png.phys_to_dpi(phys);
+ 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);
@@ -65,7 +65,7 @@ main :: proc() {
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 := png.text(c);
+ 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);
@@ -73,11 +73,11 @@ main :: proc() {
fmt.printf("[tEXt/zTXt] %v: %v\n", res.keyword, res.text);
}
}
- defer png.text_destroy(res);
+ defer text_destroy(res);
case .bKGD:
fmt.printf("[bKGD] %v\n", img.background);
case .eXIf:
- res, ok_exif := png.exif(c);
+ res, ok_exif := exif(c);
if ok_exif {
/*
Other than checking the signature and byte order, we don't handle Exif data.
@@ -86,45 +86,45 @@ main :: proc() {
fmt.printf("[eXIf] %v\n", res);
}
case .PLTE:
- plte, plte_ok := png.plte(c);
+ plte, plte_ok := plte(c);
if plte_ok {
fmt.printf("[PLTE] %v\n", plte);
} else {
fmt.printf("[PLTE] Error\n");
}
case .hIST:
- res, ok_hist := png.hist(c);
+ res, ok_hist := hist(c);
if ok_hist {
fmt.printf("[hIST] %v\n", res);
}
case .cHRM:
- res, ok_chrm := png.chrm(c);
+ res, ok_chrm := chrm(c);
if ok_chrm {
fmt.printf("[cHRM] %v\n", res);
}
case .sPLT:
- res, ok_splt := png.splt(c);
+ res, ok_splt := splt(c);
if ok_splt {
fmt.printf("[sPLT] %v\n", res);
}
- png.splt_destroy(res);
+ splt_destroy(res);
case .sBIT:
- if res, ok_sbit := png.sbit(c); ok_sbit {
+ if res, ok_sbit := sbit(c); ok_sbit {
fmt.printf("[sBIT] %v\n", res);
}
case .iCCP:
- res, ok_iccp := png.iccp(c);
+ res, ok_iccp := iccp(c);
if ok_iccp {
fmt.printf("[iCCP] %v\n", res);
}
- png.iccp_destroy(res);
+ iccp_destroy(res);
case .sRGB:
- if res, ok_srgb := png.srgb(c); ok_srgb {
+ if res, ok_srgb := srgb(c); ok_srgb {
fmt.printf("[sRGB] Rendering intent: %v\n", res);
}
case:
type := c.header.type;
- name := png.chunk_type_to_name(&type);
+ name := chunk_type_to_name(&type);
fmt.printf("[%v]: %v\n", name, c.data);
}
}