title: trying to render an equirectangular panorama
body: <p>I have an equirectangular panorama source image which is 360 degrees of longitude and 120 degrees of latitude.</p>
  
  <p>I want to write a function which can render this, given width and height of the viewport and a rotation in longitude. I want to can my output image so that it's the full 120 degrees in height.</p>
  
  <p>has anyone got any pointers? I can't get my head around the maths on how to transform from target coordinates back to source.</p>
  
  <p>thanks</p>
  
  <p>slip</p>
  
  <p>Here is my code so far:- (create a c# 2.0 console app, add a ref to system.drawing)</p>
  
  <pre><code>static void Main(string[] args)
      {
  
          Bitmap src = new Bitmap(@"C:\Users\jon\slippyr4\pt\grid2.jpg");
  
          // constant stuff
          double view_width_angle = d2r(150);
          double view_height_angle = d2r(120);
          double rads_per_pixel = 2.0 * Math.PI / src.Width;
  
          // scale everything off the height
          int output_image_height = src.Width;
  
          // compute radius (from chord trig - my output image forms a chord of a circle with angle view_height_angle)
          double radius = output_image_height / (2.0 * Math.Sin(view_height_angle / 2.0));
  
          // work out the image width with that radius.
          int output_image_width = (int)(radius * 2.0 * Math.Sin(view_width_angle / 2.0));
  
          // source centres for later
          int source_centre_x = src.Width / 2;
          int source_centre_y = src.Height / 2;
  
          // work out adjacent length
          double adj = radius * Math.Cos(view_width_angle / 2.0);
  
          // create output bmp
          Bitmap dst = new Bitmap(output_image_width, output_image_height);
  
          // x &amp; y are output pixels offset from output centre
          for (int x = output_image_width / -2; x &lt; output_image_width / 2; x++)
          {
              // map this x to an angle &amp; then a pixel
              double x_angle = Math.Atan(x / adj);
              double src_x = (x_angle / rads_per_pixel) + source_centre_x;
  
              // work out the hypotenuse of that triangle
              double x_hyp = adj / Math.Cos(x_angle);
  
              for (int y = output_image_height / -2; y &lt; output_image_height / 2; y++)
              {
                  // compute the y angle and then it's pixel
                  double y_angle = Math.Atan(y / x_hyp);
                  double src_y = (y_angle / rads_per_pixel) + source_centre_y;
  
                  Color c = Color.Magenta;
                  // this handles out of range source pixels. these will end up magenta in the target
                  if (src_x &gt;= 0 &amp;&amp; src_x &lt; src.Width &amp;&amp; src_y &gt;= 0 &amp;&amp; src_y &lt; src.Height)
                  {
                      c = src.GetPixel((int)src_x, (int)src_y);
                  }
  
  
                  dst.SetPixel(x + (output_image_width / 2), y + (output_image_height / 2), c);
              }
          }
  
          dst.Save(@"C:\Users\slippyr4\Desktop\pana.jpg");
  
      }
  
      static double d2r(double degrees)
      {
          return degrees * Math.PI / 180.0;
      }
  </code></pre>
  
  <p><img src="https://i.stack.imgur.com/7gPqw.jpg" alt="source image i am using"></p>
  
  <p>With this code, i get the results i expect when i set my target image width to 120 degrees. I see the right curvature of horizontal lines etc, as below, and when i try it with a real-life equirectangular panorama, it looks like commercial viewers render.
  <img src="https://i.stack.imgur.com/hR2nI.png" alt="correct output at 120 degrees by 120 degrees"></p>
  
  <p>But, when i make the output image wider, it all goes wrong. You start to see the invalid pixels in a parabola top and bottom at the centre, as shown here with the image 150 degrees wide by 120 degrees high:-</p>
  
  <p><img src="https://i.stack.imgur.com/feK32.png" alt="enter image description here"></p>
  
  <p>What commericial viewers seem to do is sort of zoom in - so the in the centre, the image is 120 degrees high and therefore at the sides, more is clipped. and therfore, there is no magenta (ie, no invalid source pixels).</p>
  
  <p>But i can't get my head around how to do that in the maths.</p>
  
  <p>This isn't homework, it's a hobby project. hence why i am lacking the understanding of what is going on!. Also, please forgive the severe inefficeincy of the code, i will optimise it when i have it working propertly.</p>
  
  <p>thanks again</p>