Skip to content

Commit

Permalink
API to write camera intrinsic matrix (#1164)
Browse files Browse the repository at this point in the history
  • Loading branch information
farindk committed Jun 16, 2024
1 parent 97c1806 commit 2590903
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 33 deletions.
14 changes: 14 additions & 0 deletions libheif/bitstream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,20 @@ void StreamWriter::write32(uint32_t v)
}


void StreamWriter::write32s(int32_t v32s)
{
uint32_t v;
if (v32s >= 0) {
v = static_cast<uint32_t>(v32s);
}
else {
v = ~static_cast<uint32_t>((-v32s-1));
}

write32(v);
}


void StreamWriter::write64(uint64_t v)
{
size_t required_size = m_position + 8;
Expand Down
2 changes: 2 additions & 0 deletions libheif/bitstream.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ class StreamWriter

void write32(uint32_t);

void write32s(int32_t);

void write64(uint64_t);

void write(int size, uint64_t value);
Expand Down
84 changes: 76 additions & 8 deletions libheif/box.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3316,32 +3316,100 @@ Error Box_cmin::parse(BitstreamRange& range)
{
parse_full_box_header(range);

uint32_t denominatorShift = (get_flags() & 0x1F00) >> 8;
uint32_t denominator = (1 << denominatorShift);
m_denominatorShift = (get_flags() & 0x1F00) >> 8;
uint32_t denominator = (1 << m_denominatorShift);

m_matrix.focal_length_x = range.read32s() / (double)denominator;
m_matrix.principal_point_x = range.read32s() / (double)denominator;
m_matrix.principal_point_y = range.read32s() / (double)denominator;

if (get_flags() & 1) {
uint32_t skewDenominatorShift = ((get_flags()) & 0x1F0000) >> 16;
uint32_t skewDenominator = (1<<skewDenominatorShift);
m_skewDenominatorShift = ((get_flags()) & 0x1F0000) >> 16;
uint32_t skewDenominator = (1<<m_skewDenominatorShift);

m_matrix.focal_length_y = range.read32s() / (double)denominator;
m_matrix.skew = range.read32s() / (double)skewDenominator;

m_matrix.is_anisotropic = true;
}
else {
// TODO: this is wrong. We cannot simply set f_y = f_x because both use a different normalization.
// However, we also cannot compute this here without knowing the image size.
m_matrix.focal_length_y = m_matrix.focal_length_x;

m_matrix.is_anisotropic = false;
m_matrix.focal_length_y = 0;
m_matrix.skew = 0;
}
return range.get_error();
}


static uint32_t get_signed_fixed_point_shift(double v)
{
if (v==0) {
return 31;
}

v = std::abs(v);

uint32_t shift = 0;
while (v < (1<<30)) {
v *= 2;
shift++;

if (shift==31) {
return shift;
}
}

return shift;
}


void Box_cmin::set_intrinsic_matrix(IntrinsicMatrix matrix)
{
m_matrix = matrix;

uint32_t flags = 0;
flags |= matrix.is_anisotropic ? 1 : 0;

uint32_t shift_fx = get_signed_fixed_point_shift(matrix.focal_length_x);
uint32_t shift_px = get_signed_fixed_point_shift(matrix.principal_point_x);
uint32_t shift_py = get_signed_fixed_point_shift(matrix.principal_point_y);
m_denominatorShift = std::min(std::min(shift_fx, shift_px), shift_py);

if (matrix.is_anisotropic) {
uint32_t shift_fy = get_signed_fixed_point_shift(matrix.focal_length_y);
m_denominatorShift = std::min(m_denominatorShift, shift_fy);

m_skewDenominatorShift = get_signed_fixed_point_shift(matrix.skew);
}
else {
m_skewDenominatorShift = 0;
}

flags |= (m_denominatorShift << 8);
flags |= (m_skewDenominatorShift << 16);

set_flags(flags);
}


Error Box_cmin::write(StreamWriter& writer) const
{
size_t box_start = reserve_box_header_space(writer);

uint32_t denominator = (1<<m_denominatorShift);

writer.write32s(static_cast<int32_t>(m_matrix.focal_length_x * denominator));
writer.write32s(static_cast<int32_t>(m_matrix.principal_point_x * denominator));
writer.write32s(static_cast<int32_t>(m_matrix.principal_point_y * denominator));

if (get_flags() & 1) {
writer.write32s(static_cast<int32_t>(m_matrix.focal_length_y * denominator));

uint32_t skewDenominator = (1 << m_skewDenominatorShift);
writer.write32s(static_cast<int32_t>(m_matrix.skew * skewDenominator));
}

prepend_header(writer, box_start);

return Error::Ok;
}
5 changes: 4 additions & 1 deletion libheif/box.h
Original file line number Diff line number Diff line change
Expand Up @@ -1039,7 +1039,7 @@ class Box_cmin : public FullBox

IntrinsicMatrix get_intrinsic_matrix() const { return m_matrix; }

void set_intrinsic_matrix(IntrinsicMatrix matrix) { m_matrix = matrix; }
void set_intrinsic_matrix(IntrinsicMatrix matrix);

protected:
Error parse(BitstreamRange& range) override;
Expand All @@ -1048,6 +1048,9 @@ class Box_cmin : public FullBox

private:
IntrinsicMatrix m_matrix;

uint32_t m_denominatorShift = 0;
uint32_t m_skewDenominatorShift = 0;
};


