title: Changing image hue with Python PIL
body: <p>Using Python PIL, I'm trying to adjust the hue of a given image.</p>
  
  <p>I'm not very comfortable with the jargon of graphics, so what I mean by “adjusting hue” is doing the Photoshop operation called <a href="http://www.guidebookgallery.org/pics/apps/photoshop/usage/colours/huesaturation/900.png" rel="noreferrer">“Hue/saturation”</a>: this is to change the color of the image uniformly as shown below:</p>
  
  <ul>
  <li>Original: <img src="https://i.stack.imgur.com/YSTgM.png" alt="Original"></li>
  <li>With hue adjusted to +180 (red): <img src="https://i.stack.imgur.com/bGe2a.png" alt="hue: -180"></li>
  <li>With hue adjusted to -78 (green): <img src="https://i.stack.imgur.com/Mqmh1.png" alt="hue: -78"></li>
  </ul>
  
  <p>FYI, Photoshop uses a scale of -180 to +180 for this hue setting (where -180 equals +180), that may represents the <a href="http://en.wikipedia.org/wiki/HSL_and_HSV#Hue_and_chroma" rel="noreferrer">HSL hue scale</a> (expressed in 0-360 degree).</p>
  
  <p>What I'm looking for is <strong>a function that, given an PIL image and a float <em>hue</em> within [0, 1] (or int within [0, 360], it doesn't matter), returns the image with its hue shifted by <em>hue</em></strong> as in the example above.</p>
  
  <p>What I've done so far is ridiculous and obviously doesn't give the desired result. It just half-blend my original image with a color-filled layer.</p>
  
  <pre><code>import Image
  
  im = Image.open('tweeter.png')
  layer = Image.new('RGB', im.size, 'red') # "hue" selection is done by choosing a color...
  output = Image.blend(im, layer, 0.5)
  output.save('output.png', 'PNG')
  </code></pre>
  
  <p>(Please-don't-laugh-at-) result: <img src="https://i.stack.imgur.com/A9fjk.png" alt="output.png"></p>
  
  <p>Thanks in advance!</p>
  
  <hr>
  
  <p><strong>Solution</strong>: here is the unutbu code updated so it fits exactly what I've described.</p>
  
  <pre><code>import Image
  import numpy as np
  import colorsys
  
  rgb_to_hsv = np.vectorize(colorsys.rgb_to_hsv)
  hsv_to_rgb = np.vectorize(colorsys.hsv_to_rgb)
  
  def shift_hue(arr, hout):
      r, g, b, a = np.rollaxis(arr, axis=-1)
      h, s, v = rgb_to_hsv(r, g, b)
      h = hout
      r, g, b = hsv_to_rgb(h, s, v)
      arr = np.dstack((r, g, b, a))
      return arr
  
  def colorize(image, hue):
      """
      Colorize PIL image `original` with the given
      `hue` (hue within 0-360); returns another PIL image.
      """
      img = image.convert('RGBA')
      arr = np.array(np.asarray(img).astype('float'))
      new_img = Image.fromarray(shift_hue(arr, hue/360.).astype('uint8'), 'RGBA')
  
      return new_img
  </code></pre>