Vectorizing sRGB to linear conversion properly in Numpy
<p>In my image editing app I have a function for converting a 32 bit float image from sRGB to linear color space. The formula is:</p>

<pre><code>if value &lt;= 0.04045: (value / 12.92)
if value &gt; 0.04045: ((value + 0.055) / 1.055)^2.4)
</code></pre>

<p>My image is a three-dimensional <strong>numpy.ndarray</strong> named <strong>img32</strong>.</p>

<p>My implementation so far:</p>

<pre><code>boolarray = img32 &lt;= 0.04045
lower = (img32 / 12.92) * boolarray.astype(np.int)
upper = np.power(((img32 + 0.055) / 1.055), 2.4) * np.invert(boolarray).astype(np.int)
img32 = lower + upper
</code></pre>

<p>So, I am creating a new array <strong>boolarray</strong> with truth values for &lt;= 0.04045 and multiply by that.</p>

<p>What would be a better solution?</p>

<p>I tried something like:</p>

<pre><code>img32[img32 &lt; 0.04045] = img32 / 12.92
</code></pre>

<p>which works on the first step but fails on the second:</p>

<pre><code>img32[img32 &gt;= 0.04045] = np.power(((img32 + 0.055) / 1.055), 2.4)
</code></pre>

<p>probably because it doesn't work when wrapped in the <strong>np.power</strong> function</p>

<p>Any help is appreciated.</p>

<p>You could also use <a href="http://docs.scipy.org/doc/numpy/reference/generated/numpy.piecewise.html" rel="nofollow">numpy.piecewise</a>:</p>

<pre><code>In [11]: img32 = np.random.rand(800, 600).astype(np.float32)

In [12]: img_linear = np.piecewise(img32, 
           [img32  &lt;= 0.04045, img32 &gt; 0.04045], 
           [lambda v: v/12.92, lambda v: ((v + 0.055)/1.055)**2.4] )

In [13]: img_linear.shape
Out[13]: (800, 600)

In [14]: img_linear.dtype
Out[14]: dtype('float32')
</code></pre>

python numpy vectorization color-space srgb