Expand Down
92 changes: 79 additions & 13 deletions libheif/heif_properties.cc
Original file line number Diff line number Diff line change
Expand Up @@ -447,22 +447,22 @@ struct heif_error heif_item_get_property_camera_intrinsic_matrix(const struct he
}


void heif_intrinsic_matrix_release(struct heif_camera_intrinsic_matrix* matrix)
void heif_camera_intrinsic_matrix_release(struct heif_camera_intrinsic_matrix* matrix)
{
delete matrix;
}

struct heif_error heif_intrinsic_matrix_get_focal_length(const struct heif_camera_intrinsic_matrix* matrix,
int image_width, int image_height,
double* out_focal_length_x,
double* out_focal_length_y)
struct heif_error heif_camera_intrinsic_matrix_get_focal_length(const struct heif_camera_intrinsic_matrix* matrix,
int image_width, int image_height,
double* out_focal_length_x,
double* out_focal_length_y)
{
if (!matrix) {
return {heif_error_Usage_error, heif_suberror_Invalid_parameter_value, "NULL passed as matrix"};
}

double fx, fy;
matrix->matrix.compute_focal_length(image_width, image_height, fx,fy);
matrix->matrix.compute_focal_length(image_width, image_height, fx, fy);

if (out_focal_length_x) *out_focal_length_x = fx;
if (out_focal_length_y) *out_focal_length_y = fy;
Expand All @@ -471,17 +471,17 @@ struct heif_error heif_intrinsic_matrix_get_focal_length(const struct heif_camer
}


struct heif_error heif_intrinsic_matrix_get_principal_point(const struct heif_camera_intrinsic_matrix* matrix,
int image_width, int image_height,
double* out_principal_point_x,
double* out_principal_point_y)
struct heif_error heif_camera_intrinsic_matrix_get_principal_point(const struct heif_camera_intrinsic_matrix* matrix,
int image_width, int image_height,
double* out_principal_point_x,
double* out_principal_point_y)
{
if (!matrix) {
return {heif_error_Usage_error, heif_suberror_Invalid_parameter_value, "NULL passed as matrix"};
}

double px, py;
matrix->matrix.compute_principal_point(image_width, image_height, px,py);
matrix->matrix.compute_principal_point(image_width, image_height, px, py);

if (out_principal_point_x) *out_principal_point_x = px;
if (out_principal_point_y) *out_principal_point_y = py;
Expand All @@ -490,8 +490,8 @@ struct heif_error heif_intrinsic_matrix_get_principal_point(const struct heif_ca
}


struct heif_error heif_intrinsic_matrix_get_skew(const struct heif_camera_intrinsic_matrix* matrix,
double* out_skew)
struct heif_error heif_camera_intrinsic_matrix_get_skew(const struct heif_camera_intrinsic_matrix* matrix,
double* out_skew)
{
if (!matrix || !out_skew) {
return {heif_error_Usage_error, heif_suberror_Invalid_parameter_value, "NULL passed"};
Expand All @@ -501,3 +501,69 @@ struct heif_error heif_intrinsic_matrix_get_skew(const struct heif_camera_intrin

return heif_error_success;
}


struct heif_camera_intrinsic_matrix* heif_camera_intrinsic_matrix_alloc()
{
return new heif_camera_intrinsic_matrix;
}

void heif_camera_intrinsic_matrix_set_simple(struct heif_camera_intrinsic_matrix* matrix,
int image_width, int image_height,
double focal_length, double principal_point_x, double principal_point_y)
{
if (!matrix) {
return;
}

matrix->matrix.is_anisotropic = false;
matrix->matrix.focal_length_x = focal_length / image_width;
matrix->matrix.principal_point_x = principal_point_x / image_width;
matrix->matrix.principal_point_y = principal_point_y / image_height;
}

void heif_camera_intrinsic_matrix_set_full(struct heif_camera_intrinsic_matrix* matrix,
int image_width, int image_height,
double focal_length_x,
double focal_length_y,
double principal_point_x, double principal_point_y,
double skew)
{
if (!matrix) {
return;
}

if (focal_length_x == focal_length_y && skew == 0) {
heif_camera_intrinsic_matrix_set_simple(matrix, image_width, image_height, focal_length_x, principal_point_x, principal_point_y);
return;
}

matrix->matrix.is_anisotropic = true;
matrix->matrix.focal_length_x = focal_length_x / image_width;
matrix->matrix.focal_length_y = focal_length_y / image_width;
matrix->matrix.principal_point_x = principal_point_x / image_width;
matrix->matrix.principal_point_y = principal_point_y / image_height;
matrix->matrix.skew = skew;
}


struct heif_error heif_item_add_property_camera_intrinsic_matrix(const struct heif_context* context,
heif_item_id itemId,
const struct heif_camera_intrinsic_matrix* matrix,
heif_property_id* out_propertyId)
{
if (!context || !matrix) {
return {heif_error_Usage_error, heif_suberror_Null_pointer_argument, "NULL passed"};
}

auto cmin = std::make_shared<Box_cmin>();
cmin->set_intrinsic_matrix(matrix->matrix);

heif_property_id id = context->context->add_property(itemId, cmin, false);

if (out_propertyId) {
*out_propertyId = id;
}

return heif_error_success;
}
44 changes: 33 additions & 11 deletions libheif/heif_properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,23 +176,45 @@ struct heif_error heif_item_get_property_camera_intrinsic_matrix(const struct he
struct heif_camera_intrinsic_matrix** out_matrix);

LIBHEIF_API
void heif_intrinsic_matrix_release(struct heif_camera_intrinsic_matrix* matrix);
void heif_camera_intrinsic_matrix_release(struct heif_camera_intrinsic_matrix* matrix);

LIBHEIF_API
struct heif_error heif_intrinsic_matrix_get_focal_length(const struct heif_camera_intrinsic_matrix* matrix,
int image_width, int image_height,
double* out_focal_length_x,
double* out_focal_length_y);
struct heif_error heif_camera_intrinsic_matrix_get_focal_length(const struct heif_camera_intrinsic_matrix* matrix,
int image_width, int image_height,
double* out_focal_length_x,
double* out_focal_length_y);

LIBHEIF_API
struct heif_error heif_intrinsic_matrix_get_principal_point(const struct heif_camera_intrinsic_matrix* matrix,
int image_width, int image_height,
double* out_principal_point_x,
double* out_principal_point_y);
struct heif_error heif_camera_intrinsic_matrix_get_principal_point(const struct heif_camera_intrinsic_matrix* matrix,
int image_width, int image_height,
double* out_principal_point_x,
double* out_principal_point_y);

LIBHEIF_API
struct heif_error heif_intrinsic_matrix_get_skew(const struct heif_camera_intrinsic_matrix* matrix,
double* out_skew);
struct heif_error heif_camera_intrinsic_matrix_get_skew(const struct heif_camera_intrinsic_matrix* matrix,
double* out_skew);

LIBHEIF_API
struct heif_camera_intrinsic_matrix* heif_camera_intrinsic_matrix_alloc();

LIBHEIF_API
void heif_camera_intrinsic_matrix_set_simple(struct heif_camera_intrinsic_matrix* matrix,
int image_width, int image_height,
double focal_length, double principal_point_x, double principal_point_y);

LIBHEIF_API
void heif_camera_intrinsic_matrix_set_full(struct heif_camera_intrinsic_matrix* matrix,
int image_width, int image_height,
double focal_length_x,
double focal_length_y,
double principal_point_x, double principal_point_y,
double skew);

LIBHEIF_API
struct heif_error heif_item_add_property_camera_intrinsic_matrix(const struct heif_context* context,
heif_item_id itemId,
const struct heif_camera_intrinsic_matrix* matrix,
heif_property_id* out_propertyId);

#ifdef __cplusplus
}
Expand Down

0 comments on commit 2590903

Please sign in to comment.