Note that there are some explanatory texts on larger screens.

plurals
  1. POPIL's Image.frombuffer expected data length when using ctypes array
    primarykey
    data
    text
    <p>I am using Python, PIL and ctypes to do image manipulation. As I hacked stuff together, I used PIL's <code>fromstring</code> function to get the pixel buffer from ctypes into a PIL object. I simply iterated over the array, building the python string. </p> <p><strong>This works</strong></p> <pre><code>tx = foo.tx tx.restype = POINTER(c_ubyte) result = tx(...args...) #TODO there must also be a better way to do this pystr = "" for i in xrange(w*h*4): pystr += result[i] i = Image.fromstring("RGBA", (w, h), pystr) i.save("out.png") </code></pre> <p>It wasn't pretty, but it worked. Commented with a TODO and moved on. After getting the initial plumbing in place, profiling showed significant performance issues with this code block. Not surprising, I guess.</p> <p><strong>This does not work</strong></p> <p>Similar to this question: <a href="https://stackoverflow.com/questions/6368645/pixel-manipulation-with-pil-image-and-ctypes">Pixel manipulation with PIL.Image and ctypes</a>, I am trying to use <code>frombuffer()</code> to get the pixel data into the PIL object more efficiently: </p> <pre><code>tx = foo.tx tx.restype = POINTER(c_ubyte) result = tx(...args...) i = Image.frombuffer('RGBA', (w, h), result, 'raw', 'RGBA', 0, 1) i.save("out.png") </code></pre> <p>Despite <code>fromstring</code> working, using <code>frombuffer</code> results in the following exception:</p> <pre><code>Traceback (most recent call last): File "test.py", line 53, in &lt;module&gt; i = Image.frombuffer('RGBA', (w, h), res, 'raw', 'RGBA', 0, 1) File "/Library/Python/2.7/site-packages/PIL/Image.py", line 1853, in frombuffer core.map_buffer(data, size, decoder_name, None, 0, args) ValueError: buffer is not large enough </code></pre> <p><strong>Environment</strong></p> <p>The buffer is <code>malloc</code>'ed in C as:</p> <pre><code>unsigned char *pixels_color = (unsigned char*)malloc((WIDTH*HEIGHT*4)*sizeof(unsigned char*)); </code></pre> <ul> <li>The buffer has 4 bytes per pixel for each of the bands RGBA.</li> <li>Mac OS X 10.7, python2.7.1, PIL 1.1.7</li> </ul> <p><strong>Edit</strong></p> <p>Based on <a href="https://stackoverflow.com/users/205580/eryksun">eryksun</a>'s comment and answer below, I moved the buffer allocation from the <code>malloc</code> in the C library into Python and passed the pointer into C:</p> <pre><code>tx = foo.tx tx.restype = POINTER(c_ubyte) pix_clr = (c_ubyte*(w*h*4))() tx(...args..., pix_clr) i = Image.frombuffer('RGBA', (w, h), pix_clr, 'raw', 'RGBA', 0, 1) i.save("out.png") </code></pre> <p>This works as expected. It still doesn't explain <em>why</em> PIL was unhappy with the C-allocated buffer, but this is the better structure for memory management anyway. Thanks to both ErykSun and HYRY!</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload