Skip to content

Commit

Permalink
Merge pull request #7 from fnands/staging
Browse files Browse the repository at this point in the history
Staging to main
  • Loading branch information
fnands authored Jul 27, 2024
2 parents bee72ee + f716eb2 commit 5d447f1
Show file tree
Hide file tree
Showing 8 changed files with 35 additions and 31 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## Unreleased

# 0.1.1

### Changed
- Migrated to Mojo 24.4

## 0.1.0

### Added
Expand Down
11 changes: 5 additions & 6 deletions mimage/PngImagePlugin.mojo
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from math import abs
from tensor import Tensor, TensorSpec, TensorShape
from utils.index import Index
from testing import assert_true
Expand Down Expand Up @@ -78,7 +77,7 @@ struct Chunk(Movable, Copyable):
"""The lengh of the chunk (in bytes)."""
var type: String
"""The type of the chunk."""
var data: List[Int8]
var data: List[UInt8]
"""The data contained in the chunk."""
var crc: UInt32
"""The CRC32 checksum of the chunk."""
Expand All @@ -89,7 +88,7 @@ struct Chunk(Movable, Copyable):
inout self,
length: UInt32,
chunk_type: String,
data: List[Int8],
data: List[UInt8],
crc: UInt32,
end: Int,
):
Expand Down Expand Up @@ -133,7 +132,7 @@ struct Chunk(Movable, Copyable):
self.end = existing.end


def parse_next_chunk(data: List[Int8], read_head: Int) -> Chunk:
def parse_next_chunk(data: List[UInt8], read_head: Int) -> Chunk:
"""Parses the chunk starting at read head.
Args:
Expand Down Expand Up @@ -171,7 +170,7 @@ struct PNGImage(Copyable, Movable):

var image_path: Path
"""The path to the PNG image."""
var raw_data: List[Int8]
var raw_data: List[UInt8]
"""The raw bytes of the PNG image."""
var width: Int
"""The width of the PNG image."""
Expand Down Expand Up @@ -259,7 +258,7 @@ struct PNGImage(Copyable, Movable):
# Scan over chunks until end found
var ended = False
var data_found = False
var uncompressd_data = List[Int8]()
var uncompressd_data = List[UInt8]()
while read_head < len(self.raw_data) and not ended:
var chunk = parse_next_chunk(self.raw_data, read_head)
read_head = chunk.end
Expand Down
26 changes: 13 additions & 13 deletions mimage/utils/binary.mojo
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from math.bit import bswap, bitreverse
from bit import byte_swap, bit_reverse
from testing import assert_true
from algorithm import vectorize
from sys.info import simdwidthof
Expand All @@ -7,7 +7,7 @@ from sys.info import simdwidthof
alias simd_width = simdwidthof[DType.uint32]()


fn bytes_to_string(list: List[Int8]) -> String:
fn bytes_to_string(list: List[UInt8]) -> String:
"""Converts a list of bytes to a string.
Args:
Expand All @@ -23,7 +23,7 @@ fn bytes_to_string(list: List[Int8]) -> String:
return word


