Repository: scikit-image/scikit-image

Issue:
freeimage save/load tests broken for rgb on big endian
the freeimage save/load  tests fail on big endian architectures, the loaded image is reversed in the first two dimensions.
I suspect the write normalization function is broken for 3d inputs.
changing:

```
return arr.T[:, ::-1]
```

to

```
return arr.T[..., ::-1]
```

in `_array_to_bitmap` seems to fix the issue, but I am not familiar with freeimages format so I can't judge if this is correct.



Discussion:
Hello Julian,

I had noticed the same behavior
for skimage_0.9.3-4 on Debian for big endian archs:

https://buildd.debian.org/status/fetch.php?pkg=skimage&arch=sparc&ver=0.9.3-4&stamp=1396463072
https://buildd.debian.org/status/fetch.php?pkg=skimage&arch=s390x&ver=0.9.3-4&stamp=1403702835
https://buildd.debian.org/status/fetch.php?pkg=skimage&arch=powerpc&ver=0.9.3-4&stamp=1404604318
https://buildd.debian.org/status/fetch.php?pkg=skimage&arch=powerpc&ver=0.9.3-4&stamp=1404604318

I was able to solve this issue for mips in
skimage/io/_plugins/freeimage_plugin.py,
but my solution was to drop <code>FI.FreeImage_IsLittleEndian()</code> condition in <code>_array_to_bitmap</code> and <code>_array_from_bitmap</code>.

With these changes, I was able to successfully build skimage for mips and mipsel.

Unfortunately, I am not an expert neither.

As I see, there is a new 0.10.1-1 version,
so I could test both yours and mine solutions on mips (BE).

I don't have access to these types of machines, so I really appreciate your
help!

I don't think dropping FreeImage_IsLittleEndian is correct as the library is not little endian
I changed a line that looks like a bug, it assumed a 2d input where it is 3d, leading to the flipped axis. the read side correctly assumed 3d data.
an issue is that as the write is broken changing the write side will probably prevent loading previously saved big endian images, but compatibility with non-skimage readers is probably preferable to that.

@stefanv my changes fixes the existing tests, if those are not sufficient can you provide more testes so I can check if my test is correct?
I guess one thing I can do is to save an image on a big endian and try reading it in little endian and vice versa.


Resolving patch:
diff --git a/skimage/io/_plugins/freeimage_plugin.py b/skimage/io/_plugins/freeimage_plugin.py
--- a/skimage/io/_plugins/freeimage_plugin.py
+++ b/skimage/io/_plugins/freeimage_plugin.py
@@ -672,29 +672,28 @@ def _array_to_bitmap(array):
         raise RuntimeError('Could not allocate image for storage')
     try:
         def n(arr):  # normalise to freeimage's in-memory format
-            return arr.T[:, ::-1]
+            return arr.T[..., ::-1]
 
         wrapped_array = _wrap_bitmap_bits_in_array(bitmap, w_shape, dtype)
         # swizzle the color components and flip the scanlines to go to
         # FreeImage's BGR[A] and upside-down internal memory format
-        if len(shape) == 3:
+        if len(shape) == 3 and _FI.FreeImage_IsLittleEndian():
             R = array[:, :, 0]
             G = array[:, :, 1]
             B = array[:, :, 2]
 
-            if _FI.FreeImage_IsLittleEndian():
-                if dtype.type == numpy.uint8:
-                    wrapped_array[0] = n(B)
-                    wrapped_array[1] = n(G)
-                    wrapped_array[2] = n(R)
-                elif dtype.type == numpy.uint16:
-                    wrapped_array[0] = n(R)
-                    wrapped_array[1] = n(G)
-                    wrapped_array[2] = n(B)
-
-                if shape[2] == 4:
-                    A = array[:, :, 3]
-                    wrapped_array[3] = n(A)
+            if dtype.type == numpy.uint8:
+                wrapped_array[0] = n(B)
+                wrapped_array[1] = n(G)
+                wrapped_array[2] = n(R)
+            elif dtype.type == numpy.uint16:
+                wrapped_array[0] = n(R)
+                wrapped_array[1] = n(G)
+                wrapped_array[2] = n(B)
+
+            if shape[2] == 4:
+                A = array[:, :, 3]
+                wrapped_array[3] = n(A)
         else:
             wrapped_array[:] = n(array)
         if len(shape) == 2 and dtype.type == numpy.uint8:


Test patch: