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;
}