LCOV - code coverage report
Current view: top level - src/IC - BMP.H (source / functions) Hit Total Coverage
Test: coverage_merged.info Lines: 72 104 69.2 %
Date: 2024-11-18 05:28:54 Functions: 5 5 100.0 %

          Line data    Source code
       1             : // 
       2             : // Initialize a field using a bitmap image. (2D only)
       3             : //
       4             : // Note that in GIMP, you must select "do not write color space information"
       5             : // and "24 bit R8 G8 B8" when exporting the BMP file.
       6             : //
       7             : 
       8             : #ifndef IC_BMP_H
       9             : #define IC_BMP_H
      10             : #include <cmath>
      11             : 
      12             : #include "IC/IC.H"
      13             : #include "Util/Util.H"
      14             : #include "Util/BMP.H"
      15             : #include "Set/Set.H"
      16             : #include "IO/ParmParse.H"
      17             : 
      18             : namespace IC
      19             : {
      20             : class BMP : public IC
      21             : {
      22             : public:
      23             :     static constexpr const char* name = "bmp";
      24             : 
      25             :     //enum Type {XYZ, XY, YZ, XZ};
      26             :     enum Fit {Stretch,FitWidth,FitHeight,Coord};
      27             :     enum Channel {R=0, G=1, B=2};
      28             : 
      29           2 :     BMP (amrex::Vector<amrex::Geometry> &_geom) : IC(_geom)  {}
      30             : 
      31           2 :     BMP (amrex::Vector<amrex::Geometry> &_geom, IO::ParmParse &pp, std::string name) : BMP(_geom)
      32             :     {
      33           2 :         pp_queryclass(name,*this);
      34           2 :     }
      35             : 
      36             :     void Define(std::string bmpfilename)
      37             :     {
      38             :         bmp.Define(bmpfilename);//"Interface_Blur2.bmp");
      39             :     }
      40             :   
      41          12 :     void Add(const int &lev, Set::Field<Set::Scalar> &a_field, Set::Scalar)
      42             :     {        
      43             :         
      44          12 :         Set::Vector DX(geom[lev].CellSize());
      45          12 :         amrex::Box domain = geom[lev].Domain();
      46             : 
      47             :         //Set::Scalar width  = geom[lev].ProbHi()[0] - geom[lev].ProbLo()[0];
      48             :         //Set::Scalar height = geom[lev].ProbHi()[1] - geom[lev].ProbLo()[1];
      49             : 
      50          12 :         Set::Scalar img_width = (Set::Scalar)(bmp.nx-1);
      51          12 :         Set::Scalar img_height = (Set::Scalar)(bmp.ny-1);
      52          12 :         Set::Scalar img_dx = 1.0;
      53          12 :         Set::Scalar img_dy = 1.0;
      54             : 
      55          12 :         amrex::IndexType type = a_field[lev]->ixType();
      56          12 :         domain.convert(type);
      57             : 
      58          12 :         Set::Vector domlo(AMREX_D_DECL(geom[lev].ProbLo()[0],geom[lev].ProbLo()[1],0.0));
      59          12 :         Set::Vector domhi(AMREX_D_DECL(geom[lev].ProbHi()[0],geom[lev].ProbHi()[1],0.0));
      60             : 
      61          24 :         for (amrex::MFIter mfi(*a_field[lev],amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
      62             :         {
      63          12 :             amrex::Box bx;
      64          24 :             if (type == amrex::IndexType::TheNodeType()) bx = mfi.grownnodaltilebox();
      65          24 :             if (type == amrex::IndexType::TheCellType()) bx = mfi.growntilebox();
      66          12 :             bx = bx & domain;
      67             : 
      68             : 
      69          12 :             amrex::Array4<Set::Scalar> const& field = a_field[lev]->array(mfi);
      70          12 :             amrex::ParallelFor (bx,[=] AMREX_GPU_DEVICE(int i, int j, int k) 
      71             :             {
      72      241664 :                 Set::Vector x = Set::Vector::Zero();
      73             :                 // NODE
      74      483328 :                 if (type == amrex::IndexType::TheNodeType())
      75             :                 {
      76           0 :                     x(0) = domlo(0) + ((amrex::Real)(i)) * geom[lev].CellSize()[0];
      77           0 :                     x(1) = domlo(1) + ((amrex::Real)(j)) * geom[lev].CellSize()[1];
      78             :                 }
      79      483328 :                 else if (type == amrex::IndexType::TheCellType())
      80             :                 {
      81      241664 :                     x(0) = domlo(0) + ((amrex::Real)(i) + 0.5) * geom[lev].CellSize()[0];
      82      241664 :                     x(1) = domlo(1) + ((amrex::Real)(j) + 0.5) * geom[lev].CellSize()[1];
      83             :                 }
      84             : 
      85             :                 //Set::Scalar x, y;
      86      241664 :                 Set::Vector ximg;
      87             : 
      88      241664 :                 if (fit == Fit::Stretch)
      89             :                 {
      90           0 :                     ximg(0) = (x(0) - domlo(0)) / (domhi(0) - domlo(0)); 
      91           0 :                     ximg(1) = (x(1) - domlo(1)) / (domhi(1) - domlo(1)); 
      92             :                 }
      93      241664 :                 else if (fit == Fit::FitWidth)
      94             :                 {
      95      724992 :                     Set::Scalar aspect_ratio = img_width / img_height;
      96      241664 :                     ximg(0) = (x(0) - domlo(0)) / (domhi(0) - domlo(0)); 
      97      241664 :                     ximg(1) = (x(1) - domlo(1)) / (domhi(1) - domlo(1)); 
      98      241664 :                     ximg(1) -= 0.5 - 0.5 / aspect_ratio;
      99      241664 :                     ximg(1) *= aspect_ratio;
     100             :                 }
     101           0 :                 else if (fit == Fit::FitHeight)
     102             :                 {
     103           0 :                     Set::Scalar aspect_ratio = img_height / img_width;
     104           0 :                     ximg(0) = (x(0) - domlo(0)) / (domhi(0) - domlo(0)); 
     105           0 :                     ximg(1) = (x(1) - domlo(1)) / (domhi(1) - domlo(1)); 
     106           0 :                     ximg(0) -= 0.5 - 0.5 / aspect_ratio;
     107           0 :                     ximg(0) *= aspect_ratio;
     108             :                 }
     109           0 :                 else if (fit == Fit::Coord)
     110             :                 {
     111           0 :                     ximg(0) = (x(0) - coord_lo(0)) / (coord_hi(0)-coord_lo(0));
     112           0 :                     ximg(1) = (x(1) - coord_lo(1)) / (coord_hi(1)-coord_lo(1));
     113             :                 }
     114             : 
     115      241664 :                 ximg(0) = std::min(ximg(0),1.0); ximg(1) = std::min(ximg(1),1.0);
     116      241664 :                 ximg(0) = std::max(ximg(0),0.0); ximg(1) = std::max(ximg(1),0.0);
     117             :                 
     118      241664 :                 ximg(0) *= img_width;
     119      241664 :                 ximg(1) *= img_height;
     120             : 
     121      241664 :                 int I = (int)(ximg(0));
     122      241664 :                 int J = (int)(ximg(1));
     123             : 
     124      483328 :                 Set::Scalar x1 = I*img_dx, x2 = (I+1)*img_dx;
     125      483328 :                 Set::Scalar y1 = J*img_dy, y2 = (J+1)*img_dy;
     126             : 
     127      241664 :                 if (I < bmp.nx-1 && J < bmp.ny - 1)
     128             :                 {
     129      483328 :                     Set::Scalar fQ11 = ((Set::Scalar)(bmp(I,  J  )[channel]) - min) / (max - min);
     130      483328 :                     Set::Scalar fQ12 = ((Set::Scalar)(bmp(I,  J+1)[channel]) - min) / (max - min);
     131      483328 :                     Set::Scalar fQ21 = ((Set::Scalar)(bmp(I+1,J  )[channel]) - min) / (max - min);
     132      483328 :                     Set::Scalar fQ22 = ((Set::Scalar)(bmp(I+1,J+1)[channel]) - min) / (max - min);
     133             : 
     134      483328 :                     field(i,j,k) =
     135      483328 :                         (fQ11*(x2-ximg(0))*(y2-ximg(1)) + fQ21*(ximg(0)-x1)*(y2-ximg(1)) + fQ12*(x2-ximg(0))*(ximg(1)-y1) + fQ22*(ximg(0)-x1)*(ximg(1)-y1)) / (img_dx * img_dy);
     136             :                 }
     137           0 :                 else if (I == bmp.nx-1 && J <  bmp.ny - 1)
     138             :                 {
     139           0 :                     Set::Scalar fQ11 = ((Set::Scalar)(bmp(I  ,J  )[channel]) - min) / (max - min);
     140           0 :                     Set::Scalar fQ12 = ((Set::Scalar)(bmp(I  ,J+1)[channel]) - min) / (max - min);
     141           0 :                     field(i,j,k) = fQ11 + (fQ12-fQ11) * (ximg(1) - y1);
     142             :                 }
     143           0 :                 else if (I <  bmp.nx-1 && J == bmp.ny - 1)
     144             :                 {
     145           0 :                     Set::Scalar fQ11 = ((Set::Scalar)(bmp(I  ,J  )[channel]) - min) / (max - min);
     146           0 :                     Set::Scalar fQ21 = ((Set::Scalar)(bmp(I+1,J  )[channel]) - min) / (max - min);
     147           0 :                     field(i,j,k) = fQ11 + (fQ21-fQ11) * (ximg(0) - x1);
     148             :                 }
     149           0 :                 else if (I ==  bmp.nx-1 && J == bmp.ny - 1)
     150             :                 {
     151           0 :                     Set::Scalar fQ11 = ((Set::Scalar)(bmp(I  ,J  )[channel]) - min) / (max - min);
     152           0 :                     field(i,j,k) = fQ11;
     153             :                 }
     154             :                 else
     155             :                 {
     156           0 :                     field(i,j,k) = 0.0;
     157             :                 }
     158             : 
     159      483328 :                 if (field.nComp() > 1) field(i,j,k,1) = 1.0 - field(i,j,k,0);
     160             : 
     161      241664 :             });
     162             :         }
     163          12 :         a_field[lev]->FillBoundary();
     164          12 :     };
     165             :   
     166             : private:
     167             :     Util::BMP bmp;
     168             :     Fit fit = Fit::Stretch;
     169             :     Channel channel = Channel::G;
     170             :     Set::Scalar min=NAN, max=NAN;
     171             :     Set::Vector coord_lo = Set::Vector::Zero();
     172             :     Set::Vector coord_hi = Set::Vector::Zero();
     173             : 
     174             : 
     175             : public:
     176           2 :     static void Parse(BMP & value, IO::ParmParse & pp)
     177             :     {
     178           4 :         std::string filename;
     179           2 :         pp_query_file("filename",filename); // BMP filename.
     180           2 :         value.bmp.Define(filename);
     181             : 
     182           4 :         std::string fit;
     183             :         // How to position image in space
     184           2 :         pp_query_validate("fit",fit,{"stretch","fitheight","fitwidth","coord"}); 
     185           2 :         if (fit=="stretch")        value.fit = Fit::Stretch;
     186           2 :         else if (fit=="fitheight") value.fit = Fit::FitHeight;
     187           2 :         else if (fit=="fitwidth")  value.fit = Fit::FitWidth;
     188           0 :         else if (fit=="coord")
     189             :         {
     190           0 :             value.fit = Fit::Coord;
     191           0 :             pp_queryarr("coord.lo",value.coord_lo); // Location of lower-left corner in the domain
     192           0 :             pp_queryarr("coord.hi",value.coord_hi); // Location of upper-right corner in the domain
     193             :         }
     194           0 :         else Util::Abort(INFO,"Invalid value for bmp fit - should be stretch/fitheight/fitwidth but received '",fit,"'");
     195             : 
     196           2 :         std::string channel;
     197             :         // Color channel to use
     198           2 :         pp_query_validate("channel",channel,{"r","g","b","R","G","B"}); 
     199           2 :         if      (channel=="r" || channel=="R") value.channel = Channel::R;
     200           2 :         else if (channel=="g" || channel=="G") value.channel = Channel::G;
     201           0 :         else if (channel=="b" || channel=="B") value.channel = Channel::B;
     202           0 :         else Util::Abort(INFO,"Invalid value for bmp channel - should be r/g/b but received '",channel,"'");
     203             : 
     204           2 :         value.min = (Set::Scalar) value.bmp.min()[value.channel];
     205           2 :         value.max = (Set::Scalar) value.bmp.max()[value.channel];
     206           2 :         pp_query_default("min",value.min,0.0); // Scaling value - minimum
     207           2 :         pp_query_default("max",value.max,255.0); // Scaling value - maximum
     208           2 : }    
     209             : };
     210             : }
     211             : #endif

Generated by: LCOV version 1.14