"""
Author: Ismael Seidel (ismael.seidel@ufsc.br)
Affiliation: Embedded Computing Lab (ECL), Federal University of Santa Catarina (UFSC)
Description:
This module contains the implementation of YUV->PPM conversion.
"""
from pathlib import Path
from typing import Union
import yuvio
from lfc_toolkit.src.data_handlers.encoding_orders import (
ScanFunctionType,
get_serpentine_scan_list,
)
from lfc_toolkit.src.data_handlers.formatters import get_view_name_with_leading_zeros
from lfc_toolkit.src.data_handlers.lightfield import (
RAW_BT709_FR_YUV444p10le_LightField_Data,
RAW_RGB_PPM_LightField_Data,
)
from lfc_toolkit.src.file.ppm_handler import PPMHandler
[docs]
def generate_ppm_from_yuv(
raw_light_field_data: RAW_BT709_FR_YUV444p10le_LightField_Data,
ppm_path: Union[str, Path],
scan_order: ScanFunctionType = get_serpentine_scan_list,
remove_after_using: bool = False,
) -> RAW_RGB_PPM_LightField_Data:
"""
Get RAW PPM light field object from RAW YUV light field data.
:param raw_light_field_data: RAW YUV light field to be converted
:type raw_light_field_data: RAW_BT709_FR_YUV444p10le_LightField_Data
:param ppm_path: Path to save the PPM files
:type ppm_path: Union[str, Path]
:param scan_order: Function defining the scan order
:type scan_order: ScanFunctionType
:param remove_after_using: Whether to remove intermediate files
:type remove_after_using: bool
:return: Converted PPM light field data
:rtype: RAW_RGB_PPM_LightField_Data
"""
assert raw_light_field_data.colour_space == "BT.709 Full Range"
assert raw_light_field_data.pix_fmt == "yuv444p10le"
lightfield = raw_light_field_data.copy()
output_raw_lf = RAW_RGB_PPM_LightField_Data(
lightfield=lightfield,
ppm_path=ppm_path,
bpp_for_naming=raw_light_field_data.bpp_for_naming,
remove_after_using=remove_after_using,
)
hand = PPMHandler()
scan_list = scan_order(
raw_light_field_data.n_views_width,
raw_light_field_data.n_views_height,
0,
0,
1,
1,
) # always in this format 0,0,1,1 as it is expected by the JPLM
input_yuv_filename = raw_light_field_data.raw_path
reader = yuvio.get_reader(
input_yuv_filename,
raw_light_field_data.view_width,
raw_light_field_data.view_height,
raw_light_field_data.pix_fmt,
)
for (x, y), yuv_frame in zip(scan_list, reader):
view_filename = f"{get_view_name_with_leading_zeros(x, y)}.ppm"
rgb = yuvio.to_rgb(yuv_frame, specification="bt709", value_range="full")
path = output_raw_lf.raw_path / view_filename
path.parent.mkdir(parents=True, exist_ok=True)
hand.write(path=path, data=rgb, depth=raw_light_field_data.bits_per_sample)
return output_raw_lf
[docs]
def main():
import argparse
# 1. Create the ArgumentParser object with a description
parser = argparse.ArgumentParser(description="Convert a single YUV LF to PPM.")
# 2. Add a positional argument (required input, no dashes)
parser.add_argument(
"--name", "-n", required=True, type=str, help="The name of the light field."
)
parser.add_argument("--n-views-height", "-t", required=True, type=int, help="T")
parser.add_argument("--n-views-width", "-s", required=True, type=int, help="S")
parser.add_argument("--view-height", "-v", required=True, type=int, help="V")
parser.add_argument("--view-width", "-u", required=True, type=int, help="U")
parser.add_argument(
"--bits-per-sample", "-b", required=True, type=int, help="Bits per sample"
)
parser.add_argument(
"--input_path", "-i", required=True, type=str, help="Input path"
)
parser.add_argument(
"--output_path", "-o", required=True, type=str, help="Output path"
)
# 3. Parse the arguments from the command line
args = parser.parse_args()
from lfc_toolkit.src.data_handlers.lightfield import LightField
lf = RAW_BT709_FR_YUV444p10le_LightField_Data(
lightfield=LightField(
name=args.name,
view_width=args.view_width,
view_height=args.view_height,
n_views_width=args.n_views_width,
n_views_height=args.n_views_height,
),
yuv_path=args.input_path,
bpp_for_naming=args.bits_per_sample,
)
generate_ppm_from_yuv(
raw_light_field_data=lf, ppm_path=args.output_path, remove_after_using=False
)
if __name__ == "__main__":
main()