Source code for src.converters.lightfield_converter

"""
Author: Ismael Seidel (ismael.seidel@ufsc.br)
Affiliation: Embedded Computing Lab (ECL), Federal University of Santa Catarina (UFSC)

Description:
    The class LightfieldConverter handles conversion for all of the currently 
    supported  formats in the LFC Toolkit (e. g, PPM->PGX, PGX->YUV...)
"""

from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Optional, Union

from lfc_toolkit.src.converters.ffmpeg import FFMPEGLightFieldFormatConverter
from lfc_toolkit.src.converters.pgx_from_yuv import generate_pgx_from_yuv
from lfc_toolkit.src.converters.png_from_ppm import generate_png_from_ppm
from lfc_toolkit.src.converters.ppm_from_png import generate_ppm_from_png
from lfc_toolkit.src.converters.ppm_from_yuv import generate_ppm_from_yuv
from lfc_toolkit.src.converters.yuv_from_pgx import generate_yuv_from_pgx
from lfc_toolkit.src.data_handlers.lightfield import RAWLightFieldData


[docs] class LightfieldConverter: @staticmethod def __resolve_decoded_raw_path(path: Path, destination_type: str) -> Path: """Resolves the output path for decoded raw data based on parent structure. :param path: Path to the source raw data :type path: Path :param destination_type: Destination format type (e.g. PGX, YUV) :type destination_type: str :return: Resolved path for the destination type :rtype: Path """ before_type = path.parent.parent return before_type / destination_type
[docs] @staticmethod def convert( source: RAWLightFieldData, destination_type: str, output_path: Optional[Union[str, Path]] = None, remove_after_using: bool = False, ) -> Optional[RAWLightFieldData]: """ Light field converter method :param source: Input raw light field :type source: RAWLightFieldData :param destination_type: Output file format (e.g, PGX, YUV, PNG) :type destination_type: str :param output_path: Output path for converted files :type output_path: Optional[Union[str, Path]] :param remove_after_using: Whether to remove intermediate files :return: Converted light field :rtype: RAWLightFieldData | None """ print(source) if destination_type == source.type: return source if not output_path: output_path = LightfieldConverter.__resolve_decoded_raw_path( path=source.raw_path, destination_type=destination_type ) if source.type.lower() == "yuv": if destination_type.lower() == "pgx": return generate_pgx_from_yuv( raw_light_field_data=source, pgx_path=output_path, scan_order=source.scan_order, remove_after_using=remove_after_using, ) if destination_type.lower() == "ppm": return generate_ppm_from_yuv( raw_light_field_data=source, ppm_path=output_path, scan_order=source.scan_order, remove_after_using=remove_after_using, ) if destination_type.lower() == "png": with TemporaryDirectory() as tmpdir: tmp_ppm_path = Path(tmpdir) / "temp.ppm" ppm_lf = generate_ppm_from_yuv( raw_light_field_data=source, ppm_path=tmp_ppm_path, scan_order=source.scan_order, remove_after_using=False, ) png_lf = generate_png_from_ppm( raw_light_field_data=ppm_lf, png_path=output_path, scan_order=ppm_lf.scan_order, remove_after_using=remove_after_using, ) return png_lf raise Exception(f"Cannot convert from yuv to {destination_type}") if source.type.lower() == "pgx": remove_yuv = (destination_type.lower() == "ppm") or remove_after_using yuv_from_pgx = generate_yuv_from_pgx( raw_light_field_data=source, yuv_path=output_path, scan_order=source.scan_order, remove_after_using=remove_yuv, ) if destination_type.lower() == "yuv": return yuv_from_pgx if destination_type.lower() == "ppm": converted_yuv = generate_ppm_from_yuv( raw_light_field_data=yuv_from_pgx, ppm_path=output_path, scan_order=source.scan_order, remove_after_using=remove_after_using, ) return converted_yuv if destination_type.lower() == "png": with TemporaryDirectory() as tmpdir: tmp_ppm_path = Path(tmpdir) / "temp.ppm" ppm_lf = generate_ppm_from_yuv( raw_light_field_data=yuv_from_pgx, ppm_path=tmp_ppm_path, scan_order=source.scan_order, remove_after_using=False, ) png_lf = generate_png_from_ppm( raw_light_field_data=ppm_lf, png_path=output_path, scan_order=ppm_lf.scan_order, remove_after_using=remove_after_using, ) return png_lf raise Exception(f"Cannot convert from pgx to {destination_type}") if source.type.lower() == "ppm": remove_yuv = (destination_type.lower() == "pgx") or remove_after_using yuv_lf = FFMPEGLightFieldFormatConverter.convert_rgb_ppm_lf_to_bt709fr_yuv( raw_light_field_rgb_ppm=source, yuv_path=output_path, remove_after_using=remove_yuv, ) if destination_type.lower() == "yuv": return yuv_lf if destination_type.lower() == "pgx": pgx_lf = generate_pgx_from_yuv( raw_light_field_data=yuv_lf, pgx_path=output_path, scan_order=yuv_lf.scan_order, remove_after_using=remove_after_using, ) return pgx_lf if destination_type.lower() == "png": png_lf = generate_png_from_ppm( raw_light_field_data=source, ppm_path=output_path, scan_order=source.scan_order, remove_after_using=remove_after_using, ) return png_lf if source.type.lower() == "png": if destination_type.lower() == "ppm": return generate_ppm_from_png( raw_light_field_data=source, ppm_path=output_path, scan_order=source.scan_order, remove_after_using=remove_after_using, ) if destination_type.lower() == "pgx": with TemporaryDirectory() as tmpdir: tmp_ppm_path = Path(tmpdir) / "temp.ppm" tmp_yuv_path = Path(tmpdir) / "temp.yuv" ppm_lf = generate_ppm_from_png( raw_light_field_data=source, ppm_path=tmp_ppm_path, scan_order=source.scan_order, remove_after_using=False, ) yuv_lf = FFMPEGLightFieldFormatConverter.convert_rgb_ppm_lf_to_bt709fr_yuv( raw_light_field_rgb_ppm=ppm_lf, yuv_path=tmp_yuv_path, remove_after_using=False, ) pgx_lf = generate_pgx_from_yuv( raw_light_field_data=yuv_lf, pgx_path=output_path, scan_order=yuv_lf.scan_order, remove_after_using=remove_after_using, ) return pgx_lf if destination_type.lower() == "yuv": with TemporaryDirectory() as tmpdir: tmp_ppm_path = Path(tmpdir) / "temp.ppm" ppm_lf = generate_ppm_from_png( raw_light_field_png=source, ppm_path=tmp_ppm_path, scan_order=source.scan_order, remove_after_using=False, ) yuv_lf = FFMPEGLightFieldFormatConverter.convert_rgb_ppm_lf_to_bt709fr_yuv( raw_light_field_rgb_ppm=ppm_lf, yuv_path=output_path, remove_after_using=remove_yuv, ) return yuv_lf raise Exception("I should not be here (end of LFConverter.convert)")
[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" ) parser.add_argument( "--from-format", "-from", required=True, type=str, help="Input format" ) parser.add_argument( "--to-format", "-to", required=True, type=str, help="Output format" ) # 3. Parse the arguments from the command line args = parser.parse_args() # from lfc_toolkit.src.data_handlers.lightfield import LightField input_format = args.from_format print(input_format) match input_format: case "pgx": raw_type="pgx", raw_pix_fmt="PGX", raw_colour_space="BT.709 Full Range", case "png": raw_type="png" raw_pix_fmt="rgb24" raw_colour_space="sRGB" case "ppm": raw_type="ppm" raw_pix_fmt="PPM" raw_colour_space="sRGB" case "yuv": raw_type="yuv", raw_pix_fmt="yuv444p10le", raw_colour_space="BT.709 Full Range", case _: raise Exception("Unknown input format", input_format) from lfc_toolkit.src.data_handlers.encoding_orders import get_serpentine_scan_list from lfc_toolkit.src.data_handlers.lightfield import LightField input_lf = RAWLightFieldData( 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, ), raw_path=args.input_path, bits_per_sample=args.bits_per_sample, type=raw_type, pix_fmt=raw_pix_fmt, colour_space=raw_colour_space, initial_width=0, initial_height=0, step_width=1, step_height=1, #bpp_for_naming=bpp_for_naming, scan_order=get_serpentine_scan_list, remove_after_using=False ) LightfieldConverter.convert( source=input_lf, destination_type=args.to_format, output_path=args.output_path, remove_after_using= False, )
if __name__ == "__main__": main()