@@ -45,15 +45,6 @@ namespace po = boost::program_options;
4545namespace fs = boost::filesystem;
4646namespace pt = boost::property_tree;
4747
48- struct Contact
49- {
50- int rank;
51- std::string path;
52- int width;
53- int height;
54- sfmData::EEXIFOrientation orientation;
55- };
56-
5748/* *
5849 * A simple class for gaussian pyramid
5950 */
@@ -665,16 +656,93 @@ class CircleDetector
665656 size_t _minimal_size;
666657};
667658
668- void resample (image::Image<image::RGBfColor>& output, const image::Image<image::RGBfColor>& input)
659+ /* *
660+ * @brief Utility function for resizing an image.
661+ */
662+ void resample (image::Image<image::RGBfColor>& output,
663+ const image::Image<image::RGBfColor>& input)
669664{
670665 const oiio::ImageBuf inBuf (oiio::ImageSpec (input.Width (), input.Height (), 3 , oiio::TypeDesc::FLOAT),
671666 const_cast <image::RGBfColor*>(input.data ()));
667+
672668 oiio::ImageBuf outBuf (oiio::ImageSpec (output.Width (), output.Height (), 3 , oiio::TypeDesc::FLOAT),
673669 (image::RGBfColor*)output.data ());
674670
675671 oiio::ImageBufAlgo::resample (outBuf, inBuf, false );
676672}
677673
674+ /* *
675+ * @brief Utility function for rotating an image given its orientation metadata.
676+ */
677+ void applyOrientation (image::Image<image::RGBfColor>& output,
678+ const image::Image<image::RGBfColor>& input,
679+ sfmData::EEXIFOrientation orientation)
680+ {
681+ const oiio::ImageBuf inBuf (oiio::ImageSpec (input.Width (), input.Height (), 3 , oiio::TypeDesc::FLOAT),
682+ const_cast <image::RGBfColor*>(input.data ()));
683+
684+ oiio::ImageBuf outBuf (oiio::ImageSpec (output.Width (), output.Height (), 3 , oiio::TypeDesc::FLOAT),
685+ (image::RGBfColor*)output.data ());
686+
687+ switch (orientation)
688+ {
689+ case sfmData::EEXIFOrientation::UPSIDEDOWN:
690+ oiio::ImageBufAlgo::rotate180 (outBuf, inBuf);
691+ break ;
692+ case sfmData::EEXIFOrientation::LEFT:
693+ oiio::ImageBufAlgo::rotate90 (outBuf, inBuf);
694+ break ;
695+ case sfmData::EEXIFOrientation::RIGHT:
696+ oiio::ImageBufAlgo::rotate270 (outBuf, inBuf);
697+ break ;
698+ default :
699+ outBuf.copy (inBuf);
700+ break ;
701+ }
702+ }
703+
704+ /* *
705+ * @brief Utility struct for contact sheet elements.
706+ */
707+ struct Contact
708+ {
709+ int rank;
710+ std::string path;
711+ int width;
712+ int height;
713+ sfmData::EEXIFOrientation orientation;
714+ };
715+
716+ /* *
717+ * @brief Width of contact sheet element, taking into account orientation metadata.
718+ */
719+ int orientedWidth (const Contact& contact)
720+ {
721+ switch (contact.orientation )
722+ {
723+ case sfmData::EEXIFOrientation::LEFT:
724+ case sfmData::EEXIFOrientation::RIGHT:
725+ return contact.height ;
726+ default :
727+ return contact.width ;
728+ }
729+ }
730+
731+ /* *
732+ * @brief Height of contact sheet element, taking into account orientation metadata.
733+ */
734+ int orientedHeight (const Contact& contact)
735+ {
736+ switch (contact.orientation )
737+ {
738+ case sfmData::EEXIFOrientation::LEFT:
739+ case sfmData::EEXIFOrientation::RIGHT:
740+ return contact.width ;
741+ default :
742+ return contact.height ;
743+ }
744+ }
745+
678746bool buildContactSheetImage (image::Image<image::RGBfColor>& output,
679747 const std::map<int , std::map<int , Contact>>& contactSheetInfo, int contactSheetItemMaxSize)
680748{
@@ -686,8 +754,8 @@ bool buildContactSheetImage(image::Image<image::RGBfColor>& output,
686754 {
687755 for (const auto & item : rowpair.second )
688756 {
689- maxdim = std::max (maxdim, item.second . width );
690- maxdim = std::max (maxdim, item.second . height );
757+ maxdim = std::max (maxdim, orientedWidth ( item.second ) );
758+ maxdim = std::max (maxdim, orientedHeight ( item.second ) );
691759 }
692760 }
693761 double ratioResize = double (contactSheetItemMaxSize) / double (maxdim);
@@ -702,8 +770,8 @@ bool buildContactSheetImage(image::Image<image::RGBfColor>& output,
702770
703771 for (const auto & item : rowpair.second )
704772 {
705- int resizedHeight = int (ratioResize * double (item.second . height ));
706- int resizedWidth = int (ratioResize * double (item.second . width ));
773+ int resizedHeight = int (ratioResize * double (orientedHeight ( item.second ) ));
774+ int resizedWidth = int (ratioResize * double (orientedWidth ( item.second ) ));
707775
708776 rowHeight = std::max (rowHeight, resizedHeight);
709777 rowWidth += resizedWidth + space;
@@ -729,8 +797,8 @@ bool buildContactSheetImage(image::Image<image::RGBfColor>& output,
729797
730798 for (const auto & item : rowpair.second )
731799 {
732- int resizedHeight = int (ratioResize * double (item.second . height ));
733- int resizedWidth = int (ratioResize * double (item.second . width ));
800+ int resizedHeight = int (ratioResize * double (orientedHeight ( item.second ) ));
801+ int resizedWidth = int (ratioResize * double (orientedWidth ( item.second ) ));
734802
735803 rowHeight = std::max (rowHeight, resizedHeight);
736804 rowWidth += resizedWidth + space;
@@ -742,15 +810,20 @@ bool buildContactSheetImage(image::Image<image::RGBfColor>& output,
742810 int posX = space;
743811 for (const auto & item : rowpair.second )
744812 {
745- int resizedHeight = int (ratioResize * double (item.second .height ));
746- int resizedWidth = int (ratioResize * double (item.second .width ));
813+ int rawResizedHeight = int (ratioResize * double (item.second .height ));
814+ int rawResizedWidth = int (ratioResize * double (item.second .width ));
815+
816+ int resizedHeight = int (ratioResize * double (orientedHeight (item.second )));
817+ int resizedWidth = int (ratioResize * double (orientedWidth (item.second )));
747818
748819 image::Image<image::RGBfColor> input;
820+ image::Image<image::RGBfColor> rawThumbnail (rawResizedWidth, rawResizedHeight);
749821 image::Image<image::RGBfColor> thumbnail (resizedWidth, resizedHeight);
750822
751823 image::readImage (item.second .path , input, image::EImageColorSpace::SRGB);
752824
753- resample (thumbnail, input);
825+ resample (rawThumbnail, input);
826+ applyOrientation (thumbnail, rawThumbnail, item.second .orientation );
754827
755828 rowOutput.block (0 , posX, resizedHeight, resizedWidth) = thumbnail;
756829 posX += resizedWidth + space;
@@ -1154,9 +1227,32 @@ int main(int argc, char* argv[])
11541227 for (const auto & item_rotation : rotations)
11551228 {
11561229 IndexT viewIdx = namesWithRank[index].second ;
1157- if (item_rotation.second .trace () != 0 )
1230+ const sfmData::View& v = sfmData.getView (viewIdx);
1231+
1232+ sfmData::EEXIFOrientation orientation = v.getMetadataOrientation ();
1233+ double orientationAngle = 0 .;
1234+ switch (orientation)
1235+ {
1236+ case sfmData::EEXIFOrientation::UPSIDEDOWN:
1237+ orientationAngle = boost::math::constants::pi<double >();
1238+ break ;
1239+ case sfmData::EEXIFOrientation::LEFT:
1240+ orientationAngle = boost::math::constants::pi<double >() * .5 ;
1241+ break ;
1242+ case sfmData::EEXIFOrientation::RIGHT:
1243+ orientationAngle = boost::math::constants::pi<double >() * -.5 ;
1244+ break ;
1245+ default :
1246+ break ;
1247+ }
1248+
1249+ const Eigen::AngleAxis<double > Morientation (orientationAngle, Eigen::Vector3d::UnitZ ());
1250+
1251+ const Eigen::Matrix3d viewRotation = Morientation.toRotationMatrix ().transpose () * item_rotation.second ;
1252+
1253+ if (viewRotation.trace () != 0 )
11581254 {
1159- sfmData::CameraPose pose (geometry::Pose3 (item_rotation. second , Eigen::Vector3d::Zero ()));
1255+ sfmData::CameraPose pose (geometry::Pose3 (viewRotation , Eigen::Vector3d::Zero ()));
11601256 sfmData.setAbsolutePose (viewIdx, pose);
11611257 }
11621258 ++index;
0 commit comments