65

I'm working with my new app which processed captured image from cellphone camera. My phone is Nexus S, 2.3.4.

I create a ARGB_8888 Bitmap with captured data. I know the ndk image lib, but it's only support 2.2 and above. So I pass the int[] of Bitmap to NDK and found the color byte order is little-endian.

I searched the wiki and found arm architecture is bi-endian. http://en.wikipedia.org/wiki/Endianness#Bi-endian_hardware

My question is if arm is bi-endian, how to judge the byte order in specific device? Should I test the byte order every time before access the data?

Matrix Bai
  • 1,097
  • 3
  • 11
  • 20
  • I'm surprised it's necessary, doesn't bi-endianity imply that the OS would configure a common endian format across all devices? Have you come across any situation where the colour byte order is not little-endian? – Jodes Jun 02 '11 at 10:05
  • 4
    Since ARMv6, you can dynamically switch the endian-ness of ARM, but iOS, Android and Windows (all flavors) use little-endian. This does not change on different devices. – BitBank Jun 08 '11 at 14:32
  • Thank you, Jodes and BitBank. It seems like I should only focus on the little-endian on Android devices. – Matrix Bai Jun 09 '11 at 08:21

7 Answers7

44

Directly from my Nexus S:

> import java.nio.*;
> System.out.println(ByteOrder.nativeOrder());
LITTLE_ENDIAN

There should also be some way to get the ordering in the NDK.

lxgr
  • 3,719
  • 7
  • 31
  • 46
40

Yes most cpus bi-endian, but most end user operating systems in use today choose to use the cpus in little-endian. Along those lines, ARM can operate in both as a convenience, its actual default after ARM 3 is little-endianess which is the endian mode it starts up in. I think one can safely assume that all Android devices are little endian, otherwise it would be extra work if different android devices were a mixture of endianess.

Because network byte order is big-endian, it can be helpful to convert any format you plan on using for data interchange to network byte order. Again, though, Mac OS X on Intel, Windows, iOS and Android are little-endian, so you might just code up structures with the native endianness and hope the next great OS you want to port data to doesn't go big-endian.

dlamblin
  • 43,965
  • 20
  • 101
  • 140
mP.
  • 18,002
  • 10
  • 71
  • 105
24

ARM processors (on which some Android is running) supports both endian formats.

In NDK-ROOT/platforms/android-[x]/arch-arm/usr/include/machine/endian.h you can find:

#ifdef __ARMEB__
#define _BYTE_ORDER _BIG_ENDIAN
#else
#define _BYTE_ORDER _LITTLE_ENDIAN
#endif

__ARMEB__ is defined by the gcc compiler when using the -mbig-endian ARM option. Even if most Android architectures are using little endian by default you shouldn't take this for granted and for portability reasons your native code should be able to handle both endiannes.

To do that you should #include <endian.h> and check BYTE_ORDER to architecture your code properly.

Community
  • 1
  • 1
mihaipopescu
  • 957
  • 9
  • 15
11

To provide very straightforward answer, here is a list:

  • armeabi: LITTLE_ENDIAN
  • armeabi-v7a: LITTLE_ENDIAN
  • arm64-v8a: LITTLE_ENDIAN
  • mips: LITTLE_ENDIAN
  • mips64: LITTLE_ENDIAN
  • x86: LITTLE_ENDIAN
  • x86_64: LITTLE_ENDIAN

... as of Android API level 21.

Ales Teska
  • 1,198
  • 1
  • 17
  • 38
5
bool isLittleEndian() {
    unsigned short word=0x0102;
    return *(char*)&word==2;
}

simple.

NoAngel
  • 1,072
  • 2
  • 18
  • 27
0

Android NDK has below macros which may be used to check at compile time:

#if defined(__LITTLE_ENDIAN_BITFIELD)
#  error "Arch is Little Endian"
#elif defined (__BIG_ENDIAN_BITFIELD)
#  error "Arch is Big Endian"
#endif

in your case you should assume Little-Endian and place below some-where in the Native source if any:

#if _BYTE_ORDER != _LITTLE_ENDIAN || defined (__BIG_ENDIAN_BITFIELD)
#  error "Big-Endian Arch is not supported"
#endif
Top-Master
  • 7,611
  • 5
  • 39
  • 71
0

I tried with the "lxgr" answer, and I got LITTLE_ENDIAN also.

But working with C++, I read some file with this info: 50 4B 03 04 14 00 00 00 08 00 55 8A F4 3C 9B AA ...

I read the first 4 bytes as UnsignedLong, and I get 67324752 which (in hexa) is:

4034B50

(the first 4 bits, but reversed, as if i was working on a BIG_ENDIAN arch )

So, probably the "System.out.println(ByteOrder.nativeOrder());" reffers to how to handle them in java, but working in c++ with the NDK, you will have to check yourself, here is some code to shrink endiannes (from long readed in BIG_ENDIAN):

long shrinkEndian(long value){
    long result = 0;
    result += (value & 4278190080) >> 24;
    result += (value & 16711680) >> 8;
    result += (value & 65280) << 8;
    result += (value & 255) << 24;

    return result;
}
Sebastian Corradi
  • 1,353
  • 2
  • 14
  • 25
  • 1
    In little-endian, the bytes are stored reversed in memory and in files, so the behaviour above (reading `50 4B 03 04` as `0x04034B50`) is correct for **little-endian** machines, not big-endian as you incorrectly claim. – Miral Jan 22 '19 at 23:24