fn bytes_to_hex_string(list: List[Int8]) -> String:
fn bytes_to_hex_string(list: List[UInt8]) -> String:
"""Converts a list of bytes to a hex string.
Args:
Expand All @@ -39,7 +39,7 @@ fn bytes_to_hex_string(list: List[Int8]) -> String:
return word


fn bytes_to_uint32_be(owned list: List[Int8]) raises -> List[UInt32]:
fn bytes_to_uint32_be(owned list: List[UInt8]) raises -> List[UInt32]:
"""Converts a list of bytes into a list of UInt32s.
Args:
Expand All @@ -53,25 +53,25 @@ fn bytes_to_uint32_be(owned list: List[Int8]) raises -> List[UInt32]:
"""
assert_true(
len(list) % 4 == 0,
"List[Int8] length must be a multiple of 4 to convert to List[Int32]",
"List[UInt8] length must be a multiple of 4 to convert to List[UInt32]",
)
var result_length = len(list) // 4

# get the data pointer with ownership.
# This avoids copying and makes sure only one List owns a pointer to the underlying address.
var ptr_to_int8 = list.steal_data()
var ptr_to_uint32 = ptr_to_int8.bitcast[UInt32]()
var ptr_to_uint8 = list.steal_data()
var ptr_to_uint32 = ptr_to_uint8.bitcast[UInt32]()
var dtype_ptr = DTypePointer[DType.uint32](Pointer[UInt32](ptr_to_uint32.address))

# vectorize bswap over DTypePointer
# vectorize byte_swap over DTypePointer
@parameter
fn _bswap[_width: Int](i: Int):
# call bswap on a batch of UInt32 values
var bit_swapped = bswap(dtype_ptr.load[width=_width](i))
fn _byte_swap[_width: Int](i: Int):
# call byte_swap on a batch of UInt32 values
var bit_swapped = byte_swap(dtype_ptr.load[width=_width](i))
# We are updating in place and both ptr_to_uint32 and dtype_ptr share the addresses
dtype_ptr.store[width=_width](i, bit_swapped)

# swap the bytes in each UInt32 to convert from big-endian to little-endian
vectorize[_bswap, simd_width](result_length)
vectorize[_byte_swap, simd_width](result_length)

return List[UInt32](data=ptr_to_uint32, size=result_length, capacity=result_length)
return List[UInt32](unsafe_pointer=ptr_to_uint32, size=result_length, capacity=result_length)
6 changes: 3 additions & 3 deletions mimage/utils/compression.mojo
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from sys import ffi

alias Bytef = Scalar[DType.int8]
alias Bytef = Scalar[DType.uint8]
alias uLong = UInt64
alias zlib_type = fn (
_out: Pointer[Bytef],
Expand All @@ -25,7 +25,7 @@ fn _log_zlib_result(Z_RES: Int, compressing: Bool = True) raises -> NoneType:
raise Error("ERROR " + prefix.upper() + "COMPRESSING: Unhandled exception")


fn uncompress(data: List[Int8], quiet: Bool = True) raises -> List[UInt8]:
fn uncompress(data: List[UInt8], quiet: Bool = True) raises -> List[UInt8]:
"""Uncompresses a zlib compressed byte List.
Args:
Expand Down Expand Up @@ -64,5 +64,5 @@ fn uncompress(data: List[Int8], quiet: Bool = True) raises -> List[UInt8]:
# Can probably do something more efficient here with pointers, but eh.
var res = List[UInt8]()
for i in range(uncompressed_len[0]):
res.append(uncompressed[i].cast[DType.uint8]())
res.append(uncompressed[i])
return res
8 changes: 4 additions & 4 deletions mimage/utils/crc.mojo
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from math.bit import bitreverse
from bit import bit_reverse


fn CRC32(
data: List[SIMD[DType.int8, 1]],
data: List[SIMD[DType.uint8, 1]],
value: SIMD[DType.uint32, 1] = 0xFFFFFFFF,
) -> SIMD[DType.uint32, 1]:
"""Calculate the CRC32 value for a given list of bytes.
Expand All @@ -16,11 +16,11 @@ fn CRC32(
"""
var crc32 = value
for byte in data:
crc32 = (bitreverse(byte[]).cast[DType.uint32]() << 24) ^ crc32
crc32 = (bit_reverse(byte[]).cast[DType.uint32]() << 24) ^ crc32
for i in range(8):
if crc32 & 0x80000000 != 0:
crc32 = (crc32 << 1) ^ 0x04C11DB7
else:
crc32 = crc32 << 1

return bitreverse(crc32 ^ 0xFFFFFFFF)
return bit_reverse(crc32 ^ 0xFFFFFFFF)
2 changes: 1 addition & 1 deletion mimage/utils/files.mojo
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from mimage.utils.binary import bytes_to_hex_string


fn determine_file_type(data: List[Int8]) -> String:
fn determine_file_type(data: List[UInt8]) -> String:
"""Determine the type of the file by reading the first few bytes.
Args:
Expand Down
6 changes: 3 additions & 3 deletions mod.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
[package]
name = "mimage"
version = "0.1.0"
version = "0.1.1"
description = "A Mojo library for parsing images"
authors = ["Ferdinand Schenck <[email protected]>"]
license = "Apache License v2.0 with LLVM Exceptions"
repository = ""
edition = "2023"
mojo-version = "24.3.0"
edition = "2024"
mojo-version = "24.4.0"


[dependencies]
2 changes: 1 addition & 1 deletion scripts/check-docstrings.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def main():
command = [
"mojo",
"doc",
"--warn-missing-doc-strings",
"--diagnose-missing-doc-strings",
"-o",
"/dev/null",
"./mimage",
Expand Down

0 comments on commit 5d447f1

Please sign in to comment.