title: How to display an image on a MKOverlayView?
body: <p><strong>UPDATE:</strong> </p>
  
  <p>Images who are projected on the MKMapView using a MKOverlayView use the <a href="http://en.wikipedia.org/wiki/Mercator_projection" rel="noreferrer">Mercator projection</a>, while the image that I use as input data uses a WGS84 projection. Is there a way to convert the input image, to the right projection WGS84 -> Mercator, without tiling the image up and can it done on the fly? </p>
  
  <p>Normally you could convert a image to right projection using the program <a href="http://www.gdal.org/gdal2tiles.html" rel="noreferrer">gdal2tiles</a>.
  The input data however changes every fifteen minutes, so the image has to be converted every fifteen minutes. So the conversion has to be done on the fly. I also want the tiling to be done by Mapkit and not by myself using gdal2tiles or the GDAL framework. </p>
  
  <p><strong>UPDATE END</strong></p>
  
  <p>I'm currently working on a project which displays a rainfall radar over some part of the world. The radar image is provided by EUMETSAT, they offer a KML file which can be loaded into Google Earth or Google Maps. If I load the KML file in Google Maps it displays perfectly, but if I draw the image using a MKOverlayView on a MKMapView, the image is slightly of.</p>
  
  <p>For example, on the left side, Google Maps and on the right side the same image is displayed at a MKMapView.</p>
  
  <p><img src="https://i.stack.imgur.com/Wu3IZ.png" alt="alt text"></p>
  
  <p><img src="https://i.stack.imgur.com/r6jVK.png" alt="alt text"></p>
  
  <p>The surface that the image covers can be viewed on <a href="http://maps.google.com/maps?f=q&amp;source=s_q&amp;hl=nl&amp;geocode=&amp;q=http:%2F%2Foiswww.eumetsat.org%2FIPPS%2Fhtml%2FGE%2FEUM.kml&amp;sll=37.0625,-95.677068&amp;sspn=48.287373,114.169922&amp;ie=UTF8&amp;ll=32.842674,7.734375&amp;spn=150.886926,96.679687&amp;z=2" rel="noreferrer">Google Maps</a>, the satellite that is used for the image is the "Meteosat 0 Degree" satellite.</p>
  
  <p>The surface that both images cover is of the same size, this is the LatLonBox from the KML file, it specifies where the top, bottom, right, and left sides of a bounding box for the ground overlay are aligned. </p>
  
  <pre><code>  &lt;LatLonBox id="GE_MET0D_VP-MPE-latlonbox"&gt;
          &lt;north&gt;57.4922&lt;/north&gt;
          &lt;south&gt;-57.4922&lt;/south&gt;
          &lt;east&gt;57.4922&lt;/east&gt;
          &lt;west&gt;-57.4922&lt;/west&gt;
          &lt;rotation&gt;0&lt;/rotation&gt;
    &lt;/LatLonBox&gt;
  </code></pre>
  
  <p>I create a new custom MKOverlay object called RadarOverlay with these parameters,</p>
  
  <pre><code>[[RadarOverlay alloc] initWithImageData:[[self.currentRadarData objectAtIndex:0] valueForKey:@"Image"] withLowerLeftCoordinate:CLLocationCoordinate2DMake(-57.4922, -57.4922) withUpperRightCoordinate:CLLocationCoordinate2DMake(57.4922, 57.4922)];
  </code></pre>
  
  <p>The implementation of the custom MKOverlay object; RadarOverlay</p>
  
  <pre><code>- (id) initWithImageData:(NSData*) imageData withLowerLeftCoordinate:(CLLocationCoordinate2D)lowerLeftCoordinate withUpperRightCoordinate:(CLLocationCoordinate2D)upperRightCoordinate
  {
       self.radarData = imageData;
  
       MKMapPoint lowerLeft = MKMapPointForCoordinate(lowerLeftCoordinate);
       MKMapPoint upperRight = MKMapPointForCoordinate(upperRightCoordinate);
  
       mapRect = MKMapRectMake(lowerLeft.x, upperRight.y, upperRight.x - lowerLeft.x, lowerLeft.y - upperRight.y);
  
       return self;
  }
  
  - (CLLocationCoordinate2D)coordinate
  {
       return MKCoordinateForMapPoint(MKMapPointMake(MKMapRectGetMidX(mapRect), MKMapRectGetMidY(mapRect)));
  }
  
  - (MKMapRect)boundingMapRect
  {
       return mapRect;
  }
  </code></pre>
  
  <p>The implementation of the custom MKOverlayView, RadarOverlayView</p>
  
  <pre><code>- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context
  {
      RadarOverlay* radarOverlay = (RadarOverlay*) self.overlay;
  
      UIImage *image          = [[UIImage alloc] initWithData:radarOverlay.radarData];
  
      CGImageRef imageReference = image.CGImage;
  
      MKMapRect theMapRect    = [self.overlay boundingMapRect];
     CGRect theRect           = [self rectForMapRect:theMapRect];
      CGRect clipRect     = [self rectForMapRect:mapRect];
  
      NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
      CGContextSetAlpha(context, [preferences floatForKey:@"RadarTransparency"]);
  
      CGContextAddRect(context, clipRect);
      CGContextClip(context);
  
      CGContextDrawImage(context, theRect, imageReference);
  
      [image release]; 
  }
  </code></pre>
  
  <p>When I download the image, I flip the image so it can be easily drawn in the MKOverlayView</p>
  
  <pre><code>size_t width    = (CGImageGetWidth(imageReference) / self.scaleFactor);
  size_t height   = (CGImageGetHeight(imageReference) / self.scaleFactor);
  
  // Calculate colorspace for the specified image
  CGColorSpaceRef imageColorSpace = CGImageGetColorSpace(imageReference);
  
  // Allocate and clear memory for the data of the image
  unsigned char *imageData = (unsigned char*) malloc(height * width * 4);
  memset(imageData, 0, height * width * 4);
  
  // Define the rect for the image
  CGRect imageRect;
  if(image.imageOrientation==UIImageOrientationUp || image.imageOrientation==UIImageOrientationDown) 
      imageRect = CGRectMake(0, 0, width, height); 
  else 
      imageRect = CGRectMake(0, 0, height, width); 
  
  // Create the imagecontext by defining the colorspace and the address of the location to store the data
  CGContextRef imageContext = CGBitmapContextCreate(imageData, width, height, 8, width * 4, imageColorSpace, kCGImageAlphaPremultipliedLast);
  
  CGContextSaveGState(imageContext);
  
  // Scale the image to the opposite orientation so it can be easylier drawn with CGContectDrawImage
  CGContextTranslateCTM(imageContext, 0, height);
  CGContextScaleCTM(imageContext, 1.0, -1.0);
  
  if(image.imageOrientation==UIImageOrientationLeft) 
  {
      CGContextRotateCTM(imageContext, M_PI / 2);
      CGContextTranslateCTM(imageContext, 0, -width);
  }
  else if(image.imageOrientation==UIImageOrientationRight) 
  {
      CGContextRotateCTM(imageContext, - M_PI / 2);
      CGContextTranslateCTM(imageContext, -height, 0);
  } 
  else if(image.imageOrientation==UIImageOrientationDown) 
  {
      CGContextTranslateCTM(imageContext, width, height);
      CGContextRotateCTM(imageContext, M_PI);
  }
  
  // Draw the image in the context
  CGContextDrawImage(imageContext, imageRect, imageReference);
  CGContextRestoreGState(imageContext);
  </code></pre>
  
  <p>After I flipped the image, I manipulate it and then store it in memory as a NSData object.</p>
  
  <p>It looks like the image got stretched, but it looks allright at the center of the image, which is at the equator.</p>