Trouble converting packed BGRA image buffer to RGB with OpenCV in Python
<p>Some context:<br>
I have a <a href="http://www.fileformat.info/mirror/egff/ch09_02.htm" rel="nofollow">packed BGRA</a> image in a buffer that I would like to convert to RGB.  </p>

<p>I use the following code to convert it to RGB using OpenCV:  </p>

<pre><code>np_a = np.array( image_buffer ) #image_buffer is an array of uint8
rgb_a = cv2.cvtColor( image_buffer, cv2.COLOR_BGRA2RGB )
</code></pre>

<p>But:  </p>

<pre><code>OpenCV Error: Assertion failed (scn == 3 || scn == 4) in ipp_cvtColor,
file /home/username/opencv/opencv-3.1.0/modules/imgpro/src/color.cpp, line 7341
</code></pre>

<p>As OpenCV is open source, I have dived into the <a href="https://github.com/Itseez/opencv/blob/master/modules/imgproc/src/color.cpp" rel="nofollow">source code</a> to figure out what happened.</p>

<pre><code>    static bool ipp_cvtColor( Mat &amp;src, OutputArray _dst, int code, int dcn )
    {
    int stype = src.type();
    int scn = CV_MAT_CN(stype), depth = CV_MAT_DEPTH(stype);

    Mat dst;
    Size sz = src.size();

    switch( code )
    {
#if IPP_VERSION_X100 &gt;= 700
        case CV_BGR2BGRA: case CV_RGB2BGRA: case CV_BGRA2BGR:
        case CV_RGBA2BGR: case CV_RGB2BGR: case CV_BGRA2RGBA:
            CV_Assert( scn == 3 || scn == 4 );
</code></pre>

<p>And:</p>

<pre><code>#define CV_MAT_CN (flags) ((((flags) &amp; CV_MAT_CN_MASK) &gt;&gt; CV_CN_SHIFT) + 1)
#define CV_MAT_CN_MASK ((CV_CN_MAX - 1) &lt;&lt; CV_CN_SHIFT)
#define CV_CN_MAX 512
#define CV_CN_SHIFT 3
</code></pre>

<p>I am not sure to understand these lines of code.<br>
I assume <code>scn</code> is the "source channel number" and that it is related to the number of dimension of the array. The assertion would then fail because the array was created as a 1D array.<br>
Indeed, <code>print np_a.ndim</code> outputs <code>1</code> and <code>print np_a.shape</code> outputs <code>(422400,)</code>.</p>

<p>I tried many things. Among them, setting the array's shape manually with <code>np_a.shape = (image_height, image_width)</code>, which ends with this error:  </p>

<pre><code>Program received signal SIGSEGV, Segmentation fault.
0x0000000000570558 in visit_decref ()
</code></pre>

<p>What am I missing?<br>
Am I supposed to manually unpack the image before converting it? How?</p>

<hr>

<p><strong>FIRST EDIT:</strong><br>
The buffer is filled using a C API. It is supposed to be an array of UINT8.</p>

<p>Also, this:</p>

<pre><code>print type( np_a )
print type( np_a[ 0 ] )
print np_a.shape
</code></pre>

<p>Outputs:</p>

<pre><code>&lt;type 'numpy.ndarray'&gt;
&lt;type 'numpy.uint8'&gt;
(422400,)
</code></pre>

<hr>

<p><strong>SECOND EDIT:</strong></p>

<p><strong><em>The issue is already solved, this is only for a better understanding / another way.</em></strong></p>

<p>Using:</p>

<pre><code>np_a           = np.array( image_buffer )
np_a_reshaped  = np_a.reshape( height, width, depth )
np_a_converted = np_a_reshaped[ ...,:3 ][ ...,::-1 ]
print len( np_a_converted )
</code></pre>

<p>Outputs: 480.</p>

<p>So yes, I was probably using <code>np_a.reshape( ... )</code> alone and assumed that it would change the shape of np_a. Why would you want to change the shape of the buffer <strong><em>and</em></strong> create a new variable?</p>

<p>However, the size of np_a_converted is still not correct. Indeed, later in the program, there is the following code:</p>

<pre><code>img = wx.ImageFromBuffer( width, height, np_a_converted )
bmp = wx.Bitmap( img )
</code></pre>

<p>To create a wx.Bitmap from the buffer, without copy of the data.</p>

<p>From <a href="http://wxpython.org/Phoenix/docs/html/functions.html#ImageFromBuffer" rel="nofollow">wx.ImageFromBuffer's documentation</a>:</p>

<blockquote>
  <p>The dataBuffer object is expected to contain a series of RGB bytes and
  be width*height*3 bytes long.</p>
</blockquote>

<p>And it gives this error:</p>

<pre><code>File "/usr/local/lib/python2.7/dist-packages/wx/core.py", line 656, in ImageFromBuffer
img.SetDataBuffer(dataBuffer)
ValueError: Invalid data buffer size.
</code></pre>