#!/usr/bin/env python3

# python3 -m pip install -U tifffile[all]
from tifffile import (imread, imwrite, TiffFile)

filename_input = "rgb-16bits.tif"
filename_output = "rgb-8bits.tif"


def extract_and_convert(filename_input):

	with TiffFile(filename_input) as tif:
		for page_index, page in enumerate(tif.pages):
			for line_index, line in enumerate(page.asarray()):
				for pixel_index, pixel in enumerate(line):

					print(f"==== Pixel {page_index}{line_index}{pixel_index} =====")

					print(f"Read 16 bits data\t:\t", end="")
					print(f"Red = 0x{pixel[0]:04x}\tGreen = 0x{pixel[1]:04x}\tBlue = 0x{pixel[2]:04x}")

					"""
					to divide by the maximum value of 16 bits, you put your value inside [0...1] range
					where	0x0000 = 0.0000
							0xFF00 = 0.5000
							0xFFFF = 1.0000
					with this value, you can now move this value inside any space !
					if you want to put this value inside :
					8 bits space  =   <value> * 0xFF
					12 bits space =   <value> * 0xFFF
					16 bits space =   <value> * 0xFFFF
					32 bits space =   <value> * 0xFFFFFFFF
					"""

					print(f"Place into 1...0 Map\t:\t", end="")
					red1   = (pixel[0] / 0xFFFF)
					green1 = (pixel[1] / 0xFFFF)
					blue1  = (pixel[2] / 0xFFFF)
					print(f"Red = {red1:.04f}\tGreen = {green1:.04f}\tBlue = {blue1:.04f}")

					print(f"Conversion to 8 bits\t:\t", end="")
					red8   = (red1 * 0xFF)      # FF = 255 (max value for 8 bits)
					green8 = (green1 * 0xFF)    # FF = 255 (max value for 8 bits)
					blue8  = (blue1 * 0xFF)     # FF = 255 (max value for 8 bits)
					print(f"Red = {red8:.03f}\tGreen = {green8:.03f}\tBlue = {blue8:.03f}")

					# Round
					red8_round   = int(round(red8))
					green8_round = int(round(green8))
					blue8_round  = int(round(blue8))
					print(f"Round+Int values (dec)\t:\tRed = {red8_round:d}\tGreen = {green8_round:d}\tBlue = {blue8_round:d}")
					print(f"Round+Int Values (hex)\t:\tRed = 0x{red8_round:02x}\tGreen = 0x{green8_round:02x}\tBlue = 0x{blue8_round:02x}")

					# push 3 octets (1 octet for each components r,g,b) to bytes format
					# needed for yield
					yield red8_round.to_bytes(1, byteorder='little') \
						+ green8_round.to_bytes(1, byteorder='little') \
						+ blue8_round.to_bytes(1, byteorder='little')



# get informations about input file
image = imread(filename_input)

# shape = (width, height, number_of_components)
print("shape =", image.shape)
# dtype = size_of_component (ex: uint16)
print("dtype =", image.dtype)

imwrite(
	filename_output,
	data=extract_and_convert(filename_input),  # iterate is better for memory
	photometric='rgb',
	shape=image.shape,
	dtype='uint8',  # force uint8 by component
	metadata=None
)
print(f"\nwrite to {filename_output} ... {image.shape} => uint8")
