"""
Author: Ismael Seidel (ismael.seidel@ufsc.br)
Affiliation: Embedded Computing Lab (ECL), Federal University of Santa Catarina (UFSC)
Description:
This module defines the LightfieldPreprocess class, which provides static methods for pre-processing
Light Field data in different formats (e.g., PPM, PNG). The pre-processing includes tasks such as
reordering views, resizing, and creating symbolic links for efficient data handling.
"""
import os
from pathlib import Path
from lfc_toolkit.src.configuration.configuration_reader import \
ConfigurationReader
from lfc_toolkit.src.ctc.lightfield_factory import LightFieldFactory
from lfc_toolkit.src.data_handlers.encoding_orders import get_serpentine_scan_list
from lfc_toolkit.src.data_handlers.formatters import (
get_sequential_view_name_with_leading_zeros,
get_view_name_with_leading_zeros)
from lfc_toolkit.src.data_handlers.lightfield import (
RAW_RGB_PNG_LightField_Data, RAW_RGB_PPM_LightField_Data,
RAWLightFieldData)
[docs]
class LightfieldPreprocess:
"""Class for pre-processing Light Field data in various formats."""
[docs]
@staticmethod
def get(configuration: ConfigurationReader, lightfield: RAWLightFieldData):
"""Pre-processes the given Light Field data based on its type.
:param configuration: ConfigurationReader instance containing Light Field configurations
:type configuration: ConfigurationReader
:param lightfield: Light Field data to be pre-processed
:type lightfield: RAWLightFieldData
:return: Pre-processed Light Field data
:rtype: RAWLightFieldData
"""
print(f"Pre-processing lightfield {lightfield.name}")
if isinstance(lightfield, RAW_RGB_PPM_LightField_Data):
return LightfieldPreprocess.get_ppm(configuration=configuration, lightfield=lightfield)
if isinstance(lightfield, RAW_RGB_PNG_LightField_Data):
return LightfieldPreprocess.get_png(configuration=configuration, lightfield=lightfield)
raise Exception("Invalid state of LightfieldPreprocess get method...")
[docs]
@staticmethod
def get_ppm(configuration: ConfigurationReader, lightfield: RAW_RGB_PPM_LightField_Data):
"""Pre-processes PPM Light Field data by reordering views and creating symbolic links.
:param configuration: ConfigurationReader instance containing Light Field configurations
:type configuration: ConfigurationReader
:param lightfield: PPM Light Field data to be pre-processed
:type lightfield: RAW_RGB_PPM_LightField_Data
:return: Pre-processed PPM Light Field data
:rtype: RAW_RGB_PPM_LightField_Data
"""
print(f"Pre-processing PPM lightfield {lightfield.name}")
lf_encoding_configuration = configuration.lightfield_configurations[lightfield.name]["encode-size"]
scan_list_source = get_serpentine_scan_list(
n_views_width=lightfield.n_views_width,
n_views_height=lightfield.n_views_height,
initial_width=lightfield.initial_width,
initial_height=lightfield.initial_height,
step_width=lightfield.step_width,
step_height=lightfield.step_height,
)
scan_list_destination = get_serpentine_scan_list(
n_views_width=lf_encoding_configuration["number-of-columns"], n_views_height=lf_encoding_configuration["number-of-rows"]
)
assert len(scan_list_source) == len(scan_list_destination)
destination_path = Path(configuration["raw_paths"]["ppm"]) / lightfield.name
destination_path.mkdir(parents=True, exist_ok=True)
for source, destination in zip(scan_list_source, scan_list_destination):
source_name_ppm = Path(lightfield.raw_path) / f"{get_view_name_with_leading_zeros(source[0], source[1])}.ppm"
source_name_pgm = Path(lightfield.raw_path) / f"{get_view_name_with_leading_zeros(source[0], source[1])}.pgm"
destination_name_ppm = destination_path / f"{get_view_name_with_leading_zeros(destination[0], destination[1])}.ppm"
destination_name_pgm = destination_path / f"{get_view_name_with_leading_zeros(destination[0], destination[1])}.pgm"
if os.path.islink(destination_name_ppm):
os.unlink(destination_name_ppm)
if os.path.islink(destination_name_pgm):
os.unlink(destination_name_pgm)
os.symlink(src=source_name_ppm, dst=destination_name_ppm)
if source_name_pgm.exists():
os.symlink(src=source_name_pgm, dst=destination_name_pgm)
return LightFieldFactory.get_raw_lightfield(configuration=configuration, lightfield_name=lightfield.name, raw_type="ppm")
[docs]
@staticmethod
def get_png(configuration: ConfigurationReader, lightfield: RAW_RGB_PNG_LightField_Data):
"""Pre-processes PNG Light Field data by resizing and creating symbolic links.
:param configuration: ConfigurationReader instance containing Light Field configurations
:type configuration: ConfigurationReader
:param lightfield: PNG Light Field data to be pre-processed
:type lightfield: RAW_RGB_PNG_LightField_Data
:return: Pre-processed PNG Light Field data
:rtype: RAW_RGB_PNG_LightField_Data
"""
print(f"Pre-processing lightfield {lightfield.name}")
lf_encoding_configuration = configuration.lightfield_configurations[lightfield.name]["encode-size"]
resizing_step_w = configuration.lightfield_configurations[lightfield.name]["pre-processing"]["resize"].get("step-width", 1)
resizing_step_h = configuration.lightfield_configurations[lightfield.name]["pre-processing"]["resize"].get("step-height", 1)
naming = configuration.lightfield_configurations[lightfield.name]["pre-processing"].get("naming", dict())
name_prefix = naming.get("prefix", "")
leading_zeros = naming.get("leading-zeros", 5)
scan_order = naming.get("scan-order", "raster")
# right_to_left
scan_function_name = f"get_{scan_order}_scan_list"
scan_function = globals()[scan_function_name]
scan_list_destination = scan_function(
n_views_width=lf_encoding_configuration["number-of-columns"], n_views_height=lf_encoding_configuration["number-of-rows"]
)
destination_path = Path(configuration["raw_paths"]["png-preprocessed"]) / lightfield.name
destination_path.mkdir(parents=True, exist_ok=True)
start = 0
source = start - resizing_step_w
destination_old = scan_list_destination[0][1]
for destination in scan_list_destination:
if destination_old == destination[1]:
source += resizing_step_w
else:
source += resizing_step_h
source_name_png = (
Path(lightfield.raw_path) / f"{name_prefix}{get_sequential_view_name_with_leading_zeros(source, leading_zeros=leading_zeros)}.png"
)
destination_name_png = destination_path / f"{get_view_name_with_leading_zeros(destination[0], destination[1])}.png"
print(f"{source_name_png} -> {destination_name_png}")
if os.path.islink(destination_name_png):
os.unlink(destination_name_png)
os.symlink(src=source_name_png, dst=destination_name_png)
destination_old = destination[1]
return LightFieldFactory.get_raw_lightfield(
configuration=configuration,
lightfield_name=lightfield.name,
raw_type="png",
raw_path=Path(configuration["raw_paths"]["png-preprocessed"]),
)