RegionCoordinateTransform RegionCoordinateTransform::create()

in libheif/region.cc [438:537]


RegionCoordinateTransform RegionCoordinateTransform::create(std::shared_ptr<HeifFile> file,
                                                            heif_item_id item_id,
                                                            int reference_width, int reference_height)
{
  std::vector<std::shared_ptr<Box>> properties;

  Error err = file->get_properties(item_id, properties);
  if (err) {
    return {};
  }

  int image_width = 0, image_height = 0;

  for (auto& property : properties) {
    if (property->get_short_type() == fourcc("ispe")) {
      auto ispe = std::dynamic_pointer_cast<Box_ispe>(property);
      image_width = ispe->get_width();
      image_height = ispe->get_height();
      break;
    }
  }

  if (image_width == 0 || image_height == 0) {
    return {};
  }

  RegionCoordinateTransform transform;
  transform.a = image_width / (double) reference_width;
  transform.d = image_height / (double) reference_height;

  for (auto& property : properties) {
    switch (property->get_short_type()) {
      case fourcc("imir"): {
        auto imir = std::dynamic_pointer_cast<Box_imir>(property);
        if (imir->get_mirror_direction() == heif_transform_mirror_direction_horizontal) {
          transform.a = -transform.a;
          transform.b = -transform.b;
          transform.tx = image_width - 1 - transform.tx;
        }
        else {
          transform.c = -transform.c;
          transform.d = -transform.d;
          transform.ty = image_height - 1 - transform.ty;
        }
        break;
      }
      case fourcc("irot"): {
        auto irot = std::dynamic_pointer_cast<Box_irot>(property);
        RegionCoordinateTransform tmp;
        switch (irot->get_rotation()) {
          case 90:
            tmp.a = transform.c;
            tmp.b = transform.d;
            tmp.c = -transform.a;
            tmp.d = -transform.b;
            tmp.tx = transform.ty;
            tmp.ty = -transform.tx + image_width - 1;
            transform = tmp;
            std::swap(image_width, image_height);
            break;
          case 180:
            transform.a = -transform.a;
            transform.b = -transform.b;
            transform.tx = image_width - 1 - transform.tx;
            transform.c = -transform.c;
            transform.d = -transform.d;
            transform.ty = image_height - 1 - transform.ty;
            break;
          case 270:
            tmp.a = -transform.c;
            tmp.b = -transform.d;
            tmp.c = transform.a;
            tmp.d = transform.b;
            tmp.tx = -transform.ty + image_height - 1;
            tmp.ty = transform.tx;
            transform = tmp;
            std::swap(image_width, image_height);
            break;
          default:
            break;
        }
        break;
      }
      case fourcc("clap"): {
        auto clap = std::dynamic_pointer_cast<Box_clap>(property);
        int left = clap->left_rounded(image_width);
        int top = clap->top_rounded(image_height);
        transform.tx -= left;
        transform.ty -= top;
        image_width = clap->get_width_rounded();
        image_height = clap->get_height_rounded();
        break;
      }
      default:
        break;
    }
  }

  return transform;
}