def _create_image_dicom_metadata()

in pathology/transformation_pipeline/ingestion_lib/dicom_gen/dicom_slide_coordinates_microscopic_image.py [0:0]


def _create_image_dicom_metadata(image_path: str) -> _ImageDicomMetadata:
  """Creates image metadata for VL Slide-Coordinates DICOM.

  Args:
    image_path: Path to an image.

  Returns:
    Image metadata for VL Slide-Coordinates DICOM.

  Raises:
    InvalidFlatImageError: If invalid flat image (e.g. invalid path, error
      reading image, unsupported image format or dimensions, etc).
  """
  try:
    with PIL.Image.open(image_path) as img:
      img.load()
  except Exception as exp:
    raise InvalidFlatImageError(
        f'Failed to open image: {image_path}.',
        ingest_const.ErrorMsgs.FLAT_IMAGE_FAILED_TO_OPEN,
    ) from exp
  if img.format not in _SUPPORTED_IMAGE_FORMATS:
    raise InvalidFlatImageError(
        f'Unexpected image format {img.format} in {image_path}.',
        ingest_const.ErrorMsgs.FLAT_IMAGE_UNEXPECTED_FORMAT,
    )
  if img.width > _MAX_IMAGE_SIZE or img.height > _MAX_IMAGE_SIZE:
    raise InvalidFlatImageError(
        (
            f'Unexpected image dimensions {img.width} x {img.height} '
            f'in {image_path}. Expected <= {_MAX_IMAGE_SIZE}.'
        ),
        ingest_const.ErrorMsgs.FLAT_IMAGE_UNEXPECTED_DIMENSIONS,
    )

  tif_tags = _TifTagsDicomMetadata()
  if img.format == 'PNG':
    if img.mode == 'RGBA' and _is_opaque(img):
      img = img.convert(mode='RGB')
    with io.BytesIO() as jpg_bytes:
      img.save(jpg_bytes, format='JPEG2000', irreversible=False)
      image_bytes = jpg_bytes.getvalue()
      with PIL.Image.open(jpg_bytes) as img:
        img.load()
    image_type = _DICOM_IMAGE_TYPE_DERIVED
    transfer_syntax = ingest_const.DicomImageTransferSyntax.JPEG_2000
  elif img.format == 'TIFF':
    if img.mode == 'RGBA' and _is_opaque(img):
      img = img.convert(mode='RGB')
      img.save(image_path)
    ancillary_image_path = os.path.splitext(image_path)[0] + '.jpg'
    ancillary_image = ancillary_image_extractor.AncillaryImage(
        path=ancillary_image_path
    )
    if not ancillary_image_extractor.extract_jpg_image(
        image_path,
        ancillary_image,
        convert_to_jpeg_2000=True,
    ):
      raise InvalidFlatImageError(
          f'Failed to convert TIF to JPG: {image_path}',
          ingest_const.ErrorMsgs.FLAT_IMAGE_FAILED_TO_CONVERT_TIF_TO_JPG,
      )
    with PIL.Image.open(ancillary_image.path) as img:
      img.load()
    with open(ancillary_image.path, 'rb') as img_file:
      image_bytes = img_file.read()
    if ancillary_image.extracted_without_decompression:
      image_type = _DICOM_IMAGE_TYPE_ORIGINAL
      transfer_syntax = ingest_const.DicomImageTransferSyntax.JPEG_LOSSY
    else:
      image_type = _DICOM_IMAGE_TYPE_DERIVED
      transfer_syntax = ingest_const.DicomImageTransferSyntax.JPEG_2000
    tif_tags = _extract_tif_tags_metadata(image_path)
  else:
    with open(image_path, 'rb') as img_file:
      image_bytes = img_file.read()
    image_type = _DICOM_IMAGE_TYPE_ORIGINAL
    transfer_syntax = ingest_const.DicomImageTransferSyntax.JPEG_LOSSY

  if img.mode not in ['RGB', 'RGBA', '1', 'L']:
    raise InvalidFlatImageError(
        f'Unexpected image mode {img.mode} in {image_path}.',
        ingest_const.ErrorMsgs.FLAT_IMAGE_UNEXPECTED_PIXEL_MODE,
    )

  if img.mode in ['RGB', 'RGBA']:
    if transfer_syntax == ingest_const.DicomImageTransferSyntax.JPEG_LOSSY:
      photometric_interpretation = 'YBR_FULL_422'
    else:
      photometric_interpretation = 'RGB'
    samples_per_pixel = 3
  else:
    photometric_interpretation = 'MONOCHROME2'
    samples_per_pixel = 1

  compression_ratio = str(
      round(
          (img.width * img.height * samples_per_pixel)
          / os.path.getsize(image_path),
          2,
      )
  )

  return _ImageDicomMetadata(  # pytype: disable=wrong-arg-types  # pillow-102-upgrade
      image_bytes,
      img.width,
      img.height,
      photometric_interpretation,
      samples_per_pixel,
      compression_ratio,
      image_type,
      icc_profile=img.info.get('icc_profile'),
      transfer_syntax=transfer_syntax,
      tif_tags=tif_tags,
  )