title: HTML5 canvas scaling issue on iOS platforms
body: <p>I've been developing a project in phonegap, attempting to build for Android and iOS.  The main idea is to access a saved picture on the phone library, save that picture to an HTML img element, and then draw that img element onto a canvas.  From there, the user can scale and rotate the image.</p>
  
  <p>I've had no issues on the Android.  I've tested using emulators and devices, and have tested a wide array of devices (different pixel ratios, densities, etc.) and the resulting canvas transformations always give the expected result.</p>
  
  <p>The iOS version, on the other hand, has not been as successful.  Scaling/Rotating the canvas looks fine, until I scale the canvas slightly larger than its original size (about 4-5 pixels larger than original).  After scaling the canvas up in size, the image drawn on the canvas changes.  Instead of now seeing the entire image displayed, I usually get a small portion of the image (usually the top-left corner) drawn over the entire canvas.</p>
  
  <p>My canvas in html:</p>
  
  <pre><code>&lt;canvas id="sourceImgCanvas" width="200" height="200" style="z-index:1; position:absolute; left:5%; top:100px;"&gt;&lt;/canvas&gt;
  </code></pre>
  
  <p>The image I receive from the phone library is almost always too large for the phone screen.  I scale the image down and record the ratio by which I shrank the image (drawRatio is 1 if no scaling occured, greater than 1 if image was shrank to fit screen).  PhoneGap handles grabbing the picture from the phone library, and I simply use the imageURI returned from the photo and set it to an img element <a href="http://docs.phonegap.com/phonegap_camera_camera.md.html#Camera" rel="nofollow">Phonegap Camera API</a>:</p>
  
  <pre><code>// Called when a photo is successfully retrieved
  function onPhotoURISuccess(imageURI) 
  {
      sourceImage = document.getElementById('sourceImg');
      sourceImage.src = imageURI;
  
      //signal that user can manipulate photo with touch inputs
      b_editPhotoAllowed = true;
  }
  </code></pre>
  
  <p>To scale the canvas, I have an arrow on the bottom-right corner of the canvas.  Upon being dragged, it records how far away it is from the top-left corner of the canvas and sets the canvas height/width based on the distance.</p>
  
  <pre><code>//Calls when user is dragging the arrow resize button.  Updates the source image size
  function ResizeSourceImage() {
      var horizontalDistanceFromTopLeft = parseFloat(ovalCanvas.style.left) + ovalCanvas.width - endX;
      var verticalDistanceFromTopLeft = parseFloat(ovalCanvas.style.top) + ovalCanvas.height - endY;
  
      //update canvas size with new length
      sourceImgCanvas.width = originalSrcImgWidth - horizontalDistanceFromTopLeft;
      sourceImgCanvas.height = originalSrcImgHeight - verticalDistanceFromTopLeft;
  
      //re-draw based on new size
      sourceImgContext.drawImage(sourceImg, 0, 0, pictureWidth * drawRatio * drawRatioMod, pictureHeight * drawRatio * drawRatioMod, 0, 0, sourceImgCanvas.width, sourceImgCanvas.height);
  }
  </code></pre>
  
  <p>The above drawRatio is the ratio I store upon re-sizing an image (code not shown here; it's rather long, but simple.)  </p>
  
  <p>The <code>drawRatioMod</code> is a value I set while experimenting, and is the main focus of my question.  On Android, I set <code>drawRatioMod = 1</code> so that drawing is not affected.  On iPhone4/iPad (the devices I have available to test with), I set <code>drawRatioMod = 0.5</code>.  This solved some initial issues I was experiencing with the html5 canvas on the iOS: since the iPhone4's resolution is actually twice it's screen size, I reduced the length/width of the source image to be drawn by half.</p>
  
  <p>The above <code>ResizeSourceImage()</code> function is called everytime the user moves the resize arrow tool, thus updating the canvas size.  The image adjusts properly to the new canvas size <em>only</em> if I scale down.  If I scale the canvas up more than about 5-6 pixels, the canvas no longer draws the entire source image; instead, the canvas draws only the top-left corner of the image over the entire canvas.</p>
  
  <p>I've been tackling this issue for a few days and have had no luck.  I initially thought it had something to do with the device pixel ratio (accessible thru Javascript <code>window.devicePixelRatio</code>) but I've tested on several Android devices of varying ratios and have never had this result.  </p>
  
  <p>I feel like I'm very close to solving, as the image only displays incorrectly when scaling up on the iOS.  Any pointers/tips are greatly appreciated!  I've tried several fixes related to <code>window.devicePixelRatio</code> but my iPad's iPhone4 simulator always returns a pixelRatio of 1 (which seems incorrect) and I've had no luck with such fixes.</p>
  
  <p>Cheers!  (I attempted to post the bare-bones code dealing with the scaling and drawing of the canvas.  If you would like to see additional code, I can post more; was hoping to have a post that didn't resemble the great wall of China :) )</p>