Skip to content

Commit

Permalink
feat: Simplify averaging + attempt to fix bad mipmap access
Browse files Browse the repository at this point in the history
  • Loading branch information
koerismo committed Jul 28, 2024
1 parent aee391d commit 177e48b
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 26 deletions.
3 changes: 3 additions & 0 deletions src/module/core/io/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ def grayscale(self):
gray = r.mult(0.2126).add(g.mult(0.7152)).add(b.mult(0.0722))
return gray

def average(self):
return np.average(self.data, (0, 1))

def get_channel(self, channel: int) -> int:
if channel >= self.channels: raise ValueError(f'Attempted to get channel {channel+1} of {self.channels}-channel image!')
return self.data.swapaxes(0, 2)[channel]
Expand Down
26 changes: 13 additions & 13 deletions src/module/core/io/imio.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def _append_data(self, im: ArrayLike, meta: Dict[str, Any]) -> None:

format = None
flags = vtf.VTFFlags.EMPTY
max_value = 255
match (bands, im.dtype):
case (1, 'uint8'): format = ImageFormats.I8
case (3, 'uint8'): format = ImageFormats.RGB888
Expand All @@ -73,30 +74,29 @@ def _append_data(self, im: ArrayLike, meta: Dict[str, Any]) -> None:
case (4, 'uint16'):
format = ImageFormats.RGBA16161616
flags |= vtf.VTFFlags.EIGHTBITALPHA
max_value = 0xffff
case (4, 'float16'):
format = ImageFormats.RGBA16161616F
flags |= vtf.VTFFlags.EIGHTBITALPHA
max_value = 1.0

if format is None:
raise TypeError(f"Could not match format {im.dtype}x{bands}!")

self.vtf = vtf.VTF(width, height, (7, self.version), fmt=format, flags=flags)
self.vtf.get().copy_from(im.tobytes('C'), format)

# Force 1x1 mipmap to generate
self.vtf.mipmap_count += 1
self.vtf.compute_mipmaps()

# Use color for reflectivity
smallestMipmap = self.vtf.get(mipmap=self.vtf.mipmap_count)
smallestMipmap.load()
if smallestMipmap._data:
self.vtf.reflectivity.x += smallestMipmap._data[0] / 255
self.vtf.reflectivity.y += smallestMipmap._data[1] / 255
self.vtf.reflectivity.z += smallestMipmap._data[2] / 255

# Exclude 1x1 mipmap in the exported image
self.vtf.mipmap_count -= 1
average = np.average(im, (0, 1))
if bands >= 3:
self.vtf.reflectivity.x = average[0] / max_value
self.vtf.reflectivity.y = average[1] / max_value
self.vtf.reflectivity.z = average[2] / max_value
else:
amount = average[0] / max_value
self.vtf.reflectivity.x = amount
self.vtf.reflectivity.y = amount
self.vtf.reflectivity.z = amount

# Save
self.vtf.save(self.file)
Expand Down
27 changes: 14 additions & 13 deletions src/module/core/io/qtio.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ def save(image: Image, path: str | Path, version: int=4) -> None:
raise NotImplementedError(f'Failed to save {path.name} . Use imageio backend for non-vtf output!')

format = None
max_value = 255
flags = VTFFlags.EMPTY
match (bands, image.data.dtype):
case (1, 'uint8'): format = ImageFormats.I8
Expand All @@ -69,30 +70,30 @@ def save(image: Image, path: str | Path, version: int=4) -> None:
case (4, 'uint16'):
format = ImageFormats.RGBA16161616
flags |= VTFFlags.EIGHTBITALPHA
max_value = 0xffff
case (4, 'float16'):
format = ImageFormats.RGBA16161616F
flags |= VTFFlags.EIGHTBITALPHA
max_value = 1.0

if format is None:
raise TypeError(f"Could not match format {image.data.dtype}x{bands}!")

vtf = VTF(width, height, (7, version), fmt=format, flags=flags)
vtf.get().copy_from(image.data.tobytes('C'), format)

# Force 1x1 mipmap to generate
vtf.mipmap_count += 1
vtf.compute_mipmaps()

# Use color for reflectivity
smallestMipmap = vtf.get(mipmap=vtf.mipmap_count)
smallestMipmap.load()
if smallestMipmap._data:
vtf.reflectivity.x += smallestMipmap._data[0] / 255
vtf.reflectivity.y += smallestMipmap._data[1] / 255
vtf.reflectivity.z += smallestMipmap._data[2] / 255

# Exclude 1x1 mipmap in the exported image
vtf.mipmap_count -= 1
average = image.average()
if bands >= 3:
vtf.reflectivity.x = average[0] / max_value
vtf.reflectivity.y = average[1] / max_value
vtf.reflectivity.z = average[2] / max_value
else:
amount = average[0] / max_value
vtf.reflectivity.x = amount
vtf.reflectivity.y = amount
vtf.reflectivity.z = amount


with open(path, 'wb') as file:
vtf.save(file)
Expand Down

0 comments on commit 177e48b

Please sign in to comment.