[SciPy-User] FreeImage <-> numpy IO wrappers
Tue Oct 19 11:10:07 CDT 2010
Thanks -- I hope this winds up being useful. Stéfan tried out this
code a while ago and ran into a segfault loading a color jpeg that I
was never able to reproduce... perhaps something to do with the fact
that his python/FreeImage were 64-bit. Anyhow, beware that caveat.
> Here are some comment and questions:
> 1) I would rename it to freeImage.py - or alike
Yeah, sure, that's reasonable. Below is a new version of the code
that's a package that you import as "FreeImage"...
> 2) Compiling freeimage from source went really well. No configure,
> simple a "make" and it ran through. Except in my version
> freeimage-3.14.1 I had to add "#include <string.h>" to file
> ImathMatrix.h so that it would accept the use of memset(...)
Huh... that's odd. Good to know!
> 3) you are changing the FreeImage convention of 0,0 being bottom-left
> to 0,0 being top-left -- to make it more like "all other" image
> software. I actually come from UCSF where we used the MRC format
> having 0,0 being left-bottom. How strong do you feel about this ?
Pretty much all of the common basic image formats (TIFF, PNG, JPG and
the like) have 0,0 as top-left, so I tried to make it so that images
loaded would index just the same as they would in any other image
viewer like MetaMorph or ImageJ or Photoshop, etc. This explains the
0,0-as-top-left as well as your question 5 below about the striding.
Also, the image formats I'm most familiar with are by-and-large stored
on-disk in scanline order from top to bottom, then additional image
planes (also in scanline order). Which corresponds to fortran-order
(fast axis first) xy[zt] in memory, with 0,0 at the top-left. Which is
also what most libraries expect when passed an memory region that's
supposed to be an image (e.g. OpenGL, other UI libs, etc.), so I tried
to make the output conform to the most usual "expected" memory pattern.
One strange thing crops up with color images. Usually RGB(A) pixels
are stored next to eachother, so the fortran-order memory format is
cxyzt (again, this is what external libraries expect). But a
quick .view() operation with a structured RGB(A) dtype makes this work
more "naturally" (if desired).
> 4) For the return numpy-array you explicitly call copy() - I guess
> this is needed because one has to call FreeImage's unload() , right ?
Yes, this is the case.
I think there's some way in the numpy C-api (or perhaps the new py3
buffer api?) to specify a function pointer to be called when an array
needs to be freed (if the array is constructed around some external
chunk of memory). So if some numpy hacker who knows the C api better
than I could comment on how one might do this, it could be arranged
such that FreeImage_unload is called by numpy, so that we don't need
to copy the array and then manually unload the image.
> 5) you define the array strides to have the pitch (that is, the line
> width) last -- this is somewhat against the C-convention of having the
> fast axis last. Obviously you did this, to get arrays with indices i,j
> having x,y order rather than y,x -- how strong do you feel about this
> ? I accepted at some point that the fast (x) coordinate would be last
> and thus always write coordinates as y,x.
> (In 3D this becomes semi-naturally z,y,x rather then z,x,y - BTW - )
See above... given that images are usually fortran-order on disk and
that most external libraries expect them to be that way too, I think
that this is the most reasonable. It's just that PIL has been so
broken for so long that people on Python are used to indexing images
as i[y,x] instead of i[x,y]. But fortran-order arrays are just as
natural as C-order, and i[x,y,z,t] is also as natural, if not more so,
Again, the code is barely a few hundred lines, so feel free to modify
to the conventions that are most natural for your application! But I
think this is the best general-case approach.
> Do you happen to have os-x binaries of libfreeimage.dylib ?
I do -- 32-bit only though. (Pretty easy to build...) Do you want me
to send the dylib?
Attached is the latest version of my code, which has a few new bug
fixes from the previous version. (Can read palletized grey-scale
images, for example.) Just drop whatever .dylib, .dll, or .so
FreeImage shared library you've got into the directory with image.py
and the setup.py script will detect it and install it alongside the
python code. Then just do "import FreeImage" and you're good to go.
-------------- next part --------------
A non-text attachment was scrubbed...
Size: 5312 bytes
Desc: not available
Url : http://mail.scipy.org/pipermail/scipy-user/attachments/20101019/a2d8cd7b/attachment-0001.zip
-------------- next part --------------
More information about the SciPy-User