This part (use of tileLoadFunction) is a bit hackish. For example there's no guarantee that the image.onload callback will be executed before that of the ImageTile object. Instead of defining a tileLoadFunction it may be possible to create an ol.ZoomifyTile class with a specific getImage function that returns a canvas when the image is smaller than a tile.